00001 /**************************************************************************** 00002 Copyright (C)2001 by Andrei Alexandrescu 00003 00004 This file is a derivative of a file from the Loki Library written by 00005 Andrei Alexandrescu. It was distributed by him under the terms 00006 listed below (titled Loki Original Distribution Terms). 00007 In accordance with the terms, this distribution contains the copyright 00008 notice here and the copyright notice and permission notice 00009 in supporting documentation. The terms do *not* require 00010 redistribution under those same terms. This code is distributed 00011 to you under the terms of the GNU General Public License (GPL) 00012 below. The GPL does not require you to maintain the terms of 00013 the Loki Original Distribution Terms, but you are encouraged to do so. 00014 00015 This program/file is free software; you can redistribute it and/or modify 00016 it under the terms of the GNU General Public License as published by 00017 the Free Software Foundation; either version 2 of the License, or 00018 (at your option) any later version. 00019 00020 This program is distributed in the hope that it will be useful, 00021 but WITHOUT ANY WARRANTY; without even the implied warranty of 00022 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00023 GNU General Public License for more details. (http://www.gnu.org) 00024 00025 You should have received a copy of the GNU General Public License 00026 along with this program; if not, write to the Free Software 00027 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00028 00029 **************************************************************************** 00030 Loki Original Distribution Terms: 00031 00032 The Loki Library 00033 Copyright (c) 2001 by Andrei Alexandrescu 00034 This code accompanies the book: 00035 Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design 00036 Patterns Applied". Copyright (c) 2001. Addison-Wesley. 00037 Permission to use, copy, modify, distribute and sell this software for any 00038 purpose is hereby granted without fee, provided that the above copyright 00039 notice appear in all copies and that both that copyright notice and this 00040 permission notice appear in supporting documentation. 00041 The author or Addison-Welsey Longman make no representations about the 00042 suitability of this software for any purpose. It is provided "as is" 00043 without express or implied warranty. 00044 **************************************************************************** 00045 00046 $Id: TypeManip 1029 2004-02-11 20:45:54Z jungd $ 00047 $Revision: 1.1 $ 00048 $Date: 2004-02-11 15:45:54 -0500 (Wed, 11 Feb 2004) $ 00049 $Author: jungd $ 00050 00051 ****************************************************************************/ 00052 00053 // Last update: June 20, 2001 00054 00055 #ifndef TYPEMANIP_INC_ 00056 #define TYPEMANIP_INC_ 00057 00058 namespace base 00059 { 00060 //////////////////////////////////////////////////////////////////////////////// 00061 // class template Int2Type 00062 // Converts each integral constant into a unique type 00063 // Invocation: Int2Type<v> where v is a compile-time constant integral 00064 // Defines 'value', an enum that evaluates to v 00065 //////////////////////////////////////////////////////////////////////////////// 00066 00067 template <int v> 00068 struct Int2Type 00069 { 00070 enum { value = v }; 00071 }; 00072 00073 //////////////////////////////////////////////////////////////////////////////// 00074 // class template Type2Type 00075 // Converts each type into a unique, insipid type 00076 // Invocation Type2Type<T> where T is a type 00077 // Defines the type OriginalType which maps back to T 00078 //////////////////////////////////////////////////////////////////////////////// 00079 00080 template <typename T> 00081 struct Type2Type 00082 { 00083 typedef T OriginalType; 00084 }; 00085 00086 //////////////////////////////////////////////////////////////////////////////// 00087 // class template Select 00088 // Selects one of two types based upon a boolean constant 00089 // Invocation: Select<flag, T, U>::Result 00090 // where: 00091 // flag is a compile-time boolean constant 00092 // T and U are types 00093 // Result evaluates to T if flag is true, and to U otherwise. 00094 //////////////////////////////////////////////////////////////////////////////// 00095 00096 template <bool flag, typename T, typename U> 00097 struct Select 00098 { 00099 typedef T Result; 00100 }; 00101 template <typename T, typename U> 00102 struct Select<false, T, U> 00103 { 00104 typedef U Result; 00105 }; 00106 00107 //////////////////////////////////////////////////////////////////////////////// 00108 // Helper types Small and Big - guarantee that sizeof(Small) < sizeof(Big) 00109 //////////////////////////////////////////////////////////////////////////////// 00110 00111 namespace Private 00112 { 00113 template <class T, class U> 00114 struct ConversionHelper 00115 { 00116 typedef char Small; 00117 struct Big { char dummy[2]; }; 00118 static Big Test(...); 00119 static Small Test(U); 00120 static T MakeT(); 00121 }; 00122 } 00123 00124 //////////////////////////////////////////////////////////////////////////////// 00125 // class template Conversion 00126 // Figures out the conversion relationships between two types 00127 // Invocations (T and U are types): 00128 // a) Conversion<T, U>::exists 00129 // returns (at compile time) true if there is an implicit conversion from T 00130 // to U (example: Derived to Base) 00131 // b) Conversion<T, U>::exists2Way 00132 // returns (at compile time) true if there are both conversions from T 00133 // to U and from U to T (example: int to char and back) 00134 // c) Conversion<T, U>::sameType 00135 // returns (at compile time) true if T and U represent the same type 00136 // 00137 // Caveat: might not work if T and U are in a private inheritance hierarchy. 00138 //////////////////////////////////////////////////////////////////////////////// 00139 00140 template <class T, class U> 00141 struct Conversion 00142 { 00143 typedef Private::ConversionHelper<T, U> H; 00144 #ifndef __MWERKS__ 00145 enum { exists = sizeof(typename H::Small) == sizeof(H::Test(H::MakeT())) }; 00146 #else 00147 enum { exists = false }; 00148 #endif 00149 enum { exists2Way = exists && Conversion<U, T>::exists }; 00150 enum { sameType = false }; 00151 }; 00152 00153 template <class T> 00154 struct Conversion<T, T> 00155 { 00156 enum { exists = 1, exists2Way = 1,sameType = 1 }; 00157 }; 00158 00159 template <class T> 00160 struct Conversion<void, T> 00161 { 00162 enum { exists = 1, exists2Way = 0,sameType = 0 }; 00163 }; 00164 00165 template <class T> 00166 struct Conversion<T, void> 00167 { 00168 enum { exists = 1, exists2Way = 0,sameType = 0 }; 00169 }; 00170 00171 template <> 00172 class Conversion<void, void> 00173 { 00174 public: 00175 enum { exists = 1, exists2Way = 1,sameType = 1 }; 00176 }; 00177 } 00178 00179 //////////////////////////////////////////////////////////////////////////////// 00180 // macro SUPERSUBCLASS 00181 // Invocation: SUPERSUBCLASS(B, D) where B and D are types. 00182 // Returns true if B is a public base of D, or if B and D are aliases of the 00183 // same type. 00184 // 00185 // Caveat: might not work if T and U are in a private inheritance hierarchy. 00186 //////////////////////////////////////////////////////////////////////////////// 00187 00188 #define SUPERSUBCLASS(T, U) \ 00189 (::base::Conversion<const U*, const T*>::exists && \ 00190 !::base::Conversion<const T*, const void*>::sameType) 00191 00192 //////////////////////////////////////////////////////////////////////////////// 00193 // macro SUPERSUBCLASS 00194 // Invocation: SUPERSUBCLASS(B, D) where B and D are types. 00195 // Returns true if B is a public base of D. 00196 // 00197 // Caveat: might not work if T and U are in a private inheritance hierarchy. 00198 //////////////////////////////////////////////////////////////////////////////// 00199 00200 #define SUPERSUBCLASS_STRICT(T, U) \ 00201 (SUPERSUBCLASS(T, U) && \ 00202 !::base::Conversion<const T, const U>::sameType) 00203 00204 //////////////////////////////////////////////////////////////////////////////// 00205 // Change log: 00206 // June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!! 00207 //////////////////////////////////////////////////////////////////////////////// 00208 00209 #endif // TYPEMANIP_INC_