STL bind1st question

S

silverburgh.meryl

I am reading an bind1st example from
http://www.roguewave.com/support/docs/sourcepro/stdlibref/bind1st.html

Can someone please tell me why
// Even better, construct the new predicate on the fly.
vector::iterator it2 =
std::find_if (v1.begin (), v1.end (),
std::bind1st (equal_to (), 3));

is better than
// Now use this new predicate in a call to find_if.
vector::iterator it1 = std::find_if (v1.begin (),
v1.end (),
equal_to_3);

And why I need to use 'std::binder1st' to begin with. Can't I just
create a binary predicate?

Thanks for any help.

Complete code:

int main ()
{
typedef std::vector<int, std::allocator<int> > vector;
typedef std::equal_to<vector::value_type> equal_to;

const vector::value_type arr [] = { 1, 2, 3, 4 };

// Set up a vector.
vector v1 (arr + 0, arr + sizeof arr / sizeof *arr);

// Create an 'equal to 3' unary predicate by binding 3 to
// the equal_to binary predicate.
std::binder1st<equal_to> equal_to_3 =
bind1st (equal_to (), 3);

// Now use this new predicate in a call to find_if.
vector::iterator it1 = std::find_if (v1.begin (),
v1.end (),
equal_to_3);

// Even better, construct the new predicate on the fly.
vector::iterator it2 =
std::find_if (v1.begin (), v1.end (),
std::bind1st (equal_to (), 3));

// And now the same thing using bind2nd.
// Same result since equal_to is commutative.
vector::iterator it3 =
std::find_if (v1.begin (), v1.end (),
std::bind2nd (equal_to (), 3));

// Output results.
std::cout << *it1 << " " << *it2 << " "
<< *it3 << std::endl;

return 0;
}
 
D

David Harmon

On 13 Jan 2006 14:55:49 -0800 in comp.lang.c++,
(e-mail address removed) wrote,
I am reading an bind1st example from
http://www.roguewave.com/support/docs/sourcepro/stdlibref/bind1st.html

Can someone please tell me why
// Even better, construct the new predicate on the fly.
vector::iterator it2 =
std::find_if (v1.begin (), v1.end (),
std::bind1st (equal_to (), 3));

std::bind1st() already exists.
std::equal_to() already exists.
3 already exists.
Done.
is better than
// Now use this new predicate in a call to find_if.
vector::iterator it1 = std::find_if (v1.begin (),
v1.end (),
equal_to_3);

equal_to_3 does not already exist. Somebody has to write it.
Somebody has to test it. Somebody has to maintain it.
 
H

Howard Hinnant

Can someone please tell me why
// Even better, construct the new predicate on the fly.
vector::iterator it2 =
std::find_if (v1.begin (), v1.end (),
std::bind1st (equal_to (), 3));

is better than
// Now use this new predicate in a call to find_if.
vector::iterator it1 = std::find_if (v1.begin (),
v1.end (),
equal_to_3);

And why I need to use 'std::binder1st' to begin with. Can't I just
create a binary predicate?

Yes you can (well, as long as it is a unary predicate :) ). Be sure to
name it well (as you have in this example). Otherwise the reader has to
stop and look up what your predicate does.

Fwiw, std::tr1::bind (aka boost::bind) is even nicer than std::bind1st
(imho):

using namespace std::tr1::placeholders;

const vector::value_type arr [] = { 1, 2, 3, 4 };

// Set up a vector.
vector v1 (arr + 0, arr + sizeof arr / sizeof *arr);

vector::iterator it1 = std::find_if(v1.begin (),
v1.end (), std::tr1::bind(equal_to(), 3, _1));

I like the flexibility of tr1::bind, and the fact that one facility
(with one name) covers all of the functionality of bind1st, bind2nd, and
much more. So once you learn it, it is easier to remember.

-Howard
 
E

Earl Purple

Thanks. One more question: what are the advantages of the Boost.bind
library over
the bind functions come with STL?

http://www.boost.org/libs/bind/bind.html

Well for one thing you will commonly want to do something like this.

class Foo
{
std::vector< Bar > myVect;

void fun2( Bar & aBar );

void fun1() // which may be public, it's irrelevant
{
std::for_each( myVect.begin(), myVect.end(), &Foo::fun2 );
}
};

well that's what you'd like to do but that won't compile because fun2
needs a "this" which isn't automatically passed through. I don't think
any of the binders allow you to pass the "this" through. (Do they?)

Now as far as I'm aware with standard binders you can't resolve the
problem (The Bar class doesn't know anything about Foo and mem_fun etc
is for members of Bar, not Foo).
Of course you can always write a functor to solve it, but why should
you have to?

With boost::bind you can (although unfortunately I find this particular
simple case badly documented on boost too).
 
H

Howard Hinnant

"Earl Purple said:
Well for one thing you will commonly want to do something like this.

class Foo
{
std::vector< Bar > myVect;

void fun2( Bar & aBar );

void fun1() // which may be public, it's irrelevant
{
std::for_each( myVect.begin(), myVect.end(), &Foo::fun2 );
}
};

well that's what you'd like to do but that won't compile because fun2
needs a "this" which isn't automatically passed through. I don't think
any of the binders allow you to pass the "this" through. (Do they?)

Now as far as I'm aware with standard binders you can't resolve the
problem (The Bar class doesn't know anything about Foo and mem_fun etc
is for members of Bar, not Foo).
Of course you can always write a functor to solve it, but why should
you have to?

With boost::bind you can (although unfortunately I find this particular
simple case badly documented on boost too).

Additionally you can do more things with bind such as:

void foo(int x, int y, int z);

for_each(begin(), end(), bind(foo, foo(_1, 2, 3));

or:

bool foo(int x, int y);

unique(begin(), end(), bind(_2, _1));

I.e. you can adapt N-parameter functors to M-parameter functors where N
= M, switching the order of parameters as you please. This is far more
powerful than bind1st, bind2nd.

-Howard
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Staff online

Members online

Forum statistics

Threads
473,961
Messages
2,570,130
Members
46,689
Latest member
liammiller

Latest Threads

Top