Boost.Lambda で使用されている演算子のオーバーロードをユーザ側で定義する
Boost.Lambda の仕組みなんかをまとめようとすると、わたしの頭がオーバーロードしてしまうので、覚書程度に。
ぶっちゃけ、間違ってるかも知れないので適当に。
さて、次のような『演算子をアダプタとして使用する』コードでは Boost.Lambda を使用する事は出来ません。
#include <boost/lambda/lambda.hpp> #include <iostream> template<typename T> struct value_holder{ value_holder(T t) : value_(t){} T value(){ return value_; } private: T value_; }; template<typename T, typename U> void operator |(value_holder<T> t, U u){ u(t.value()); } template<typename T> value_holder<T> make_value(T t){ return value_holder<T>(t); } struct disp{ template<typename T> void operator ()(T t) const{ std::cout << t << std::endl; } }; int main(){ using boost::lambda::_1; make_value(10) |disp(); make_value("hoge")|disp(); // Boost.Lambda でも operator | が定義されているので、呼び出しがあいまいになる make_value(3.14f) |std::cout << _1 << "\n"; return 0; }
これは、Boost.Lambda でも、operator | が定義されており、呼び出しがあいまいになってしまう為、コンパイルエラーになります。
これを回避する為に、いくつか定義を追加します。
#include <boost/lambda/lambda.hpp> #include <iostream> template<typename T> struct value_holder{ value_holder(T t) : value_(t){} T value(){ return value_; } private: T value_; }; template<typename T, typename U> void operator |(value_holder<T> t, U u){ u(t.value()); } template<typename T> value_holder<T> make_value(T t){ return value_holder<T>(t); } //---------------------------------------------------------- // Boost.Lambda を使えるようにする為の定義 template<typename T, typename Arg> void operator |(value_holder<T> t, boost::lambda::lambda_functor<Arg> u){ u(t.value()); } // 引数によって、戻り値型がわかる時のみ、以下のような定義を記述する /* namespace boost { namespace lambda{ template<typename T, typename U> struct return_type_2<bitwise_action<or_action>, value_holder<T>, U>{ typedef void type; }; }} // namespace boost{ namespace lambda{ */ //---------------------------------------------------------- struct disp{ template<typename T> void operator ()(T t) const{ std::cout << t << std::endl; } }; int main(){ using boost::lambda::_1; make_value(10) |disp(); make_value("hoge")|disp(); make_value(3.14f) |std::cout << _1 << "\n"; make_value(true) |std::cout << (_1|_1) << "\n"; return 0; }
[出力]
10 hoge 3.14 1
これでコンパイルが通り、問題なく動くようになります。
[boost]
ver 1.46.1
[参照]
http://boost.cppll.jp/HEAD/libs/lambda/doc/ar01s06.html
http://www.boost.org/doc/libs/1_46_1/doc/html/lambda/extending.html
http://d.hatena.ne.jp/iorate/20110429/1304064910