Build system improvements
[ustl.git] / traits.h
blobaa15ab5af95d444a089701cdc0b865ea3e210e22
1 // This file is part of the ustl library, an STL implementation.
2 //
3 // Copyright (c) 2007 by Mike Sharov <msharov@users.sourceforge.net>
4 //
5 // This implementation is adapted from the Loki library, distributed under
6 // the MIT license with Copyright (c) 2001 by Andrei Alexandrescu.
7 //
8 // traits.h
9 //
10 // Implements type trait templates for metaprogramming.
13 #ifndef TRAITS_H_4AA3DDE15E16C947392711ED08FB1FF6
14 #define TRAITS_H_4AA3DDE15E16C947392711ED08FB1FF6
16 #include "typelist.h"
18 namespace ustl {
19 namespace tm {
20 namespace {
22 //----------------------------------------------------------------------
23 // Type classes and type modifiers
24 //----------------------------------------------------------------------
26 typedef tl::Seq<unsigned char, unsigned short, unsigned, unsigned long>::Type
27 StdUnsignedInts;
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
46 template <typename T>
47 struct IsFunctionPointerRaw { enum { result = false}; };
48 template <typename T>
49 struct IsMemberFunctionPointerRaw { enum { result = false}; };
51 #define TM_FPR_MAXN 9
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
56 template <typename T>
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
68 template <typename T>
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, ;);
127 #undef TM_FPR_SPEC
128 #undef TM_FPR_SPEC_ELLIPSIS
129 #undef TM_MFPR_SPEC
130 #undef TM_MFPR_SPEC_ELLIPSIS
131 #undef TM_CMFPR_SPEC
132 #undef TM_CMFPR_SPEC_ELLIPSIS
133 #undef TM_FPR_TYPENAME
134 #undef TM_FPR_TYPE
135 #undef TM_FPR_MAXN
137 } // namespace
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
172 /// T, if any
173 /// - ConstParameterType: returns the optimal type to be used as a parameter
174 /// for functions that take 'const T's
176 template <typename T>
177 class TypeTraits {
178 private:
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 }; };
197 #undef TMTT2
198 #undef TMTT1
199 public:
200 typedef typename UnConst<T>::Result
201 NonConstType;
202 typedef typename UnVolatile<T>::Result
203 NonVolatileType;
204 typedef typename UnVolatile<typename UnConst<T>::Result>::Result
205 UnqualifiedType;
206 typedef typename PointerTraits<UnqualifiedType>::PointeeType
207 PointeeType;
208 typedef typename ReferenceTraits<T>::ReferredType
209 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 ||
224 isFunctionPointer };
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
250 ParameterType;
253 } // namespace tm
254 } // namespace ustl
256 #endif