#ifndef DELEGATE_H #define DELEGATE_H //Container interface template class IContainer { public: virtual void Call(Args...) {} virtual ~IContainer() {} IContainer *next; }; //Container realization template< typename T, typename M, typename... Args > class MContainer : public IContainer { public: MContainer(T* c, M m) : mClass(c), mMethod(m) {} void Call(Args... args) { (mClass->*mMethod)(args...); } private: T *mClass; M mMethod; }; template< typename M, typename... Args > class FContainer : public IContainer { public: FContainer(M m) : mMethod(m) {} void Call(Args... args) { (mMethod)(args...); } private: M mMethod; }; //Delegate template class Delegate { public: Delegate() { mContainerHead = new IContainer(); mContainerTail = mContainerHead; mContainerHead->next = 0; } ~Delegate() { IContainer *container = mContainerHead; while(container) { IContainer *temp = container->next; delete container; container = temp; } } void Clear() { IContainer *container = mContainerHead->next; while(container) { IContainer *temp = container->next; delete container; container = temp; } mContainerHead->next = 0; mContainerTail = mContainerHead; } template void Connect(T *c, M m) { mContainerTail->next = new MContainer< T, M, Args... >(c, m); mContainerTail->next->next = 0; mContainerTail = mContainerTail->next; } template void Connect(M m) { mContainerTail->next = new FContainer< M, Args... >(m); mContainerTail->next->next = 0; mContainerTail = mContainerTail->next; } template void Disconnect(T *c, M m) { IContainer *container = mContainerHead; while(container->next) { MContainer *temp = dynamic_cast*>(container->next); if(temp) { if(container->next == mContainerTail) { mContainerTail = container; } container->next = container->next->next; delete temp; break; } container = container->next; } } template void Disconnect(M m) { IContainer *container = mContainerHead; while(container->next) { FContainer *temp = dynamic_cast*>(container->next); if(temp) { if(container->next == mContainerTail) { mContainerTail = container; } container->next = container->next->next; delete temp; break; } container = container->next; } } void operator ()(Args... args) { Call(args...); } void Call(Args... args) { IContainer *container = mContainerHead; while(container) { container->Call(args...); container = container->next; } } private: IContainer *mContainerHead; IContainer *mContainerTail; }; #endif // DELEGATE_H