たとえば、次の擬似コードでは、クラスBはB :: m_cbメンバを介してA :: Action()を呼び出す必要があります。
目的は、テンプレートではない一般的なコールバッククラスを作成する方法です。したがって、 "B"はテンプレートでなくてもよく、 "コールバック"はあらゆる種類の関数シグネチャを保持できます。
これまで私はこのようなコードを使用していましたが、今はその実装が見つかりません。 「コールバック」自体はテンプレートではありませんが、メンバーテンプレート
が含まれています - -
ヘルパー関数テンプレートmake_callbackは
C++コールバック - コールバック型をデカップリングする方法
は、誰もがpoiinterを与えるできるコールバックオブジェクトをインスタンス化します:私が覚えているすべてはありますか?
Class A
{
public:
void Action(){//...};
};
class CallBack
{
//...
// CallBack it self it is a NOT a template
// It can wrap member template though
};
class B
{
public:
void SetCallback(CallBack to){
m_cb = to;
}
void do_something()
{
//...
m_cb.Execute();
//...
}
private:
CallBack m_cb;
};
int main()
{
A obj1;
CallBack cb = make_callback(&obj1, &A::Action);
B obj2;
obj2.SetCallback(cb);
//....
obj2.do_something();
}
私はこの同じウェブサイトから得たサンプルコードです。 私はそれを少し改良したので、任意のコールバック関数の戻り値の型を許容することができます。しかし、18行目のように任意の数の引数を扱うことはできません。また、Tはメンバ関数へのポインタです。これはCに依存する必要があります。これを強制する方法はわかりません。
#include <iostream>
#include <memory>
// INTERNAL CLASSES
class CallbackSpecBase
{
public:
virtual ~CallbackSpecBase() {}
virtual void operator()(...) const = 0;
};
template<class C, class T>
class CallbackSpec : public CallbackSpecBase
{
public:
CallbackSpec(C& o, T m) : obj(o), method(m) {}
/*line 18*/ void operator()(...) const { (&obj->*method)(); } // how to pass "..." into method(...)
private:
C& obj;
T method;
};
// PUBLIC API
class Callback
{
public:
Callback() {}
void operator()() { (*spec)(); }
template<class C, class T>
void set(C& o, T m) { spec.reset(new CallbackSpec<C, T>(o, m)); }
private:
std::auto_ptr<CallbackSpecBase> spec;
};
// TEST CODE
class Test
{
public:
void foo() { std::cout << "Working" << std::endl; }
void bar() { std::cout << "Like a charm" << std::endl; }
};
int main()
{
Test t;
Callback c;
c.set(t, &Test::foo);
c();
c.set(t, &Test::bar);
c();
}
ヒント:[Boost.Bind(http://www.boost.org/doc/libs/1_47_0 /libs/bind/bind.html)はすでにこの種の機能を提供していますので、自分で実装する必要はありません。 –
Boost.Bindは任意のコールバック関数の署名を処理できますか?任意の型のように、引数の任意の数? –