#include < vector >
#include < assert.h >
// Okay, so this solution might be a bit too loose. However, it can be implemented
// to do all checks when registering new listeners. To use it, you add a value to
// an enum and create a wrapper class to hold your event arguments.
// The key point is that the manager doesn't need to know anything about the event arguments.
// ---------------------------------------------------------------------------
// Framework
// All event type must be enumerated. An enum is the easiest way to go if we want to avoid templates.
enum EEventType
{
EFT_Fruit = 0,
EFT_UNUSED_LAST
};
// Base class for events.
// Should in "principle" be completely abstract, but there's no real need.
class ZEventArgs
{
public:
ZEventArgs( const EEventType eType ) : m_eType( eType ) {}
EEventType GetType() const { return m_eType; }
private:
EEventType m_eType;
};
// This would be a member function in your case, but I don't want to go through all the wrapping syntax.
// I suspect your delegate wrapper doesn't care.
//
// Like the ZEventArgs, this could also be made into a class, e.g ZEventReciever.
// It could also have a EEventType member so correspondence could be checked when registering the listener.
// Making it a class would also enable you to register/unregister on contruction/destruction.
typedef void (*ZEventCB)( const ZEventArgs* );
// Manager class never needs to be updated.
class ZManager
{
public:
void Register( const EEventType eType, const ZEventCB EventListener )
{
// maybe also check it's not there already.
m_aaListeners[eType].push_back( EventListener );
}
void RecieveEvent( const ZEventArgs* Args ) const
{
const std::vector
for( size_t i = 0; i < aListeners.size(); ++i )
{
aListeners[i]( Args );
}
}
private:
// array of listeners
std::vector< ZEventCB > m_aaListeners[EFT_UNUSED_LAST];
};
// ---------------------------------------------------------------------------
// Example
// Implementation of Fruit args.
class ZFruitEventArgs : public ZEventArgs
{
public:
// constructor initializes type.
ZFruitEventArgs() : ZEventArgs( EFT_Fruit ) {}
// real args go here
float m_fTastines;
int m_nHowManyMore;
};
void TastyPrinter( const ZEventArgs* Args )
{
assert( Args->GetType() == EFT_Fruit );
const ZFruitEventArgs* FruitArgs = (ZFruitEventArgs*) Args;
std::cout << "mmm, tasty: " << FruitArgs->m_fTastines << std::endl;
}
void ManyPrinter( const ZEventArgs* Args )
{
assert( Args->GetType() == EFT_Fruit );
const ZFruitEventArgs* FruitArgs = (ZFruitEventArgs*) Args;
std::cout << "more: " << FruitArgs->m_nHowManyMore << std::endl;
}
int main()
{
ZManager TheMan;
TheMan.Register( EFT_Fruit, TastyPrinter );
TheMan.Register( EFT_Fruit, ManyPrinter );
ZFruitEventArgs Fruity;
Fruity.m_fTastines = 1.2f;
Fruity.m_nHowManyMore = 6;
TheMan.RecieveEvent( &Fruity );
}