TypeManip.h

00001 
00002 // The Loki Library
00003 // Copyright (c) 2001 by Andrei Alexandrescu
00004 // This code accompanies the book:
00005 // Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design 
00006 //     Patterns Applied". Copyright (c) 2001. Addison-Wesley.
00007 // Permission to use, copy, modify, distribute and sell this software for any 
00008 //     purpose is hereby granted without fee, provided that the above copyright 
00009 //     notice appear in all copies and that both that copyright notice and this 
00010 //     permission notice appear in supporting documentation.
00011 // The author or Addison-Welsey Longman make no representations about the 
00012 //     suitability of this software for any purpose. It is provided "as is" 
00013 //     without express or implied warranty.
00015 #ifndef LOKI_TYPEMANIP_INC_
00016 #define LOKI_TYPEMANIP_INC_
00017 
00018 // $Id: TypeManip.h 749 2006-10-17 19:49:26Z syntheticpp $
00019 
00020 
00021 namespace Loki
00022 {
00024 // class template Int2Type
00025 // Converts each integral constant into a unique type
00026 // Invocation: Int2Type<v> where v is a compile-time constant integral
00027 // Defines 'value', an enum that evaluates to v
00029 
00030     template <int v>
00031     struct Int2Type
00032     {
00033         enum { value = v };
00034     };
00035     
00037 // class template Type2Type
00038 // Converts each type into a unique, insipid type
00039 // Invocation Type2Type<T> where T is a type
00040 // Defines the type OriginalType which maps back to T
00042 
00043     template <typename T>
00044     struct Type2Type
00045     {
00046         typedef T OriginalType;
00047     };
00048     
00050 // class template Select
00051 // Selects one of two types based upon a boolean constant
00052 // Invocation: Select<flag, T, U>::Result
00053 // where:
00054 // flag is a compile-time boolean constant
00055 // T and U are types
00056 // Result evaluates to T if flag is true, and to U otherwise.
00058 
00059     template <bool flag, typename T, typename U>
00060     struct Select
00061     {
00062         typedef T Result;
00063     };
00064     template <typename T, typename U>
00065     struct Select<false, T, U>
00066     {
00067         typedef U Result;
00068     };
00069     
00071 // class template IsSameType
00072 // Return true iff two given types are the same
00073 // Invocation: SameType<T, U>::value
00074 // where:
00075 // T and U are types
00076 // Result evaluates to true iff U == T (types equal)
00078 
00079     template <typename T, typename U>
00080     struct IsSameType
00081     {
00082         enum { value = false };
00083     };
00084     
00085     template <typename T>
00086     struct IsSameType<T,T>
00087     {
00088         enum { value = true };
00089     };
00090 
00092 // Helper types Small and Big - guarantee that sizeof(Small) < sizeof(Big)
00094 
00095     namespace Private
00096     {
00097         template <class T, class U>
00098         struct ConversionHelper
00099         {
00100             typedef char Small;
00101             struct Big { char dummy[2]; };
00102             static Big   Test(...);
00103             static Small Test(U);
00104             static T MakeT();
00105         };
00106     }
00107 
00109 // class template Conversion
00110 // Figures out the conversion relationships between two types
00111 // Invocations (T and U are types):
00112 // a) Conversion<T, U>::exists
00113 // returns (at compile time) true if there is an implicit conversion from T
00114 // to U (example: Derived to Base)
00115 // b) Conversion<T, U>::exists2Way
00116 // returns (at compile time) true if there are both conversions from T
00117 // to U and from U to T (example: int to char and back)
00118 // c) Conversion<T, U>::sameType
00119 // returns (at compile time) true if T and U represent the same type
00120 //
00121 // Caveat: might not work if T and U are in a private inheritance hierarchy.
00123 
00124     template <class T, class U>
00125     struct Conversion
00126     {
00127         typedef Private::ConversionHelper<T, U> H;
00128 #ifndef __MWERKS__
00129         enum { exists = sizeof(typename H::Small) == sizeof((H::Test(H::MakeT()))) };
00130 #else
00131         enum { exists = false };
00132 #endif
00133         enum { exists2Way = exists && Conversion<U, T>::exists };
00134         enum { sameType = false };
00135     };
00136     
00137     template <class T>
00138     struct Conversion<T, T>    
00139     {
00140         enum { exists = 1, exists2Way = 1, sameType = 1 };
00141     };
00142     
00143     template <class T>
00144     struct Conversion<void, T>    
00145     {
00146         enum { exists = 0, exists2Way = 0, sameType = 0 };
00147     };
00148     
00149     template <class T>
00150     struct Conversion<T, void>    
00151     {
00152         enum { exists = 0, exists2Way = 0, sameType = 0 };
00153     };
00154     
00155     template <>
00156     struct Conversion<void, void>    
00157     {
00158     public:
00159         enum { exists = 1, exists2Way = 1, sameType = 1 };
00160     };
00161 
00163 // class template SuperSubclass
00164 // Invocation: SuperSubclass<B, D>::value where B and D are types. 
00165 // Returns true if B is a public base of D, or if B and D are aliases of the 
00166 // same type.
00167 //
00168 // Caveat: might not work if T and U are in a private inheritance hierarchy.
00170 
00171 template <class T, class U>
00172 struct SuperSubclass
00173 {
00174     enum { value = (::Loki::Conversion<const volatile U*, const volatile T*>::exists &&
00175                   !::Loki::Conversion<const volatile T*, const volatile void*>::sameType) };
00176       
00177     // Dummy enum to make sure that both classes are fully defined.
00178     enum{ dontUseWithIncompleteTypes = ( sizeof (T) == sizeof (U) ) };
00179 };
00180 
00181 template <>
00182 struct SuperSubclass<void, void> 
00183 {
00184     enum { value = false };
00185 };
00186 
00187 template <class U>
00188 struct SuperSubclass<void, U> 
00189 {
00190     enum { value = (::Loki::Conversion<const volatile U*, const volatile void*>::exists &&
00191                   !::Loki::Conversion<const volatile void*, const volatile void*>::sameType) };
00192       
00193     // Dummy enum to make sure that both classes are fully defined.
00194     enum{ dontUseWithIncompleteTypes = ( 0 == sizeof (U) ) };
00195 };
00196 
00197 template <class T>
00198 struct SuperSubclass<T, void> 
00199 {
00200     enum { value = (::Loki::Conversion<const volatile void*, const volatile T*>::exists &&
00201                   !::Loki::Conversion<const volatile T*, const volatile void*>::sameType) };
00202       
00203     // Dummy enum to make sure that both classes are fully defined.
00204     enum{ dontUseWithIncompleteTypes = ( sizeof (T) == 0 ) };
00205 };
00206 
00208 // class template SuperSubclassStrict
00209 // Invocation: SuperSubclassStrict<B, D>::value where B and D are types. 
00210 // Returns true if B is a public base of D.
00211 //
00212 // Caveat: might not work if T and U are in a private inheritance hierarchy.
00214 
00215 template<class T,class U>
00216 struct SuperSubclassStrict
00217 {
00218     enum { value = (::Loki::Conversion<const volatile U*, const volatile T*>::exists &&
00219                  !::Loki::Conversion<const volatile T*, const volatile void*>::sameType &&
00220                  !::Loki::Conversion<const volatile T*, const volatile U*>::sameType) };
00221     
00222     // Dummy enum to make sure that both classes are fully defined.
00223     enum{ dontUseWithIncompleteTypes = ( sizeof (T) == sizeof (U) ) };
00224 };
00225 
00226 template<>
00227 struct SuperSubclassStrict<void, void> 
00228 {
00229     enum { value = false };
00230 };
00231 
00232 template<class U>
00233 struct SuperSubclassStrict<void, U> 
00234 {
00235     enum { value = (::Loki::Conversion<const volatile U*, const volatile void*>::exists &&
00236                  !::Loki::Conversion<const volatile void*, const volatile void*>::sameType &&
00237                  !::Loki::Conversion<const volatile void*, const volatile U*>::sameType) };
00238     
00239     // Dummy enum to make sure that both classes are fully defined.
00240     enum{ dontUseWithIncompleteTypes = ( 0 == sizeof (U) ) };
00241 };
00242 
00243 template<class T>
00244 struct SuperSubclassStrict<T, void> 
00245 {
00246     enum { value = (::Loki::Conversion<const volatile void*, const volatile T*>::exists &&
00247                  !::Loki::Conversion<const volatile T*, const volatile void*>::sameType &&
00248                  !::Loki::Conversion<const volatile T*, const volatile void*>::sameType) };
00249     
00250     // Dummy enum to make sure that both classes are fully defined.
00251     enum{ dontUseWithIncompleteTypes = ( sizeof (T) == 0 ) };
00252 };
00253 
00254 
00255 }   // namespace Loki
00256 
00258 // macro SUPERSUBCLASS
00259 // Invocation: SUPERSUBCLASS(B, D) where B and D are types. 
00260 // Returns true if B is a public base of D, or if B and D are aliases of the 
00261 // same type.
00262 //
00263 // Caveat: might not work if T and U are in a private inheritance hierarchy.
00264 // Deprecated: Use SuperSubclass class template instead.
00266 
00267 #define LOKI_SUPERSUBCLASS(T, U) \
00268     ::Loki::SuperSubclass<T,U>::value
00269 
00271 // macro SUPERSUBCLASS_STRICT
00272 // Invocation: SUPERSUBCLASS(B, D) where B and D are types. 
00273 // Returns true if B is a public base of D.
00274 //
00275 // Caveat: might not work if T and U are in a private inheritance hierarchy.
00276 // Deprecated: Use SuperSubclassStrict class template instead.
00278 
00279 #define LOKI_SUPERSUBCLASS_STRICT(T, U) \
00280     ::Loki::SuperSubclassStrict<T,U>::value
00281 
00282 
00283 #endif // end file guardian
00284 

Generated on Sun Feb 25 16:52:29 2007 for Loki by  doxygen 1.5.1-p1