By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
445,778 Members | 1,957 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 445,778 IT Pros & Developers. It's quick & easy.

how second and first arg are binded?

P: n/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
Jul 22 '05 #1
Share this Question
Share on Google+
8 Replies


P: n/a
Hunter Hou wrote:
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
Jul 22 '05 #2

P: n/a
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
Jul 22 '05 #3

P: n/a

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
Jul 22 '05 #4

P: n/a
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.

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
===
Jul 22 '05 #5

P: n/a

"Hunter Hou" <hy***@lucent.com> wrote in message
news:cf********@netnews.proxy.lucent.com...
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.

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

Jul 22 '05 #6

P: n/a
In article <cf********@netnews.proxy.lucent.com>,
Hunter Hou <hy***@lucent.com> wrote:
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.

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?


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);
};
Jul 22 '05 #7

P: n/a
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
Jul 22 '05 #8

P: n/a
AlesD napsal(a):
BTW: Are you sure about the list<Shape*>? Shouldn't it be list<Shape>?


Hmm - probably not.

A.
Jul 22 '05 #9

This discussion thread is closed

Replies have been disabled for this discussion.