メタプログラミング

なんとなくSFINAEをやってみたくなったのでやってみた。
やっぱり知ってるだけじゃなくてちゃんと組んでみないとわかったつもりでも全然わかってないことって多いね・・・

#include <boost/utility/enable_if.hpp>
#include <boost/type_traits.hpp>
#include <iostream>
#include <vector>
#include <queue>

template<typename T>
T& value();

template<typename T>
class A {
	private:
		typedef	char		vec[1];
		typedef	char		que[2];
		typedef	char		oth[3];

		template<typename C>
		class checker_vec {
			private:
				template<typename U>
				static auto check( U &u ) -> decltype( u.pop(), boost::true_type() );

				static auto check( ... ) -> decltype( boost::false_type() );

			public:
				typedef		decltype( check( value<C>() ) )		val;
				const static bool value = val::value;
		};

		template<typename C>
		class checker_que {
			private:
				template<typename U>
				static auto check( U &u ) -> decltype( u.pop_back(), boost::true_type() );

				static auto check( ... ) -> decltype( boost::false_type() );

			public:
				typedef		decltype( check( value<C>() ) )		val;
				const static bool value = val::value;
		};

		template<typename C>
		static vec& func( C &c, typename boost::enable_if<decltype( c.pop_back(), boost::true_type() )>::type* = 0, typename boost::disable_if_c<checker_vec<C>::value>::type* = 0 );

		template<typename C>
		static que& func( C &c, typename boost::disable_if_c<checker_que<C>::value>::type* = 0, typename boost::enable_if<decltype( c.pop(), boost::true_type() )>::type* = 0 );

		static oth& func( ... );

	public:
		const static char value = sizeof( decltype( func(value<T>()) ) ) == sizeof( vec ) ? 'v' : sizeof( decltype( func(value<T>()) ) ) == sizeof( que ) ? 'q' : 'o';
};

int main()
{
	using namespace std;
	cout << A<vector<int>>::value << endl;
	cout << A<queue<int>>::value << endl;
	cout << A<char>::value << endl;
}

実行結果

%g++ -std=c++0x test.cpp
%./a.exe
v
q
o
%

GCC 4.5.1 on Cygwin with Boost 1.43でコンパイル&動作確認済み。
ちなみにVC++2010EEではコンパイラが落ちますw

これで少しメタプログラミングってものがわかった気がします。
気だけですが・・・