1 ////////////////////////////////////////////////////////////////////////////////
3 // Copyright (c) 2001 by Andrei Alexandrescu
4 // This code accompanies the book:
5 // Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design
6 // Patterns Applied". Copyright (c) 2001. Addison-Wesley.
7 // Permission to use, copy, modify, distribute and sell this software for any
8 // purpose is hereby granted without fee, provided that the above copyright
9 // notice appear in all copies and that both that copyright notice and this
10 // permission notice appear in supporting documentation.
11 // The author or Addison-Welsey Longman make no representations about the
12 // suitability of this software for any purpose. It is provided "as is"
13 // without express or implied warranty.
14 ////////////////////////////////////////////////////////////////////////////////
15 #ifndef LOKI_TYPEMANIP_INC_
16 #define LOKI_TYPEMANIP_INC_
18 // $Id: TypeManip.h,v 1.1 2007/12/10 11:58:52 ben Exp $
23 ////////////////////////////////////////////////////////////////////////////////
24 // class template Int2Type
25 // Converts each integral constant into a unique type
26 // Invocation: Int2Type<v> where v is a compile-time constant integral
27 // Defines 'value', an enum that evaluates to v
28 ////////////////////////////////////////////////////////////////////////////////
36 ////////////////////////////////////////////////////////////////////////////////
37 // class template Type2Type
38 // Converts each type into a unique, insipid type
39 // Invocation Type2Type<T> where T is a type
40 // Defines the type OriginalType which maps back to T
41 ////////////////////////////////////////////////////////////////////////////////
46 typedef T OriginalType
;
49 ////////////////////////////////////////////////////////////////////////////////
50 // class template Select
51 // Selects one of two types based upon a boolean constant
52 // Invocation: Select<flag, T, U>::Result
54 // flag is a compile-time boolean constant
56 // Result evaluates to T if flag is true, and to U otherwise.
57 ////////////////////////////////////////////////////////////////////////////////
59 template <bool flag
, typename T
, typename U
>
64 template <typename T
, typename U
>
65 struct Select
<false, T
, U
>
70 ////////////////////////////////////////////////////////////////////////////////
71 // class template IsSameType
72 // Return true iff two given types are the same
73 // Invocation: SameType<T, U>::value
76 // Result evaluates to true iff U == T (types equal)
77 ////////////////////////////////////////////////////////////////////////////////
79 template <typename T
, typename U
>
82 enum { value
= false };
86 struct IsSameType
<T
,T
>
88 enum { value
= true };
91 ////////////////////////////////////////////////////////////////////////////////
92 // Helper types Small and Big - guarantee that sizeof(Small) < sizeof(Big)
93 ////////////////////////////////////////////////////////////////////////////////
97 template <class T
, class U
>
98 struct ConversionHelper
101 struct Big
{ char dummy
[2]; };
102 static Big
Test(...);
103 static Small
Test(U
);
108 ////////////////////////////////////////////////////////////////////////////////
109 // class template Conversion
110 // Figures out the conversion relationships between two types
111 // Invocations (T and U are types):
112 // a) Conversion<T, U>::exists
113 // returns (at compile time) true if there is an implicit conversion from T
114 // to U (example: Derived to Base)
115 // b) Conversion<T, U>::exists2Way
116 // returns (at compile time) true if there are both conversions from T
117 // to U and from U to T (example: int to char and back)
118 // c) Conversion<T, U>::sameType
119 // returns (at compile time) true if T and U represent the same type
121 // Caveat: might not work if T and U are in a private inheritance hierarchy.
122 ////////////////////////////////////////////////////////////////////////////////
124 template <class T
, class U
>
127 typedef Private::ConversionHelper
<T
, U
> H
;
129 enum { exists
= sizeof(typename
H::Small
) == sizeof((H::Test(H::MakeT()))) };
131 enum { exists
= false };
133 enum { exists2Way
= exists
&& Conversion
<U
, T
>::exists
};
134 enum { sameType
= false };
138 struct Conversion
<T
, T
>
140 enum { exists
= 1, exists2Way
= 1, sameType
= 1 };
144 struct Conversion
<void, T
>
146 enum { exists
= 0, exists2Way
= 0, sameType
= 0 };
150 struct Conversion
<T
, void>
152 enum { exists
= 0, exists2Way
= 0, sameType
= 0 };
156 struct Conversion
<void, void>
159 enum { exists
= 1, exists2Way
= 1, sameType
= 1 };
162 ////////////////////////////////////////////////////////////////////////////////
163 // class template SuperSubclass
164 // Invocation: SuperSubclass<B, D>::value where B and D are types.
165 // Returns true if B is a public base of D, or if B and D are aliases of the
168 // Caveat: might not work if T and U are in a private inheritance hierarchy.
169 ////////////////////////////////////////////////////////////////////////////////
171 template <class T
, class U
>
174 enum { value
= (::Loki::Conversion
<const volatile U
*, const volatile T
*>::exists
&&
175 !::Loki::Conversion
<const volatile T
*, const volatile void*>::sameType
) };
177 // Dummy enum to make sure that both classes are fully defined.
178 enum{ dontUseWithIncompleteTypes
= ( sizeof (T
) == sizeof (U
) ) };
182 struct SuperSubclass
<void, void>
184 enum { value
= false };
188 struct SuperSubclass
<void, U
>
190 enum { value
= (::Loki::Conversion
<const volatile U
*, const volatile void*>::exists
&&
191 !::Loki::Conversion
<const volatile void*, const volatile void*>::sameType
) };
193 // Dummy enum to make sure that both classes are fully defined.
194 enum{ dontUseWithIncompleteTypes
= ( 0 == sizeof (U
) ) };
198 struct SuperSubclass
<T
, void>
200 enum { value
= (::Loki::Conversion
<const volatile void*, const volatile T
*>::exists
&&
201 !::Loki::Conversion
<const volatile T
*, const volatile void*>::sameType
) };
203 // Dummy enum to make sure that both classes are fully defined.
204 enum{ dontUseWithIncompleteTypes
= ( sizeof (T
) == 0 ) };
207 ////////////////////////////////////////////////////////////////////////////////
208 // class template SuperSubclassStrict
209 // Invocation: SuperSubclassStrict<B, D>::value where B and D are types.
210 // Returns true if B is a public base of D.
212 // Caveat: might not work if T and U are in a private inheritance hierarchy.
213 ////////////////////////////////////////////////////////////////////////////////
215 template<class T
,class U
>
216 struct SuperSubclassStrict
218 enum { value
= (::Loki::Conversion
<const volatile U
*, const volatile T
*>::exists
&&
219 !::Loki::Conversion
<const volatile T
*, const volatile void*>::sameType
&&
220 !::Loki::Conversion
<const volatile T
*, const volatile U
*>::sameType
) };
222 // Dummy enum to make sure that both classes are fully defined.
223 enum{ dontUseWithIncompleteTypes
= ( sizeof (T
) == sizeof (U
) ) };
227 struct SuperSubclassStrict
<void, void>
229 enum { value
= false };
233 struct SuperSubclassStrict
<void, U
>
235 enum { value
= (::Loki::Conversion
<const volatile U
*, const volatile void*>::exists
&&
236 !::Loki::Conversion
<const volatile void*, const volatile void*>::sameType
&&
237 !::Loki::Conversion
<const volatile void*, const volatile U
*>::sameType
) };
239 // Dummy enum to make sure that both classes are fully defined.
240 enum{ dontUseWithIncompleteTypes
= ( 0 == sizeof (U
) ) };
244 struct SuperSubclassStrict
<T
, void>
246 enum { value
= (::Loki::Conversion
<const volatile void*, const volatile T
*>::exists
&&
247 !::Loki::Conversion
<const volatile T
*, const volatile void*>::sameType
&&
248 !::Loki::Conversion
<const volatile T
*, const volatile void*>::sameType
) };
250 // Dummy enum to make sure that both classes are fully defined.
251 enum{ dontUseWithIncompleteTypes
= ( sizeof (T
) == 0 ) };
257 ////////////////////////////////////////////////////////////////////////////////
258 // macro SUPERSUBCLASS
259 // Invocation: SUPERSUBCLASS(B, D) where B and D are types.
260 // Returns true if B is a public base of D, or if B and D are aliases of the
263 // Caveat: might not work if T and U are in a private inheritance hierarchy.
264 // Deprecated: Use SuperSubclass class template instead.
265 ////////////////////////////////////////////////////////////////////////////////
267 #define LOKI_SUPERSUBCLASS(T, U) \
268 ::Loki::SuperSubclass<T,U>::value
270 ////////////////////////////////////////////////////////////////////////////////
271 // macro SUPERSUBCLASS_STRICT
272 // Invocation: SUPERSUBCLASS(B, D) where B and D are types.
273 // Returns true if B is a public base of D.
275 // Caveat: might not work if T and U are in a private inheritance hierarchy.
276 // Deprecated: Use SuperSubclassStrict class template instead.
277 ////////////////////////////////////////////////////////////////////////////////
279 #define LOKI_SUPERSUBCLASS_STRICT(T, U) \
280 ::Loki::SuperSubclassStrict<T,U>::value
283 #endif // end file guardian