How does bind1st() work in this case?

Discussion in 'C++' started by wenmang, Aug 8, 2003.

  1. wenmang

    wenmang Guest

    Hi, all:
    I am reading Herb Sutter's article:
    http://www.cuj.com/documents/s=8840/cujexp0309sutter/
    I have trouble to understand for following lines:

    class Subject {
    // ...
    public:
    virtual void Attach( function<void (Subject*)> o ) {
    obs_.push_back(o); } --Line1
    virtual void Detach( function<void (Subject*)> o ) { /* ... */ }
    virtual void Notify() {
    for( list<function<void (Subject*)> >::iterator i = obs_.begin();
    i != obs_.end(); ++i )
    (*i)( this );
    }
    private:
    list<function<void (Subject*)> > obs_;
    };

    class ClockTimer : public Subject { // as before
    // ...
    void Tick() {
    // ... timekeeping logic...
    Notify(); // every so often, tick
    }
    };

    class DigitalClock : /*...*/ public Observer { // still works
    // ...
    public:
    DigitalClock( ClockTimer* t ) : timer_(t)
    { timer_->Attach( bind1st( mem_fun( &DigitalClock::OnUpdateOf ),
    this ) ); } --Line2
    ~DigitalClock()
    { timer_->Detach( bind1st( mem_fun( &DigitalClock::OnUpdateOf ),
    this ) ); }
    void OnUpdateOf( Subject* timer ) { /* query timer and redraw */ }
    private:
    ClockTimer* timer_;
    };

    Here are my questions:
    1. mem_fun() generates the unary functor, but bind1st() takes binary
    function as its 1st argument, how does Line2 work?
    2. Could you please provide stepwise explanation how Line2 being
    expanded to fit member function signature of Attach(function<void
    (Subject*)> )?
    3. is "this" on Line2 a DigitalClock*? DigitalClocl* is not Subject*
    for Attach(), isn't?

    Thanks.
     
    wenmang, Aug 8, 2003
    #1
    1. Advertising

  2. "wenmang" <> wrote...
    > I am reading Herb Sutter's article:
    > http://www.cuj.com/documents/s=8840/cujexp0309sutter/
    > I have trouble to understand for following lines:
    >
    > class Subject {
    > // ...
    > public:
    > virtual void Attach( function<void (Subject*)> o ) {
    > obs_.push_back(o); } --Line1
    > virtual void Detach( function<void (Subject*)> o ) { /* ... */ }
    > virtual void Notify() {
    > for( list<function<void (Subject*)> >::iterator i = obs_.begin();
    > i != obs_.end(); ++i )
    > (*i)( this );
    > }
    > private:
    > list<function<void (Subject*)> > obs_;
    > };
    >
    > class ClockTimer : public Subject { // as before
    > // ...
    > void Tick() {
    > // ... timekeeping logic...
    > Notify(); // every so often, tick
    > }
    > };
    >
    > class DigitalClock : /*...*/ public Observer { // still works
    > // ...
    > public:
    > DigitalClock( ClockTimer* t ) : timer_(t)
    > { timer_->Attach( bind1st( mem_fun( &DigitalClock::OnUpdateOf ),
    > this ) ); } --Line2
    > ~DigitalClock()
    > { timer_->Detach( bind1st( mem_fun( &DigitalClock::OnUpdateOf ),
    > this ) ); }
    > void OnUpdateOf( Subject* timer ) { /* query timer and redraw */ }
    > private:
    > ClockTimer* timer_;
    > };
    >
    > Here are my questions:
    > 1. mem_fun() generates the unary functor, but bind1st() takes binary
    > function as its 1st argument, how does Line2 work?


    bind1st basically converts a two-argument member function (well,
    you have to know about the "hidden argument" to understand why I
    call a non-static member with one argument a two-argument function)
    into a functor that acts like a one-argument non-member function.
    IOW, a call

    this->OnUpdateOf(???)

    gets converted into _someSpecialCase_of_OnUpdateOf(???), where 'this'
    is the object stored in what 'bind1st' returns:

    void _result_of_applying_bind1st_(Subject* t) {
    return stored_object_pointer->OnUpdateOf(t);
    }

    > 2. Could you please provide stepwise explanation how Line2 being
    > expanded to fit member function signature of Attach(function<void
    > (Subject*)> )?


    Well, I don't know what 'function' is, so you'll have to excuse me
    if I won't satisfy your request. Why can't you do it?

    > 3. is "this" on Line2 a DigitalClock*?


    Yes.

    > DigitalClocl* is not Subject*
    > for Attach(), isn't?


    No, it's the hidden first (or, rather, zeroth) argument of that
    member function, passed to the OnUpdateOf by the functor returned
    from the call to 'bind1st'.

    'mem_fun' returns an object that uses its first argument as a pointer
    to the class.

    Take the <functional> header and look at the implementation. It will
    become clearer. If not, buy the Josuttis' book "The C++ Standard
    Library".

    Victor
     
    Victor Bazarov, Aug 8, 2003
    #2
    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. Fred Ma
    Replies:
    2
    Views:
    2,058
    Fred Ma
    Feb 5, 2004
  2. Denis Remezov

    binary_function and bind1st

    Denis Remezov, May 19, 2004, in forum: C++
    Replies:
    6
    Views:
    749
    P.J. Plauger
    May 21, 2004
  3. Marc
    Replies:
    6
    Views:
    685
    Denis Remezov
    Jul 6, 2004
  4. John Black
    Replies:
    3
    Views:
    486
    John Harrison
    Aug 8, 2004
  5. Alberto
    Replies:
    1
    Views:
    1,305
    Clark S. Cox III
    Feb 7, 2005
Loading...

Share This Page