PageRenderTime 22ms CodeModel.GetById 17ms app.highlight 3ms RepoModel.GetById 1ms app.codeStats 0ms

/src/rt/msvc/typeof.h

http://github.com/jruderman/rust
C Header | 97 lines | 46 code | 17 blank | 34 comment | 1 complexity | ceb4922594a9141d07fe70cf9e585056 MD5 | raw file
 1// This piece of magic brought to you by:
 2//     http://www.nedproductions.biz/blog/
 3//     implementing-typeof-in-microsofts-c-compiler 
 4
 5#ifndef MSVC_TYPEOF_H
 6#define MSVC_TYPEOF_H
 7
 8#if defined(_MSC_VER) && _MSC_VER>=1400
 9namespace msvc_typeof_impl {
10	/* This is a fusion of Igor Chesnokov's method (http://rsdn.ru/forum/src/1094305.aspx)
11	and Steven Watanabe's method (http://lists.boost.org/Archives/boost/2006/12/115006.php)
12
13	How it works:
14	C++ allows template type inference for templated function parameters but nothing else.
15	What we do is to pass the expression sent to typeof() into the templated function vartypeID()
16	as its parameter, thus extracting its type. The big problem traditionally now is how to get
17	that type out of the vartypeID() instance, and here's how we do it:
18		1. unique_type_id() returns a monotonically increasing integer for every unique type
19		   passed to it during this compilation unit. It also specialises an instance of
20		   msvc_extract_type<unique_type_id, type>::id2type_impl<true>.
21		2. vartypeID() returns a sized<unique_type_id> for the type where
22		   sizeof(sized<unique_type_id>)==unique_type_id. We vector through sized as a means
23		   of returning the unique_type_id at compile time rather than runtime.
24		3. msvc_extract_type<unique_type_id> then extracts the type by using a bug in MSVC to
25		   reselect the specialised child type (id2type_impl<true>) from within the specialisation
26		   of itself originally performed by the above instance of unique_type_id. This bug works
27		   because when MSVC calculated the signature of the specialised
28		   msvc_extract_type<unique_type_id, type>::id2type_impl<true>, it does not include the
29		   value of type in the signature of id2type_impl<true>. Therefore when we reselect
30		   msvc_extract_type<unique_type_id>::id2type_impl<true> it erroneously returns the one
31		   already in its list of instantiated types rather than correctly generating a newly
32		   specialised msvc_extract_type<unique_type_id, msvc_extract_type_default_param>::id2type_impl<true>
33
34	This bug allows the impossible and gives us a working typeof() in MSVC. Hopefully Microsoft
35	won't fix this bug until they implement a native typeof.
36	*/
37
38	struct msvc_extract_type_default_param {};
39	template<int ID, typename T = msvc_extract_type_default_param> struct msvc_extract_type;
40
41	template<int ID> struct msvc_extract_type<ID, msvc_extract_type_default_param>
42	{
43		template<bool> struct id2type_impl; 
44
45		typedef id2type_impl<true> id2type; 
46	};
47
48	template<int ID, typename T> struct msvc_extract_type : msvc_extract_type<ID, msvc_extract_type_default_param> 
49	{ 
50		template<> struct id2type_impl<true> //VC8.0 specific bugfeature 
51		{ 
52			typedef T type; 
53		}; 
54		template<bool> struct id2type_impl; 
55
56		typedef id2type_impl<true> id2type; 
57	}; 
58
59
60	template<int N> class CCounter;
61
62	// TUnused is required to force compiler to recompile CCountOf class
63	template<typename TUnused, int NTested = 0> struct CCountOf
64	{
65		enum
66		{
67			__if_exists(CCounter<NTested>) { count = CCountOf<TUnused, NTested + 1>::count }
68			__if_not_exists(CCounter<NTested>) { count = NTested }
69		};
70	};
71
72	template<class TTypeReg, class TUnused, int NValue> struct CProvideCounterValue { enum { value = NValue }; };
73
74	// type_id
75	#define unique_type_id(type) \
76		(CProvideCounterValue< \
77			/*register TYPE--ID*/ typename msvc_extract_type<CCountOf<type >::count, type>::id2type, \
78			/*increment compile-time Counter*/ CCounter<CCountOf<type >::count>, \
79			/*pass value of Counter*/CCountOf<type >::count \
80		 >::value)
81
82	// Lets type_id() be > than 0
83	class __Increment_type_id { enum { value = unique_type_id(__Increment_type_id) }; };
84
85	// vartypeID() returns a type with sizeof(type_id)
86	template<int NSize>	class sized { char m_pad[NSize]; };
87	template<typename T> typename sized<unique_type_id(T)> vartypeID(T&);
88	template<typename T> typename sized<unique_type_id(const T)> vartypeID(const T&);
89	template<typename T> typename sized<unique_type_id(volatile  T)> vartypeID(volatile T&);
90	template<typename T> typename sized<unique_type_id(const volatile T)> vartypeID(const volatile T&);
91}
92
93#define typeof(expression) msvc_typeof_impl::msvc_extract_type<sizeof(msvc_typeof_impl::vartypeID(expression))>::id2type::type
94#endif
95
96#endif
97