LoginSignup
2
2

More than 5 years have passed since last update.

Visual Studio 2013で可変長テンプレートが対応されたのでdelegateのようなものを作ってみた

Posted at

カッとなってやった。

Delegate.h
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);

同じインスタンスの同じメンバ関数は同時に登録できない。
リストの中身はタプルにしたけどもっと良い方法は無いかな?
もちろんお仕事では使えない。(コンパイラが云々かんぬん)

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2