using bind with find_if

Hello, I am currently using find_if with bind2nd to perform a search on a vector. My current code looks like this: struct OverrideMatches : public std::binary_function<const TItemOverride, const TItemOverride, bool> { bool operator()( const TItemOverride& OverrideSource, TItemOverride OverrideTarget ) const { return OverrideSource.ChildAssyItemRecNo == OverrideTarget.ChildAssyItemRecNo && OverrideSource.LinkItemRecNo == OverrideTarget.LinkItemRecNo; } }; TItemOverrideGateway::Container_t::iterator where = std::find_if( FOverridesContainer.begin(), FOverridesContainer.end(), std::bind2nd( OverrideMatches(), TItemOverride( "", 0, "", 0, ChildItemRecNo, LinkItemRecNo ) ) ); I would like to eliminate the need for that temporary object to hold the values I am searching for (and just specify the values instead), and to do that, I want to try using boost::bind instead of std::bind2nd, but I have not been able to determing exactly what that syntax would look like. I know I will need placeholders for the values to search on (ChildItemRecNo, LinkItemRecNo), but then how does the element from the vector get passed to the I think I want the functor to look something like this: struct OverrideMatches { bool operator()( const TItemOverride &OverrideSource, const RecNo_t ChildItemRecNo, const RecNo_t LinkItemRecNo ) { return OverrideSource.ChildAssyItemRecNo == ChildItemRecNo && OverrideSource.LinkItemRecNo == LinkItemRecNo; } }; If the above functor is correct (and maybe it's not, in which case, please correct me), how do I then rewrite std::find_if to use it with boost::bind? Thank you very much, Dennis Jones

I am currently using find_if with bind2nd to perform a search on a vector. My current code looks like this:
struct OverrideMatches : public std::binary_function<const TItemOverride, const TItemOverride, bool> { bool operator()( const TItemOverride& OverrideSource, TItemOverride OverrideTarget ) const { return OverrideSource.ChildAssyItemRecNo == OverrideTarget.ChildAssyItemRecNo && OverrideSource.LinkItemRecNo == OverrideTarget.LinkItemRecNo; } };
TItemOverrideGateway::Container_t::iterator where = std::find_if( FOverridesContainer.begin(), FOverridesContainer.end(), std::bind2nd( OverrideMatches(), TItemOverride( "", 0, "", 0, ChildItemRecNo, LinkItemRecNo ) ) );
Excuse my ignorance, but if you just want to find elements equal to some specific element, why don't you use simply std::find() -- without binds etc.?

----- Original Message ----- From: "Igor R" <boost.lists@gmail.com> To: <boost-users@lists.boost.org> Sent: Wednesday, March 09, 2011 12:30 PM Subject: Re: [Boost-users] using bind with find_if
I am currently using find_if with bind2nd to perform a search on a vector. My current code looks like this:
struct OverrideMatches : public std::binary_function<const TItemOverride, const TItemOverride, bool> { bool operator()( const TItemOverride& OverrideSource, TItemOverride OverrideTarget ) const { return OverrideSource.ChildAssyItemRecNo == OverrideTarget.ChildAssyItemRecNo && OverrideSource.LinkItemRecNo == OverrideTarget.LinkItemRecNo; } };
TItemOverrideGateway::Container_t::iterator where = std::find_if( FOverridesContainer.begin(), FOverridesContainer.end(), std::bind2nd( OverrideMatches(), TItemOverride( "", 0, "", 0, ChildItemRecNo, LinkItemRecNo ) ) );
Excuse my ignorance, but if you just want to find elements equal to some specific element, why don't you use simply std::find() -- without binds etc.?
I don't want to find elements equal to a specific element. I want to find an element that meets specific criteria -- that is, find the element for which two of its data members have specific values. If I already had all the criteria for the element, I wouldn't need to find it in the first place! - Dennis

I don't want to find elements equal to a specific element. I want to find an element that meets specific criteria -- that is, find the element for which two of its data members have specific values. If I already had all the criteria for the element, I wouldn't need to find it in the first place!
I see... You can do something like this: std::find_if(FOverridesContainer.begin(), FOverridesContainer.end(), boost::bind(OverrideMatches(), _1, ChildItemRecNo, LinkItemRecNo)); or with Boost.Range algorithm: boost::find_if(FOverridesContainer, boost::bind(OverrideMatches(), _1, ChildItemRecNo, LinkItemRecNo));

"Igor R" <boost.lists@gmail.com> wrote in message news:AANLkTimji+kRLMOcYKSmgZibD5cGYuh0__eLtqqmVaiZ@mail.gmail.com...
I see... You can do something like this:
std::find_if(FOverridesContainer.begin(), FOverridesContainer.end(), boost::bind(OverrideMatches(), _1, ChildItemRecNo, LinkItemRecNo));
Oh, of course! Now that I see it, it makes perfect sense. For some reason, I was thinking that I needed placeholders for all values being passed to the functor, when all I really needed was the placeholder for the element in the vector because I have the actual values for the 2nd and 3 parameters. I just have to add: typedef bool result_type; to my functor, or call boost::bind<bool>. Thanks! - Dennis

I just have to add:
typedef bool result_type;
to my functor, or call boost::bind<bool>.
Or just define a simple function instead of the functor (which is stateless anyway). By the way, if you've got a lot of tasks where you extract elements according to some criteria, it's worth taking a look at Boost.MultiIndex - it's quite powerful tool for both trivial and complicated cases.

"Igor R" <boost.lists@gmail.com> wrote in message news:AANLkTimdhsHw+Ow8VAfrNZQe=5g79R9KudWiokwN8a54@mail.gmail.com...
I just have to add:
typedef bool result_type;
to my functor, or call boost::bind<bool>.
Or just define a simple function instead of the functor (which is stateless anyway).
Thanks for the suggestion. However, this: bool OverrideMatches( const TItemOverride &OverrideSource, const RecNo_t ChildItemRecNo, <-- note: these are const const RecNo_t LinkItemRecNo ) { return OverrideSource.ChildAssyItemRecNo == ChildItemRecNo && OverrideSource.LinkItemRecNo == LinkItemRecNo; } const RecNo_t ChildItemRecNo = 123; <-- note: these are const too const RecNo_t LinkItemRecNo = 456; std::find_if( FOverridesContainer.begin(), FOverridesContainer.end(), boost::bind(OverrideMatches, _1, ChildItemRecNo, LinkItemRecNo) ); results in an error: [C++ Error] bind_cc.hpp(50, 4): E2034 Cannot convert '_bi::bind_t<bool,bool (*)(const TItemOverride &,const unsigned int,const unsigned int),_bi::list3<arg<1> (*)(),_bi::value<const unsigned int>,_bi::value<const unsigned int> > >' to '_bi::bind_t<bool,bool (*)(const TItemOverride &,unsigned int,unsigned int),_bi::list3<arg<1> (*)(),_bi::value<const unsigned int>,_bi::value<const unsigned int> > >' This is odd, because the arguments are const and the parameters in the function are declared as const. It seems to me that it should compile, but doesn't. Why not? (compiler bug?) Now, if I remove the 'const' from the integer parameter declarations, or if I make them const references, it compiles fine. - Dennis

Thanks for the suggestion. However, this:
bool OverrideMatches( const TItemOverride &OverrideSource, const RecNo_t ChildItemRecNo, <-- note: these are const const RecNo_t LinkItemRecNo ) { return OverrideSource.ChildAssyItemRecNo == ChildItemRecNo && OverrideSource.LinkItemRecNo == LinkItemRecNo; }
const RecNo_t ChildItemRecNo = 123; <-- note: these are const too const RecNo_t LinkItemRecNo = 456;
std::find_if( FOverridesContainer.begin(), FOverridesContainer.end(), boost::bind(OverrideMatches, _1, ChildItemRecNo, LinkItemRecNo) );
results in an error:
[C++ Error] bind_cc.hpp(50, 4): E2034 Cannot convert '_bi::bind_t<bool,bool (*)(const TItemOverride &,const unsigned int,const unsigned int),_bi::list3<arg<1> (*)(),_bi::value<const unsigned int>,_bi::value<const unsigned int> > >' to '_bi::bind_t<bool,bool (*)(const TItemOverride &,unsigned int,unsigned int),_bi::list3<arg<1> (*)(),_bi::value<const unsigned int>,_bi::value<const unsigned int> > >'
What version do you use? I 1.45 the following compiles well: #include <vector> #include <algorithm> #include <boost/bind.hpp> struct element { int a_; int b_; }; bool compare(const element &el, const int a, const int b) { return el.a_ == a && el.b_ == b; } int main() { using std::vector; vector<element> v; vector<element>::iterator curr = std::find_if(v.begin(), v.end(), boost::bind(compare, _1, 1, 2)); }

Ah, forgot to mention that I test it with MSVC10. And IIRC, I saw recently on this list some issue, which is similar to yours, and if I remember correctly it was related to a bug in an older version of gcc.
Here it is: http://thread.gmane.org/gmane.comp.lib.boost.user/65634/focus=65639

On 10 March 2011 08:30, Dennis Jones <djones@grassvalleysoftware.com> wrote:
I am using Boost 1.33.1 with Borland C++Builder 5 (an old compiler, to be sure).
If you can upgrade to Boost 1.36 or later, the following should work (note: untested): bind(&TItemOverride::ChildAssyItemRecNo, _1) == ChildItemRecNo && bind(&TItemOverride::LinkItemRecNo, _1) == LinkItemRecNo and you don't even need your OverrideMatches class. Alternatively, that should also work using the lambda library (boost::lambda::bind instead of boost::bind), even under Boost 1.33.1. -- Nevin ":-)" Liber <mailto:nevin@eviloverlord.com> (847) 691-1404

"Nevin Liber" <nevin@eviloverlord.com> wrote in message news:AANLkTi=4J9_XT73gxNBG2-GWbU0VX3_f6uj1UzZ8Ua_f@mail.gmail.com... On 10 March 2011 08:30, Dennis Jones <djones@grassvalleysoftware.com> wrote: I am using Boost 1.33.1 with Borland C++Builder 5 (an old compiler, to be sure). If you can upgrade to Boost 1.36 or later, the following should work (note: untested): bind(&TItemOverride::ChildAssyItemRecNo, _1) == ChildItemRecNo && bind(&TItemOverride::LinkItemRecNo, _1) == LinkItemRecNo and you don't even need your OverrideMatches class. Alternatively, that should also work using the lambda library (boost::lambda::bind instead of boost::bind), even under Boost 1.33.1. Unfortunately, BCB5 will not work with any version of Boost newer than 1.33.1, which is why I am still using 1.33.1. BCB5 also does not support the lambda library (even the current product does not support lambda yet). So that syntax, although appealing, is not an option. But thanks anyway! - Dennis
participants (3)
-
Dennis Jones
-
Igor R
-
Nevin Liber