从C ++ 11开始,在算法库中我们有all_of
, any_of
and none_of
来确定谓词是否包含范围的所有元素,任何元素或者没有元素。对这些算法之一的单个调用返回1位信息,而对于特定范围和谓词,有4种可能性:
是否有简明有效的方法来查找此信息?调用all_of
后跟none_of
是可能的,但是(a)无法在单遍范围上工作,并且(b)仅在必要时准确地评估谓词。提升是可以接受的。
答案 0 :(得分:10)
如果您手动检查第一个元素并根据结果选择all_of
或none_of
,则可以消除(a)(b)问题。
代码(从@Angew借用enum
):
enum class Result {
empty, all, none, some
};
template <class FwIt, class Pred>
Result examine_range(FwIt from, FwIt to, Pred pred)
{
if (from == to) return Result::empty;
if (pred(*from)) {
++from;
return all_of(from,to,pred) ? Result::all : Result::some;
} else {
++from;
return none_of(from,to,pred) ? Result::none : Result::some;
}
}
答案 1 :(得分:1)
我是否错误地理解了这个问题,或者这是你可以通过std::accumulate
做的事情?
using eana = std::tuple<bool, bool, bool, bool>;
template <typename T, typename FwdIt, typename Pred>
auto empty_all_none_any(FwdIt begin, FwdIt end, Pred predicate) -> eana {
auto result = eana{begin == end, begin != end, begin != end, false};
result = std::accumulate(begin, end, result, [&](eana& res, T& val) {
if (predicate(val)) {
std::get<2>(res) = false;
std::get<3>(res) = true;
}
else {
std::get<1>(res) = false;
}
return res;
});
return result;
}
答案 2 :(得分:0)
这是我首选的算法(来自@Angew的枚举):
enum class Result {
empty, all, none, some
};
template<class InputIt, class UnaryPredicate>
Result examine_range(InputIt first, InputIt last, UnaryPredicate p)
{
bool all = true, none = true;
for (; first != last && (all || none); ++first)
(p(*first) ? none : all) = false;
return all ? (none ? Result::empty : Result::all)
: (none ? Result::none : Result::some);
}
答案 3 :(得分:0)
您可以使用您描述的标准库函数执行此操作。测试任何元素是否为真,以及任何元素是否为假,然后根据此表组合结果:
any true | none true
======================
any false | mixed | all false |
none false | all true | empty |