引数の型だけ違う関数オブジェクトの処理をtemplateで切り分ける−3
記事のまとめ
続いたのでまとめておく。
本文
で説明されてるFunction traits使えばかなりよくなった。Boostにはあるんだけど、C++11にはないっぽいんで、アドホック自作な方向で。
#include <iostream> #include <vector> #include <type_traits> //1引数をとるメンバ関数用のテンプレート&Arg_の型で処理を切り分け namespace moge_traits { //vector/doubleを切り分けるタグ struct tagV{}; struct tagD{}; //適当なfunction traits template<typename T_> struct function_traits{}; template<typename C_, typename Arg_> struct function_traits<void(C_::*)(Arg_)>{ typedef Arg_ argument; }; //API template<typename T_> void operatorInner(T_ t, std::vector<double> x) { std::conditional<std::is_same<function_traits<decltype(&T_::operator())>::argument, double>::value, tagD, tagV>::type tag; detail::operatorInner(t, x, tag); } namespace detail { //タグに応じた実際の処理 template<typename T_> void operatorInner(T_ t, std::vector<double> x, tagV){ t(x); } template<typename T_> void operatorInner(T_ t, std::vector<double> x, tagD){ t(x[0]); } } } //引数の型が違うクラス struct A{ void operator()(double x){ std::cout << "I'm class A:" << x << std::endl; } }; struct B{ void operator()(std::vector<double> x){ std::cout << "I'm class B:" << x[0] << ", " << x[1] << ", " << x[2] << std::endl; } }; //中でA・Bクラスを使う適当なクラス template<typename T_> struct Moge { Moge(T_ x) : x_(x){} void operator()(std::vector<double> x){ moge_traits::operatorInner(x_, x); } T_ x_; }; //メイン int main() { std::vector<double> xxx = { 1, 2, 3 }; B b; Moge<B> x1(b); x1(xxx); A a; Moge<A> x2(a); x2(xxx); return 0; }