Since the C++0x supports the variadic function, it's the very time to improve original C++ event system.
The thought is as same as [2.0].
Here is the code list.
The root Object:
class TObject { public: TObject() { // Dummy } virtual ~TObject() { } };
#include "Object.h" #include <memory> namespace igame { template<typename T_RET, typename ... PARAMS> struct TEventHandler { typedef T_RET Type; typedef T_RET (TObject::*Function)(PARAMS...); std::shared_ptr<Object> _target; Function _function; __inline__ T_RET operator()(PARAMS ...params) { if (_target != nullptr && _function != nullptr) return (_target.get()->*_function)(params...); } }; template<typename T_RET, typename ... PARAMS> struct Event { typedef TEventHandler<T_RET, PARAMS...> Handler; typedef typename Handler::Function Function; Handler _handler; template <typename T_F = Function, typename T_ARG> __inline__ T_F castFunction(T_ARG arg) { return (T_F)arg; } template<typename T_FUNC> __inline__ void bind(std::shared_ptr<TObject> tag, T_FUNC func) { _handler = { tag, castFunction(func) }; } __inline__ T_RET operator()(PARAMS...params) { return _handler(params...); } }; } // ns igame
Compared with 2.0, It's more elegant, more lightweight.
Note: under G++, the inline qualifier may not work as your wish.
Now, Let's rock:
class A : public TObject { public: void foo(int x) { // cout << "Foo:" << x << endl; } void foo2(std::function<void (int)> func) { func(99); } }; class B : public TObject { public: using MyEvent = Event<void, int>; using MyFuncEvent = Event<void, std::function<void (int)>>; MyEvent event; MyFuncEvent funcEvent; void testEvent(int x) { cout << "Fxx:" << x << endl; event(x); } void testFuncEvent(std::function<void (int)> func) { funcEvent([this, func](int x){ cout<<this->message<<endl; func(x); }); } };
The following code shows how to use the Event system:
std::shared_ptr<A> a(new A()); std::shared_ptr<B> b(new B()); b->event.bind(a, &A::foo); b->funcEvent.bind(a, &A::foo2); b->testEvent(100); int x = 101; b->testFuncEvent([&](int val){ val = x; });
Actually, this implementation of Event is more like the std::function<> but a little improvement of performance: 23093ms V.s 29146.2ms for calling of 0xEFFFFFFF times in my ASUS Q200E laptop. On the other words, 5.73521ns V.s 7.23853ns for per calling.
And more straightly than std::function<>. After all, the virtual function calling consumes 4.29958ns for per calling. As a syntactic sugar, my event model works pretty well.