// delegate.h /* デリゲートを作成するマクロ delegate, delegate_void を定義しています。 戻り値の型が void の場合: delegate(デリゲート名, 仮引数リスト, 実引数リスト) それ以外の場合: delegate_ret(戻り値の型, デリゲート名, 仮引数リスト, 実引数リスト) とすれば、デリゲート型を作成できます。 例)class Test { private: delegate_ret(int, Conv, (int n), (n)); Conv m_conv; public: void run() { m_conv = Conv(this, &Test::square); cout << m_conv(5) << endl; m_conv = &Test::twice; cout << m_conv(5) << endl; } private: int square(int n) { return n * n; } static int twice(int n) { return n * 2; } }; 例)class Test { private: delegate(Conv, (int n), (n)); Conv m_conv; public: void run() { m_conv = Conv(this, &Test::square); m_conv(5); m_conv += &Test::twice; m_conv(5); m_conv -= &Test::twice; m_conv(5); m_conv -= Conv(this, &Test::square); m_conv(5); } private: void square(int n) const { cout << (n * n) << endl; } static void twice(int n) { cout << (n * 2) << endl; } }; */ #ifndef DELEGATE_H_20050415_210113_JO9EHF09_INCLUDED_ #define DELEGATE_H_20050415_210113_JO9EHF09_INCLUDED_ #include #include #ifdef __GNUC__ #define TYPENAME typename #else #define TYPENAME #endif #define DELEGATE_1_(Ret, Name, Params, Args) \ class Name { \ private: \ class I##Name { \ public: \ ~I##Name() { } \ virtual Ret operator() Params const = 0; \ virtual I##Name* clone() const = 0; \ virtual bool operator==(const I##Name& other) const = 0; \ }; \ \ class Fn##Name : \ public I##Name \ { \ public: \ typedef Ret (*Fn) Params; \ \ private: \ Fn fn; \ \ public: \ Fn##Name(const Fn##Name& other) : \ fn(other.fn) { } \ \ Fn##Name(Fn fn) : \ fn(fn) { } \ \ I##Name* clone() const { \ return new Fn##Name(*this); \ } \ \ virtual bool operator==(const I##Name& other) const { \ return (typeid(*&other) == typeid(const Fn##Name) && \ static_cast(other).fn == fn); \ } \ \ virtual Ret operator() Params const { #define DELEGATE_2_(Ret, Name, Params, Args) \ } \ }; \ \ template \ class C##Name : \ public I##Name \ { \ public: \ typedef Ret (Class::*Fn) Params; \ \ private: \ Class* obj; \ Fn fn; \ \ public: \ C##Name(const C##Name& other) : \ obj(other.obj), fn(other.fn) { } \ \ C##Name(Class* obj, Fn fn) : \ obj(obj), fn(fn) { } \ \ I##Name* clone() const { \ return new C##Name(*this); \ } \ \ virtual bool operator==(const I##Name& other) const { \ return (typeid(*&other) == typeid(const C##Name) && \ static_cast&>(other).obj == obj && \ static_cast&>(other).fn == fn); \ } \ \ virtual Ret operator() Params const { #define DELEGATE_3_(Ret, Name, Params, Args) \ } \ }; \ \ template \ class Const##Name : \ public I##Name \ { \ public: \ typedef Ret (Class::*Fn) Params const; \ \ private: \ const Class* obj; \ Fn fn; \ \ public: \ Const##Name(const Const##Name& other) : \ obj(other.obj), fn(other.fn) { } \ \ Const##Name(const Class* obj, Fn fn) : \ obj(obj), fn(fn) { } \ \ I##Name* clone() const { \ return new Const##Name(*this); \ } \ \ virtual bool operator==(const I##Name& other) const { \ return (typeid(*&other) == typeid(const Const##Name) && \ static_cast&>(other).obj == obj && \ static_cast&>(other).fn == fn); \ } \ \ virtual Ret operator() Params const { #define DELEGATE_4_(Ret, Name, Params, Args) \ } \ }; \ \ typedef std::list Delegate; \ Delegate m_list; \ \ public: \ Name() { } \ \ Name(Fn##Name::Fn fn) { \ set(fn); \ } \ \ template \ Name(Class* obj, TYPENAME C##Name::Fn fn) \ { \ set(obj, fn); \ } \ \ template \ Name(const Class* obj, TYPENAME Const##Name::Fn fn) \ { \ set(obj, fn); \ } \ \ virtual ~Name() { \ clear(); \ } \ \ void set(Fn##Name::Fn fn) { \ clear(); \ add(fn); \ } \ \ template \ void set(Class* obj, TYPENAME C##Name::Fn fn) \ { \ clear(); \ add(obj, fn); \ } \ \ template \ void set(const Class* obj, TYPENAME Const##Name::Fn fn) \ { \ clear(); \ add(obj, fn); \ } \ \ private: \ void add(I##Name* p) { \ try { \ m_list.push_back(p); \ } catch(...) { \ delete p; \ throw; \ } \ } \ \ public: \ void add(Fn##Name::Fn fn) { \ if(fn != NULL) { \ add(new Fn##Name(fn)); \ } \ } \ \ template \ void add(Class* obj, TYPENAME C##Name::Fn fn) \ { \ if(fn != NULL) { \ add(new C##Name(obj, fn)); \ } \ } \ \ template \ void add(const Class* obj, TYPENAME Const##Name::Fn fn) \ { \ if(fn != NULL) { \ add(new Const##Name(obj, fn)); \ } \ } \ \ void set(const Name& other) { \ clear(); \ add(other); \ } \ \ void add(const Name& other) { \ const Delegate& list = other.m_list; \ for(Delegate::const_iterator it = list.begin(); it != list.end(); ++it) { \ m_list.push_back((*it)->clone()); \ } \ } \ \ void erase(const Name& other) { \ const Delegate& list = other.m_list; \ for(Delegate::const_iterator it = list.begin(); it != list.end(); ++it) { \ Delegate::iterator itFind = m_list.end(); \ for(--itFind; itFind != m_list.end(); --itFind) { \ if(**it == **itFind) { \ delete *itFind; \ m_list.erase(itFind); \ break; \ } \ } \ } \ } \ \ void clear() { \ for(Delegate::iterator it = m_list.begin(); it != m_list.end(); ++it) { \ delete *it; \ } \ m_list.clear(); \ } \ \ void operator=(const Name& other) { \ set(other); \ } \ \ void operator+=(const Name& other) { \ add(other); \ } \ \ void operator-=(const Name& other) { \ erase(other); \ } \ \ Ret operator() Params const { #define DELEGATE_5_(Ret, Name, Params, Args) \ } \ } #define delegate(Name, Params, Args) \ DELEGATE_1_(void, Name, Params, Args) \ fn Args; \ DELEGATE_2_(void, Name, Params, Args) \ (obj->*fn) Args; \ DELEGATE_3_(void, Name, Params, Args) \ (obj->*fn) Args; \ DELEGATE_4_(void, Name, Params, Args) \ for(Delegate::const_iterator it = m_list.begin(); it != m_list.end(); ++it) { \ (**it) Args; \ } \ DELEGATE_5_(void, Name, Params, Args) #define delegate_ret(Ret, Name, Params, Args) \ DELEGATE_1_(Ret, Name, Params, Args) \ return fn Args; \ DELEGATE_2_(Ret, Name, Params, Args) \ return (obj->*fn) Args; \ DELEGATE_3_(Ret, Name, Params, Args) \ return (obj->*fn) Args; \ DELEGATE_4_(Ret, Name, Params, Args) \ Ret ret = Ret(); \ for(Delegate::const_iterator it = m_list.begin(); it != m_list.end(); ++it) { \ ret = (**it) Args; \ } \ return ret; \ DELEGATE_5_(Ret, Name, Params, Args) #endif // #ifndef DELEGATE_H_20050415_210113_JO9EHF09_INCLUDED_