Using the lambda is the readable way.
Only for illustration lets explore other ways. The predicate p needs to be (from cppreference):
The expression p(v) must be convertible to bool for every argument v of type (possibly const) VT, where VT is the value type of InputIt, regardless of value category, and must not modify v. Thus, a parameter type of VT& is not allowed, nor is VT unless for VT a move is equivalent to a copy(since C++11).
Implicit conversions aside, this basically means, the predicate must be a callable with signature bool (const std::vector<int>&).
std::function is a candiate. It comes with considerable overhead, because its main purpose is type erasure. We do not need type erasure, but std::function also has a mechanism to turn a member function pointer into a callable where the object is passed to the function. Ie we can transform &std::vector<int>::empty, a member function pointer, into something with signature bool (const std::vector<int>&). So far so good, but this transformation isnt implicit and does not play well with class template argument deduction. As a consequence the syntax is rather clumsy:
int main () {
std::vector<std::vector<int>> vec;
std::any_of(vec.begin(),vec.end(),std::function<bool(const std::vector<int>&)>(&std::vector<int>::empty));
}
Live Demo
Um... We can turn the member function pointer into a callable with right signature, but std::function isnt really what is needed here and it does not help for terse syntax. How about writing a custom wrapper:
template <typename T> struct class_type;
template <typename C> struct class_type<bool(C::*)() const noexcept> { using type = C;};
template <auto F>
struct bool_member_to_functor {
using type = typename class_type<std::decay_t<decltype(F)>>::type;
bool operator()(const type& c) {
return (c.*F)();
}
};
int main (int argc, char** argv)
{
std::vector<std::vector<int>> vec;
std::any_of(vec.begin(),vec.end(),bool_member_to_functor<&std::vector<int>::empty>{});
}
This leads to nice syntax on the call. Passing the member function directly is not possible, but this is as close as it can get. However, class_type is a bit of a cheat here. You'd need more specializations to cover all const / non-const, not noexcept etc variants. And it gets much worse when the member function is overloaded. Its not something you actually want to write.
Live Demo
Conclusion: A lambda expression is the lightweight, easy to read way to wrap the member function. I doubt it can get any more readable.
stdnamespace, but the standard forbids it, except for a very limited set of designated addresable functions.std::empty()clone.