#include <iostream>
#include <map>
#include <vector>
/**
* Receiver
*/
class EBaseReceiver
{
protected:
static std::size_t nextId;
};
template <class TEventData>
class Receiver : public EBaseReceiver
{
friend class EventManager;
public:
virtual void onEventReceive( const TEventData& event ) = 0;
static std::size_t getId() { return ID; }
private:
static std::size_t ID;
};
/**
* Event
*/
struct BaseEvent
{
protected:
static std::size_t nextId;
};
template <typename T>
struct Event : public BaseEvent
{
static std::size_t getId() { return ID; }
static std::size_t ID;
};
/**
* EventManager
*/
class EventManager
{
private:
typedef std::vector<EBaseReceiver*> ReceiverArray;
typedef std::map<std::size_t, ReceiverArray> ImplSubscriberArray;
ImplSubscriberArray subscribers;
public:
template< class TEvent, template<class> class TReceiver>
void subscribe( TReceiver<TEvent>* receiver )
{
const std::size_t eventId = TEvent::getId();
this->subscribers[eventId].push_back(receiver);
}
template <typename TEvent>
void emit( const TEvent& event )
{
const ReceiverArray& receivers = this->subscribers[TEvent::getId()];
for( auto& receiver : receivers )
{
static_cast<Receiver<TEvent>&>((*receiver)).onEventReceive(event);
}
}
};
/**
* Test events
*/
EventManager eventManager;
struct HealthEvent : public Event<HealthEvent>{};
struct DamageEvent : public Event<DamageEvent>{};
/**
* Test classes
*/
class DamageSystem : public Receiver<HealthEvent>, public Receiver<DamageEvent>
{
public:
DamageSystem() : Receiver<HealthEvent>(), Receiver<DamageEvent>()
{
eventManager.subscribe<HealthEvent, ::Receiver>(this);
eventManager.subscribe<DamageEvent, ::Receiver>(this);
}
void onEventReceive( const HealthEvent& event ) { std::cout << "HealthEvent !" << std::endl; };
void onEventReceive( const DamageEvent& event ) { std::cout << "DamageEvent !" << std::endl; };
};
int main()
{
DamageSystem system;
eventManager.emit(DamageEvent());
return 0;
}