Since C++11, in the algorithms library we have all_of
, any_of
and none_of
to determine whether a predicate holds on all, any or none of the elements of a range. A single call to one of these algorithms returns 1 bit of information, whereas for a particular range and predicate there are 4 possibilities:
Is there a concise and efficient way to find this information? Calling all_of
followed by none_of
is a possibility, but (a) fails to work on single-pass ranges, and (b) evaluates the predicate exactly once more than necessary. Boost would be acceptable.
You can eliminate both (a) the (b) problems if you examine the first element manually and choose between all_of
or none_of
depending on the result.
Code (borrowed the enum
from @Angew):
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;
}
}
Am I understanding this question wrongly, or is this something you could do via 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;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With