Using find_if on a vector of object
I have a vector of that looks like the following:
class Foo
{
//whatever
};
class MyClass
{
int myInt;
vector<Foo> foo_v;
};
And let's say, in the main:
int main (void)
{
vector<MyClass> myClass_v;
}
I want to find a object in myClass_v that has myInt == bar. I don't care about foo_v. I thought of using the std::find_if function:
std::find_if(myClass_v.begin(),myClass_v.end(),condition);
with
bool MyClass::condition(MyClass mc)
{
if(mc.myInt==5)
return true;
else
return false;
}
However the compiler says that condition() is missing arguments. Could you tell me what am I doing wrong? I thought that std::find开发者_开发知识库_if would call condition(*First), with First being a pointer to a myClass object.
Or is there another good way to do the same thing?
That's not how predicates work. You have to supply either a free function bool Comparator(const MyClass & m) { ... }, or build a function object, a class that overloads operator():
struct MyClassComp
{
explicit MyClassComp(int i) n(i) { }
inline bool operator()(const MyClass & m) const { return m.myInt == n; }
private:
int n;
};
std::find_if(v.begin(), v.end(), MyClassComp(5));
In C++0x:
std::find_if(v.begin(), v.end(),
[](const MyClass & m) -> bool { return m.myInt == 5; });
This captureless lambda is in fact equivalent to a free function. Here is a capturing version that mimics the predicate object:
const int n = find_me();
std::find_if(v.begin(), v.end(),
[n](const MyClass & m) -> bool { return m.myInt == n; });
struct condition {
bool operator()(const MyClass& mc) {
return mc.myInt == 5;
}
}
You can do it with a functor or a regular function that is not part of MyClass, or with a static function inside MyClass - here's an example with non-member function (basically just removing the MyClass:: part of the condition definition):
#include <algorithm>
#include <vector>
using namespace std;
class Foo
{
//whatever
};
class MyClass
{
public:
int myInt;
vector<Foo> foo_v;
};
bool condition(MyClass mc)
{
if(mc.myInt==5)
return true;
else
return false;
}
int main (void)
{
vector<MyClass> myClass_v;
std::find_if(myClass_v.begin(),myClass_v.end(),condition);
}
Besides what Kerrek SB wrote, you can also use the member function as a predicate.
Define it as bool MyClass::condition() { return mc.myInt==5; } - parameter is unnecessary since it already takes object as implicit parameter.
When using it, wrap &MyClass::condition (pointer to a member function) in std::mem_fcn from functional header.
std::find_if(myClass_v.begin(), myClass_v.end(), std::mem_fcn(&MyClass::condition));
A more verbose way to do it, is to use std::function or std::bind. Replace:
std::mem_fcn(&MyClass::condition)
with
std::function<bool (MyClass &)>(&MyClass::condition) , or
std::bind(&MyClass::condition, std::placeholders::_1).
If MyClass_v has been declared as std::vector<MyClass *> myClass_v;,
std::function<bool (MyClass &)>(&MyClass::condition) should be altered to: std::function<bool (MyClass *)>(&MyClass::condition).
For std::mem_fn and std::bind - no changes are needed.
Code:
#include <vector>
#include <functional>
#include <algorithm>
#include <iostream>
class Foo{};
struct MyClass
{
int myInt;
std::vector<Foo> foo_v;
bool condition(){ return myInt==5; }
};
int main (void)
{
std::vector<MyClass> myClass_v{ {1,{}}, {3,{}}, {5,{}}, {6,{}} };
std::cout << std::find_if(myClass_v.begin(), myClass_v.end(), std::mem_fn(&MyClass::condition))->myInt << std::endl;
return 0;
}
加载中,请稍侯......
精彩评论