How does bind1st() work in this case?

W

wenmang

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.
 
V

Victor Bazarov

wenmang said:
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
 

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

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,009
Latest member
GidgetGamb

Latest Threads

Top