メタプログラミング
なんとなく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
これで少しメタプログラミングってものがわかった気がします。
気だけですが・・・