Hunter Hou napsal(a):

hello,

I'm reading <the C++ programming language>, here's a question for bind2nd.

Who can help explain what on earth bind2nd is working?

...

void rotate_all( list<Shape*>& ls, int angle )

{

for_each( ls.begin(), ls.end(), bind2nd( mem_fun( &Shape::rotate ),

angle ));

}

This code is very easy to understand, but when i tried to use bind2nd and

mem_fun() source code to see what's going on here, I don't understand how

"angle" is binded as second argument? And how the first arg is binded as

Shape* under the condition of op(x, arg2) of binder2nd?

Thanks,

Hunter

Hello,

short explaintation:

bind2nd convert function which takes two arguments into function which

takes only 1 argument and call the original with 2nd argument replaced

by constant.

definitions:

If f is an object of class binder2nd<AdaptableBinaryFunction>, then f(x)

returns F(x, c), where F is an object of class AdaptableBinaryFunction

and where c is a constant. Both F and c are passed as arguments to

binder2nd's constructor.

example:

Suppose you have function which takes two arguments - say:

void my_function(my_type& my_object, int some_number);

Then you have vector of my_type objects:

vector<my_type> my_vector(10);

and you want to apply my_function() to all bojects in the vector with

constant second argument (equal to 5). There is STL function for_each

which can help, but it has chatch: it takes only unary function so you

have to:

a) define new version of your function

void my_function2(my_type& my_object) {

my_function(my_object, 5);

}

This has the disadvantage that you can't change the value of second

parameter. To overcome this you can also:

b) define functor which uses your function

class my_functor

{

private:

int second_argument;

public:

my_functor(int init_second_argument)

: second_argument(init_second_argument) {};

operator()(my_type& first_argument)

{

my_function(first_argument, second_argument);

};

}

and use it:

my_functor(5) f;

f(my_object); // this equals to: my_function(my_object, 5);

binder2nd does actually same thing, but can save you the typing...

3) Use function adaptor binder2nd

which will turn your function into unary function "on-line"

bind2nd(my_function(), 5) (my_object);

^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^

new functor created argument

Compare the final results:

1) ------------------

void my_function(my_type& my_object, int some_number);

void my_function2(my_type& my_object) {

my_function(my_object, 5);

}

int main()

{

vector<my_type> my_vector(10);

for_each(my_vector.begin(), my_vector.end(), my_function2());

}

2) ------------------

void my_function(my_type& my_object, int some_number);

class my_functor

{

private:

int second_argument;

public:

my_functor(int init_second_argument)

: second_argument(init_second_argument) {};

operator()(my_type& first_argument)

{

my_function(first_argument, second_argument);

};

}

int main()

{

vector<my_type> my_vector(10);

for_each(my_vector.begin(), my_vector.end(), my_functor(5));

}

3) ------------------

void my_function(my_type& my_object, int some_number);

int main()

{

vector<my_type> my_vector(10);

for_each(my_vector.begin(), my_vector.end(),

bind2nd(my_function(), 5));

}

---------------------

For more information see

http://www.sgi.com/tech/stl/binder2nd.html
Have a nice day. Ales