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