Подтвердить что ты не робот

Использование 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.

Или есть еще один хороший способ сделать то же самое?

4b9b3361

Ответ 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;
}