Найти внутри класса, если элемент существует в векторе пар

Я пишу в C++. У меня есть проект с таким количеством файлов. У меня есть вектор пар с именем list следующим образом:

std::vector< std::pair< structure1, double> > list;

и я хочу проверить, если для конкретного двойного значения z существует элемент: el в списке таких что: el.second == z

Я хочу использовать find_if

Для этого я реализовал метод: Scheduled это принимает два аргумента: первый - это элемент, подобный тем, которые хранятся в списке, второй - конкретное значение, которое нужно искать. Я пробовал несколько способов, но в итоге получаю ошибку всегда 1-й способ:

 bool classA::Scheduled(std::pair< structure1,double > const el, double const t )
{
  return el.second==t;

}

внутри другого метода, но все еще в том же классе: classA

auto Scheduled1 = std::bind(&classA::Scheduled,this,_1,z);



 bool call=std::find_if(list.begin(),list.end(),Scheduled1)=!list.end();

Это решение дает следующую ошибку:

 error: ‘Scheduled1’ does not name a type

2-й способ: напрямую с помощью лямбды

bool call = std::find_if(list.begin(),list.end(),[this](std::pair<struct1,double> const& el){return el.second==z;})!=list.end();

z является переменной-членом класса A. Этот второй способ кодирования приводит к этой ошибке:

error: no matching function for call to 

'find_if(std::vector >::iterator, std::vector >::iterator, classA::method1(int)::__lambda0)'

2 ответа

Решение

Там нет необходимости смешивать bind, bind1st а также mem_fun сделать это (последние два устарели в C++11); просто используйте лямбду

bool call = std::find_if(list.begin(), list.end(),
                         [this](std::pair< strucure1,double > const& el) {
                           return el.second == z;
                         }) != list.end();

Или если вы хотите позвонить Scheduled

bool call = std::find_if(list.begin(), list.end(),
                         [this](std::pair< strucure1,double > const& el) {
                           return Scheduled(el, z);
                         }) != list.end();

Если вы должны использовать bind

bool call = std::find_if(list.begin(), list.end(),
                         std::bind(&classA::Scheduled, this, _1, z)) != list.end();

В любом случае, вы можете изменить Scheduled быть static функция-член, так как ей не нужен доступ к каким-либо нестатическим элементам, в этом случае bind вариант становится

bool call = std::find_if(list.begin(), list.end(),
                         std::bind(&classA::Scheduled, _1, z)) != list.end();

Также, Scheduled вероятно, следует взять std::pair аргумент const& чтобы избежать ненужных копий.

Другой вариант заключается в использовании any_of вместо find_if что позволяет избежать необходимости сравнивать результат с конечным интегратором

bool call = std::any_of(list.begin(), list.end(),
                        <insert lambda or bind expression>);

Вот объяснение того, что не так с вашей попыткой.

auto Scheduled1=std::bind(Scheduled, _1, z);

Scheduled является нестатической функцией-членом, что означает, что она принимает неявный первый аргумент, указатель на экземпляр, на который она должна быть вызвана, т.е. this указатель. Кроме того, синтаксис для создания указателя на функцию-член &ClassName::MemberFunctionName, Таким образом, приведенная выше строка должна быть

auto Scheduled1=std::bind(&classA::Scheduled, this, _1, z);

bind возвращает объект функции неопределенного типа, но вы используете этот объект, как если бы он был функцией-членом (mem_fun(&classA::Scheduled1)) что явно неверно. Просто передавая выше Scheduled1 объект в качестве третьего аргумента find_if в вашем примере должно работать.

Как упомянул @Praetorian, вы могли бы использовать лямбды. Однако связыватели позволяют использовать существующие функции предикатов "из коробки", хотя и иногда более читабельны (тот факт, что новый std::bind автоматически связывает функцию-член с экземпляром, позволяет использовать открытый интерфейс типа из коробки). Я добавил пример, аналогичный вашему (который компилируется), в котором я объясню некоторые вещи (см. Комментарии к коду):

#include <iostream>
#include <vector>
#include <utility>
#include <functional>
#include <algorithm>

// Replaces your structure...
struct Xs{};


// typedef so that we can alias the ugly thing...    
typedef std::vector<std::pair<Xs, double>> XDoubleVector;

// --- From your code, I've just named it A for brevity....
struct A
{
    bool Scheduled(std::pair<Xs,double> const el, double const t )
    {
      return el.second==t;
    }
};


int main() {

    using namespace std::placeholders;
    //Instantiate it.... replaced your list.
    XDoubleVector doubleVect;
    //--- and add some elements....

    //We need to instantiate A, in order to invoke 
    // a member function...
    A a;

    // Returns true if found...
    return std::find_if(
        doubleVect.begin(),
        doubleVect.end(),
        //Notes:
        //- Scheduled is a member function of A
        //- For that reason, we need to pass an instance of
        //   A to binder (almost seen as first bound).
        //- _1 indicates that the first parameter to Scheduled will be            
        //   passed in by algorithm
        //- We've hardcoded the second parameter (it is therefore 
        //   bound early).
        std::bind(&A::Scheduled, a, _1, 20.9)) != doubleVect.end();

}

С уважением, Вернер

Другие вопросы по тегам