1 // This file is part of the ustl library, an STL implementation.
3 // Copyright (c) 2007 by Mike Sharov <msharov@users.sourceforge.net>
5 // This implementation is adapted from the Loki library, distributed under
6 // the MIT license with Copyright (c) 2001 by Andrei Alexandrescu.
10 // Implements type trait templates for metaprogramming.
13 #ifndef TRAITS_H_4AA3DDE15E16C947392711ED08FB1FF6
14 #define TRAITS_H_4AA3DDE15E16C947392711ED08FB1FF6
22 //----------------------------------------------------------------------
23 // Type classes and type modifiers
24 //----------------------------------------------------------------------
26 typedef tl::Seq
<unsigned char, unsigned short, unsigned, unsigned long>::Type
28 typedef tl::Seq
<signed char, short, int, long>::Type StdSignedInts
;
29 typedef tl::Seq
<bool, char, wchar_t>::Type StdOtherInts
;
30 typedef tl::Seq
<float, double>::Type StdFloats
;
32 template <typename U
> struct AddPointer
{ typedef U
* Result
; };
33 template <typename U
> struct AddPointer
<U
&> { typedef U
* Result
; };
34 template <typename U
> struct AddReference
{ typedef U
& Result
; };
35 template <typename U
> struct AddReference
<U
&> { typedef U
& Result
; };
36 template <> struct AddReference
<void> { typedef NullType Result
; };
37 template <typename U
> struct AddParameterType
{ typedef const U
& Result
; };
38 template <typename U
> struct AddParameterType
<U
&> { typedef U
& Result
; };
39 template <> struct AddParameterType
<void> { typedef NullType Result
; };
41 //----------------------------------------------------------------------
42 // Function pointer testers
43 //----------------------------------------------------------------------
44 // Macros expand to numerous parameters
47 struct IsFunctionPointerRaw
{ enum { result
= false}; };
49 struct IsMemberFunctionPointerRaw
{ enum { result
= false}; };
52 #define TM_FPR_TYPE(n) PASTE(T,n)
53 #define TM_FPR_TYPENAME(n) typename TM_FPR_TYPE(n)
55 // First specialize for regular functions
57 struct IsFunctionPointerRaw
<T(*)(void)>
58 {enum {result
= true};};
60 #define TM_FPR_SPEC(n) \
61 template <typename T, COMMA_LIST(n, TM_FPR_TYPENAME)> \
62 struct IsFunctionPointerRaw<T(*)(COMMA_LIST(n, TM_FPR_TYPE))> \
63 { enum { result = true }; }
65 LIST (TM_FPR_MAXN
, TM_FPR_SPEC
, ;);
67 // Then for those with an ellipsis argument
69 struct IsFunctionPointerRaw
<T(*)(...)>
70 {enum {result
= true};};
72 #define TM_FPR_SPEC_ELLIPSIS(n) \
73 template <typename T, COMMA_LIST(n, TM_FPR_TYPENAME)> \
74 struct IsFunctionPointerRaw<T(*)(COMMA_LIST(n, TM_FPR_TYPE), ...)> \
75 { enum { result = true }; }
77 LIST (TM_FPR_MAXN
, TM_FPR_SPEC_ELLIPSIS
, ;);
79 // Then for member function pointers
80 template <typename T
, typename S
>
81 struct IsMemberFunctionPointerRaw
<T (S::*)(void)>
82 { enum { result
= true }; };
84 #define TM_MFPR_SPEC(n) \
85 template <typename T, typename S, COMMA_LIST(n, TM_FPR_TYPENAME)> \
86 struct IsMemberFunctionPointerRaw<T (S::*)(COMMA_LIST(n, TM_FPR_TYPE))> \
87 { enum { result = true };};
89 LIST (TM_FPR_MAXN
, TM_MFPR_SPEC
, ;);
91 // Then for member function pointers with an ellipsis argument
92 template <typename T
, typename S
>
93 struct IsMemberFunctionPointerRaw
<T (S::*)(...)>
94 { enum { result
= true }; };
96 #define TM_MFPR_SPEC_ELLIPSIS(n) \
97 template <typename T, typename S, COMMA_LIST(n, TM_FPR_TYPENAME)> \
98 struct IsMemberFunctionPointerRaw<T (S::*)(COMMA_LIST(n, TM_FPR_TYPE), ...)> \
99 { enum { result = true }; };
101 LIST (TM_FPR_MAXN
, TM_MFPR_SPEC_ELLIPSIS
, ;);
103 // Then for const member function pointers (getting tired yet?)
104 template <typename T
, typename S
>
105 struct IsMemberFunctionPointerRaw
<T (S::*)(void) const>
106 { enum { result
= true }; };
108 #define TM_CMFPR_SPEC(n) \
109 template <typename T, typename S, COMMA_LIST(n, TM_FPR_TYPENAME)> \
110 struct IsMemberFunctionPointerRaw<T (S::*)(COMMA_LIST(n, TM_FPR_TYPE)) const> \
111 { enum { result = true };};
113 LIST (TM_FPR_MAXN
, TM_CMFPR_SPEC
, ;);
115 // Finally for const member function pointers with an ellipsis argument (whew!)
116 template <typename T
, typename S
>
117 struct IsMemberFunctionPointerRaw
<T (S::*)(...) const>
118 { enum { result
= true }; };
120 #define TM_CMFPR_SPEC_ELLIPSIS(n) \
121 template <typename T, typename S, COMMA_LIST(n, TM_FPR_TYPENAME)> \
122 struct IsMemberFunctionPointerRaw<T (S::*)(COMMA_LIST(n, TM_FPR_TYPE), ...) const> \
123 { enum { result = true }; };
125 LIST (TM_FPR_MAXN
, TM_CMFPR_SPEC_ELLIPSIS
, ;);
128 #undef TM_FPR_SPEC_ELLIPSIS
130 #undef TM_MFPR_SPEC_ELLIPSIS
132 #undef TM_CMFPR_SPEC_ELLIPSIS
133 #undef TM_FPR_TYPENAME
139 //----------------------------------------------------------------------
140 // Type traits template
141 //----------------------------------------------------------------------
143 /// Figures out at compile time various properties of any given type
144 /// Invocations (T is a type, TypeTraits<T>::Propertie):
146 /// - isPointer : returns true if T is a pointer type
147 /// - PointeeType : returns the type to which T points if T is a pointer
148 /// type, NullType otherwise
149 /// - isReference : returns true if T is a reference type
150 /// - ReferredType : returns the type to which T refers if T is a reference
151 /// type, NullType otherwise
152 /// - isMemberPointer : returns true if T is a pointer to member type
153 /// - isStdUnsignedInt: returns true if T is a standard unsigned integral type
154 /// - isStdSignedInt : returns true if T is a standard signed integral type
155 /// - isStdIntegral : returns true if T is a standard integral type
156 /// - isStdFloat : returns true if T is a standard floating-point type
157 /// - isStdArith : returns true if T is a standard arithmetic type
158 /// - isStdFundamental: returns true if T is a standard fundamental type
159 /// - isUnsignedInt : returns true if T is a unsigned integral type
160 /// - isSignedInt : returns true if T is a signed integral type
161 /// - isIntegral : returns true if T is a integral type
162 /// - isFloat : returns true if T is a floating-point type
163 /// - isArith : returns true if T is a arithmetic type
164 /// - isFundamental : returns true if T is a fundamental type
165 /// - ParameterType : returns the optimal type to be used as a parameter for
166 /// functions that take Ts
167 /// - isConst : returns true if T is a const-qualified type
168 /// - NonConstType : Type with removed 'const' qualifier from T, if any
169 /// - isVolatile : returns true if T is a volatile-qualified type
170 /// - NonVolatileType : Type with removed 'volatile' qualifier from T, if any
171 /// - UnqualifiedType : Type with removed 'const' and 'volatile' qualifiers from
173 /// - ConstParameterType: returns the optimal type to be used as a parameter
174 /// for functions that take 'const T's
176 template <typename T
>
179 #define TMTT1 template <typename U> struct
180 #define TMTT2 template <typename U, typename V> struct
181 TMTT1 ReferenceTraits
{ enum { result
= false }; typedef U ReferredType
; };
182 TMTT1 ReferenceTraits
<U
&> { enum { result
= true }; typedef U ReferredType
; };
183 TMTT1 PointerTraits
{ enum { result
= false }; typedef NullType PointeeType
; };
184 TMTT1 PointerTraits
<U
*> { enum { result
= true }; typedef U PointeeType
; };
185 TMTT1 PointerTraits
<U
*&> { enum { result
= true }; typedef U PointeeType
; };
186 TMTT1 PToMTraits
{ enum { result
= false }; };
187 TMTT2 PToMTraits
<U
V::*> { enum { result
= true }; };
188 TMTT2 PToMTraits
<U
V::*&> { enum { result
= true }; };
189 TMTT1 FunctionPointerTraits
{ enum { result
= IsFunctionPointerRaw
<U
>::result
}; };
190 TMTT1 PToMFunctionTraits
{ enum { result
= IsMemberFunctionPointerRaw
<U
>::result
}; };
191 TMTT1 UnConst
{ typedef U Result
; enum { isConst
= false }; };
192 TMTT1 UnConst
<const U
> { typedef U Result
; enum { isConst
= true }; };
193 TMTT1 UnConst
<const U
&> { typedef U
& Result
; enum { isConst
= true }; };
194 TMTT1 UnVolatile
{ typedef U Result
; enum { isVolatile
= false }; };
195 TMTT1 UnVolatile
<volatile U
>{ typedef U Result
; enum { isVolatile
= true }; };
196 TMTT1 UnVolatile
<volatile U
&> {typedef U
& Result
;enum { isVolatile
= true }; };
200 typedef typename UnConst
<T
>::Result
202 typedef typename UnVolatile
<T
>::Result
204 typedef typename UnVolatile
<typename UnConst
<T
>::Result
>::Result
206 typedef typename PointerTraits
<UnqualifiedType
>::PointeeType
208 typedef typename ReferenceTraits
<T
>::ReferredType
211 enum { isConst
= UnConst
<T
>::isConst
};
212 enum { isVolatile
= UnVolatile
<T
>::isVolatile
};
213 enum { isReference
= ReferenceTraits
<UnqualifiedType
>::result
};
214 enum { isFunction
= FunctionPointerTraits
<typename AddPointer
<T
>::Result
>::result
};
215 enum { isFunctionPointer
= FunctionPointerTraits
<
216 typename ReferenceTraits
<UnqualifiedType
>::ReferredType
>::result
};
217 enum { isMemberFunctionPointer
= PToMFunctionTraits
<
218 typename ReferenceTraits
<UnqualifiedType
>::ReferredType
>::result
};
219 enum { isMemberPointer
= PToMTraits
<
220 typename ReferenceTraits
<UnqualifiedType
>::ReferredType
>::result
||
221 isMemberFunctionPointer
};
222 enum { isPointer
= PointerTraits
<
223 typename ReferenceTraits
<UnqualifiedType
>::ReferredType
>::result
||
225 enum { isStdUnsignedInt
= tl::IndexOf
<StdUnsignedInts
, UnqualifiedType
>::value
>= 0 ||
226 tl::IndexOf
<StdUnsignedInts
,
227 typename ReferenceTraits
<UnqualifiedType
>::ReferredType
>::value
>= 0};
228 enum { isStdSignedInt
= tl::IndexOf
<StdSignedInts
, UnqualifiedType
>::value
>= 0 ||
229 tl::IndexOf
<StdSignedInts
,
230 typename ReferenceTraits
<UnqualifiedType
>::ReferredType
>::value
>= 0};
231 enum { isStdIntegral
= isStdUnsignedInt
|| isStdSignedInt
||
232 tl::IndexOf
<StdOtherInts
, UnqualifiedType
>::value
>= 0 ||
233 tl::IndexOf
<StdOtherInts
,
234 typename ReferenceTraits
<UnqualifiedType
>::ReferredType
>::value
>= 0};
235 enum { isStdFloat
= tl::IndexOf
<StdFloats
, UnqualifiedType
>::value
>= 0 ||
236 tl::IndexOf
<StdFloats
,
237 typename ReferenceTraits
<UnqualifiedType
>::ReferredType
>::value
>= 0};
238 enum { isStdArith
= isStdIntegral
|| isStdFloat
};
239 enum { isStdFundamental
= isStdArith
|| isStdFloat
|| Conversion
<T
, void>::sameType
};
241 enum { isUnsignedInt
= isStdUnsignedInt
};
242 enum { isSignedInt
= isStdSignedInt
};
243 enum { isIntegral
= isStdIntegral
|| isUnsignedInt
|| isSignedInt
};
244 enum { isFloat
= isStdFloat
};
245 enum { isArith
= isIntegral
|| isFloat
};
246 enum { isFundamental
= isStdFundamental
|| isArith
};
248 typedef typename Select
<isStdArith
|| isPointer
|| isMemberPointer
, T
,
249 typename AddParameterType
<T
>::Result
>::Result