how second and first arg are binded?

H

Hunter Hou

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
 
V

Victor Bazarov

Hunter said:
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?

All those elements of the standard library are templates. Please take
a look at the headers where those things are defined, it should be easy
enough to understand. Whenever in doubt, use the source.

V
 
A

AlesD

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));
}
 
H

Hunter Hou

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.

Thanks! Ales. I understand what you said since you are talking about
function with 2 args(acturally i read source code of bind2nd() ). What i
didn't figure out is how bind2nd works with mem_fun() because member
function has one arg while bind2nd() deals with two args function.

Could you give an example like what you did above?

Regards,
Hunter
 
H

Hunter Hou

All those elements of the standard library are templates. Please take
a look at the headers where those things are defined, it should be easy
enough to understand. Whenever in doubt, use the source.


Yes. This question came out after I read the source code. bind2nd( arg1,
arg2) .arg1 is a binary functor, but rotate( int ) only has one arg.

My udnerstanding of above code is
bind2nd( mem_fun( &Shape::rotate ), angle ) ( obj ),

next is
mem_fun( &Shape::rotate ) ( obj, angle )

but what's next? How is obj handled since member function has only one
argument?

Hope i can explain my question clearly.

thanks,
Hunter
===
 
J

John Harrison

Hunter Hou said:
Yes. This question came out after I read the source code. bind2nd( arg1,
arg2) .arg1 is a binary functor, but rotate( int ) only has one arg.

My udnerstanding of above code is
bind2nd( mem_fun( &Shape::rotate ), angle ) ( obj ),

next is
mem_fun( &Shape::rotate ) ( obj, angle )

but what's next? How is obj handled since member function has only one
argument?

Hope i can explain my question clearly.

thanks,
Hunter
===

Shape::rotate has only one arg but mem_fun( &Shape::rotate ) is a functor
with two args. The first argument to mem_fun( &Shape::rotate ) is a pointer
to the shape you want to rotate, then second arg is the angle.

john
 
D

Daniel T.

All those elements of the standard library are templates. Please take
a look at the headers where those things are defined, it should be easy
enough to understand. Whenever in doubt, use the source.


Yes. This question came out after I read the source code. bind2nd( arg1,
arg2) .arg1 is a binary functor, but rotate( int ) only has one arg.

My udnerstanding of above code is
bind2nd( mem_fun( &Shape::rotate ), angle ) ( obj ),

next is
mem_fun( &Shape::rotate ) ( obj, angle )

but what's next?[/QUOTE]

inside mem_fun( &Shape::rotate ) ( obj, angle ) is

obj->rotate( angle )

You can tell this because of the source of mem_fun1_t:

template <class _Ret, class _Tp, class _Arg>
class mem_fun1_t : public binary_function<_Tp*,_Arg,_Ret> {
public:
explicit mem_fun1_t(_Ret (_Tp::*__pf)(_Arg)) : _M_f(__pf) {}
_Ret operator()(_Tp* __p, _Arg __x) const { return (__p->*_M_f)(__x); }
private:
_Ret (_Tp::*_M_f)(_Arg);
};
 
A

AlesD

Hunter Hou napsal(a):
Thanks! Ales. I understand what you said since you are talking about
function with 2 args(acturally i read source code of bind2nd() ). What i
didn't figure out is how bind2nd works with mem_fun() because member
function has one arg while bind2nd() deals with two args function.

Could you give an example like what you did above?

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

OK, let's thake it step-by-step:

mem_fun( &Shape::rotate ) will create function (it is actually functor,
but it does not matter) which takes two arguments. First argument is
instance of Shape, second is angle - or more precisely Shape::rotate
argument. The function then calls member Shape::rotate with angle as
it's argument. You can imagine it as follows:

int call_shape_member(Shape& my_shape, int angle)
{
return my_shape.rotate(angle);
};

(I suppose that Shape::rotate argument type is int as well as it's
return type).

So you have non-member function which takes Shape& and int. Next you
convert it to unary function by binding the second parameter to constant.

bind2nd( mem_fun( &Shape::rotate ), angle)

Now you have unary function which:

1) takes Shape& as argument
2) call Shape::rotate with angle as argument

You apply it to all elements of list

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

And that's it. Simple. :)

BTW: Are you sure about the list<Shape*>? Shouldn't it be list<Shape>?

Ales
 

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

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,020
Latest member
GenesisGai

Latest Threads

Top