typeof完成させた

型を登録する際に自前でID書かなくてもいいようにした。VC8で確認。かなり重い。やっぱりmpl::vector使わずに自前のやつの方がよかったかな。
追記:あぁ、そういえばこれパラメータが一つだけのtemplateはなんか失敗するんだった。後で直す。

int_holder.hpp

#define EXIST_PP_OFFSET_1(n) (n) % 10
#define EXIST_PP_OFFSET_2(n) (n) / 10 % 10
#define EXIST_PP_OFFSET_3(n) (n) / 100 % 10
#define EXIST_PP_OFFSET_4(n) (n) / 1000 % 10
#define EXIST_PP_OFFSET_5(n) (n) / 10000 % 10
#define EXIST_PP_OFFSET_6(n) (n) / 100000 % 10
#define EXIST_PP_OFFSET_7(n) (n) / 1000000 % 10
#define EXIST_PP_OFFSET_8(n) (n) / 10000000 % 10
#define EXIST_PP_OFFSET_9(n) (n) / 100000000 % 10
#define EXIST_PP_OFFSET_10(n) (n) / 1000000000

#define EXIST_PP_NUMBER_ 0
#define EXIST_PP_NUMBER_0 1
#define EXIST_PP_NUMBER_1 1
#define EXIST_PP_NUMBER_2 1
#define EXIST_PP_NUMBER_3 1
#define EXIST_PP_NUMBER_4 1
#define EXIST_PP_NUMBER_5 1
#define EXIST_PP_NUMBER_6 1
#define EXIST_PP_NUMBER_7 1
#define EXIST_PP_NUMBER_8 1
#define EXIST_PP_NUMBER_9 1

#define EXIST_PP_NUMBER(n) BOOST_PP_CAT(EXIST_PP_NUMBER_, n)

#if EXIST_PP_OFFSET_10(EXIST_PP_INT_EXPR) == 0
# undef  EXIST_PP_DIGIT_10
# define EXIST_PP_DIGIT_10 
#elif EXIST_PP_OFFSET_10(EXIST_PP_INT_EXPR) == 1
# undef  EXIST_PP_DIGIT_10
# define EXIST_PP_DIGIT_10 1
#elif EXIST_PP_OFFSET_10(EXIST_PP_INT_EXPR) == 2
# undef  EXIST_PP_DIGIT_10
# define EXIST_PP_DIGIT_10 2
#elif EXIST_PP_OFFSET_10(EXIST_PP_INT_EXPR) == 3
# undef  EXIST_PP_DIGIT_10
# define EXIST_PP_DIGIT_10 3
#elif EXIST_PP_OFFSET_10(EXIST_PP_INT_EXPR) == 4
# undef  EXIST_PP_DIGIT_10
# define EXIST_PP_DIGIT_10 4
#elif EXIST_PP_OFFSET_10(EXIST_PP_INT_EXPR) == 5
# undef  EXIST_PP_DIGIT_10
# define EXIST_PP_DIGIT_10 5
#elif EXIST_PP_OFFSET_10(EXIST_PP_INT_EXPR) == 6
# undef  EXIST_PP_DIGIT_10
# define EXIST_PP_DIGIT_10 6
#elif EXIST_PP_OFFSET_10(EXIST_PP_INT_EXPR) == 7
# undef  EXIST_PP_DIGIT_10
# define EXIST_PP_DIGIT_10 7
#elif EXIST_PP_OFFSET_10(EXIST_PP_INT_EXPR) == 8
# undef  EXIST_PP_DIGIT_10
# define EXIST_PP_DIGIT_10 8
#elif EXIST_PP_OFFSET_10(EXIST_PP_INT_EXPR) == 9
# undef  EXIST_PP_DIGIT_10
# define EXIST_PP_DIGIT_10 9
#endif

#if EXIST_PP_OFFSET_9(EXIST_PP_INT_EXPR) == 0
# undef EXIST_PP_DIGIT_9
# if EXIST_PP_NUMBER(EXIST_PP_DIGIT_10)
#  define EXIST_PP_DIGIT_9 0
# else
#  define EXIST_PP_DIGIT_9
# endif
#elif EXIST_PP_OFFSET_9(EXIST_PP_INT_EXPR) == 1
# undef  EXIST_PP_DIGIT_9
# define EXIST_PP_DIGIT_9 1
#elif EXIST_PP_OFFSET_9(EXIST_PP_INT_EXPR) == 2
# undef  EXIST_PP_DIGIT_9
# define EXIST_PP_DIGIT_9 2
#elif EXIST_PP_OFFSET_9(EXIST_PP_INT_EXPR) == 3
# undef  EXIST_PP_DIGIT_9
# define EXIST_PP_DIGIT_9 3
#elif EXIST_PP_OFFSET_9(EXIST_PP_INT_EXPR) == 4
# undef  EXIST_PP_DIGIT_9
# define EXIST_PP_DIGIT_9 4
#elif EXIST_PP_OFFSET_9(EXIST_PP_INT_EXPR) == 5
# undef  EXIST_PP_DIGIT_9
# define EXIST_PP_DIGIT_9 5
#elif EXIST_PP_OFFSET_9(EXIST_PP_INT_EXPR) == 6
# undef  EXIST_PP_DIGIT_9
# define EXIST_PP_DIGIT_9 6
#elif EXIST_PP_OFFSET_9(EXIST_PP_INT_EXPR) == 7
# undef  EXIST_PP_DIGIT_9
# define EXIST_PP_DIGIT_9 7
#elif EXIST_PP_OFFSET_9(EXIST_PP_INT_EXPR) == 8
# undef  EXIST_PP_DIGIT_9
# define EXIST_PP_DIGIT_9 8
#elif EXIST_PP_OFFSET_9(EXIST_PP_INT_EXPR) == 9
# undef  EXIST_PP_DIGIT_9
# define EXIST_PP_DIGIT_9 9
#endif

#if EXIST_PP_OFFSET_8(EXIST_PP_INT_EXPR) == 0
# undef EXIST_PP_DIGIT_8
# if EXIST_PP_NUMBER(EXIST_PP_DIGIT_9)
#  define EXIST_PP_DIGIT_8 0
# else
#  define EXIST_PP_DIGIT_8
# endif
#elif EXIST_PP_OFFSET_8(EXIST_PP_INT_EXPR) == 1
# undef  EXIST_PP_DIGIT_8
# define EXIST_PP_DIGIT_8 1
#elif EXIST_PP_OFFSET_8(EXIST_PP_INT_EXPR) == 2
# undef  EXIST_PP_DIGIT_8
# define EXIST_PP_DIGIT_8 2
#elif EXIST_PP_OFFSET_8(EXIST_PP_INT_EXPR) == 3
# undef  EXIST_PP_DIGIT_8
# define EXIST_PP_DIGIT_8 3
#elif EXIST_PP_OFFSET_8(EXIST_PP_INT_EXPR) == 4
# undef  EXIST_PP_DIGIT_8
# define EXIST_PP_DIGIT_8 4
#elif EXIST_PP_OFFSET_8(EXIST_PP_INT_EXPR) == 5
# undef  EXIST_PP_DIGIT_8
# define EXIST_PP_DIGIT_8 5
#elif EXIST_PP_OFFSET_8(EXIST_PP_INT_EXPR) == 6
# undef  EXIST_PP_DIGIT_8
# define EXIST_PP_DIGIT_8 6
#elif EXIST_PP_OFFSET_8(EXIST_PP_INT_EXPR) == 7
# undef  EXIST_PP_DIGIT_8
# define EXIST_PP_DIGIT_8 7
#elif EXIST_PP_OFFSET_8(EXIST_PP_INT_EXPR) == 8
# undef  EXIST_PP_DIGIT_8
# define EXIST_PP_DIGIT_8 8
#elif EXIST_PP_OFFSET_8(EXIST_PP_INT_EXPR) == 9
# undef  EXIST_PP_DIGIT_8
# define EXIST_PP_DIGIT_8 9
#endif

#if EXIST_PP_OFFSET_7(EXIST_PP_INT_EXPR) == 0
# undef EXIST_PP_DIGIT_7
# if EXIST_PP_NUMBER(EXIST_PP_DIGIT_8)
#  define EXIST_PP_DIGIT_7 0
# else
#  define EXIST_PP_DIGIT_7
# endif
#elif EXIST_PP_OFFSET_7(EXIST_PP_INT_EXPR) == 1
# undef  EXIST_PP_DIGIT_7
# define EXIST_PP_DIGIT_7 1
#elif EXIST_PP_OFFSET_7(EXIST_PP_INT_EXPR) == 2
# undef  EXIST_PP_DIGIT_7
# define EXIST_PP_DIGIT_7 2
#elif EXIST_PP_OFFSET_7(EXIST_PP_INT_EXPR) == 3
# undef  EXIST_PP_DIGIT_7
# define EXIST_PP_DIGIT_7 3
#elif EXIST_PP_OFFSET_7(EXIST_PP_INT_EXPR) == 4
# undef  EXIST_PP_DIGIT_7
# define EXIST_PP_DIGIT_7 4
#elif EXIST_PP_OFFSET_7(EXIST_PP_INT_EXPR) == 5
# undef  EXIST_PP_DIGIT_7
# define EXIST_PP_DIGIT_7 5
#elif EXIST_PP_OFFSET_7(EXIST_PP_INT_EXPR) == 6
# undef  EXIST_PP_DIGIT_7
# define EXIST_PP_DIGIT_7 6
#elif EXIST_PP_OFFSET_7(EXIST_PP_INT_EXPR) == 7
# undef  EXIST_PP_DIGIT_7
# define EXIST_PP_DIGIT_7 7
#elif EXIST_PP_OFFSET_7(EXIST_PP_INT_EXPR) == 8
# undef  EXIST_PP_DIGIT_7
# define EXIST_PP_DIGIT_7 8
#elif EXIST_PP_OFFSET_7(EXIST_PP_INT_EXPR) == 9
# undef  EXIST_PP_DIGIT_7
# define EXIST_PP_DIGIT_7 9
#endif

#if EXIST_PP_OFFSET_6(EXIST_PP_INT_EXPR) == 0
# undef EXIST_PP_DIGIT_6
# if EXIST_PP_NUMBER(EXIST_PP_DIGIT_7)
#  define EXIST_PP_DIGIT_6 0
# else
#  define EXIST_PP_DIGIT_6
# endif
#elif EXIST_PP_OFFSET_6(EXIST_PP_INT_EXPR) == 1
# undef  EXIST_PP_DIGIT_6
# define EXIST_PP_DIGIT_6 1
#elif EXIST_PP_OFFSET_6(EXIST_PP_INT_EXPR) == 2
# undef  EXIST_PP_DIGIT_6
# define EXIST_PP_DIGIT_6 2
#elif EXIST_PP_OFFSET_6(EXIST_PP_INT_EXPR) == 3
# undef  EXIST_PP_DIGIT_6
# define EXIST_PP_DIGIT_6 3
#elif EXIST_PP_OFFSET_6(EXIST_PP_INT_EXPR) == 4
# undef  EXIST_PP_DIGIT_6
# define EXIST_PP_DIGIT_6 4
#elif EXIST_PP_OFFSET_6(EXIST_PP_INT_EXPR) == 5
# undef  EXIST_PP_DIGIT_6
# define EXIST_PP_DIGIT_6 5
#elif EXIST_PP_OFFSET_6(EXIST_PP_INT_EXPR) == 6
# undef  EXIST_PP_DIGIT_6
# define EXIST_PP_DIGIT_6 6
#elif EXIST_PP_OFFSET_6(EXIST_PP_INT_EXPR) == 7
# undef  EXIST_PP_DIGIT_6
# define EXIST_PP_DIGIT_6 7
#elif EXIST_PP_OFFSET_6(EXIST_PP_INT_EXPR) == 8
# undef  EXIST_PP_DIGIT_6
# define EXIST_PP_DIGIT_6 8
#elif EXIST_PP_OFFSET_6(EXIST_PP_INT_EXPR) == 9
# undef  EXIST_PP_DIGIT_6
# define EXIST_PP_DIGIT_6 9
#endif

#if EXIST_PP_OFFSET_5(EXIST_PP_INT_EXPR) == 0
# undef EXIST_PP_DIGIT_5
# if EXIST_PP_NUMBER(EXIST_PP_DIGIT_6)
#  define EXIST_PP_DIGIT_5 0
# else
#  define EXIST_PP_DIGIT_5
# endif
#elif EXIST_PP_OFFSET_5(EXIST_PP_INT_EXPR) == 1
# undef  EXIST_PP_DIGIT_5
# define EXIST_PP_DIGIT_5 1
#elif EXIST_PP_OFFSET_5(EXIST_PP_INT_EXPR) == 2
# undef  EXIST_PP_DIGIT_5
# define EXIST_PP_DIGIT_5 2
#elif EXIST_PP_OFFSET_5(EXIST_PP_INT_EXPR) == 3
# undef  EXIST_PP_DIGIT_5
# define EXIST_PP_DIGIT_5 3
#elif EXIST_PP_OFFSET_5(EXIST_PP_INT_EXPR) == 4
# undef  EXIST_PP_DIGIT_5
# define EXIST_PP_DIGIT_5 4
#elif EXIST_PP_OFFSET_5(EXIST_PP_INT_EXPR) == 5
# undef  EXIST_PP_DIGIT_5
# define EXIST_PP_DIGIT_5 5
#elif EXIST_PP_OFFSET_5(EXIST_PP_INT_EXPR) == 6
# undef  EXIST_PP_DIGIT_5
# define EXIST_PP_DIGIT_5 6
#elif EXIST_PP_OFFSET_5(EXIST_PP_INT_EXPR) == 7
# undef  EXIST_PP_DIGIT_5
# define EXIST_PP_DIGIT_5 7
#elif EXIST_PP_OFFSET_5(EXIST_PP_INT_EXPR) == 8
# undef  EXIST_PP_DIGIT_5
# define EXIST_PP_DIGIT_5 8
#elif EXIST_PP_OFFSET_5(EXIST_PP_INT_EXPR) == 9
# undef  EXIST_PP_DIGIT_5
# define EXIST_PP_DIGIT_5 9
#endif

#if EXIST_PP_OFFSET_4(EXIST_PP_INT_EXPR) == 0
# undef EXIST_PP_DIGIT_4
# if EXIST_PP_NUMBER(EXIST_PP_DIGIT_5)
#  define EXIST_PP_DIGIT_4 0
# else
#  define EXIST_PP_DIGIT_4
# endif
#elif EXIST_PP_OFFSET_4(EXIST_PP_INT_EXPR) == 1
# undef  EXIST_PP_DIGIT_4
# define EXIST_PP_DIGIT_4 1
#elif EXIST_PP_OFFSET_4(EXIST_PP_INT_EXPR) == 2
# undef  EXIST_PP_DIGIT_4
# define EXIST_PP_DIGIT_4 2
#elif EXIST_PP_OFFSET_4(EXIST_PP_INT_EXPR) == 3
# undef  EXIST_PP_DIGIT_4
# define EXIST_PP_DIGIT_4 3
#elif EXIST_PP_OFFSET_4(EXIST_PP_INT_EXPR) == 4
# undef  EXIST_PP_DIGIT_4
# define EXIST_PP_DIGIT_4 4
#elif EXIST_PP_OFFSET_4(EXIST_PP_INT_EXPR) == 5
# undef  EXIST_PP_DIGIT_4
# define EXIST_PP_DIGIT_4 5
#elif EXIST_PP_OFFSET_4(EXIST_PP_INT_EXPR) == 6
# undef  EXIST_PP_DIGIT_4
# define EXIST_PP_DIGIT_4 6
#elif EXIST_PP_OFFSET_4(EXIST_PP_INT_EXPR) == 7
# undef  EXIST_PP_DIGIT_4
# define EXIST_PP_DIGIT_4 7
#elif EXIST_PP_OFFSET_4(EXIST_PP_INT_EXPR) == 8
# undef  EXIST_PP_DIGIT_4
# define EXIST_PP_DIGIT_4 8
#elif EXIST_PP_OFFSET_4(EXIST_PP_INT_EXPR) == 9
# undef  EXIST_PP_DIGIT_4
# define EXIST_PP_DIGIT_4 9
#endif

#if EXIST_PP_OFFSET_3(EXIST_PP_INT_EXPR) == 0
# undef EXIST_PP_DIGIT_3
# if EXIST_PP_NUMBER(EXIST_PP_DIGIT_4)
#  define EXIST_PP_DIGIT_3 0
# else
#  define EXIST_PP_DIGIT_3
# endif
#elif EXIST_PP_OFFSET_3(EXIST_PP_INT_EXPR) == 1
# undef  EXIST_PP_DIGIT_3
# define EXIST_PP_DIGIT_3 1
#elif EXIST_PP_OFFSET_3(EXIST_PP_INT_EXPR) == 2
# undef  EXIST_PP_DIGIT_3
# define EXIST_PP_DIGIT_3 2
#elif EXIST_PP_OFFSET_3(EXIST_PP_INT_EXPR) == 3
# undef  EXIST_PP_DIGIT_3
# define EXIST_PP_DIGIT_3 3
#elif EXIST_PP_OFFSET_3(EXIST_PP_INT_EXPR) == 4
# undef  EXIST_PP_DIGIT_3
# define EXIST_PP_DIGIT_3 4
#elif EXIST_PP_OFFSET_3(EXIST_PP_INT_EXPR) == 5
# undef  EXIST_PP_DIGIT_3
# define EXIST_PP_DIGIT_3 5
#elif EXIST_PP_OFFSET_3(EXIST_PP_INT_EXPR) == 6
# undef  EXIST_PP_DIGIT_3
# define EXIST_PP_DIGIT_3 6
#elif EXIST_PP_OFFSET_3(EXIST_PP_INT_EXPR) == 7
# undef  EXIST_PP_DIGIT_3
# define EXIST_PP_DIGIT_3 7
#elif EXIST_PP_OFFSET_3(EXIST_PP_INT_EXPR) == 8
# undef  EXIST_PP_DIGIT_3
# define EXIST_PP_DIGIT_3 8
#elif EXIST_PP_OFFSET_3(EXIST_PP_INT_EXPR) == 9
# undef  EXIST_PP_DIGIT_3
# define EXIST_PP_DIGIT_3 9
#endif

#if EXIST_PP_OFFSET_2(EXIST_PP_INT_EXPR) == 0
# undef EXIST_PP_DIGIT_2
# if EXIST_PP_NUMBER(EXIST_PP_DIGIT_3)
#  define EXIST_PP_DIGIT_2 0
# else
#  define EXIST_PP_DIGIT_2
# endif
#elif EXIST_PP_OFFSET_2(EXIST_PP_INT_EXPR) == 1
# undef  EXIST_PP_DIGIT_2
# define EXIST_PP_DIGIT_2 1
#elif EXIST_PP_OFFSET_2(EXIST_PP_INT_EXPR) == 2
# undef  EXIST_PP_DIGIT_2
# define EXIST_PP_DIGIT_2 2
#elif EXIST_PP_OFFSET_2(EXIST_PP_INT_EXPR) == 3
# undef  EXIST_PP_DIGIT_2
# define EXIST_PP_DIGIT_2 3
#elif EXIST_PP_OFFSET_2(EXIST_PP_INT_EXPR) == 4
# undef  EXIST_PP_DIGIT_2
# define EXIST_PP_DIGIT_2 4
#elif EXIST_PP_OFFSET_2(EXIST_PP_INT_EXPR) == 5
# undef  EXIST_PP_DIGIT_2
# define EXIST_PP_DIGIT_2 5
#elif EXIST_PP_OFFSET_2(EXIST_PP_INT_EXPR) == 6
# undef  EXIST_PP_DIGIT_2
# define EXIST_PP_DIGIT_2 6
#elif EXIST_PP_OFFSET_2(EXIST_PP_INT_EXPR) == 7
# undef  EXIST_PP_DIGIT_2
# define EXIST_PP_DIGIT_2 7
#elif EXIST_PP_OFFSET_2(EXIST_PP_INT_EXPR) == 8
# undef  EXIST_PP_DIGIT_2
# define EXIST_PP_DIGIT_2 8
#elif EXIST_PP_OFFSET_2(EXIST_PP_INT_EXPR) == 9
# undef  EXIST_PP_DIGIT_2
# define EXIST_PP_DIGIT_2 9
#endif

#if EXIST_PP_OFFSET_1(EXIST_PP_INT_EXPR) == 0
# undef  EXIST_PP_DIGIT_1
# define EXIST_PP_DIGIT_1 0
#elif EXIST_PP_OFFSET_1(EXIST_PP_INT_EXPR) == 1
# undef  EXIST_PP_DIGIT_1
# define EXIST_PP_DIGIT_1 1
#elif EXIST_PP_OFFSET_1(EXIST_PP_INT_EXPR) == 2
# undef  EXIST_PP_DIGIT_1
# define EXIST_PP_DIGIT_1 2
#elif EXIST_PP_OFFSET_1(EXIST_PP_INT_EXPR) == 3
# undef  EXIST_PP_DIGIT_1
# define EXIST_PP_DIGIT_1 3
#elif EXIST_PP_OFFSET_1(EXIST_PP_INT_EXPR) == 4
# undef  EXIST_PP_DIGIT_1
# define EXIST_PP_DIGIT_1 4
#elif EXIST_PP_OFFSET_1(EXIST_PP_INT_EXPR) == 5
# undef  EXIST_PP_DIGIT_1
# define EXIST_PP_DIGIT_1 5
#elif EXIST_PP_OFFSET_1(EXIST_PP_INT_EXPR) == 6
# undef  EXIST_PP_DIGIT_1
# define EXIST_PP_DIGIT_1 6
#elif EXIST_PP_OFFSET_1(EXIST_PP_INT_EXPR) == 7
# undef  EXIST_PP_DIGIT_1
# define EXIST_PP_DIGIT_1 7
#elif EXIST_PP_OFFSET_1(EXIST_PP_INT_EXPR) == 8
# undef  EXIST_PP_DIGIT_1
# define EXIST_PP_DIGIT_1 8
#elif EXIST_PP_OFFSET_1(EXIST_PP_INT_EXPR) == 9
# undef  EXIST_PP_DIGIT_1
# define EXIST_PP_DIGIT_1 9
#endif

#undef EXIST_PP_DIGIT_CAT
#undef EXIST_PP_DIGIT_CAT_I
#define EXIST_PP_DIGIT_CAT(a, b, c, d, e, f, g, h, i, j) EXIST_PP_DIGIT_CAT_I(a, b, c, d, e, f, g, h, i, j)
#define EXIST_PP_DIGIT_CAT_I(a, b, c, d, e, f, g, h, i, j) a ## b ## c ## d ## e ## f ## g ## h ## i ## j

#undef EXIST_PP_INT_HOLDER
#define EXIST_PP_INT_HOLDER EXIST_PP_DIGIT_CAT(EXIST_PP_DIGIT_10, EXIST_PP_DIGIT_9, EXIST_PP_DIGIT_8, EXIST_PP_DIGIT_7, EXIST_PP_DIGIT_6, EXIST_PP_DIGIT_5, EXIST_PP_DIGIT_4, EXIST_PP_DIGIT_3, EXIST_PP_DIGIT_2, EXIST_PP_DIGIT_1)

#undef EXIST_PP_OFFSET_1
#undef EXIST_PP_OFFSET_2
#undef EXIST_PP_OFFSET_3
#undef EXIST_PP_OFFSET_4
#undef EXIST_PP_OFFSET_5
#undef EXIST_PP_OFFSET_6
#undef EXIST_PP_OFFSET_7
#undef EXIST_PP_OFFSET_8
#undef EXIST_PP_OFFSET_9
#undef EXIST_PP_OFFSET_10

#undef EXIST_PP_NUMBER_
#undef EXIST_PP_NUMBER_1
#undef EXIST_PP_NUMBER_2
#undef EXIST_PP_NUMBER_3
#undef EXIST_PP_NUMBER_4
#undef EXIST_PP_NUMBER_5
#undef EXIST_PP_NUMBER_6
#undef EXIST_PP_NUMBER_7
#undef EXIST_PP_NUMBER_8
#undef EXIST_PP_NUMBER_9

init_counter.hpp

#undef EXIST_PP_INT_EXPR
#define EXIST_PP_INT_EXPR 0
#include EXIST_TYPEOF_UPDATE_COUNTER()

incr_counter.hpp

#undef  EXIST_PP_INT_EXPR
#define EXIST_PP_INT_EXPR EXIST_PP_INT_HOLDER + 1
#include EXIST_TYPEOF_UPDATE_COUNTER()

typeof.hpp

#if !defined EXIST_TYPEOF_HPP_INCLUDED_
#define      EXIST_TYPEOF_HPP_INCLUDED_

#define BOOST_MPL_LIMIT_VECTOR_SIZE 50


#include <boost/mpl/vector.hpp>
#include <boost/mpl/range_c.hpp>
#include <boost/mpl/size_t.hpp>
#include <boost/mpl/transform.hpp>
#include <boost/mpl/always.hpp>
#include <boost/mpl/at.hpp>
#include <boost/mpl/copy.hpp>
#include <boost/mpl/push_back.hpp>
#include <boost/mpl/pop_front.hpp>
#include <boost/mpl/front.hpp>
#include <boost/mpl/alias.hpp>
#include <boost/mpl/size.hpp>
#include <boost/preprocessor/cat.hpp>

#define EXIST_TYPEOF_INIT_COUNTER() "init_counter.hpp"
#define EXIST_TYPEOF_UPDATE_COUNTER() "int_holder.hpp"
#define EXIST_TYPEOF_INCREMENT_COUNTER() "incr_counter.hpp"
#define EXIST_TYPEOF_UNIQUE_ID() EXIST_PP_INT_HOLDER * 0x10000 + __LINE__

#include EXIST_TYPEOF_INIT_COUNTER()

#define EXIST_TYPEOF_PUSH_BACK(V, val) typename mpl::push_back<V, mpl::size_t<val> >::type
#define EXIST_TYPEOF_ENCODE(V, M, T) typename encode_type_impl<V, M, T>::type
#define EXIST_TYPEOF_POP_FRONT(V) typename mpl::pop_front<V>::type
#define EXIST_TYPEOF_FRONT(V) typename mpl::front<V>::type
#define EXIST_TYPEOF_DECODE(V, M) decode_type_impl<EXIST_TYPEOF_POP_FRONT(V), M, EXIST_TYPEOF_FRONT(V)>


namespace exist { namespace type_of {

template<size_t n>
struct sizer {
    char size[n + 1];
};


template<typename Vector,
         template<typename, typename> class Map,
         typename T>
struct encode_type_impl {
    typedef typename Map<Vector, T>::type type;
};


template<typename Vector, 
         template<typename, typename> class Map,
         typename val>
struct decode_type_impl {
    typedef typename Map<Vector, val>::type type;
    typedef typename Map<Vector, val>::rest rest;
};


// modified type, function type, member pointer type
#define EXIST_TYPEOF_SPACE
#define EXIST_TYPEOF_PATTERN_PLANE(name, cv, T) T cv name
#define EXIST_TYPEOF_PATTERN_PTR(name, _, T) T * name
#define EXIST_TYPEOF_PATTERN_REF(name, _, T) T & name
#define EXIST_TYPEOF_PATTERN_FUN0(name, _, T) T name()
#define EXIST_TYPEOF_PATTERN_FUN1(name, _, T1, T2) T1 name(T2)
#define EXIST_TYPEOF_PATTERN_FUN2(name, _, T1, T2, T3) T1 name(T2, T3)
#define EXIST_TYPEOF_PATTERN_FUN3(name, _, T1, T2, T3, T4) T1 name(T2, T3, T4)
#define EXIST_TYPEOF_PATTERN_MEM_PTR(name, _, T1, T2) T2 (T1::* name)
#define EXIST_TYPEOF_PATTERN_MEM_FUN0(name, cv, T1, T2) T2 (T1::* name)() cv
#define EXIST_TYPEOF_PATTERN_MEM_FUN1(name, cv, T1, T2, T3) T2 (T1::* name)(T3) cv
#define EXIST_TYPEOF_PATTERN_MEM_FUN2(name, cv, T1, T2, T3, T4) T2 (T1::* name)(T3, T4) cv
#define EXIST_TYPEOF_PATTERN_MEM_FUN3(name, cv, T1, T2, T3, T4, T5) T2 (T1::* name)(T3, T4, T5) cv


#define EXIST_TYPEOF_ENCODE_DECODE_DEF_1(id, pattern, cv) \
    template<typename Vector, \
             template<typename, typename> class Map, \
             typename T> \
    struct encode_type_impl<Vector, Map, pattern(EXIST_TYPEOF_SPACE, cv, T) > { \
        typedef EXIST_TYPEOF_ENCODE( \
                    EXIST_TYPEOF_PUSH_BACK(Vector, id), Map, T) type; \
    }; \
    template<typename Vector, \
             template<typename, typename> class Map> \
    struct decode_type_impl<Vector, Map, mpl::size_t<id> > { \
        typedef EXIST_TYPEOF_DECODE(Vector, Map) decode1; \
        typedef typename decode1::type type1; \
        typedef pattern(type, cv, type1); \
        typedef typename decode1::rest rest; \
    };

#define EXIST_TYPEOF_ENCODE_DECODE_DEF_2(id, pattern, cv) \
    template<typename Vector, \
             template<typename, typename> class Map, \
             typename T1, \
             typename T2> \
    struct encode_type_impl<Vector, Map, pattern(EXIST_TYPEOF_SPACE, cv, T1, T2) > { \
        typedef EXIST_TYPEOF_ENCODE( \
                EXIST_TYPEOF_ENCODE( \
                    EXIST_TYPEOF_PUSH_BACK(Vector, id), Map, T1), \
                    Map, T2) type; \
    }; \
    template<typename Vector, template<typename, typename> class Map> \
    struct decode_type_impl<Vector, Map, mpl::size_t<id> > { \
        typedef EXIST_TYPEOF_DECODE(Vector, Map) decode1; \
        typedef EXIST_TYPEOF_DECODE(typename decode1::rest, Map) decode2; \
        typedef typename decode1::type type1; \
        typedef typename decode2::type type2; \
        typedef pattern(type, cv, type1, type2); \
        typedef typename decode2::rest rest; \
    };

#define EXIST_TYPEOF_ENCODE_DECODE_DEF_3(id, pattern, cv) \
    template<typename Vector, \
             template<typename, typename> class Map, \
             typename T1, \
             typename T2, \
             typename T3> \
    struct encode_type_impl<Vector, Map, pattern(EXIST_TYPEOF_SPACE, cv, T1, T2, T3) > { \
        typedef EXIST_TYPEOF_ENCODE( \
                EXIST_TYPEOF_ENCODE( \
                EXIST_TYPEOF_ENCODE( \
                    EXIST_TYPEOF_PUSH_BACK(Vector, id), Map, T1), \
                    Map, T2), \
                    Map, T3) type; \
    }; \
    template<typename Vector, template<typename, typename> class Map> \
    struct decode_type_impl<Vector, Map, mpl::size_t<id> > { \
        typedef EXIST_TYPEOF_DECODE(Vector, Map) decode1; \
        typedef EXIST_TYPEOF_DECODE(typename decode1::rest, Map) decode2; \
        typedef EXIST_TYPEOF_DECODE(typename decode2::rest, Map) decode3; \
        typedef typename decode1::type type1; \
        typedef typename decode2::type type2; \
        typedef typename decode3::type type3; \
        typedef pattern(type, cv, type1, type2, type3); \
        typedef typename decode3::rest rest; \
    };

#define EXIST_TYPEOF_ENCODE_DECODE_DEF_4(id, pattern, cv) \
    template<typename Vector, \
             template<typename, typename> class Map, \
             typename T1, \
             typename T2, \
             typename T3, \
             typename T4> \
    struct encode_type_impl<Vector, Map, pattern(EXIST_TYPEOF_SPACE, cv, T1, T2, T3, T4) > { \
        typedef EXIST_TYPEOF_ENCODE( \
                EXIST_TYPEOF_ENCODE( \
                EXIST_TYPEOF_ENCODE( \
                EXIST_TYPEOF_ENCODE( \
                    EXIST_TYPEOF_PUSH_BACK(Vector, id), Map, T1), \
                    Map, T2), \
                    Map, T3), \
                    Map, T4) type; \
    }; \
    template<typename Vector, template<typename, typename> class Map> \
    struct decode_type_impl<Vector, Map, mpl::size_t<id> > { \
        typedef EXIST_TYPEOF_DECODE(Vector, Map) decode1; \
        typedef EXIST_TYPEOF_DECODE(typename decode1::rest, Map) decode2; \
        typedef EXIST_TYPEOF_DECODE(typename decode2::rest, Map) decode3; \
        typedef EXIST_TYPEOF_DECODE(typename decode3::rest, Map) decode4; \
        typedef typename decode1::type type1; \
        typedef typename decode2::type type2; \
        typedef typename decode3::type type3; \
        typedef typename decode4::type type4; \
        typedef pattern(type, cv, type1, type2, type3, type4); \
        typedef typename decode4::rest rest; \
    };

#define EXIST_TYPEOF_ENCODE_DECODE_DEF_5(id, pattern, cv) \
    template<typename Vector, \
             template<typename, typename> class Map, \
             typename T1, \
             typename T2, \
             typename T3, \
             typename T4, \
             typename T5> \
    struct encode_type_impl<Vector, Map, pattern(EXIST_TYPEOF_SPACE, cv, T1, T2, T3, T4, T5) > { \
        typedef EXIST_TYPEOF_ENCODE( \
                EXIST_TYPEOF_ENCODE( \
                EXIST_TYPEOF_ENCODE( \
                EXIST_TYPEOF_ENCODE( \
                EXIST_TYPEOF_ENCODE( \
                    EXIST_TYPEOF_PUSH_BACK(Vector, id), Map, T1), \
                    Map, T2), \
                    Map, T3), \
                    Map, T4), \
                    Map, T5) type; \
    }; \
    template<typename Vector, template<typename, typename> class Map> \
    struct decode_type_impl<Vector, Map, mpl::size_t<id> > { \
        typedef EXIST_TYPEOF_DECODE(Vector, Map) decode1; \
        typedef EXIST_TYPEOF_DECODE(typename decode1::rest, Map) decode2; \
        typedef EXIST_TYPEOF_DECODE(typename decode2::rest, Map) decode3; \
        typedef EXIST_TYPEOF_DECODE(typename decode3::rest, Map) decode4; \
        typedef EXIST_TYPEOF_DECODE(typename decode4::rest, Map) decode5; \
        typedef typename decode1::type type1; \
        typedef typename decode2::type type2; \
        typedef typename decode3::type type3; \
        typedef typename decode4::type type4; \
        typedef typename decode5::type type5; \
        typedef pattern(type, cv, type1, type2, type3, type4, type5); \
        typedef typename decode5::rest rest; \
    };

#define EXIST_TYPEOF_ALL_CV_CASE_DEF(id, def_n, pattern) \
    def_n(id, pattern, EXIST_TYPEOF_SPACE) \
    def_n(id + 1, pattern, const) \
    def_n(id + 2, pattern, volatile) \
    def_n(id + 3, pattern, const volatile)

EXIST_TYPEOF_ENCODE_DECODE_DEF_1(EXIST_TYPEOF_UNIQUE_ID(), EXIST_TYPEOF_PATTERN_PLANE, const)
EXIST_TYPEOF_ENCODE_DECODE_DEF_1(EXIST_TYPEOF_UNIQUE_ID(), EXIST_TYPEOF_PATTERN_PLANE, volatile)
EXIST_TYPEOF_ENCODE_DECODE_DEF_1(EXIST_TYPEOF_UNIQUE_ID(), EXIST_TYPEOF_PATTERN_PLANE, const volatile)
EXIST_TYPEOF_ENCODE_DECODE_DEF_1(EXIST_TYPEOF_UNIQUE_ID(), EXIST_TYPEOF_PATTERN_PTR, EXIST_TYPEOF_SPACE)
EXIST_TYPEOF_ENCODE_DECODE_DEF_1(EXIST_TYPEOF_UNIQUE_ID(), EXIST_TYPEOF_PATTERN_REF, EXIST_TYPEOF_SPACE)
EXIST_TYPEOF_ENCODE_DECODE_DEF_1(EXIST_TYPEOF_UNIQUE_ID(), EXIST_TYPEOF_PATTERN_FUN0, EXIST_TYPEOF_SPACE)
EXIST_TYPEOF_ENCODE_DECODE_DEF_2(EXIST_TYPEOF_UNIQUE_ID(), EXIST_TYPEOF_PATTERN_FUN1, EXIST_TYPEOF_SPACE)
EXIST_TYPEOF_ENCODE_DECODE_DEF_3(EXIST_TYPEOF_UNIQUE_ID(), EXIST_TYPEOF_PATTERN_FUN2, EXIST_TYPEOF_SPACE)
EXIST_TYPEOF_ENCODE_DECODE_DEF_4(EXIST_TYPEOF_UNIQUE_ID(), EXIST_TYPEOF_PATTERN_FUN3, EXIST_TYPEOF_SPACE)
EXIST_TYPEOF_ENCODE_DECODE_DEF_2(EXIST_TYPEOF_UNIQUE_ID(), EXIST_TYPEOF_PATTERN_MEM_PTR, EXIST_TYPEOF_SPACE)

EXIST_TYPEOF_ALL_CV_CASE_DEF(
    EXIST_TYPEOF_UNIQUE_ID(),
    EXIST_TYPEOF_ENCODE_DECODE_DEF_2,
    EXIST_TYPEOF_PATTERN_MEM_FUN0)

EXIST_TYPEOF_ALL_CV_CASE_DEF(
    EXIST_TYPEOF_UNIQUE_ID(),
    EXIST_TYPEOF_ENCODE_DECODE_DEF_3,
    EXIST_TYPEOF_PATTERN_MEM_FUN1)

EXIST_TYPEOF_ALL_CV_CASE_DEF(
    EXIST_TYPEOF_UNIQUE_ID(),
    EXIST_TYPEOF_ENCODE_DECODE_DEF_4,
    EXIST_TYPEOF_PATTERN_MEM_FUN2)

EXIST_TYPEOF_ALL_CV_CASE_DEF(
    EXIST_TYPEOF_UNIQUE_ID(),
    EXIST_TYPEOF_ENCODE_DECODE_DEF_5,
    EXIST_TYPEOF_PATTERN_MEM_FUN3)

#undef EXIST_TYPEOF_SPACE
#undef EXIST_TYPEOF_PATTERN_PLANE
#undef EXIST_TYPEOF_PATTERN_PTR
#undef EXIST_TYPEOF_PATTERN_REF
#undef EXIST_TYPEOF_PATTERN_FUN0
#undef EXIST_TYPEOF_PATTERN_FUN1
#undef EXIST_TYPEOF_PATTERN_FUN2
#undef EXIST_TYPEOF_PATTERN_FUN3
#undef EXIST_TYPEOF_PATTERN_MEM_PTR
#undef EXIST_TYPEOF_PATTERN_MEM_FUN0
#undef EXIST_TYPEOF_PATTERN_MEM_FUN1
#undef EXIST_TYPEOF_PATTERN_MEM_FUN2
#undef EXIST_TYPEOF_PATTERN_MEM_FUN3

#undef EXIST_TYPEOF_ENCODE_DECODE_DEF_1
#undef EXIST_TYPEOF_ENCODE_DECODE_DEF_2
#undef EXIST_TYPEOF_ENCODE_DECODE_DEF_3
#undef EXIST_TYPEOF_ENCODE_DECODE_DEF_4
#undef EXIST_TYPEOF_ENCODE_DECODE_DEF_5
#undef EXIST_TYPEOF_ALL_CV_CASE_DEF

// array
#define EXIST_TYPEOF_ARRAY_ENCODE_DECODE() \
    template<typename Vector, \
             template<typename, typename> class Map, \
             typename T, \
             size_t n> \
    struct encode_type_impl<Vector, Map, T[n]> { \
        typedef EXIST_TYPEOF_PUSH_BACK( \
                EXIST_TYPEOF_ENCODE( \
                    EXIST_TYPEOF_PUSH_BACK(Vector, EXIST_TYPEOF_UNIQUE_ID()), Map, T), \
                    n) type; \
    }; \
    template<typename Vector,template<typename, typename> class Map> \
    struct decode_type_impl<Vector, Map, mpl::size_t<EXIST_TYPEOF_UNIQUE_ID()> > { \
        typedef EXIST_TYPEOF_DECODE(Vector, Map) decode; \
        typedef typename decode::type type[mpl::front<typename decode::rest>::type::value]; \
        typedef EXIST_TYPEOF_POP_FRONT(typename decode::rest) rest; \
    };

EXIST_TYPEOF_ARRAY_ENCODE_DECODE()

// template parameter
template<typename Vector,
         template<typename, typename> class Map,
         template<typename> class TC,
         typename T>
struct encode_type_impl<Vector, Map, TC<T> > {
    typedef EXIST_TYPEOF_ENCODE(Vector, Map, T) type;
};


#define EXIST_TYPEOF_ENCODE_NONTYPE_TEMPLATE_PARAM_DEF(valueType) \
    template<typename Vector, \
             template<typename, typename> class Map, \
             template<valueType> class TC, \
             valueType val> \
    struct encode_type_impl<Vector, Map, TC<val> > { \
        typedef EXIST_TYPEOF_PUSH_BACK(EXIST_TYPEOF_PUSH_BACK(Vector, EXIST_TYPEOF_UNIQUE_ID()), val) type; \
    };

#define EXIST_TYPEOF_ENCODE_DECODE_NONTYPE_TEMPLATE_PARAM() \
    EXIST_TYPEOF_ENCODE_NONTYPE_TEMPLATE_PARAM_DEF(char) \
    EXIST_TYPEOF_ENCODE_NONTYPE_TEMPLATE_PARAM_DEF(signed char) \
    EXIST_TYPEOF_ENCODE_NONTYPE_TEMPLATE_PARAM_DEF(unsigned char) \
    EXIST_TYPEOF_ENCODE_NONTYPE_TEMPLATE_PARAM_DEF(short) \
    EXIST_TYPEOF_ENCODE_NONTYPE_TEMPLATE_PARAM_DEF(unsigned short) \
    EXIST_TYPEOF_ENCODE_NONTYPE_TEMPLATE_PARAM_DEF(int) \
    EXIST_TYPEOF_ENCODE_NONTYPE_TEMPLATE_PARAM_DEF(unsigned int) \
    EXIST_TYPEOF_ENCODE_NONTYPE_TEMPLATE_PARAM_DEF(long) \
    EXIST_TYPEOF_ENCODE_NONTYPE_TEMPLATE_PARAM_DEF(unsigned long) \
    template<typename Vector, template<typename, typename> class Map> \
    struct decode_type_impl<Vector, Map, mpl::size_t<EXIST_TYPEOF_UNIQUE_ID()> > { \
        typedef mpl::size_t<mpl::front<Vector>::type::value> type; \
        typedef EXIST_TYPEOF_POP_FRONT(Vector) rest; \
    };

EXIST_TYPEOF_ENCODE_DECODE_NONTYPE_TEMPLATE_PARAM()

#undef EXIST_TYPEOF_ENCODE_DECODE_NONTYPE_TEMPLATE_PARAM
#undef EXIST_TYPEOF_ENCODE_NONTYPE_TEMPLATE_PARAM_DEF


template<typename Decoder, typename TypeParam>
struct decode_template_param {
    typedef typename Decoder::template set<TypeParam>::type type;
};


template<typename Decoder, size_t val>
struct decode_template_param<Decoder, mpl::size_t<val> > {
    typedef typename Decoder::template set<val>::type type;
};


// end of decode
template<typename Vector, template<typename, typename> class Map>
struct decode_type_impl<Vector, Map, mpl::size_t<0> > {
    typedef mpl::void_ type;
    typedef Vector rest;
};

}} // namespace exist { namespace { type_of


namespace { namespace type_of {

template<typename Vector, typename T>
struct encode_map;


template<typename Vector, typename val>
struct decode_map;


template<typename T>
struct encode_type {
    typedef
        typename mpl::copy<
            typename mpl::transform<
                mpl::range_c<
                    size_t,
                    mpl::size<
                        typename exist::type_of::encode_type_impl<
                            mpl::vector<>,
                            encode_map,
                            T>::type>::value,
                    BOOST_MPL_LIMIT_VECTOR_SIZE >,
                mpl::always<mpl::size_t<0> >,
                mpl::back_inserter<mpl::vector0<> > >::type,
            mpl::back_inserter<
                typename exist::type_of::encode_type_impl<
                    mpl::vector<>,
                    encode_map,
                    T>::type> >::type
        type;
};


template<typename Vector>
struct decode_type
    : public exist::type_of::decode_type_impl<
        EXIST_TYPEOF_POP_FRONT(Vector),
        decode_map,
        EXIST_TYPEOF_FRONT(Vector)>
{};


template<size_t index, typename Expr>
exist::type_of::sizer<
    mpl::at_c<
        typename encode_type<Expr>::type,
        index>::type::value>
encode_result_type(Expr const &);

}} // namespace { namespace type_of {


#undef EXIST_TYPEOF_PUSH_BACK
#undef EXIST_TYPEOF_ENCODE
#undef EXIST_TYPEOF_FRONT
#undef EXIST_TYPEOF_POP_FRONT
#undef EXIST_TYPEOF_DECODE


#define EXIST_TYPEOF_REGIST_TYPE_IMPL(id, type_) \
namespace { namespace type_of { \
    template<typename Vector> \
    struct encode_map<Vector, type_ > { \
        typedef typename mpl::push_back<Vector, mpl::size_t<id> >::type type; \
    }; \
    template<typename Vector> \
    struct decode_map<Vector, mpl::size_t<id> > { \
        typedef type_ type; \
        typedef Vector rest; \
    }; \
}}

#define EXIST_TYPEOF_REGIST_TEMPLATE_1_IMPL(id, template_, param1_type) \
namespace { namespace type_of { \
    template<typename Vector, param1_type param1> \
    struct encode_map<Vector, template_<param1> > { \
        template<param1_type> struct param1_wrapper; \
        typedef typename \
            exist::type_of::encode_type_impl< \
                typename mpl::push_back<Vector, mpl::size_t<id> >::type, \
                ::type_of::encode_map, \
                param1_wrapper<param1> >::type \
            type; \
    }; \
    template<typename Vector> \
    struct decode_map<Vector, mpl::size_t<id> > { \
        typedef \
            exist::type_of::decode_type_impl< \
                typename mpl::pop_front<Vector>::type, \
                ::type_of::decode_map, \
                typename mpl::front<Vector>::type> \
            decode1; \
        struct param_decoder { \
            template<param1_type param1> struct set { \
                typedef template_<param1> type; \
            }; \
        }; \
        typedef \
            typename exist::type_of::decode_template_param< \
                param_decoder, \
                typename decode1::type>::type \
            type; \
        typedef typename decode1::rest rest; \
    }; \
}}

#define EXIST_TYPEOF_REGIST_TEMPLATE_2_IMPL(id, template_, param1_type, param2_type) \
namespace { namespace type_of { \
    template<typename Vector, param1_type param1, param2_type param2> \
    struct encode_map<Vector, template_<param1, param2> > { \
        template<param1_type> struct param1_wrapper; \
        template<param2_type> struct param2_wrapper; \
        typedef typename \
            exist::type_of::encode_type_impl< \
                typename exist::type_of::encode_type_impl< \
                    typename mpl::push_back<Vector, mpl::size_t<id> >::type, \
                    ::type_of::encode_map, \
                    param1_wrapper<param1> >::type, \
                ::type_of::encode_map, \
                param2_wrapper<param2> >::type  \
            type; \
    }; \
    template<typename Vector> \
    struct decode_map<Vector, mpl::size_t<id> > { \
        typedef \
            exist::type_of::decode_type_impl< \
                typename mpl::pop_front<Vector>::type, \
                ::type_of::decode_map, \
                typename mpl::front<Vector>::type> \
            decode1; \
        typedef \
            exist::type_of::decode_type_impl< \
                typename mpl::pop_front<typename decode1::rest>::type, \
                ::type_of::decode_map, \
                typename mpl::front<typename decode1::rest>::type> \
            decode2; \
        struct param_decoder { \
            template<param1_type param1> struct set { \
                struct param_decoder { \
                    template<param2_type param2> struct set { \
                        typedef template_<param1, param2> type; \
                    }; \
                }; \
                typedef \
                    typename exist::type_of::decode_template_param< \
                        param_decoder, \
                        typename decode2::type>::type \
                    type; \
            }; \
        }; \
        typedef \
            typename exist::type_of::decode_template_param< \
                param_decoder, \
                typename decode1::type>::type \
            type; \
        typedef typename decode2::rest rest; \
    }; \
}}

#define EXIST_TYPEOF_REGIST_TEMPLATE_3_IMPL(id, template_, param1_type, param2_type, param3_type) \
namespace { namespace type_of { \
    template<typename Vector, param1_type param1, param2_type param2, param3_type param3> \
    struct encode_map<Vector, template_<param1, param2, param3> > { \
        template<param1_type> struct param1_wrapper; \
        template<param2_type> struct param2_wrapper; \
        template<param3_type> struct param3_wrapper; \
        typedef typename \
            exist::type_of::encode_type_impl< \
                typename exist::type_of::encode_type_impl< \
                    typename exist::type_of::encode_type_impl< \
                        typename mpl::push_back<Vector, mpl::size_t<id> >::type, \
                        ::type_of::encode_map, \
                        param1_wrapper<param1> >::type, \
                    ::type_of::encode_map, \
                    param2_wrapper<param2> >::type,  \
                ::type_of::encode_map, \
                param3_wrapper<param3> >::type  \
            type; \
    }; \
    template<typename Vector> \
    struct decode_map<Vector, mpl::size_t<id> > { \
        typedef \
            exist::type_of::decode_type_impl< \
                typename mpl::pop_front<Vector>::type, \
                ::type_of::decode_map, \
                typename mpl::front<Vector>::type> \
            decode1; \
        typedef \
            exist::type_of::decode_type_impl< \
                typename mpl::pop_front<typename decode1::rest>::type, \
                ::type_of::decode_map, \
                typename mpl::front<typename decode1::rest>::type> \
            decode2; \
        typedef \
            exist::type_of::decode_type_impl< \
                typename mpl::pop_front<typename decode2::rest>::type, \
                ::type_of::decode_map, \
                typename mpl::front<typename decode2::rest>::type> \
            decode3; \
        struct param_decoder { \
            template<param1_type param1> struct set { \
                struct param_decoder { \
                    template<param2_type param2> struct set { \
                        struct param_decoder { \
                            template<param3_type param3> struct set { \
                                typedef template_<param1, param2, param3> type; \
                            }; \
                        }; \
                        typedef \
                            typename exist::type_of::decode_template_param< \
                                param_decoder, \
                                typename decode3::type>::type \
                            type; \
                    }; \
                }; \
                typedef \
                    typename exist::type_of::decode_template_param< \
                        param_decoder, \
                        typename decode2::type>::type \
                    type; \
            }; \
        }; \
        typedef \
            typename exist::type_of::decode_template_param< \
                param_decoder, \
                typename decode1::type>::type \
            type; \
        typedef typename decode3::rest rest; \
    }; \
}}


#define EXIST_TYPEOF_REGIST_TYPE(type) \
    EXIST_TYPEOF_REGIST_TYPE_IMPL(EXIST_TYPEOF_UNIQUE_ID(), type)

#define EXIST_TYPEOF_REGIST_TEMPLATE_1(template_, param1_type) \
    EXIST_TYPEOF_REGIST_TEMPLATE_1_IMPL(EXIST_TYPEOF_UNIQUE_ID(), template_, param1_type)

#define EXIST_TYPEOF_REGIST_TEMPLATE_2(template_, param1_type, param2_type) \
    EXIST_TYPEOF_REGIST_TEMPLATE_2_IMPL(EXIST_TYPEOF_UNIQUE_ID(), template_, param1_type, param2_type)

#define EXIST_TYPEOF_REGIST_TEMPLATE_3(template_, param1_type, param2_type, param3_type) \
    EXIST_TYPEOF_REGIST_TEMPLATE_3_IMPL(EXIST_TYPEOF_UNIQUE_ID(), template_, param1_type, param2_type, param3_type)

#define EXIST_TYPEOF_ENCODED_PARAMETERS(expr) \
    mpl::vector50< \
        mpl::size_t<sizeof(::type_of::encode_result_type<0>(expr).size) - 1>, \
        mpl::size_t<sizeof(::type_of::encode_result_type<1>(expr).size) - 1>, \
        mpl::size_t<sizeof(::type_of::encode_result_type<2>(expr).size) - 1>, \
        mpl::size_t<sizeof(::type_of::encode_result_type<3>(expr).size) - 1>, \
        mpl::size_t<sizeof(::type_of::encode_result_type<4>(expr).size) - 1>, \
        mpl::size_t<sizeof(::type_of::encode_result_type<5>(expr).size) - 1>, \
        mpl::size_t<sizeof(::type_of::encode_result_type<6>(expr).size) - 1>, \
        mpl::size_t<sizeof(::type_of::encode_result_type<7>(expr).size) - 1>, \
        mpl::size_t<sizeof(::type_of::encode_result_type<8>(expr).size) - 1>, \
        mpl::size_t<sizeof(::type_of::encode_result_type<9>(expr).size) - 1>, \
        mpl::size_t<sizeof(::type_of::encode_result_type<10>(expr).size) - 1>, \
        mpl::size_t<sizeof(::type_of::encode_result_type<11>(expr).size) - 1>, \
        mpl::size_t<sizeof(::type_of::encode_result_type<12>(expr).size) - 1>, \
        mpl::size_t<sizeof(::type_of::encode_result_type<13>(expr).size) - 1>, \
        mpl::size_t<sizeof(::type_of::encode_result_type<14>(expr).size) - 1>, \
        mpl::size_t<sizeof(::type_of::encode_result_type<15>(expr).size) - 1>, \
        mpl::size_t<sizeof(::type_of::encode_result_type<16>(expr).size) - 1>, \
        mpl::size_t<sizeof(::type_of::encode_result_type<17>(expr).size) - 1>, \
        mpl::size_t<sizeof(::type_of::encode_result_type<18>(expr).size) - 1>, \
        mpl::size_t<sizeof(::type_of::encode_result_type<19>(expr).size) - 1>, \
        mpl::size_t<sizeof(::type_of::encode_result_type<20>(expr).size) - 1>, \
        mpl::size_t<sizeof(::type_of::encode_result_type<21>(expr).size) - 1>, \
        mpl::size_t<sizeof(::type_of::encode_result_type<22>(expr).size) - 1>, \
        mpl::size_t<sizeof(::type_of::encode_result_type<23>(expr).size) - 1>, \
        mpl::size_t<sizeof(::type_of::encode_result_type<24>(expr).size) - 1>, \
        mpl::size_t<sizeof(::type_of::encode_result_type<25>(expr).size) - 1>, \
        mpl::size_t<sizeof(::type_of::encode_result_type<26>(expr).size) - 1>, \
        mpl::size_t<sizeof(::type_of::encode_result_type<27>(expr).size) - 1>, \
        mpl::size_t<sizeof(::type_of::encode_result_type<28>(expr).size) - 1>, \
        mpl::size_t<sizeof(::type_of::encode_result_type<29>(expr).size) - 1>, \
        mpl::size_t<sizeof(::type_of::encode_result_type<30>(expr).size) - 1>, \
        mpl::size_t<sizeof(::type_of::encode_result_type<31>(expr).size) - 1>, \
        mpl::size_t<sizeof(::type_of::encode_result_type<32>(expr).size) - 1>, \
        mpl::size_t<sizeof(::type_of::encode_result_type<33>(expr).size) - 1>, \
        mpl::size_t<sizeof(::type_of::encode_result_type<34>(expr).size) - 1>, \
        mpl::size_t<sizeof(::type_of::encode_result_type<35>(expr).size) - 1>, \
        mpl::size_t<sizeof(::type_of::encode_result_type<36>(expr).size) - 1>, \
        mpl::size_t<sizeof(::type_of::encode_result_type<37>(expr).size) - 1>, \
        mpl::size_t<sizeof(::type_of::encode_result_type<38>(expr).size) - 1>, \
        mpl::size_t<sizeof(::type_of::encode_result_type<39>(expr).size) - 1>, \
        mpl::size_t<sizeof(::type_of::encode_result_type<40>(expr).size) - 1>, \
        mpl::size_t<sizeof(::type_of::encode_result_type<41>(expr).size) - 1>, \
        mpl::size_t<sizeof(::type_of::encode_result_type<42>(expr).size) - 1>, \
        mpl::size_t<sizeof(::type_of::encode_result_type<43>(expr).size) - 1>, \
        mpl::size_t<sizeof(::type_of::encode_result_type<44>(expr).size) - 1>, \
        mpl::size_t<sizeof(::type_of::encode_result_type<45>(expr).size) - 1>, \
        mpl::size_t<sizeof(::type_of::encode_result_type<46>(expr).size) - 1>, \
        mpl::size_t<sizeof(::type_of::encode_result_type<47>(expr).size) - 1>, \
        mpl::size_t<sizeof(::type_of::encode_result_type<48>(expr).size) - 1>, \
        mpl::size_t<sizeof(::type_of::encode_result_type<49>(expr).size) - 1> >

#define EXIST_TYPEOF(expr) \
    ::type_of::decode_type<EXIST_TYPEOF_ENCODED_PARAMETERS(expr)>::type


#define EXIST_AUTO(name, expr) \
    EXIST_TYPEOF(expr) name = expr

EXIST_TYPEOF_REGIST_TYPE(void)
EXIST_TYPEOF_REGIST_TYPE(char)
EXIST_TYPEOF_REGIST_TYPE(signed char)
EXIST_TYPEOF_REGIST_TYPE(unsigned char)
EXIST_TYPEOF_REGIST_TYPE(short)
EXIST_TYPEOF_REGIST_TYPE(unsigned short)
EXIST_TYPEOF_REGIST_TYPE(int)
EXIST_TYPEOF_REGIST_TYPE(unsigned int)
EXIST_TYPEOF_REGIST_TYPE(long)
EXIST_TYPEOF_REGIST_TYPE(unsigned long)
EXIST_TYPEOF_REGIST_TYPE(float)
EXIST_TYPEOF_REGIST_TYPE(double)
EXIST_TYPEOF_REGIST_TYPE(long double)
EXIST_TYPEOF_REGIST_TYPE(wchar_t)


#endif    // EXIST_TYPEOF_HPP_INCLUDED_