It has been noted in similar questions (e.g. here) that you cannot pass class method pointers as predicates to std::all_of
.
However, with C++17, we have std::invoke
, which should make it easy for std::all_of
and similar functions to accept member function (and even member variable) pointers.
To be more specific, the following does not compile on GCC 9.2:
#include <algorithm>
#include <vector>
struct S {
bool check() const { return true; }
};
int main() {
std::vector<S> vs;
std::all_of(vs.begin(), vs.end(), &S::check);
}
This Godbolt link contains some example code and a toy version of all_of
using invoke.
Why this restriction? Am I missing something? I imagined that when std::invoke
was standardised, it should also have been applied to appropriate STL functions.
Reason 1: No one has ever proposed it. P0312R1 proposed to make pointer-to-member-functions callable in the language but was rejected (no consensus for making this change).
Reason 2: With lambda's (and std::bind
prior to that), there's very little motivation. If S
is a std-defined type (e.g. vector
), the member-to-pointer option would be illegal for other reasons.
std::all_of(vs.begin(), vs.end(), [](auto const& s) {return s.check();});
The next generation of algorithms (those in the std::ranges
namespace) accept predicates that are called with std::invoke
, exactly as you suggest (https://godbolt.org/z/uaPoJf):
std::ranges::all_of(vs.begin(), vs.end(), &S::check);
or shorter (https://godbolt.org/z/_qiO8G):
std::ranges::all_of(vs, &S::check);
Furthermore, they accept an additional argument called a “projection”, which is a unary transformation function passed to the algorithm that gets applied to each element before the algorithm operates on the element. For example (https://godbolt.org/z/gWY-OR):
std::ranges::all_of(vs, std::logical_not(), &S::check);
You can already use all of the above with either Casey Carter’s cmcstl2 or Eric Niebler’s range-v3.
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