//////////////////////////////////////////////////////////////////////////////// // The Loki Library // Copyright (c) 2001 by Andrei Alexandrescu // This code accompanies the book: // Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design // Patterns Applied". Copyright (c) 2001. Addison-Wesley. // Permission to use, copy, modify, distribute and sell this software for any // purpose is hereby granted without fee, provided that the above copyright // notice appear in all copies and that both that copyright notice and this // permission notice appear in supporting documentation. // The author or Addison-Welsey Longman make no representations about the // suitability of this software for any purpose. It is provided "as is" // without express or implied warranty. //////////////////////////////////////////////////////////////////////////////// // Last update: February 19, 2001 #ifndef TYPEMANIP_INC_ #define TYPEMANIP_INC_ namespace Loki { //////////////////////////////////////////////////////////////////////////////// // class template Int2Type // Converts each integral constant into a unique type // Invocation: Int2Type where v is a compile-time constant integral // Defines 'value', an enum that evaluates to v //////////////////////////////////////////////////////////////////////////////// template struct Int2Type { enum { value = v }; }; //////////////////////////////////////////////////////////////////////////////// // class template Type2Type // Converts each type into a unique, insipid type // Invocation Type2Type where T is a type // Defines the type OriginalType which maps back to T //////////////////////////////////////////////////////////////////////////////// template struct Type2Type { typedef T OriginalType; }; //////////////////////////////////////////////////////////////////////////////// // class template Select // Selects one of two types based upon a boolean constant // Invocation: Select::Result // where: // flag is a compile-time boolean constant // T and U are types // Result evaluates to T if flag is true, and to U otherwise. //////////////////////////////////////////////////////////////////////////////// template struct Select { typedef T Result; }; template struct Select { typedef U Result; }; //////////////////////////////////////////////////////////////////////////////// // Helper types Small and Big - guarantee that sizeof(Small) < sizeof(Big) //////////////////////////////////////////////////////////////////////////////// namespace Private { typedef char Small; class Big { char dummy[2]; }; } //////////////////////////////////////////////////////////////////////////////// // class template Conversion // Figures out the conversion relationships between two types // Invocations (T and U are types): // a) Conversion::exists // returns (at compile time) true if there is an implicit conversion from T // to U (example: Derived to Base) // b) Conversion::exists2Way // returns (at compile time) true if there are both conversions from T // to U and from U to T (example: int to char and back) // c) Conversion::sameType // returns (at compile time) true if T and U represent the same type // // Caveat: might not work if T and U are in a private inheritance hierarchy. //////////////////////////////////////////////////////////////////////////////// template class Conversion { static Private::Big Test(...); static Private::Small Test(U); static T MakeT(); public: enum { exists = sizeof(Test(MakeT())) == sizeof(Private::Small) }; enum { exists2Way = exists && Conversion::exists }; enum { sameType = false }; }; template class Conversion { public: enum { exists = 1, exists2Way = 1,sameType = 1 }; }; template class Conversion { public: enum { exists = 1, exists2Way = 0,sameType = 0 }; }; template class Conversion { public: enum { exists = 1, exists2Way = 0,sameType = 0 }; }; template <> class Conversion { public: enum { exists = 1, exists2Way = 1,sameType = 1 }; }; } //////////////////////////////////////////////////////////////////////////////// // macro SUPERSUBCLASS // Invocation: SUPERSUBCLASS(B, D) where B and D are types. // Returns true if B is a public base of D, or if B and D are aliases of the // same type. // // Caveat: might not work if T and U are in a private inheritance hierarchy. //////////////////////////////////////////////////////////////////////////////// #define SUPERSUBCLASS(T, U) \ (::Loki::Conversion::exists && \ !::Loki::Conversion::sameType) //////////////////////////////////////////////////////////////////////////////// // macro SUPERSUBCLASS // Invocation: SUPERSUBCLASS(B, D) where B and D are types. // Returns true if B is a public base of D. // // Caveat: might not work if T and U are in a private inheritance hierarchy. //////////////////////////////////////////////////////////////////////////////// #define SUPERSUBCLASS_STRICT(T, U) \ (SUPERSUBCLASS(T, U) && \ !::Loki::Conversion::sameType) #endif // TYPEMANIP_INC_