This may seem to be an academic question, but still I would be very interested in the 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 doing the same using find_if
and the compare
method of the STL strings as predicate, but how? Something like
find_if(s.begin(), s.end(), bind2nd(mem_fun_ref(&string::compare), string("findme")) );
does not work, because the compare method has several overloads and the compiler does not know which one to choose.
As a second step: My motivation for using find_if instead of find is that I have a vector of objects derived from a class having a string property name
and I want to find an object with a given name. Is this possible (without writing an extra function to be used as predicate)?
EDIT: As some (most :) answers mentioned using Boost -- I would prefer not to have to include Boost for this. (As far as I know, most of the Boost libraries are "only" templates, so there should be a way without using Boost.)
One option is to cast the member function pointer to suitable type. Another thing you are forgetting is that std::string::compare returns 0 for equal strings, so you'll also need to negate the functor. All in all:
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 to your rationale against boost: its templates are an order of a magnitude more flexible than what you can find in STL functional header. It's either boost, you wait for C++0x lambdas (which I believe will be the preferable way in such situations) or you write some helpers yourself. Currently it can't get 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 it seems the convenience of overloaded operator== will not be there.
Select 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 get stuck with the reference to reference problem "Item #50 of Effective STL". And the boost.Bind lib or boost.Lambda is the solution for that.
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")));
If a function has overloaded functions, you can cast the function to correct signature like (void (*)(int,int))(&f)
.
For your second question, if you use 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);
I think you will find that the syntax rapidly gets unweildy, if you are trying to call several functions together. Did you try something like this?
find_if(s.begin(), s.end(), bind2nd(mem_fun_ref(&string::compare), "findme"));
Does this not match the char *
overload?
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.