Gianni Mariani wrote:
a) What is the accepted definition of "observer pattern". While I can't
point to anything specific, I do remember having issues with
inconsistency in the definition.
Aside, and probably OT, I've written a little generic class that
performs
RAII subscription/unsubsription. I attempted to make it definition
independent, handling either attach/detach, subscribe/unsubscribe or
add/remove as potential interface. It was merely a nice exercise for
SFINAE (and credit to some posts in c.l.c++, as well as boost
archives).
CAVEAT: Does not use weak pointer yet as described in my other
mail. I just at the time of writing this have not thought of that
problem
yet.
Here goes:
namespace AviGen {
namespace GenSubPriv{
typedef char (&subscribe)[0];
typedef char (&add)[1];
typedef char (&attach)[2];
template < typename T, void (T::*)() >
struct ptmf_helper {};
template< typename T subscribe get_method_literal( ... ); //
Subscribe
template< typename T add
get_method_literal( ptmf_helper<T,&T::add>* );
template< typename T attach
get_method_literal( ptmf_helper<T,&T::attach>* );
template <class PubT, class SubT, std::size_t>
class GenSubBase;
// Used subscribe/unsubscribe to subscribe.
template <class PubT, class SubT>
class GenSubBase<PubT, SubT, sizeof(subscribe): public SubT
{
protected:
GenSubBase( PubT& publisher ): publisher_( publisher )
{ publisher_.subscribe( *this ); }
virtual ~GenSubBase()
{ publisher_.unsubscribe( *this ); }
private:
PubT* publisher_;
};
// Used add/remove to subscribe.
template <class PubT, class SubT>
class GenSubBase<PubT, SubT, sizeof(add): public SubT
{
protected:
GenSubBase( PubT& publisher ): publisher_( publisher )
{ publisher_.add( *this ); }
virtual ~GenSubBase()
{ publisher_.remove( *this ); }
private:
PubT* publisher_;
};
// Used attach/detach to subscribe.
template <class PubT, class SubT>
class GenSubBase<PubT, SubT, sizeof(attach): public SubT
{
protected:
GenSubBase( PubT& publisher ): publisher_( publisher )
{ publisher_.attach( *this ); }
virtual ~GenSubBase()
{ publisher_.detach( *this ); }
private:
PubT* publisher_;
};
}//end namespace GenSubPriv
//
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
// Author : werasmus
// Date : Sep 22, 2007 7:41:39 PM
// Description:
// This class provides the ability to subscribe/unsubscribe in a RAII
fashion.
// Currently it caters for the publisher to outlive the subscriber,
hence the
// publisher is accepted as reference in the constructor.
// Note:
// Currently works for Publishers with interface <add/remove>, <attach/
detachand
// <subscribe/unsubscribe>.
// TODO:
// We could modify the publisher member iaw. a policy at later stage,
the default
// probably being weak pointer.
//
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
template <class PubT, class SubT>
class GenSubscriber
: public GenSubPriv::GenSubBase<PubT,
SubT,sizeof(GenSubPriv::get_method_literal<PubT>(0 ))>
{
protected:
typedef typename GenSubPriv::GenSubBase<PubT,
SubT,sizeof(GenSubPriv::get_method_literal<PubT>(0 ))Base;
//_____________ operations _____________//
GenSubscriber( PubT& publisher ): Base( publisher ){ }
};