问题
I have an object type like this:
struct T
{
int x;
bool y;
};
and a container of them like this:
std::vector<T> v;
and a burning desire to determine — in a single statement — whether any of the elements of v
have y == true
. This likely involves std::find_if
.
My understanding is that std::bind
and boost::bind
are for member functions and cannot be applied to member data.
Because I dislike them, I wish to avoid:
- comparison functions/functors
- loops
Because my environment is C++03, the following are not available:
- lambdas
回答1:
My understanding is that
std::bind
andboost::bind
are for member functions and cannot be applied to member data.
Remarkably, this is not the case! boost::bind
will happily bind to member data and allow you to perform operations on it during an "inline iteration".
From the documentation:
Pointers to member functions and pointers to data members are not function objects, because they do not support
operator()
. For convenience, bind accepts member pointers as its first argument, and the behavior is as if boost::mem_fn has been used to convert the member pointer into a function object. In other words, the expressionbind(&X::f, args)
is equivalent to
bind<R>(mem_fn(&X::f), args)
where R is the return type of X::f (for member functions) or the type of the member (for data members.)
Also, from the documentation for boost::mem_fn
:
mem_fn also supports pointers to data members by treating them as functions taking no arguments and returning a (const) reference to the member.
So, you can do this:
#include <vector>
#include <string>
#include <algorithm>
#include <iostream>
#include <boost/bind.hpp>
struct T
{
int x;
bool y;
};
void f(const std::string& name, const std::vector<T>& v)
{
const bool found = std::find_if(
v.begin(),
v.end(),
boost::bind(&T::y, _1) == true
) != v.end();
std::cout << name << ": " << (found ? " FOUND" : " not found") << '\n';
}
int main()
{
T a = { 0, false };
T b = { 1, false };
T c = { 2, true };
std::vector<T> v;
f("a", v);
v.push_back(a);
v.push_back(b);
f("b", v);
v.push_back(c);
f("c", v);
}
Output:
a: not found
b: not found
c: FOUND
回答2:
What you want (to determine — in a single statement — whether any of the elements of v have y == true) seems to be:
inline bool y_is_true(std::vector<T>::iterator i) { return i->y; };
(outside your function) and
bool found = std::find_if(v.begin(), v.end(), y_is_true) != v.end();
Another option is to use boost::lambda
:
bool found = std::find_if(v.begin(), v.end(), _1.y) != v.end();
来源:https://stackoverflow.com/questions/17196690/how-can-i-search-a-container-of-objects-for-a-data-member-value