引数の組み合わせを Boost.MPL で簡単にする

こういう時こそ Boost.MPL の出番ですね。
って事で簡単にやってみました。

[条件]

  • 3つの引数に X が1つでも含まれている関数 plus を定義する

[ソース]

#include <boost/mpl/count.hpp>
#include <boost/mpl/less_equal.hpp>
#include <boost/mpl/vector.hpp>
#include <boost/utility/enable_if.hpp>

struct X{
    X(int value) : value(value){}
    int value;
};


namespace mpl = boost::mpl;

int
get_value(X const& x){
    return x.value;
}

template<typename T>
T const&
get_value(T const& t){
    return t;
}


// 引数に1つでも X が含まれている場合に呼ばれる関数
template<
    typename T1, typename T2, typename T3
>
int
plus(
    T1 const& t1, T2 const& t2, T3 const& t3,
    typename boost::enable_if<
        typename mpl::less_equal<
            mpl::int_<1>,
            mpl::count<mpl::vector<T1, T2, T3>, X>
        >::type
    >::type* = 0
){
    return get_value(t1) + get_value(t2) + get_value(t3);
}


#include <cassert>

int
main(){
    X x1 = 1;
    X x2 = 2;
    X x3 = 3;

    assert(plus(x1,  2,  3) == 6);
    assert(plus( 1, x2,  3) == 6);
    assert(plus( 1,  2, x3) == 6);
    assert(plus(x1, x2,  3) == 6);
    assert(plus(x1, x2, x3) == 6);

//     assert(plus(1, 2,  3) == 6);    // X が含まれていないのでコンパイルエラー

    return 0;
}


Boost.MPL 便利ですね。
Variadic Templates が使えれば引数の数も関係なくなります。


ただ、引数の条件が複雑になるようであればコードが見づらくなると思うので、そこら辺は少し工夫する必要があると思います。

[boost]

  • ver 1.49.0