テンプレートでたらいまわし(8回目)

継続渡し風味。

#include <iostream>

/* True */
class True;

/* False */
class False;

/* Bool */
template <bool b>
struct Bool;

template <>
struct Bool<true>
{
    typedef True Result;
};

template <>
struct Bool<false>
{
    typedef False Result;
};

/* NullType */
class NullType;

/* Typelist */
template <class T, class U>
struct Typelist;

#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) >

/* Append */
template <class T, class U>
struct Append;

template <class U>
struct Append<NullType, U>
{
    typedef U Result;
};

template <class T1, class T2, class U>
struct Append<Typelist<T1, T2>, U>
{
    typedef Typelist<T1, typename Append<T2, U>::Result> Result;
};

/* Int */
template <int x>
struct Int
{
    enum { value = x };
};

/* Delay */
template <class TList>
struct Delay;

/* Force */
class Force;

/* Tarai */
template <int x, int y, int z>
struct Tarai;

template <class TList>
struct TaraiBody;

template <class X, class Y, class Z, class R>
struct Tarai0;

template <class Y, class Z, class X, class R>
struct Tarai1;

template <class Z, class X, class Y, class R>
struct Tarai2;

template <class B, class Z, class X, class Y, class R>
struct Tarai3;

template <class X, class Y, class Z, class R>
struct Tarai4;

template <class Y, class Z, class X, class R>
struct Tarai5;

template <class Y, class Z, class X, class R>
struct Tarai6;

template <int x, int y, int z>
struct Tarai
{
    typedef TYPELIST_4(Int<0>, Int<x>, Int<y>, Int<z>) TList;
    enum { value = TaraiBody<TList>::value };
};

template <class X, class Y, class Z, class R>
struct Tarai0
{
    typedef TYPELIST_3(Int<1>, Y, Z) K;
    typedef TYPELIST_2(Force, X) T;
    typedef typename Append<T, Typelist<K, R> >::Result TList;
    enum { value = TaraiBody<TList>::value };
};

template <class Y, class Z, class X, class R>
struct Tarai1
{
    typedef TYPELIST_3(Int<2>, Z, X) K;
    typedef TYPELIST_2(Force, Y) T;
    typedef typename Append<T, Typelist<K, R> >::Result TList;
    enum { value = TaraiBody<TList>::value };
};

template <int x, int y, class Z, class R>
struct Tarai2< Z, Int<x>, Int<y>, R >
{
    typedef typename Bool< (x <= y) >::Result B;
    typedef TYPELIST_5(Int<3>, B, Z, Int<x>, Int<y>) T;
    typedef typename Append<T, R>::Result TList;
    enum { value = TaraiBody<TList>::value };
};

template <class X, class Y, class Z, class R>
struct Tarai3< True, Z, X, Y, R >
{
    typedef TYPELIST_2(Force, Y) T;
    typedef typename Append<T, R>::Result TList;
    enum { value = TaraiBody<TList>::value };
};

template <class X, class Y, class Z, class R>
struct Tarai3< False, Z, X, Y, R >
{
    typedef Delay<TYPELIST_4(Int<4>, X, Y, Z)> XX;
    typedef Delay<TYPELIST_4(Int<4>, Y, Z, X)> YY;
    typedef Delay<TYPELIST_4(Int<4>, Z, X, Y)> ZZ;
    typedef TYPELIST_4(Int<0>, XX, YY, ZZ) T;
    typedef typename Append<T, R>::Result TList;
    enum { value = TaraiBody<TList>::value };
};

template <class X, class Y, class Z, class R>
struct Tarai4
{
    typedef TYPELIST_3(Int<5>, Y, Z) K;
    typedef TYPELIST_2(Force, X) T;
    typedef typename Append<T, Typelist<K, R> >::Result TList;
    enum { value = TaraiBody<TList>::value };
};

template <int x, class Y, class Z, class R>
struct Tarai5< Y, Z, Int<x>, R >
{
    typedef TYPELIST_4(Int<0>, Int<x - 1>, Y, Z) T;
    typedef typename Append<T, R>::Result TList;
    enum { value = TaraiBody<TList>::value };
};

template <class X, class Y, class Z, class R>
struct TaraiBody< Typelist<Int<0>,
                           Typelist<X,
                                    Typelist<Y,
                                             Typelist<Z, R> > > > >
{
    enum { value = Tarai0<X, Y, Z, R>::value };
};

template <class X, class Y, class Z, class R>
struct TaraiBody< Typelist<Int<1>,
                           Typelist<Y,
                                    Typelist<Z,
                                             Typelist<X, R> > > > >
{
    enum { value = Tarai1<Y, Z, X, R>::value };
};

template <class X, class Y, class Z, class R>
struct TaraiBody< Typelist<Int<2>,
                           Typelist<Z,
                                    Typelist<X,
                                             Typelist<Y, R> > > > >
{
    enum { value = Tarai2<Z, X, Y, R>::value };
};

template <class X, class Y, class Z, class R, class B>
struct TaraiBody< Typelist<Int<3>,
                           Typelist<B,
                                    Typelist<Z,
                                             Typelist<X,
                                                      Typelist<Y, R> > > > > >
{
    enum { value = Tarai3<B, Z, X, Y, R>::value };
};

template <class X, class Y, class Z, class R>
struct TaraiBody< Typelist<Int<4>,
                           Typelist<X,
                                    Typelist<Y,
                                             Typelist<Z, R> > > > >
{
    enum { value = Tarai4<X, Y, Z, R>::value };
};

template <class X, class Y, class Z, class R>
struct TaraiBody< Typelist<Int<5>,
                           Typelist<Y,
                                    Typelist<Z,
                                             Typelist<X, R> > > > >
{
    enum { value = Tarai5<Y, Z, X, R>::value };
};

template <int n>
struct TaraiBody< Typelist<Force, Typelist<Int<n>, NullType> > >
{
    enum { value = n };
};

template <int n, class R1, class R2>
struct TaraiBody< Typelist<Force, Typelist<Int<n>, Typelist<R1, R2> > > >
{
    typedef typename Append< R1, Typelist<Int<n>, R2> >::Result TList;
    enum { value = TaraiBody<TList>::value };
};

template <class T, class R>
struct TaraiBody< Typelist<Force, Typelist<Delay<T>, R> > >
{
    typedef typename Append<T, R>::Result TList;
    enum { value = TaraiBody<TList>::value };
};

int main(int argc, char *argv[])
{
    int n = Tarai<12, 6, 0>::value;
    std::cout << n << std::endl;

    return 0;
}