引数の型だけ違う関数オブジェクトの処理を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;
}