4

ある種のコールバックメソッドを必要とするクラスを使用しているので、boost::functionを使用して関数ポインターを格納しています。

コールバックに1つのオプションの引数が必要ですが、boost :: functionではオプションの引数の種類を定義できないことがわかったので、次のコードを試してみましたが、うまくいきました。

//the second argument is optional  
typedef boost::function< int (int, char*)> myHandler;  

class A   
{  
public:  
     //handler with 2 arguments  
     int foo(int x,char* a) {printf("%s\n",a);   return 0;}; 
     //handler with 1 argument
     int boo(int x) {return 1;};       
}

A* a = new A;  
myHandler fooHandler= boost::bind(&A::foo,a,_1,_2);  
myHandler booHandler= boost::bind(&A::boo,a,_1);    

char* anyCharPtr = "just for demo";  
//This works as expected calling a->foo(5,anyCharPtr)  
fooHandler(5,anyCharPtr);  
//Surprise, this also works as expected, calling a->boo(5) and ignores anyCharPtr 
booHandler(5,anyCharPtr);   

私はそれが機能したことにショックを受けました、質問はそれが機能するべきか、そしてそれは合法ですか?
より良い解決策はありますか?

4

1 に答える 1

3

おそらく、バインド->関数変換の型安全性の穴です。 boost::bindはstd::functionを返しませんが、非常に複雑なタイプの関数オブジェクトを返します。の場合

boost::bind(&A::boo,a,_1);

上記のように、返されるオブジェクトのタイプは

boost::_bi::bind_t<
  int, 
  boost::_mfi::mf1<int,A,int>,
  boost::_bi::list2<boost::_bi::value<A*>, boost::arg<1> > 
>

std :: functionは、指定された関数オブジェクトが「互換性がある」ことを確認するだけです。この場合、最初の引数としてintを使用し、2番目の引数としてcharへのポインターを使用して呼び出すことができるかどうかを確認します。* boost :: bind_t *テンプレートを調べると、実際に一致する関数呼び出し演算子があることがわかります。

template<class A1, class A2> result_type operator()(A1 & a1, A2 & a2)

この関数内では、2番目の引数が黙って破棄されてしまいます。これは仕様によるものです。ドキュメントから:余分な引数は黙って無視されます(...)

于 2011-03-04T12:27:06.933 に答える