2011-09-12 10 views
24

を使用すると、結果のは、バインドされたオブジェクトが予想するよりも多くの引数を受け取ることがあります。概念的:その署名は、それが引数を取らないことを示していてもboost :: bindを使用して、予想よりも多くの引数を渡しても安全ですか?

int func() { return 42; } 
boost::function<int (int,int,int)> boundFunc = boost::bind(&func); 
int answer = boundFunc(1,2,3); 

この場合、func()は、スタック上の1,2、及び3を受信します。

これは値がより少ない引数を取るが、が正しい数の引数を供給するバインドされたオブジェクトを呼び出すときboost::functionをもたらす特定のオブジェクトのために固定されているpartial applicationためboost::bindのより典型的な使用とは異なります。

次のコードは、両方のMSVC++ 2010 SP1で機能します。これは、転記される形が縮小されています。元のコードは、Linuxのg ++​​ 4.4でも動作します。

以下は、C++標準に従って明確に定義されていますか?

#include <iostream> 
#include <boost/bind.hpp> 
#include <boost/function.hpp> 

using namespace std; 

void func1(int x) { std::cout << "func1(" << x << ")\n"; } // end func1() 

void func0() { std::cout << "func0()\n"; } // end func0() 

int main(int argc,char* argv[]) 
{ 
     typedef boost::function<void (int)> OneArgFunc; 
     OneArgFunc oneArg = boost::bind(&func1,_1); 
     // here we bind a function that accepts no arguments 
     OneArgFunc zeroArg = boost::bind(&func0); 
     oneArg(42); 
     // here we invoke a function that takes no arguments 
     // with an argument. 
     zeroArg(42); 

    return 0; 
} // end main() 

は私がなぜzeroArg(42)作品を理解する:未使用の引数は、呼び出されたルーチンで呼び出すルーチンによってスタックに入れて、単純にアクセスされません。呼び出されたルーチンが戻ると、呼び出し側ルーチンはスタックをクリーンアップします。引数をスタックに置くので、引数を取り除く方法を知っています。

別のアーキテクチャまたはコンパイラに移動するとこれが破損しますか?より積極的な最適化はこれを壊すでしょうか?


私は、Boostの文書または標準化文書のいずれかから、より強い声明を探しています。私はいずれかの中で明確な位置を見つけることができませんでした。

デバッガを使用してアセンブリとスタックを調べると、最初の例のfuncは値1,2と3を受け取らないことがわかります。 2番目の例ではfunc0についても同様です。これは、少なくとも私が見ている実装、MSVC++ 2010SP1、およびg ++ 4.4/Linuxでは当てはまります。最後の例では、関数オブジェクトがによって生成、という

bind(f, _2, _1)(x, y);     // f(y, x) 

bind(g, _1, 9, _1)(x);     // g(x, 9, x) 

bind(g, _3, _3, _3)(x, y, z);   // g(z, z, z) 

bind(g, _1, _1, _1)(x, y, z);   // g(x, x, x) 

注:私は、追加の引数を渡すために安全であることを希望として参照ブーストのドキュメントを見て

、それはのようにはっきりしていませんbind(g, _1, _1, _1)には、最初の引数以外の引数への参照は含まれていませんが、複数の引数で引き続き使用できます。 3番目の例で最初の引数と2番目の引数が無視されるように、余分な引数は無視されます。 [重点鉱山。]

文の余分な引数については無視されているが、私は、これは一般的なケースでは真実であることを私を説得したいほど曖昧でないではありません。 TR1を見ると、呼び出し可能オブジェクトbindから返され、対象オブジェクトが期待する数とは異なる引数で呼び出すことができることが、3.6.3項から明らかです。それは最高の保証が利用可能ですか?

+5

+1は完璧な最初の質問です。私はあなたを少し愛しています。 –

答えて

14

はい、これは安全で移植性があり、the documentationに明示的に記載されているように–です。boost::bindによって返されるbind-expressionは、余分な引数を自動的に無視します。

Ieは、あなたの最初の例では、funcはないが値を受け取るん12、および3boundFuncは値12、および3を受信して​​、安全に受信して、含まれているバインド表現、に転送しますそれらを無視し、func()を呼び出します。同様に、2番目の例では、zeroArgは値42を受け取り、値を受け取って無視し、func0()を呼び出すバインド式に転送します。

+3

確かに。 'func()'は、予想以上に多くのオブジェクトを魔法のように呼び出すことはありません。 'boost :: bind'(実際には仲介関数)はそれらを受け入れます(そしてそれで問題はありません)。そしてそれを最終的な呼び出し先に渡しません。 –

+0

デバッガを使用してアセンブリとスタックを見ると、最初の例の 'func'は値1,2と3を受け取らないことがわかります。少なくとも、私が見ている実装については、MSVC++ 2010SP1とg ++ 4.4/Linuxです。 –

関連する問題