boost.lambda普及(させて意味不明のコンパイルエラーで人々を惑わせよう)委員会

id:rich850:20040906, id:rich850:20040907
おとなり日記にあったので気になってしまいました.

// なんか、駄目。
n = boost::bind( plus< int >(), _1, _2 )( a, b );

std名前空間が見えていないか,ヘッダincludeし忘れてませんか?

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