1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103
|
#pragma once
#include <map>
#include <utility>
namespace events
{
template <typename ReturnT, typename ParamT>
class HandlerBase
{
public:
virtual ReturnT Process(ParamT message) = 0;
};
template <typename TargetT, typename ReturnT, typename ParamT>
class Handler : public HandlerBase<ReturnT,ParamT>
{
private:
typedef ReturnT (TargetT::*method_t)(ParamT);
TargetT* mObject;
method_t mMethod;
public:
Handler(TargetT* object, method_t method)
: mObject(object), mMethod(method) { }
ReturnT Process(ParamT param) override
{
return (mObject->*mMethod)(param);
}
};
template <typename ReturnT,typename ParamT>
class Event
{
private:
typedef std::multimap<long, HandlerBase<ReturnT,ParamT>*> eventMap;
long id;
static long counter;
static eventMap mapper;
typename static eventMap::iterator iter;
static eventMap StartMapping()
{
eventMap temp;
return temp;
}
public:
Event() : id(++counter) { };
~Event()
{
for(iter = mapper.find(id); iter != mapper.end(); iter = mapper.find(id))
{
delete iter->second;
mapper.erase(iter);
}
}
template<typename TargetT>
void attach(TargetT* object, ReturnT (TargetT::*method)(ParamT))
{
mapper.insert(std::make_pair(id, new Handler<TargetT, ReturnT, ParamT>(object, method)));
}
void Emit(ParamT param)
{
for(iter = mapper.begin(); iter != mapper.end(); ++iter)
if (iter->first == id)
iter->second->Process(param);
}
};
template<typename ReturnT,typename ParamT>
long Event<typename ReturnT,typename ParamT>::counter = 0;
template<typename ReturnT,typename ParamT>
typename Event<typename ReturnT,typename ParamT>::eventMap::iterator
Event<typename ReturnT,typename ParamT>::iter = Event<typename ReturnT,typename ParamT>::mapper.begin();
template<typename ReturnT,typename ParamT>
typename Event<typename ReturnT,typename ParamT>::eventMap
Event<typename ReturnT,typename ParamT>::mapper(Event<typename ReturnT,typename ParamT>::StartMapping());
template<typename ReturnT,typename ParamT>
class Object
{
protected:
virtual ~Object() = 0 { }
public:
template<typename TargetT>
void Register(Event<ReturnT, ParamT>& evn, ReturnT (TargetT::*method)(ParamT))
{
evn.attach(dynamic_cast<TargetT*>(this), method);
}
};
}
|