
Timmo Stange wrote:
struct some_observer { signals::tracked ptr_to_some_secret_object; some_observer(); // Sets up ptr_to_some_secret_object void operator()(); // Uses ptr_to_some_secret_object };
...
signal0<void> sig; sig.connect(some_observer());
The advantage is that the party establishing the connection does not need to know what objects have to be tracked. It's not such a big asset, but it's something you cannot do with the explicit track().
Something along the lines of: template<class Sig> class slot { private: shared_ptr< slot_impl<Sig> > pi_; public: template<class F> slot( F f ): pi_( new slot_impl<Sig>( f ) ) {} result_type operator()( ... ) { return (*pi_)( ... ) } template<class T> void track( shared_ptr<T> pt ) { pi_->track( pt ); } }; template<class Sig> class signal { private: std::vector< slot<Sig> > slots_; mutable mutex mx_; public: // illustration only void operator()( ... ) const { scoped_lock lock( mx_ ); std::vector< slot<Sig> > tmp( slots_ ); lock.unlock(); for_each( tmp.begin(), tmp.end(), bind( &slot<Sig>::operator(), _1, ... ) ); } }; allows your example to be restated as: slot<void()> make_observer_slot( ... ) { return slot<void()>( some_observer( ... ) ).track( whatever ); } // ... signal<void()> sig; sig.connect( make_observer_slot() ); with some_observer no longer needing to have a dependency on signals.