C++ count_until和accumulate_until的实现?

C++ count_until和accumulate_until的实现?,c++,algorithm,boost,c++11,stl,C++,Algorithm,Boost,C++11,Stl,给定一个输入序列,标准算法std::count和std::acculate计算特定值(或与std::count\u匹配的谓词,如果)的出现次数和给定关联运算(和、积、布尔或/和、最小/最大、字符串串联等)的累积次数,分别 如果一个人想知道一个输入序列是否包含完全/至少/最多n发生/匹配,或者累计到完全/至少/最多n?蛮力方法是将std::count或std::acculate的结果与目标n进行比较,但当计数或累积超过输入序列一半时,这将错过提前退出的机会 例如,可以进行一次计数,直到 templ

给定一个输入序列,标准算法
std::count
std::acculate
计算特定值(或与
std::count\u匹配的谓词,如果
)的出现次数和给定关联运算(和、积、布尔或/和、最小/最大、字符串串联等)的累积次数,分别

如果一个人想知道一个输入序列是否包含完全/至少/最多
n
发生/匹配,或者累计到完全/至少/最多
n
?蛮力方法是将
std::count
std::acculate
的结果与目标
n
进行比较,但当计数或累积超过输入序列一半时,这将错过提前退出的机会

例如,可以进行一次
计数,直到

template<class InputIt, class T, class Pred>
auto count_until(InputIt first, InputIt last, const T& value, Pred pred)
{
    auto res = 0;
    for (; first != last; ++first)
        if (*first == value && pred(++res))
            break; // early exit if predicate is satisfied
    return std::make_pair(first, res); // iterator and value to allow continuation    
}
模板
自动计数\u直到(第一次输入、最后一次输入、常量T和值、Pred-Pred)
{
自动恢复=0;
for(;first!=last;++first)
if(*first==值和pred(++res))
break;//如果满足谓词,则提前退出
返回std::make_pair(first,res);//迭代器和允许继续的值
}
通过使用合适的谓词并与返回的计数进行比较,可以从中测试相等性/至少/最多

问题

  • 是否可以使用现有标准算法的组合(可能与合适的算法组合)写入
    count_直到
    (类似地,对于
    累加_直到
  • 特别是,我想到了一个
    find\u if
    遍历
    accumulate\u迭代器,谓词将从迭代器中提取计数或和
    
  • 或者,
    count_直到
    acculate_直到
    可以保证作为独立原语包含在标准库的未来版本中吗

Edit:我认为最有用的公式是返回迭代器的
std::pair
,以及谓词第一次满足时的计数。这允许用户继续迭代。

我在考虑std::find_if与状态谓词的组合: (Pred是正常的用户谓词。)

模板
类型名迭代器特征::差异类型
计数\u直到(输入开始、输入结束、常量和值、Pred-Pred)
{
类型名迭代器特征::差异类型计数=0;
自动内部_pred=[&count,&value,&pred](decltype(*begin)元素){
返回元素==值&&pred(++count);
};
std::find_if(开始、结束、内部_pred);
返回计数;
}
模板
T累计\u直到(输入开始、输入结束、T值、Pred-Pred)
{
自动内部_pred=[&value,&pred](常量T&T){
值+=t;
返回pred(值);
};
std::find_if(开始、结束、内部_pred);
返回值;
}

您可以使用
std::map
来记录发生的次数。如果
std::find\u
使用带状态的谓词,您就可以使用它执行您想要的操作了。@Jarod42是否要制定一个答案?最好是将谓词从外部传递到
count\u,直到
@TemplateRex:my version作为答案发布,在我看来,这些名称不明确,因为“直到”谓词可能指迭代器或“工作结果”。可能使用
std::Iterator\u traits::difference\u type
而不是
size\u t
。谢谢并接受。顺便说一句,
acculate\u until
只适用于单调累加(比如正整数的加法)。如果输入可以为负数,则当总数变为负数时,
累计\u直到
将停止(例如,在赌徒破产问题中)。因此我认为,
acculate\u until
应该返回迭代器和值的
std::pair
,而不仅仅是一个值,这样用户就可以决定从第一次失败开始继续迭代。我还考虑过只从
count\u返回迭代器,直到
,但似乎不可能以这种方式实现
is\u count\u等于
。这两种方法都可以返回
pair
(很容易)
是否等于(..,n)
可以计算为(..,大于(n+1))
。count的内部谓词中的短路逻辑是一件艺术品。
template<class InputIt, class T, class Pred>
typename iterator_traits<InputIterator>::difference_type
count_until(InputIt begin, InputIt end, const T& value, Pred pred)
{
    typename iterator_traits<InputIterator>::difference_type count = 0;
    auto internal_pred = [&count, &value, &pred](decltype(*begin) elem) {
        return elem == value && pred(++count);
    };

    std::find_if(begin, end, internal_pred);
    return count;
}

template<class InputIt, class T, class Pred>
T accumulate_until(InputIt begin, InputIt end, T value, Pred pred)
{
    auto internal_pred = [&value, &pred] (const T& t) {
        value += t;
        return pred(value);
    };
    std::find_if(begin, end, internal_pred);
    return value;
}