Search code examples
c++c++20std-ranges

Do C++20 ranges have value(not predicate) version of filter or any_of?


Classic C++ sometimes picks the _if suffix for predicate algorithms(versus the ones that take value) e.g. find_if/find count_if/count and sometimes it does not(for example any_of does not have _if suffix although it takes predicate, and there is no any_of value version of algorithm).

As far as I can see C++20 filter or ranges::any_of have no value overload.

I went through entire cppreference page for C+++20 and found nothing, I presume it was just because C++20 ranges library is quite limited (only few views) and it is matching existing functionality (in case of any_of).

My best attempt is to just wrap the logic and give it a new name.

template <typename Range, typename Value>
static bool contains(const Range& range, const Value& value)
{
    return std::ranges::find(range, value) != range.end();
}

edit: good news: C++23 has std::ranges::contains


Solution

  • Do C++20 ranges have value(not predicate) version of filter or any_of?

    No, C++20 does not. But it is pretty easy to write:

    std::ranges::any_of(r, [&](auto const& e){ return e == value; })
    

    Thankfully, C++23 does introduce a new ranges::contains to make this even easier:

    std::ranges::contains(r, value);
    

    Or, if that is considered too long, you could add a helper:

    inline constexpr auto equals = [](auto const& value){
        return [=](auto const& e){ return e == value; };
    };
    

    That you can use to shorten the any_of call:

    std::ranges::any_of(r, equals(value));
    

    Or you could use any number of libraries that let you write placeholder-lambdas, most recently Boost.Lambda2:

    std::ranges::any_of(r, _1 == value);