Using find_if on std :: vector <std :: string> with bind2nd and string :: compare

This may seem like an academic question, but still I'd be very interested in an answer:

I have a vector of strings s

in which I would like to find a given string findme

. This can be done using something like

find(s.begin(), s.end(), findme);

      

My question is, there must be a way to do the same using a method find_if

and compare

STL strings as a predicate, but how? Something like

find_if(s.begin(), s.end(), bind2nd(mem_fun_ref(&string::compare), string("findme")) );

      

doesn't work because the comparison method has multiple overloads and the compiler doesn't know which one to choose.

As a second step: The motivation for using find_if instead of find is that I have a vector of objects obtained from a class that has a string property name

and I want to find an object with a given name. Is this possible (without writing an additional function to be used as a predicate)?


EDIT: like some (most :) answers mentioned with Boost - I'd rather not include Boost for this. (As far as I know, most Boost libraries are "only" templates, so there must be a way without using Boost.)

+2


source to share


4 answers


One option is to provide a member function pointer for the appropriate type. Another thing you are forgetting is that std :: string :: compare returns 0 for equal strings, so you will need to negate the functor as well. Total:

std::find_if(
    vec.begin(), vec.end(),
    std::not1(
        std::bind2nd(
            std::mem_fun_ref(static_cast<int (std::string::*)(const char*)const>(&std::string::compare)),
            "findme"
        )
    )
);

      

As for your rationale against escalation: its templates are orders of magnitude more flexible than what you can find in the STL functional header. This either reinforces, you are waiting for C ++ 0x lambdas (which I believe would be the preferred way in situations like this), or you write some helpers yourself. Currently, it cannot be simpler than:



std::find_if(vec.begin(), vec.end(), boost::bind(&X::name, _1) == "findme");

      

FYI, C ++ 0x will add std :: bind, which is similar to boost :: bind, but there seems to be no convenience of the overloaded == operator.

+5


source


Choose the correct overload yourself.

int (string::*compare)(const string&) const;
compare = &string::compare;
find_if(s.begin(), s.end(), bind2nd( mem_fun_ref(compare), string("findme")));

      

But then you are stuck with a reference to the "Item # 50 of Effective STL" reference issue. And boost.Bind lib or boost.Lambda is the solution for this.



int (string::*compare)(const string&) const;
compare = &string::compare;
find_if(s.begin(), s.end(), bind(compare, _1, "findme")==0);

      

Or

find_if(s.begin(), s.end(), bind2nd(std::equal_to<string>(), string("findme")));

      

+3


source


If the function has overloaded functions, you can use the function to properly sign, eg (void (*)(int,int))(&f)

.

For your second question, if you are using boost you can do something like this,

find_if(s.begin(), s.end(), boost::bind(std::equal_to<string>(), boost::bind(&SomeClass::name, _1), name);

      

+1


source


I think you'll find that the syntax quickly becomes unweildy if you try to call multiple functions together. Have you tried something like this?

find_if(s.begin(), s.end(), bind2nd(mem_fun_ref(&string::compare), "findme"));

      

Does this not match the overload char *

?

0


source







All Articles