how second and first arg are binded?

Discussion in 'C++' started by Hunter Hou, Aug 9, 2004.

  1. Hunter Hou

    Hunter Hou Guest

    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
    Hunter Hou, Aug 9, 2004
    #1
    1. Advertising

  2. 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
    Victor Bazarov, Aug 9, 2004
    #2
    1. Advertising

  3. Hunter Hou

    AlesD Guest

    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
    AlesD, Aug 10, 2004
    #3
  4. Hunter Hou

    Hunter Hou Guest


    >
    > 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
    Hunter Hou, Aug 10, 2004
    #4
  5. Hunter Hou

    Hunter Hou Guest


    >> 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
    ===
    Hunter Hou, Aug 10, 2004
    #5
  6. "Hunter Hou" <> wrote in message
    news:cfa3m5$...
    >
    > >> 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
    John Harrison, Aug 10, 2004
    #6
  7. Hunter Hou

    Daniel T. Guest

    In article <cfa3m5$>,
    Hunter Hou <> 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);
    };
    Daniel T., Aug 10, 2004
    #7
  8. Hunter Hou

    AlesD Guest

    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
    AlesD, Aug 10, 2004
    #8
  9. Hunter Hou

    AlesD Guest

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


    Hmm - probably not.

    A.
    AlesD, Aug 10, 2004
    #9
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Mira Vizjak

    Binded DropDown list

    Mira Vizjak, Jul 15, 2003, in forum: ASP .Net
    Replies:
    4
    Views:
    455
    Anatoly
    Jul 16, 2003
  2. n00m
    Replies:
    5
    Views:
    396
  3. yelipolok
    Replies:
    4
    Views:
    252
    John W. Krahn
    Jan 27, 2010
  4. Replies:
    7
    Views:
    174
  5. Replies:
    21
    Views:
    293
    Barry Schwarz
    Mar 5, 2014
Loading...

Share This Page