もっかいtypeof

前回より高性能なtypeofを作ってみた。Boost.Preprocessorは使ってないので多少長くなってしまうが、まぁ読む分には使ってないほうがマシかと思う。
機能的には、スカラ型やユーザ定義型を登録しておけば、それらのポインタやcvで修飾した型や、それらを使った関数型も自動で使えるようになっている。templateは未実装。
この後ソースを全文載っけてあるので見たい人だけ。もう既に全文開いちゃってる人は適当に何とかしていただければ。


#if !defined EXIST_TYPEOF_HPP_INCLUDED_
#define EXIST_TYPEOF_HPP_INCLUDED_

#include <boost/utility/enable_if.hpp>
#include <boost/type_traits/is_same.hpp>


#define EXIST_ENCODED_PARAMS_DECLARE_19\
size_t p2, size_t p3, size_t p4, size_t p5, size_t p6, size_t p7, size_t p8,\
size_t p9, size_t p10, size_t p11, size_t p12, size_t p13, size_t p14, size_t p15,\
size_t p16, size_t p17, size_t p18, size_t p19, size_t p20
#define EXIST_ENCODED_PARAMS_DECLARE_20\
size_t p1, size_t p2, size_t p3, size_t p4, size_t p5, size_t p6, size_t p7, size_t p8,\
size_t p9, size_t p10, size_t p11, size_t p12, size_t p13, size_t p14, size_t p15,\
size_t p16, size_t p17, size_t p18, size_t p19, size_t p20


#define EXIST_ENCODED_PARAMS_19 p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20
#define EXIST_ENCODED_PARAMS_20 p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20


namespace exist { namespace type_of {

enum {
end = 1,
c,
v,
cv,
ptr,
ref,
fun0,
fun1,
fun2,
mem_ptr,
mem_fun0,
mem_fun1,
mem_fun2,
mem_fun0_c,
mem_fun1_c,
mem_fun2_c,
mem_fun0_v,
mem_fun1_v,
mem_fun2_v,
mem_fun0_cv,
mem_fun1_cv,
mem_fun2_cv,
};


template<size_t size>
struct int_to_size {
char sizer[size];
};


struct _ {
static size_t const value = end;
typedef _ next;
typedef _ type;
};


template<typename T, size_t index>
struct at : public at<typename T::next, index - 1> {};
template<typename T>
struct at<T, 0> {
static size_t const value = T::value;
};


template<template<typename> class Encoder, size_t index, typename Expr>
int_to_size<at<Encoder<Expr>, index>::value> encoded_type_params(Expr const &);

}} // namespace type_of, exist


namespace { namespace type_of {

template<typename T, typename Rest>
struct type_encoder_impl;


template<typename T, typename Rest>
struct type_encoder_impl<T const, Rest> {
static size_t const value = exist::type_of::c;
typedef type_encoder_impl<T, Rest> next;
};
template<typename T, typename Rest>
struct type_encoder_impl<T volatile, Rest> {
static size_t const value = exist::type_of::v;
typedef type_encoder_impl<T, Rest> next;
};
template<typename T, typename Rest>
struct type_encoder_impl<T const volatile, Rest> {
static size_t const value = exist::type_of::cv;
typedef type_encoder_impl<T, Rest> next;
};
template<typename T, typename Rest>
struct type_encoder_impl<T*, Rest> {
static size_t const value = exist::type_of::ptr;
typedef type_encoder_impl<T, Rest> next;
};
template<typename T, typename Rest>
struct type_encoder_impl<T&, Rest> {
static size_t const value = exist::type_of::ref;
typedef type_encoder_impl<T, Rest> next;
};
template<typename R, typename Rest>
struct type_encoder_impl<R(), Rest> {
static size_t const value = exist::type_of::fun0;
typedef type_encoder_impl<R, Rest> next;
};
template<typename R, typename T1, typename Rest>
struct type_encoder_impl<R(T1), Rest> {
static size_t const value = exist::type_of::fun1;
typedef type_encoder_impl<R, type_encoder_impl<T1, Rest> > next;
};
template<typename R, typename T1, typename T2, typename Rest>
struct type_encoder_impl<R(T1, T2), Rest> {
static size_t const value = exist::type_of::fun2;
typedef type_encoder_impl<R, type_encoder_impl<T1, type_encoder_impl<T2, Rest> > > next;
};
template<class C, typename T, typename Rest>
struct type_encoder_impl<T (C::*), Rest> {
static size_t const value = exist::type_of::mem_ptr;
typedef type_encoder_impl<C, type_encoder_impl<T, Rest> > next;
};
template<class C, typename R, typename Rest>
struct type_encoder_impl<R (C::*)(), Rest> {
static size_t const value = exist::type_of::mem_fun0;
typedef type_encoder_impl<C, type_encoder_impl<R, Rest> > next;
};
template<class C, typename R, typename A1, typename Rest>
struct type_encoder_impl<R (C::*)(A1), Rest> {
static size_t const value = exist::type_of::mem_fun1;
typedef type_encoder_impl<C, type_encoder_impl<R, type_encoder_impl<A1, Rest> > > next;
};
template<class C, typename R, typename A1, typename A2, typename Rest>
struct type_encoder_impl<R (C::*)(A1, A2), Rest> {
static size_t const value = exist::type_of::mem_fun2;
typedef type_encoder_impl<C, type_encoder_impl<R, type_encoder_impl<A1, type_encoder_impl<A2, Rest> > > > next;
};
template<class C, typename R, typename Rest>
struct type_encoder_impl<R (C::*)() const, Rest> {
static size_t const value = exist::type_of::mem_fun0_c;
typedef type_encoder_impl<C, type_encoder_impl<R, Rest> > next;
};
template<class C, typename R, typename A1, typename Rest>
struct type_encoder_impl<R (C::*)(A1) const, Rest> {
static size_t const value = exist::type_of::mem_fun1_c;
typedef type_encoder_impl<C, type_encoder_impl<R, type_encoder_impl<A1, Rest> > > next;
};
template<class C, typename R, typename A1, typename A2, typename Rest>
struct type_encoder_impl<R (C::*)(A1, A2) const, Rest> {
static size_t const value = exist::type_of::mem_fun2_c;
typedef type_encoder_impl<C, type_encoder_impl<R, type_encoder_impl<A1, type_encoder_impl<A2, Rest> > > > next;
};
template<class C, typename R, typename Rest>
struct type_encoder_impl<R (C::*)() volatile, Rest> {
static size_t const value = exist::type_of::mem_fun0_v;
typedef type_encoder_impl<C, type_encoder_impl<R, Rest> > next;
};
template<class C, typename R, typename A1, typename Rest>
struct type_encoder_impl<R (C::*)(A1) volatile, Rest> {
static size_t const value = exist::type_of::mem_fun1_v;
typedef type_encoder_impl<C, type_encoder_impl<R, type_encoder_impl<A1, Rest> > > next;
};
template<class C, typename R, typename A1, typename A2, typename Rest>
struct type_encoder_impl<R (C::*)(A1, A2) volatile, Rest> {
static size_t const value = exist::type_of::mem_fun2_v;
typedef type_encoder_impl<C, type_encoder_impl<R, type_encoder_impl<A1, type_encoder_impl<A2, Rest> > > > next;
};
template<class C, typename R, typename Rest>
struct type_encoder_impl<R (C::*)() const volatile, Rest> {
static size_t const value = exist::type_of::mem_fun0_cv;
typedef type_encoder_impl<C, type_encoder_impl<R, Rest> > next;
};
template<class C, typename R, typename A1, typename Rest>
struct type_encoder_impl<R (C::*)(A1) const volatile, Rest> {
static size_t const value = exist::type_of::mem_fun1_cv;
typedef type_encoder_impl<C, type_encoder_impl<R, type_encoder_impl<A1, Rest> > > next;
};
template<class C, typename R, typename A1, typename A2, typename Rest>
struct type_encoder_impl<R (C::*)(A1, A2) const volatile, Rest> {
static size_t const value = exist::type_of::mem_fun2_cv;
typedef type_encoder_impl<C, type_encoder_impl<R, type_encoder_impl<A1, type_encoder_impl<A2, Rest> > > > next;
};


template<EXIST_ENCODED_PARAMS_DECLARE_20>
struct type_decoder_impl;


template<EXIST_ENCODED_PARAMS_DECLARE_19>
struct type_decoder_impl<exist::type_of::c, EXIST_ENCODED_PARAMS_19> {
typedef typename type_decoder_impl<EXIST_ENCODED_PARAMS_19, exist::type_of::end>::rest rest;
typedef typename type_decoder_impl<EXIST_ENCODED_PARAMS_19, exist::type_of::end>::type const type;
};
template<EXIST_ENCODED_PARAMS_DECLARE_19>
struct type_decoder_impl<exist::type_of::v, EXIST_ENCODED_PARAMS_19> {
typedef typename type_decoder_impl<EXIST_ENCODED_PARAMS_19, exist::type_of::end>::rest rest;
typedef typename type_decoder_impl<EXIST_ENCODED_PARAMS_19, exist::type_of::end>::type volatile type;
};
template<EXIST_ENCODED_PARAMS_DECLARE_19>
struct type_decoder_impl<exist::type_of::cv, EXIST_ENCODED_PARAMS_19> {
typedef typename type_decoder_impl<EXIST_ENCODED_PARAMS_19, exist::type_of::end>::rest rest;
typedef typename type_decoder_impl<EXIST_ENCODED_PARAMS_19, exist::type_of::end>::type const volatile type;
};
template<EXIST_ENCODED_PARAMS_DECLARE_19>
struct type_decoder_impl<exist::type_of::ptr, EXIST_ENCODED_PARAMS_19> {
typedef typename type_decoder_impl<EXIST_ENCODED_PARAMS_19, exist::type_of::end>::rest rest;
typedef typename type_decoder_impl<EXIST_ENCODED_PARAMS_19, exist::type_of::end>::type* type;
};
template<EXIST_ENCODED_PARAMS_DECLARE_19>
struct type_decoder_impl<exist::type_of::ref, EXIST_ENCODED_PARAMS_19> {
typedef typename type_decoder_impl<EXIST_ENCODED_PARAMS_19, exist::type_of::end>::rest rest;
typedef typename type_decoder_impl<EXIST_ENCODED_PARAMS_19, exist::type_of::end>::type& type;
};
template<EXIST_ENCODED_PARAMS_DECLARE_19>
struct type_decoder_impl<exist::type_of::fun0, EXIST_ENCODED_PARAMS_19> {
typedef type_decoder_impl<EXIST_ENCODED_PARAMS_19, exist::type_of::end> result;
typedef typename result::rest rest;
typedef typename result::type type();
};
template<EXIST_ENCODED_PARAMS_DECLARE_19>
struct type_decoder_impl<exist::type_of::fun1, EXIST_ENCODED_PARAMS_19> {
typedef type_decoder_impl<EXIST_ENCODED_PARAMS_19, exist::type_of::end> result;
typedef typename result::rest arg1;
typedef typename arg1::rest rest;
typedef typename result::type type(typename arg1::type);
};
template<EXIST_ENCODED_PARAMS_DECLARE_19>
struct type_decoder_impl<exist::type_of::fun2, EXIST_ENCODED_PARAMS_19> {
typedef type_decoder_impl<EXIST_ENCODED_PARAMS_19, exist::type_of::end> result;
typedef typename result::rest arg1;
typedef typename arg1::rest arg2;
typedef typename arg2::rest rest;
typedef typename result::type type(typename arg1::type, typename arg2::type);
};
template<EXIST_ENCODED_PARAMS_DECLARE_19>
struct type_decoder_impl<exist::type_of::mem_ptr, EXIST_ENCODED_PARAMS_19> {
typedef type_decoder_impl<EXIST_ENCODED_PARAMS_19, exist::type_of::end> class_;
typedef typename class_::rest member;
typedef typename member::rest rest;
typedef typename class_::type class_type;
typedef typename member::type (class_type::* type);
};
template<EXIST_ENCODED_PARAMS_DECLARE_19>
struct type_decoder_impl<exist::type_of::mem_fun0, EXIST_ENCODED_PARAMS_19> {
typedef type_decoder_impl<EXIST_ENCODED_PARAMS_19, exist::type_of::end> class_;
typedef typename class_::rest result;
typedef typename result::rest rest;
typedef typename class_::type class_type;
typedef typename result::type (class_type::* type)();
};
template<EXIST_ENCODED_PARAMS_DECLARE_19>
struct type_decoder_impl<exist::type_of::mem_fun1, EXIST_ENCODED_PARAMS_19> {
typedef type_decoder_impl<EXIST_ENCODED_PARAMS_19, exist::type_of::end> class_;
typedef typename class_::rest result;
typedef typename result::rest arg1;
typedef typename arg1::rest rest;
typedef typename class_::type class_type;
typedef typename result::type (class_type::* type)(typename arg1::type);
};
template<EXIST_ENCODED_PARAMS_DECLARE_19>
struct type_decoder_impl<exist::type_of::mem_fun2, EXIST_ENCODED_PARAMS_19> {
typedef type_decoder_impl<EXIST_ENCODED_PARAMS_19, exist::type_of::end> class_;
typedef typename class_::rest result;
typedef typename result::rest arg1;
typedef typename arg1::rest arg2;
typedef typename arg2::rest rest;
typedef typename class_::type class_type;
typedef typename result::type (class_type::* type)(typename arg1::type, typename arg2::type);
};
template<EXIST_ENCODED_PARAMS_DECLARE_19>
struct type_decoder_impl<exist::type_of::mem_fun0_c, EXIST_ENCODED_PARAMS_19> {
typedef type_decoder_impl<EXIST_ENCODED_PARAMS_19, exist::type_of::end> class_;
typedef typename class_::rest result;
typedef typename result::rest rest;
typedef typename class_::type class_type;
typedef typename result::type (class_type::* type)() const;
};
template<EXIST_ENCODED_PARAMS_DECLARE_19>
struct type_decoder_impl<exist::type_of::mem_fun1_c, EXIST_ENCODED_PARAMS_19> {
typedef type_decoder_impl<EXIST_ENCODED_PARAMS_19, exist::type_of::end> class_;
typedef typename class_::rest result;
typedef typename result::rest arg1;
typedef typename arg1::rest rest;
typedef typename class_::type class_type;
typedef typename result::type (class_type::* type)(typename arg1::type) const;
};
template<EXIST_ENCODED_PARAMS_DECLARE_19>
struct type_decoder_impl<exist::type_of::mem_fun2_c, EXIST_ENCODED_PARAMS_19> {
typedef type_decoder_impl<EXIST_ENCODED_PARAMS_19, exist::type_of::end> class_;
typedef typename class_::rest result;
typedef typename result::rest arg1;
typedef typename arg1::rest arg2;
typedef typename arg2::rest rest;
typedef typename class_::type class_type;
typedef typename result::type (class_type::* type)(typename arg1::type, typename arg2::type) const;
};
template<EXIST_ENCODED_PARAMS_DECLARE_19>
struct type_decoder_impl<exist::type_of::mem_fun0_v, EXIST_ENCODED_PARAMS_19> {
typedef type_decoder_impl<EXIST_ENCODED_PARAMS_19, exist::type_of::end> class_;
typedef typename class_::rest result;
typedef typename result::rest rest;
typedef typename class_::type class_type;
typedef typename result::type (class_type::* type)() volatile;
};
template<EXIST_ENCODED_PARAMS_DECLARE_19>
struct type_decoder_impl<exist::type_of::mem_fun1_v, EXIST_ENCODED_PARAMS_19> {
typedef type_decoder_impl<EXIST_ENCODED_PARAMS_19, exist::type_of::end> class_;
typedef typename class_::rest result;
typedef typename result::rest arg1;
typedef typename arg1::rest rest;
typedef typename class_::type class_type;
typedef typename result::type (class_type::* type)(typename arg1::type) volatile;
};
template<EXIST_ENCODED_PARAMS_DECLARE_19>
struct type_decoder_impl<exist::type_of::mem_fun2_v, EXIST_ENCODED_PARAMS_19> {
typedef type_decoder_impl<EXIST_ENCODED_PARAMS_19, exist::type_of::end> class_;
typedef typename class_::rest result;
typedef typename result::rest arg1;
typedef typename arg1::rest arg2;
typedef typename arg2::rest rest;
typedef typename class_::type class_type;
typedef typename result::type (class_type::* type)(typename arg1::type, typename arg2::type) volatile;
};
template<EXIST_ENCODED_PARAMS_DECLARE_19>
struct type_decoder_impl<exist::type_of::mem_fun0_cv, EXIST_ENCODED_PARAMS_19> {
typedef type_decoder_impl<EXIST_ENCODED_PARAMS_19, exist::type_of::end> class_;
typedef typename class_::rest result;
typedef typename result::rest rest;
typedef typename class_::type class_type;
typedef typename result::type (class_type::* type)() const volatile;
};
template<EXIST_ENCODED_PARAMS_DECLARE_19>
struct type_decoder_impl<exist::type_of::mem_fun1_cv, EXIST_ENCODED_PARAMS_19> {
typedef type_decoder_impl<EXIST_ENCODED_PARAMS_19, exist::type_of::end> class_;
typedef typename class_::rest result;
typedef typename result::rest arg1;
typedef typename arg1::rest rest;
typedef typename class_::type class_type;
typedef typename result::type (class_type::* type)(typename arg1::type) const volatile;
};
template<EXIST_ENCODED_PARAMS_DECLARE_19>
struct type_decoder_impl<exist::type_of::mem_fun2_cv, EXIST_ENCODED_PARAMS_19> {
typedef type_decoder_impl<EXIST_ENCODED_PARAMS_19, exist::type_of::end> class_;
typedef typename class_::rest result;
typedef typename result::rest arg1;
typedef typename arg1::rest arg2;
typedef typename arg2::rest rest;
typedef typename class_::type class_type;
typedef typename result::type (class_type::* type)(typename arg1::type, typename arg2::type) const volatile;
};
template<EXIST_ENCODED_PARAMS_DECLARE_19>
struct type_decoder_impl<exist::type_of::end, EXIST_ENCODED_PARAMS_19> {
typedef type_decoder_impl<exist::type_of::end, EXIST_ENCODED_PARAMS_19> rest;
typedef exist::type_of::_ type;
};


template<typename T>
struct type_encoder : public type_encoder_impl<T, exist::type_of::_> {};


template<EXIST_ENCODED_PARAMS_DECLARE_20>
struct type_decoder : public type_decoder_impl<EXIST_ENCODED_PARAMS_20> {};


}} // namespace type_of, unnamed-namespace


#define REGIST_TYPE_IMPL(id, name)\
namespace { namespace type_of {\
template<typename Rest>\
struct type_encoder_impl<name, Rest> {\
static size_t const value = id;\
typedef Rest next;\
};\
template<EXIST_ENCODED_PARAMS_DECLARE_19>\
struct type_decoder_impl<id, EXIST_ENCODED_PARAMS_19> {\
typedef type_decoder_impl<EXIST_ENCODED_PARAMS_19, exist::type_of::end> rest;\
typedef name type;\
};\
}}


#define TYPEOF(expr)\

type_of::type_decoder<\

sizeof(exist::type_of::encoded_type_params< ::type_of::type_encoder, 0>(expr).sizer),\
sizeof(exist::type_of::encoded_type_params< ::type_of::type_encoder, 1>(expr).sizer),\
sizeof(exist::type_of::encoded_type_params< ::type_of::type_encoder, 2>(expr).sizer),\
sizeof(exist::type_of::encoded_type_params< ::type_of::type_encoder, 3>(expr).sizer),\
sizeof(exist::type_of::encoded_type_params< ::type_of::type_encoder, 4>(expr).sizer),\
sizeof(exist::type_of::encoded_type_params< ::type_of::type_encoder, 5>(expr).sizer),\
sizeof(exist::type_of::encoded_type_params< ::type_of::type_encoder, 6>(expr).sizer),\
sizeof(exist::type_of::encoded_type_params< ::type_of::type_encoder, 7>(expr).sizer),\
sizeof(exist::type_of::encoded_type_params< ::type_of::type_encoder, 8>(expr).sizer),\
sizeof(exist::type_of::encoded_type_params< ::type_of::type_encoder, 9>(expr).sizer),\
sizeof(exist::type_of::encoded_type_params< ::type_of::type_encoder, 10>(expr).sizer),\
sizeof(exist::type_of::encoded_type_params< ::type_of::type_encoder, 11>(expr).sizer),\
sizeof(exist::type_of::encoded_type_params< ::type_of::type_encoder, 12>(expr).sizer),\
sizeof(exist::type_of::encoded_type_params< ::type_of::type_encoder, 13>(expr).sizer),\
sizeof(exist::type_of::encoded_type_params< ::type_of::type_encoder, 14>(expr).sizer),\
sizeof(exist::type_of::encoded_type_params< ::type_of::type_encoder, 15>(expr).sizer),\
sizeof(exist::type_of::encoded_type_params< ::type_of::type_encoder, 16>(expr).sizer),\
sizeof(exist::type_of::encoded_type_params< ::type_of::type_encoder, 17>(expr).sizer),\
sizeof(exist::type_of::encoded_type_params< ::type_of::type_encoder, 18>(expr).sizer),\
sizeof(exist::type_of::encoded_type_params< ::type_of::type_encoder, 19>(expr).sizer)>::type


#define AUTO(name, expr)\
TYPEOF(expr) name = expr


REGIST_TYPE_IMPL(100, void)
REGIST_TYPE_IMPL(101, int)


#endif // EXIST_TYPEOF_HPP_INCLUDED_