Search code examples
c++c++11stdbindmem-fun

find inside a class if an element exists within a vector of pairs


I'm coding in C++. I have a project with so many files. I have a vector of pairs named list as follows:

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

and I want to check if for a specific double value z , there exists an element: el in the list such that: el.second == z

I want to use find_if

To do so , I've implemented a method : Scheduled that takes two arguments: the first one is an element like those stored in the list , the second one is the specific value to look for. I tried several ways but I end up getting an error always 1st way:

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

}

inside another method but still in the same class: classA

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



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

This solution gives the following error:

 error: ‘Scheduled1’ does not name a type

2nd way: directly using lambda

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

z is a member variable of classA This second way of coding gives rise to this error:

error: no matching function for call to 

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


Solution

  • There's no need to mix bind, bind1st and mem_fun to do this (the latter two are deprecated in C++11); just use a lambda

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

    Or if you want to call Scheduled

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

    If you must use bind

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

    In either case, you might want to change Scheduled to be a static member function since it doesn't need access to any non-static members, in which case the bind option becomes

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

    Also, Scheduled should probably take the std::pair argument by const& to avoid unnecessary copies.

    Another option is to use any_of instead of find_if, which avoids having to compare the result with the end interator

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

    Here's an explanation of what's wrong with your attempt.

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

    Scheduled is a non-static member function, which means it takes an implicit first argument, a pointer to the instance it must be invoked on, i.e. the this pointer. Moreover, the syntax for creating a pointer to member function is &ClassName::MemberFunctionName. So the above line should be

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

    bind returns a function object of unspecified type, but you use that object as if it were a member function (mem_fun(&classA::Scheduled1)) which is clearly incorrect. Simply passing the above Scheduled1 object as the 3rd argument to find_if in your example should work.