I have a std::vector<std::vector<int>>
, from which I want to check whether there is at least 1 sub-vector that's empty. So I have this:
std::any_of(vec.begin(), vec.end(), [](const auto& subvec) {
return subvec.empty();
});
Is there something like this in C++14?
std::any_of(vec.begin(), vec.end(), std::vector<int>::empty);
I tried the above syntax, which didn't work. Nor did sticking a &
in front of the method work, as one source claimed.
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 tobool
for every argumentv
of type (possibly const)VT
, whereVT
is the value type ofInputIt
, regardless of value category, and must not modifyv
. Thus, a parameter type ofVT&
is not allowed, nor isVT
unless forVT
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));
}
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.
Conclusion: A lambda expression is the lightweight, easy to read way to wrap the member function. I doubt it can get any more readable.