3

関数オブジェクトを受け入れてコレクションに格納する「アタッチ」関数を持つクラスがあります。クラス自体は、関数シグネチャでテンプレート化されています。このようなもの:

template<class Signature>
class Event
{
public:

 void Attach(boost::function<Signature> signature)
 {
  MySignatures.push_back(signature);
 }

private:

 std::list<boost::function<Signature>> MySignatures;
};

使用法を示すために、次のクラスを検討してください。


class Listening
{
public:

 int SomeFunction(int x, int y, int z); 
};

関数を に渡すにはListening、次のEventように記述する必要があります。


 Event<int(int, int, int)> myEvent;
 Listening myListening;

 myEvent.Attach(boost::bind(boost::mem_fn(&Listening::SomeFunction), &myListening, _1, _2, _3));

したがって、エラーが発生しやすいケースごとにそうする代わりに、次のように一連のマクロを記述します。


 #define EventArgument0(x, y)  boost::bind(boost::mem_fn(x), y)
 #define EventArgument1(x, y)  boost::bind(boost::mem_fn(x), y, _1)
 #define EventArgument2(x, y)  boost::bind(boost::mem_fn(x), y, _1, _2)
 #define EventArgument3(x, y)  boost::bind(boost::mem_fn(x), y, _1, _2, _3)
 #define EventArgument4(x, y)  boost::bind(boost::mem_fn(x), y, _1, _2, _3, _4)

 etc.

そして、私は書くことができます:


 myEvent.Attach(EventArgument3(&Listening::SomeFunction, &myListening));

これははるかに読みやすいです(私は思う)。今私の質問に:代わりにどのように書くことができますか:


 myEvent.Attach(EventArgument(&Listening::SomeFunction, &MyListening));

またはさらに良い:


 myEvent.Attach(&Listening::SomeFunction, &myListening);

、イベント Attach が <Signature> に含まれる適切な数の引数 (この例ではint(int, int, int)) で魔法のように正しくバインドされるように? 私は、あなたがここで考えているどんなテンプレート メタプログラミング マジックにもオープンです。

ありがとう。

boost::mem_fn編集:ここでは必要ないことがわかりましたboost::bind。同等であるため、マクロで使用できます:

bind(&MyClass::Hello, myClass, _1, _2, _3);

、それ以外の:

bind(mem_fn(&MyClass::Hello), myClass, _1, _2, _3);

&MyClass::Helloただし、問題は残ります。イベント クラスに渡し、テンプレートのオーバーロードを使用して、クラスのテンプレート化に使用される関数プロトタイプによって暗示された 、 、など_1_2処理するにはどうすればよいでしょうか?_3Event

4

2 に答える 2

2

Attachメンバー関数のさまざまな数のパラメーターのオーバーロード:

template<typename R,typename T,typename U>
void Attach(R (T::*pmf)(),U* p))
{
    Attach(boost::bind(pmf,p));
}

template<typename R,typename T,typename U,typename A1>
void Attach(R (T::*pmf)(A1),U* p))
{
    Attach(boost::bind(pmf,p,_1));
}

template<typename R,typename T,typename U,typename A1,typename A2>
void Attach(R (T::*pmf)(A1,A2),U* p))
{
    Attach(boost::bind(pmf,p,_1,_2));
}

constメンバー関数も処理する必要がある場合は、2 番目のオーバーロード セットが必要になります。

于 2010-08-19T15:45:47.780 に答える
2

テンプレートを作るAttach()ことで、あなたが目指していることができるようになります。コードは乱雑になりますが、好きなように呼び出すことができます。

template<typename A1>
void Attach(A1 a1);

template<typename A1, typename A2>
void Attach(A1 a1, A2 a2);

template<typename A1, typename A2, typename A3>
void Attach(A1 a1, A2 a2, A3 a3);

template<typename A1, typename A3, typename A4>
void Attach(A1 a1, A2 a2, A3 a3, A4 a4);
于 2010-08-19T14:32:26.097 に答える