boost::operator

はじめてboost::operatorなんて使ってみました。といっても、boost本にあるoperator<>ではなくて、additiveとadditive2なんですが。サンプルでは非常に簡単に見えるんですが、サポートしなくない演算子とかがある場合は結構面倒です。

#include 
class Func :
    boost::additive< Func,
    boost::additive2< Func, float
    > >
{
public:
    Func& operator+=( const Func& rhs ) { ...; }   // additive用
    Func& operator-=( const Func& rhs ) { ...; }
    Func& operator+=( float rhs ) { ...; }   // additive2用
    Func& operator-=( float rhs ) { ...; }
};

additiveは、加減算をサポートするクラスに対して使うやつです。+=と-=演算子を実装してやると、勝手に+と-演算子が作られます。additive2は、(多分)演算の引数が違うときに使われます。boost::rationalの実装が参考になるかも。気持ち悪いぐらい継承してます。
で、これを使ったプログラムを書いてて、関数をクラス化できないかとかいう考えが思い浮かびました。

template< typename T >
class Func {
public:
    T operator()( T arg );
};
class SinFunc : public Func { ... };
class CosFunc : public Func { ... };

SinFunc seigen;
CosFunc yogen;

Func mustBe1 = seigen * seigen + yogen * yogen;
ASSERT( mustBe1( rand() / 100.f ) == 1 );

みたいな。で、boost::bindがこれをやってくれるみたいです。けど、書式は違います。

using std; using boost; // <- 面倒になった
function< float ( float ) > mustBe1;
mustBe1 =
  bind( plus< float >(),
    bind( multiplies< float >(),
      bind( &sin, _1 ),
      bind( &sin, _1 )
    ),
    bind( multiplies< float >(),
      bind( &cos, _1 ),
      bind( &cos, _1 )
    )
  );
for( int i = 0; i < 10; ++i ){
    cout << mustBe1( rand() / 100.f ) << endl;
}

多分こんな感じです。なにせコンパイルしてないので分かりません。後日する気になったらします。で、本当はこの三角関数達を自分で適当に生成した確率密度関数にしたかっただけだったり。うーん、bind面白そう。とりあえず、素直に関数型言語に行くってのは無しの方向で。