Boost.Fusion の invoke に関数テンプレートを渡したかった

invoke であれば引数に sequence を渡すので
『そこから関数のシグネチャが推論出来るんじゃね?』
とか思ったんですが、引数型は推論出来ても戻り値型が推論できなくて無理でした。
とりあえず、こんな感じ。

[ソース]

#include <boost/fusion/include/vector.hpp>
#include <boost/fusion/include/make_vector.hpp>
#include <boost/fusion/include/invoke.hpp>
#include <boost/fusion/include/value_at.hpp>
#include <boost/fusion/include/is_sequence.hpp>
#include <boost/utility/enable_if.hpp>
#include <iostream>
#include <string>


template<typename T, typename U>
void
disp(T t, U u){
    std::cout << "1:" << t << std::endl;
    std::cout << "2:" << u << std::endl;
}

template<typename T, typename U>
T
plus(T t, U u){
    return t + u;
}


// とりあえず、引数が2つの場合のみ
template<typename R, typename Seq>
struct signature{
    typedef R(*type)(
        typename boost::fusion::result_of::value_at_c<Seq, 0>::type,
        typename boost::fusion::result_of::value_at_c<Seq, 1>::type
    );
};


template<typename R, typename Seq>
R
invoke(
    typename signature<R, Seq>::type func,
    Seq const& seq
){
    return boost::fusion::invoke(func, seq);
}


template<typename Seq>
typename boost::enable_if<
    boost::fusion::traits::is_sequence<Seq>,
    void
>::type
invoke(
    typename signature<void, Seq>::type func,
    Seq const& seq
){
    boost::fusion::invoke(func, seq);
}


int
main(){
    namespace f = boost::fusion;

    f::vector<int, float> v(42, 3.14f);

//  f::invoke(disp, v);                         // error
    f::invoke<void(*)(int, float)>(disp, v);    // ok


    // 戻り値型が void の場合は型推論
    ::invoke(disp, v);
    ::invoke(disp, f::make_vector(std::string("homu"), 13));


    // 戻り値型がある場合のみ明示的に定義
    int result = ::invoke<int>(plus, v);
    std::cout << result << std::endl;

    return 0;
}

[出力]

1:42
2:3.14
1:42
2:3.14
1:homu
2:13
45


関数テンプレートを関数に渡したい場合が多々あるので何かいい方法はないものか…。
一番簡単なのは関数オブジェクトでラップしてしまうことなんだけどもぐぬぬ

[boost]

  • ver 1.51.0