#include <iostream>
#include <vector>
class BaseReceiever
{
protected:
static size_t nextId;
};
size_t BaseReceiever::nextId = 0;
// if you inherit from this class,
// you are required to implement
// void recieve(const TEventData& eventData)
// where TEventData is an Event (see further down)
template <typename TEventData>
class Receiver
: public BaseReceiever
{
public:
virtual void receive(const TEventData&) = 0;
static size_t GetId()
{ return _id; }
private:
// used for internal storage
// identification
static size_t _id;
};
template<typename T>
size_t Receiver<T>::_id = BaseReceiever::nextId++;
struct BaseEvent
{
protected:
static size_t nextId;
};
size_t BaseEvent::nextId = 0;
template <typename T>
struct Event
: public BaseEvent
{
static size_t GetId()
{ return _id; }
private:
static size_t _id;
};
template <typename T>
size_t Event<T>::_id = BaseEvent::nextId++;
class EventHandler
{
// note:
// could use one vector for better performance
// but I doubt it's noticeable
typedef std::vector<BaseReceiever*> ReceiverArray;
typedef std::vector<ReceiverArray> ImplSubscriberArray;
public:
template <typename TEvent>
void emit(const TEvent& event)
{
ReceiverArray& receivers = _subscribers[TEvent::GetId()];
for(ReceiverArray::iterator i = receivers.begin(); i != receivers.end(); ++i)
{
static_cast<Receiver<TEvent>&>(*(*i)).receive(event);
}
}
template <typename TEvent, typename TReciever>
void subscribe(TReciever* receiver)
{
size_t eventId = TEvent::GetId();
size_t receiverId = TReciever::GetId();
if(_subscribers.size() <= eventId)
{
_subscribers.resize(eventId + 1);
}
ReceiverArray& receivers = _subscribers[eventId];
if(receivers.size() <= receiverId)
{
receivers.resize(receiverId + 1);
}
receivers[receiverId] = receiver;
}
template <typename TEvent, typename TReciever>
void unsubscribe(TReciever* reciever)
{
_subscribers[TEvent::GetId()][TReciever::GetId()] = NULL;
}
private:
ImplSubscriberArray _subscribers;
};
// collision event information
struct Collision
: Event<Collision>
{
typedef int Entity; // (for this examples sake)
Collision(Entity E1, Entity E2)
: e1(E1),
e2(E2)
{
}
Entity e1;
Entity e2;
};
class MyReciever
: public Receiver<Collision>
{
public:
virtual void receive(const Collision& collision) /*override*/
{
std::cout << "Collision event occured with " << collision.e1 << " and " << collision.e2 << '\n';
}
};
int main(int argc, const char * argv[])
{
MyReciever collisionReciever;
EventHandler handler;
// subscribe the reciever for events that fire Collision data
handler.subscribe<Collision>(&collisionReciever);
// make a collision object to send
Collision collision(5, 4);
// emit the event
handler.emit(collision);
return 0;
}