Visual Studio 2013で可変長テンプレートが対応されたのでdelegateのようなものを作ってみた
カッとなってやった。
template <class T, typename... Args> class Delegate { private: typedef void (T::*Func)(Args... args); std::list<std::tuple<T*, Func> > _funcs; public: void add(T* pObj, Func func) { assert(!isExists(pObj, func)); _funcs.push_back(std::make_tuple(pObj, func)); } void remove(T* pObj, Func func) { for (auto it = _funcs.begin(); it != _funcs.end(); ++it) { if (pObj == std::get<0>(*it) && func == std::get<1>(*it)) { _funcs.erase(it); break; } } } void clear() { _funcs.clear(); } bool isExists(T* pObj, Func func) { for (auto it = _funcs.begin(); it != _funcs.end(); ++it) { if (pObj == std::get<0>(*it) && func == std::get<1>(*it)) { return true; } } return false; } void call(Args... args) { for (auto it = _funcs.begin(); it != _funcs.end(); ++it) { auto pObj = std::get<0>(*it); auto func = std::get<1>(*it); (pObj->*func)(args...); } } };
こんな感じに使う。
class Test { public: void foo(int v1, float v2) {} void bar(int v1, float v2) {} }; Test t; Delegate<Test, int, float> d; d.add(&t, &Test::foo); d.add(&t, &Test::bar); d.call(1, 2.0f);
同じインスタンスの同じメンバ関数は同時に登録できない。
リストの中身はタプルにしたけどもっと良い方法は無いかな?
もちろんお仕事では使えない。(コンパイラが云々かんぬん)
同じ内容でQiitaにも投稿してる。
http://qiita.com/HogeTatu/items/188eadefe191db822823