id:rich850:20040906, id:rich850:20040907
おとなり日記にあったので気になってしまいました.
// なんか、駄目。 n = boost::bind( plus< int >(), _1, _2 )( a, b );
std名前空間が見えていないか,
int tasu( int a, int b ) { return a + b; } // これは動く。 n = boost::bind( tasu, _1, _2 )( 235, 123 ); // こうすると駄目。boost::protectでrand()を保護しようとしてもエラー。 n = boost::bind( tasu, _1, _2 )( rand(), rand() );
boost::bindで生成した関数オブジェクトは引数に右辺値(リテラル定数とか関数の参照でない戻り値)を取れないという問題を抱えています.
個人的にはboost::bindよりもboost::lambda::bindの方を強くお勧めします.こちらの方がboost.bindよりもさらに機能性が高いです.boost::bindにおける右辺値を取れない問題も,make_constというヘルパー関数で解決しています.
というか,lambda使うと足し算のような単純な関数の合成ならbindが不要です.
#include<cmath> #include<cstdlib> #include<boost/lambda/lambda.hpp> #include<boost/lambda/bind.hpp> #include<boost/function.hpp> #include<iostream> #include<functional> #include<boost/bind.hpp> void test_for_bll() { // boost.lambdaとboost.lambda.bindの場合 using boost::lambda::bind; using boost::lambda::_1; using boost::lambda::_2; using boost::lambda::make_const; int a = 1; int b = 2; std::cout << (_1 + _2)(a, b) << std::endl; std::cout << (_1 + _2)(make_const(123), make_const(456)) << std::endl; std::cout << (_1 + _2)(make_const(rand()), make_const(rand())) << std::endl; float (*p_sin)(float) = &std::sin; float (*p_cos)(float) = &std::cos; boost::function<float (float)> must_be_1 = bind(p_sin, _1) * bind(p_sin, _1) + bind(p_cos, _1) * bind(p_cos, _1) ; for( int i = 0; i < 10; ++i ){ std::cout << must_be_1( std::rand() / 100.f ) << std::endl; } } int main() { test_for_bll(); return 0; }
boost.bindに対するboost.lambda.bindの欠点は可搬性が落ちることぐらいのもんです.
ちなみに上のコードは.NET使っている場合,マネージ拡張がonになっているとboost::functionがバグるので注意が要ります.
参考:id:Cryolite:20040401