2015-05-27 3 views
0

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

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

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

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

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

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 

второй путь: непосредственно с помощью лямбда

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

г является переменной членом CLASSA Это второй способ кодирования приводит к этой ошибке:

error: no matching function for call to 

«find_if (станд :: вектор> :: итератор, станд :: вектор> :: итератор, CLASSA :: method1 (интермедиат) :: __ lambda0)»

+0

Типа вернулся из станд :: привязывать не функция-член, а Scheduled1 - значение, а не тип. –

+0

Для записи то, что вы делаете, является формой [currying] (http://en.wikipedia.org/wiki/Currying) (в некоторых случаях это может упростить поиск с использованием этого имени). –

+0

Извините, но вам нужно будет сделать лучше, если вам нужна дополнительная помощь. В добавленном вами коде есть несколько ошибок, и если вы не можете опубликовать действительный код, я больше не пытаюсь. '& ClassA :: IsItScheduled' -' c' в 'classA' теперь занимает верхний регистр? А что такое 'IsItScheduled'? '... Scheduled1) =! List.end();' - '=!' Явно неверно. И в примере лямбда результат 'find_if' не конвертируется в' bool', вам нужно сравнить это с конечным итератором, как и в другом примере. Создайте тестовый файл, который я могу скопировать-вставить как есть, и воспроизвести ошибку. См. [SSCCE] (http://sscce.org) – Praetorian

ответ

4

Там нет необходимости смешивать 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, что избавляет от необходимости сравнить результат с конца interator

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 в вашем примере должен работать.

+0

спасибо за упоминание лямбда-решения! – Alejandro

+0

Спасибо за объяснение, однако было достаточно ясно, однако, для двух первых предложений, я получаю эту ошибку: ошибка: захват непеременной classA :: z Для третьего компилятор отображает: Scheduled1 не называет тип такое же сообщение, как и раньше для третьего здесь, что я написал bool call = std :: find_if (list.begin(), list.end(), Scheduled1) == list.end() ; – Saddam

+0

@Saddam Я не знал, что 'z' был членом' classA', вам нужно заменить 'z' на' this' в списке захвата лямбда, см. Обновленный ответ. Я не уверен, в чем проблема с другим вариантом. 'auto Scheduled1 = std :: bind (& classA :: Scheduled, this, _1, z); std :: find_if (list.begin(), list.end(), Scheduled1); 'должен компилироваться. Если у вас по-прежнему возникают проблемы с этим вопросом, нажмите [edit] (https://stackoverflow.com/posts/30483667/edit) вопрос и добавьте код, который не компилируется, вместе с точным сообщением об ошибке. – Praetorian

0

Как упоминалось @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(); 

} 

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

Смежные вопросы