テンプレートでたらいまわし(3回目)
こうするとだいぶ速くなった。
#include <iostream> template <class T, class U> struct Typelist { typedef T Car; typedef U Cdr; }; class NullType; #define TYPELIST_1(T1) \ Typelist<T1, NullType> #define TYPELIST_2(T1, T2) \ Typelist<T1, TYPELIST_1(T2) > #define TYPELIST_3(T1, T2, T3) \ Typelist<T1, TYPELIST_2(T2, T3) > #define TYPELIST_4(T1, T2, T3, T4) \ Typelist<T1, TYPELIST_3(T2, T3, T4) > #define TYPELIST_5(T1, T2, T3, T4, T5) \ Typelist<T1, TYPELIST_4(T2, T3, T4, T5) > #define TYPELIST_6(T1, T2, T3, T4, T5, T6) \ Typelist<T1, TYPELIST_5(T2, T3, T4, T5, T6) > #define TYPELIST_7(T1, T2, T3, T4, T5, T6, T7) \ Typelist<T1, TYPELIST_6(T2, T3, T4, T5, T6, T7) > #define TYPELIST_8(T1, T2, T3, T4, T5, T6, T7, T8) \ Typelist<T1, TYPELIST_7(T2, T3, T4, T5, T6, T7, T8) > #define TYPELIST_9(T1, T2, T3, T4, T5, T6, T7, T8, T9) \ Typelist<T1, TYPELIST_8(T2, T3, T4, T5, T6, T7, T8, T9) > #define TYPELIST_10(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10) \ Typelist<T1, TYPELIST_9(T2, T3, T4, T5, T6, T7, T8, T9, T10) > /* Length */ template <class T> struct Length; template <> struct Length<NullType> { enum { value = 0 }; }; template <class T, class U> struct Length< Typelist<T, U> > { enum { value = 1 + Length<U>::value }; }; /* True */ class True; /* False */ class False; /* LessEq */ template <class T, class U> struct LessEq; template <> struct LessEq< NullType, NullType > { typedef True Result; }; template <class U1, class U2> struct LessEq< NullType, Typelist<U1, U2> > { typedef True Result; }; template <class T1, class T2> struct LessEq< Typelist<T1, T2>, NullType > { typedef False Result; }; template <class T1, class T2, class U1, class U2> struct LessEq< Typelist<T1, T2>, Typelist<U1, U2> > { typedef typename LessEq<T2, U2>::Result Result; }; /* Tarai */ template <class TList> struct Tarai; template <class B, class X, class Y, class Z> struct Tarai1; template <class X, class Y, class Z> struct Tarai< TYPELIST_3(X, Y, Z) > { typedef typename LessEq< X, Y>::Result B; typedef Tarai1< B, X, Y, Z > T; typedef typename T::Result Result; enum { value = T::value }; }; template <class X, class Y, class Z> struct Tarai1< True, X, Y, Z > { typedef Y Result; enum { value = Length<Y>::value }; }; template <class X1, class X2, class Y1, class Y2, class Z1, class Z2> struct Tarai1< False, Typelist<X1, X2>, Typelist<Y1, Y2>, Typelist<Z1, Z2> > { typedef Typelist<X1, X2> X; typedef Typelist<Y1, Y2> Y; typedef Typelist<Z1, Z2> Z; typedef typename Tarai< TYPELIST_3(X2, Y, Z) >::Result XX; typedef typename Tarai< TYPELIST_3(Y2, Z, X) >::Result YY; typedef typename Tarai< TYPELIST_3(Z2, X, Y) >::Result ZZ; typedef Tarai< TYPELIST_3(XX, YY, ZZ) > T; typedef typename T::Result Result; enum { value = T::value }; }; typedef NullType T0; typedef Typelist<void, T0> T1; typedef Typelist<void, T1> T2; typedef Typelist<void, T2> T3; typedef Typelist<void, T3> T4; typedef Typelist<void, T4> T5; typedef Typelist<void, T5> T6; typedef Typelist<void, T6> T7; typedef Typelist<void, T7> T8; typedef Typelist<void, T8> T9; typedef Typelist<void, T9> T10; typedef Typelist<void, T10> T11; typedef Typelist<void, T11> T12; typedef Typelist<void, T12> T13; typedef Typelist<void, T13> T14; typedef Typelist<void, T14> T15; typedef Typelist<void, T15> T16; typedef Typelist<void, T16> T17; typedef Typelist<void, T17> T18; typedef Typelist<void, T18> T19; typedef Typelist<void, T19> T20; typedef Typelist<void, T20> T21; typedef Typelist<void, T21> T22; typedef Typelist<void, T22> T23; typedef Typelist<void, T23> T24; typedef Typelist<void, T24> T25; typedef Typelist<void, T25> T26; typedef Typelist<void, T26> T27; typedef Typelist<void, T27> T28; typedef Typelist<void, T28> T29; typedef Typelist<void, T29> T30; typedef Typelist<void, T30> T31; typedef Typelist<void, T31> T32; typedef Typelist<void, T32> T33; typedef Typelist<void, T33> T34; typedef Typelist<void, T34> T35; typedef Typelist<void, T35> T36; typedef Typelist<void, T36> T37; typedef Typelist<void, T37> T38; typedef Typelist<void, T38> T39; typedef Typelist<void, T39> T40; typedef Typelist<void, T40> T41; typedef Typelist<void, T41> T42; typedef Typelist<void, T42> T43; typedef Typelist<void, T43> T44; typedef Typelist<void, T44> T45; typedef Typelist<void, T45> T46; typedef Typelist<void, T46> T47; typedef Typelist<void, T47> T48; typedef Typelist<void, T48> T49; typedef Typelist<void, T49> T50; int main(int argc, char *argv[]) { int n = Tarai< TYPELIST_3(T24, T12, T1) >::value; std::cout << n << std::endl; return 0; }
% time g++ tarai3.cpp real 0m9.604s user 0m9.449s sys 0m0.108s % time ./a.out 24 real 0m0.002s user 0m0.000s sys 0m0.000s
どうやらインスタンス化される型の数が多くなるにしたがって時間がかかるみたいだったので、x<=yを判定している部分を独立させたら結果は歴然(それでもtarai(48,24,1)のコンパイルには10分かかった)。
そろそろテンプレートの勘が掴めてきたので、次は遅延評価にチャレンジしたい。