boost-bindを使用すると、結果のboost-functionは、バインドされたオブジェクトが期待するよりも多くの引数を受け取る場合があります。概念的に:
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::bind
これは、 for partial applicationのより一般的な使用法とは異なります。この場合、特定のオブジェクトに対して値が固定され、バインドされたオブジェクトを呼び出すときに、boost::function
より少ない数の引数を取るが、正しい数の引数を提供するが生成されます。
次のコードは、両方の 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)
ています。未使用の引数は、呼び出しルーチンによってスタックに置かれ、呼び出されたルーチンによってアクセスされません。呼び出されたルーチンが戻ると、呼び出し元のルーチンはスタックをクリーンアップします。引数をスタックに置くので、それらを削除する方法を知っています。
別のアーキテクチャまたはC++コンパイラに移動すると、これが壊れますか? より積極的な最適化はこれを破りますか?
Boostのドキュメントまたは標準ドキュメントから、より強力な声明を探しています。どちらにも明確な位置を見つけることができませんでした。
デバッガーを使用してアセンブリとスタックを調べるとfunc
、最初の例から値 1、2、および 3 を受け取っていないことが明らかです。その点では正しいです。func0
2 番目の例でも同じことが言えます。これは、少なくとも私が検討している実装、MSVC++2010SP1 および g++4.4/Linux には当てはまります。
参照されている Boost のドキュメントを見ると、追加の引数を渡しても安全かどうかは、私が望むほど明確ではありません。
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を見ると、3.6.3 節から明らかなように、呼び出し可能なオブジェクトの戻り値は、ターゲット オブジェクトが期待するbind
数とは異なる数の引数で呼び出すことができます。それは利用可能な最高の保証ですか?