任意のデータを保持し、関連するクラスのメンバー関数を呼び出す汎用の「コールバック」オブジェクトを作成しようとしています。内部ポリシーにより、Boost を使用できません。
コールバック オブジェクトは次のようになります。
template<typename Object, typename Data>
class Callback
{
public:
typedef void (Object::*PHandler)(Callback*);
Callback(Object* obj, PHandler handler) : pObj(obj), pHandler(handler) {}
Callback& set(PHandler handler) { pHandler = handler; return *this; }
void run() { (pObj->*pHandler)(this); }
public:
Data data;
protected:
Object* pObj;
PHandler pHandler;
};
そして、それが動作するクラス:
struct Object1
{
struct Data { int i; };
typedef Callback<Object1, Data> Callback1;
void callback(Callback1* pDisp) { printf("%cb\n", pDisp->data.i); }
void test()
{
Callback1 cb(this, &Object1::callback);
cb.data.i = 1;
cb.run();
}
};
次のテストは期待どおりに機能します。
Object1 obj1;
obj1.test();
ここまでは順調ですね。
ただし、同僚がCallback
を使用する代わりにクラスから派生しようとするtypedef
と、互換性のないポインターが原因でコンパイル エラーが発生しました。
struct Object2
{
struct Data { int i; Data(int j) { i = j; } };
class Callback2 : public Callback<Object2, Data>
{
Callback2(Object2* obj, PHandler handler, int i) : Callback(obj, handler) { data.i = i; }
};
void callback(Callback2* pDisp) { printf("%cb\n", pDisp->data.i); }
void test()
{
Callback2 cb(this, &Object2::callback, 2);
cb.run();
}
};
Callback クラスで「奇妙な繰り返しテンプレート パターン」を使用してみましたが、派生クラスを動作させることができましたが、typedef
メソッドを使用するコードが壊れました。
私の質問は:
クラスのユーザー側で余分な作業を必要とせずに、両方のケースで動作するようにクラスを変更するにはどうすればよいですか?Callback