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