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

How does bind1st() work in this case?

P: n/a
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.
Jul 19 '05 #1
Share this Question
Share on Google+
1 Reply


P: n/a
"wenmang" <we*****@yahoo.com> 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
Jul 19 '05 #2

This discussion thread is closed

Replies have been disabled for this discussion.