めためた.hpp

メタプログラミングをこよなく愛する人に向けた云々かんぬん

templateでenumと型情報の結び付け

enumから型へ

なんとなくコードを書いている最中、唐突にenumから型情報が振り分けられたら使えるかもしれない!という訳が分からない考えが降ってきたので

書きました。

コード

template<class _Enum>
struct switch_types {
	template<
		bool _Check,
		size_t _N,
		_Enum _Select,
		_Enum _First,
		_Enum ... _Modes
	>
	struct resolve_select
	{
		static size_t const value = _N - 1;
	};

	template<
		size_t _N,
		_Enum _Select,
		_Enum _First,
		_Enum ... _Modes
	>
	struct resolve_select<false, _N, _Select,_First,_Modes ...> :
		public resolve_select<_First == _Select, _N + 1, _Select, _Modes ...>{};

	template<
		size_t _N,
		class _Check,
		class ... _Remain>
	struct resolve_type : public resolve_type<_N - 1, _Remain ... > {};

	template<
		class _Check,
		class ... _Remain>
	struct resolve_type<0, _Check, _Remain ...>
	{
		typedef _Check type;
	};

	template<_Enum ... _Modes>
	struct which {
		template<_Enum _Select>
		struct select {
			template<class ... _Types>
			struct types {
				typedef typename resolve_type<resolve_select<false, 0, _Select, _Modes ..., _Select>::value, _Types ...>::type type;
			};
		};
	};

}

使い方

enum TestEnum
{
	one = 0,	// float
	two,		// int
	three,		// double
};
template<TestEnum Select>
struct TestSelect{
	typedef typename switch_types<TestEnum>::which<one,two,three>::select<Select>::template types<float,int,double>::type type;
};

出力

int main() {
	std::cout << "float : ";
	std::cout << (typeid(TestSelect<one>::type) == typeid(float)) << std::endl;

	std::cout << "int : ";
	std::cout << (typeid(TestSelect<two>::type) == typeid(int)) << std::endl;

	std::cout << "double : ";
	std::cout << (typeid(TestSelect<three>::type) == typeid(double)) << std::endl;

	return 0;
}
float : 1
int : 1
double : 1

解説っぽいもの

switch_typeにenumの型情報を与えて
whichとtypesに対応する列挙子と型情報を順番に並べます
そしてselectで選択された列挙子とwhich内で一致する列挙子のインデックスを元にtypesから型情報を引っ張り出す仕組みです。

正直かなりごり押しした気がする。

使いどころは、そこまでない