読者です 読者をやめる 読者になる 読者になる

亀岡的プログラマ日記

京都のベッドタウン、亀岡よりだらだらとお送りいたします。

boost::lambaをいじいじしてみたり。

なんか変なところに躓いたのでメモ。C++の基本もやらずにいきなりBoostなんかに手を出すからこうなるのだけれど。

プレースホルダーも(当たり前だけど)名前空間にある

以下のコードは通りません。

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

using namespace std;

int main (int argc, const char * argv[])
{
    boost::function<double(double)> f = _1*_1 - 3*_1 + 2; //f(x) = x^2 - 3x + 2
    cout << f(3) << endl; // 2
    
    return 0;
}

なぜなら、_1などのラムダ式の引数用のプレースホルダーの定義もまた、boost::lambda名前空間にあるからです。だからどこかで、

using namespace boost::lambda

とか書いてあげないと通りません。

プレースホルダーは簡単に上書きできる

上の回避策なんですが、ラムダ式プレースホルダって簡単に書き換えられます。
こんな感じで。

boost::lambda::placeholder1_type _X;
boost::lambda::placeholder2_type _Y;
boost::lambda::placeholder3_type _Z;

こうしとくと、3引数のプレースホルダは左から_X, _Y, _Zとなります。
まぁ完全に好みの問題ですが。

複数行のメソッドを書きたい時は、コンマで区切る

複数行のメソッドをラムダ式に書きたい場合には、ラムダ式をコンマで区切ってやります。
例えば・・・

(cout << _1 << "\n", cout << _2 << "\n", cout << _1 + _2 << "\n")

とかくと、コンマで区切られた3つのラムダ式が順次実行されるシーケンスとなります。

ラムダ式の中でendlが使えない

ラムダ式の中でendlは使えません。というのも、

Note that an io manipulator is actually a unary function, taking an ostream as input, and returning an ostream. What complicates things is that it is a template function. Here's the gcc3.2.2 version:
      template<typename _CharT, typename _Traits>
       basic_ostream<_CharT, _Traits>& 
      endl(basic_ostream<_CharT, _Traits>& __os) {
         return flush(__os.put(__os.widen('')));
     }
Because it is a template, "endl" has no meaning outside of a context which supplies it type information. If you compile the above, you'll get an error something like "unknown type", since the type of endl can't be deduced.

というわけで、テンプレート関数だからラムダ式のコンテキストでは使えないらしいですね。
まぁ素直に改行コードを入れときましょう、みたいな話になります。あとは頑張ってテンプレートを展開するようなユーティリティ関数を作っておいて、ちょいと細工するか、ですね。たとえばこんなのを見つけました。

コレを使うとかんな感じにはかけます。まぁ好き好きだろうなぁ・・・

    battle.SetMeesageCallback((cout << _X << omanip(cout, endl), 
                               cout << _Y << omanip(cout, endl), 
                               cout << _X + _Y << omanip(cout, endl)));