Использование find_if для вектора объекта
У меня есть вектор, который выглядит следующим образом:
class Foo
{
//whatever
}
class MyClass
{
int myInt;
vector<Foo> foo_v;
}
И пусть говорят, в основном:
int main (void)
{
vector<MyClass> myClass_v;
}
Я хочу найти объект в myClass_v, у которого есть myInt == bar. Меня не волнует foo_v. Я думал об использовании функции find_if:
std::find_if(myClass_v.begin(),myClass_v.end(),condition);
с
bool MyClass::condition(MyClass mc)
{
if(mc.myInt==5)
return true;
else
return false;
}
Однако компилятор говорит, что в условии() отсутствуют аргументы. Не могли бы вы сказать мне, что я делаю неправильно? Я думал, что find_if будет вызывать условие (* First), причем First является указателем на объект myClass.
Или есть еще один хороший способ сделать то же самое?
Ответы
Ответ 1
Это не то, как предикаты работают. Вы должны предоставить либо свободную функцию bool Comparator(const MyClass & m) { ... }
, либо создать объект функции, класс, который перегружает 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));
В С++ 0x:
std::find_if(v.begin(), v.end(),
[](const MyClass & m) -> bool { return m.myInt == 5; });
Эта беззаботная лямбда фактически эквивалентна свободной функции. Вот захватывающая версия, которая имитирует предикатный объект:
const int n = find_me();
std::find_if(v.begin(), v.end(),
[n](const MyClass & m) -> bool { return m.myInt == n; });
Ответ 2
struct condition {
bool operator()(const MyClass& mc) {
return mc.myInt == 5;
}
}
Ответ 3
Вы можете сделать это с помощью функтора или регулярной функции, которая не является частью MyClass, или со статической функцией внутри MyClass - здесь пример с функцией, не являющейся членом (в основном просто удаление MyClass:: часть определения условия ):
#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);
}
Ответ 4
Кроме того, что написал Kerrek SB, вы также можете использовать функцию-член как предикат.
Определите его как bool MyClass::condition() { return mc.myInt==5; }
- параметр не нужен, поскольку он уже принимает объект как неявный параметр.
При использовании wrap &MyClass::condition
(указатель на функцию-член) в std::mem_fcn
из функционального заголовка.
std::find_if(myClass_v.begin(), myClass_v.end(), std::mem_fcn(&MyClass::condition));
Более подробный способ сделать это - использовать std::function
или std::bind
. Заменить:
std::mem_fcn(&MyClass::condition)
с
std::function<bool (MyClass &)>(&MyClass::condition) , or
std::bind(&MyClass::condition, std::placeholders::_1).
Если MyClass_v
было объявлено как std::vector<MyClass *> myClass_v;
,
std::function<bool (MyClass &)>(&MyClass::condition)
следует изменить на: std::function<bool (MyClass *)>(&MyClass::condition)
.
Для std::mem_fn
и std::bind
- никаких изменений не требуется.
Код:
#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;
}