library of assembled shared sources |
http://lass.cocamware.com |
00001 /** @file 00002 * @author Bram de Greve (bramz@users.sourceforge.net) 00003 * @author Tom De Muer (tomdemuer@users.sourceforge.net) 00004 * 00005 * *** BEGIN LICENSE INFORMATION *** 00006 * 00007 * The contents of this file are subject to the Common Public Attribution License 00008 * Version 1.0 (the "License"); you may not use this file except in compliance with 00009 * the License. You may obtain a copy of the License at 00010 * http://lass.sourceforge.net/cpal-license. The License is based on the 00011 * Mozilla Public License Version 1.1 but Sections 14 and 15 have been added to cover 00012 * use of software over a computer network and provide for limited attribution for 00013 * the Original Developer. In addition, Exhibit A has been modified to be consistent 00014 * with Exhibit B. 00015 * 00016 * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT 00017 * WARRANTY OF ANY KIND, either express or implied. See the License for the specific 00018 * language governing rights and limitations under the License. 00019 * 00020 * The Original Code is LASS - Library of Assembled Shared Sources. 00021 * 00022 * The Initial Developer of the Original Code is Bram de Greve and Tom De Muer. 00023 * The Original Developer is the Initial Developer. 00024 * 00025 * All portions of the code written by the Initial Developer are: 00026 * Copyright (C) 2004-2007 the Initial Developer. 00027 * All Rights Reserved. 00028 * 00029 * Contributor(s): 00030 * 00031 * Alternatively, the contents of this file may be used under the terms of the 00032 * GNU General Public License Version 2 or later (the GPL), in which case the 00033 * provisions of GPL are applicable instead of those above. If you wish to allow use 00034 * of your version of this file only under the terms of the GPL and not to allow 00035 * others to use your version of this file under the CPAL, indicate your decision by 00036 * deleting the provisions above and replace them with the notice and other 00037 * provisions required by the GPL License. If you do not delete the provisions above, 00038 * a recipient may use your version of this file under either the CPAL or the GPL. 00039 * 00040 * *** END LICENSE INFORMATION *** 00041 */ 00042 00043 00044 00045 /** @class lass::meta::TypeTraits 00046 * @brief Interesting goodies on types 00047 * @author Bram de Greve [BdG] 00048 * 00049 * @section overview 00050 * 00051 * TypeTraits gives you compile-time information on a type @a T. It will tell you if 00052 * @a T is 00053 * constant type, a pointer, a reference ... It will also able you to derive related types 00054 * at compile time, such as non-const version of a constant type. 00055 * 00056 * In contrary to the type traits in boost[1] or loki[2], our TypeTraits tries to be smarter 00057 * concerning reference. i.e. if @a T is a reference, TypeTraits will also report 00058 * properties of the referred type. And if you request a related type, it will modify 00059 * the referred type instead. All this should make sure you get exactly what you intend. 00060 * (this is still to be proven in practice [BdG]). 00061 * 00062 * Here's a list of the different fields (we suppose @a T is the template parameter): 00063 * 00064 * @par Type 00065 * a typedef to the template paramter. i.e. this is the same as @a T. 00066 * 00067 * @par isConst 00068 * is @c true if @a T is a constant type or a reference to a constant type, is @c false otherwise. 00069 * Notice that this will yield @c false for non-const pointers to const types (<tt>const int*</tt>) 00070 * but @c true for const pointers to non-const types (<tt>int* const</tt>). 00071 * 00072 * @par TNonConst 00073 * a typedef to the non-const version of @a T if @a T is const, otherwise it's @a T itself. You 00074 * can use this to get rid of the @c const qualifier of a type, e.g. <tt>const int</tt> becomes 00075 * <tt>int</tt> but <tt>const int*</tt> remains <tt>const int*</tt>. For references, the @c const 00076 * qualifier is stripped of the referred type, e.g. <tt>const int&</tt> becomes <tt>int&</tt>. 00077 * 00078 * @par TConst 00079 * This is the opposite of @b TNonConst. It appends a @c const qualifier to the (reffered) type, 00080 * <tt>const int*</tt> becomes <tt>const int* const</tt>, <tt>int&</tt> becomes <tt>const int&</tt> 00081 * 00082 * @par isPointer 00083 * is @c true if @a T is a pointer or a reference to a pointer, is @c false otherwise. 00084 * Notice that <tt>int*&</tt> will yield true. 00085 * 00086 * @par TPointee 00087 * if @b isPointer is @c true then @b TPointee is a typedef to the (referred) type points to, 00088 * otherwise it will be equal to lass::meta::NullType. both <tt>int* const</tt> and <tt>int*&</tt> 00089 * will yield <tt>int</tt>, but <tt>int</tt> and <tt>int&</tt> will yield lass::meta::NullType. 00090 * 00091 * @par isReference 00092 * is @c true if @a T is a reference, is @c false otherwise. both <tt>const int&</tt> and 00093 * <tt>int*&</tt> are references, <tt>const int</tt> and <tt>int*</tt> are not. 00094 * 00095 * @par TReferred 00096 * if @b isReference is @c true then strips the @e ampersand to get type @a T is refering to, 00097 * otherwise it's @a T itself. both <tt>const int&</tt> and <tt>const int</tt> become 00098 * <tt>const int</tt>, <tt>int*&</tt> and <tt>int*</tt> become <tt>int*</tt>. 00099 * 00100 * @par TReference 00101 * if @b isReference is @c false then adds the @e ampersand to get a type refering to a @a T, 00102 * otherwise it's @a T itself. This solves the ill-formed @e reference-to-reference-to-type 00103 * problem by keeping it a @e reference-to-type (what is exactly what you want). i.e. <tt>int</tt> 00104 * becomes <tt>int&</tt>, but <tt>int&</tt> remains <tt>int&</tt>. 00105 * 00106 * @par TStorage 00107 * yields in a type that can be used to store temporary objects. To store temporary objects, 00108 * we must get rid of the reference and the @c const qualifier of the referred type. e.g. if a 00109 * <tt>const std::string&</tt> is the type of a function parameter, you would like to @e store 00110 * tempories as <tt>std::string</tt>. This @b TStorage will give you this <tt>std::string</tt> 00111 * type. 00112 * 00113 * Here we list all possible results of TypeTraits in a table. We show it for a base type 00114 * int, but it is of course valid for any other type. 00115 * 00116 * <table><tr> 00117 * <td><b>T</b></td> <td><b>isConst</b></td> <td><b>TNonConst</b></td> <td><b>TConst</b></td> <td><b>isPointer</b></td> <td><b>TPointee</b></td> <td><b>isReference</b></td> <td><b>TReferred</b></td> <td><b>TReference</b></td> <td><b>TStorage</b></td> 00118 * </tr><tr> 00119 * <td><b>int</b></td> <td>false</td> <td>int</td> <td>const int</td> <td>false</td> <td>NullType</td> <td>false</td> <td>int</td> <td>int&</td> <td>int</td> 00120 * </tr><tr> 00121 * <td><b>int*</b></td> <td>false</td> <td>int*</td> <td>int* const</td> <td>true</td> <td>int</td> <td>false</td> <td>int*</td> <td>int*&</td> <td>int*</td> 00122 * </tr><tr> 00123 * <td><b>int* const</b></td> <td>true</td> <td>int*</td> <td>int* const</td> <td>true</td> <td>int</td> <td>false</td> <td>int* const</td> <td>int* const&</td> <td>int*</td> 00124 * </tr><tr> 00125 * <td><b>int&</b></td> <td>false</td> <td>int&</td> <td>const int&</td> <td>false</td> <td>NullType</td> <td>true</td> <td>int</td> <td>int&</td> <td>int</td> 00126 * </tr><tr> 00127 * <td><b>int*&</b></td> <td>false</td> <td>int*&</td> <td>int* const&</td> <td>true</td> <td>int</td> <td>true</td> <td>int*</td> <td>int*&</td> <td>int*</td> 00128 * </tr><tr> 00129 * <td><b>int* const&</b></td> <td>true</td> <td>int*&</td> <td>int* const&</td> <td>true</td> <td>int</td> <td>true</td> <td>int* const</td> <td>int* const&</td> <td>int*</td> 00130 * </tr><tr> 00131 * <td><b>const int</b></td> <td>true</td> <td>int</td> <td>const int</td> <td>false</td> <td>NullType</td> <td>false</td> <td>const int</td> <td>const int&</td> <td>int</td> 00132 * </tr><tr> 00133 * <td><b>const int*</b></td> <td>false</td> <td>const int*</td> <td>const int* const</td> <td>true</td> <td>const int</td> <td>false</td> <td>const int*</td> <td>const int*&</td> <td>const int*</td> 00134 * </tr><tr> 00135 * <td><b>const int* const</b></td> <td>true</td> <td>const int*</td> <td>const int* const</td> <td>true</td> <td>const int</td> <td>false</td> <td>const int* const</td> <td>const int* const&</td> <td>const int*</td> 00136 * </tr><tr> 00137 * <td><b>const int&</b></td> <td>true</td> <td>int&</td> <td>const int&</td> <td>false</td> <td>NullType</td> <td>true</td> <td>const int</td> <td>const int&</td> <td>int</td> 00138 * </tr><tr> 00139 * <td><b>const int*&</b></td> <td>false</td> <td>const int*&</td> <td>const int* const&</td> <td>true</td> <td>const int</td> <td>true</td> <td>const int*</td> <td>const int*&</td> <td>const int*</td> 00140 * </tr><tr> 00141 * <td><b>const int* const&</b></td> <td>true</td> <td>const int*&</td> <td>const int* const&</td> <td>true</td> <td>const int</td> <td>true</td> <td>const int* const</td> <td>const int* const&</td> <td>const int*</td> 00142 * </tr></table> 00143 * 00144 * @note You can see that references behave much the same as the refered type. e.g. 00145 * <tt>TypeTraits<U>::TPointee</tt> will be the same as 00146 * <tt>TypeTraits<typename TypeTraits<U>::TReferred>::TPointee</tt>, no matter what the type of @c U is. 00147 * The same is valid for @c isConst and @c isPointer. @c TConst and @c TNonConst are a bit 00148 * different, for these the @e ampersand will again be added if @c U is a reference. 00149 * 00150 * @section broken broken compilers workaround 00151 * 00152 * Unfortunately, the have a neat implementation of TypeTraits, we need partial template 00153 * specialisation, a feature not supported by MSVC6x and MSVC70. However, TypeTraits @e can be a 00154 * crucial tool to implement algorithms that would be impossible to implement if TypeTraits fail. 00155 * Thus we, @e do need a way to get this TypeTraits up and running in environments without this 00156 * partial specialisation, and we need to get it to the @e right thing! 00157 * 00158 * There's really only one way to solve this, and that's exhaustive full specialisation of all 00159 * possible parameters @a T. This means we should specialise it for <tt>int</tt>, 00160 * <tt>const int</tt>, <tt>const int*</tt>, ... (for each base type @c int, you have to specialise 00161 * for the twelve cases as in the table above). 00162 * 00163 * Of course, it is impossible for a library to do this, because we can never know all types 00164 * that will ever be needed. Therefore we have a twofolded solution: 00165 * 00166 * - we have provided full specialisations for all twelve cases of all @e fundamental types and 00167 * some more. This types are: bool, char, wchar_t, signed char, signed short, signed int, 00168 * signed long, (signed __int64), unsigned char, unsigned short, unsigned int, unsigned long, 00169 * (unsigned __int64), float, double, long double, std::string, std::complex<float>, 00170 * std::complex<double> and std::complex<long double> 00171 * - we have provided a macro LASS_META_BROKEN_TYPE_TRAITS_SPECIALISATION you can use to provide 00172 * full specialisation of all twelve cases of any other type: 00173 * 00174 * @code 00175 * namespace foo 00176 * { 00177 * struct Bar {}; 00178 * } 00179 * LASS_META_BROKEN_TYPE_TRAITS_SPECIALISATION(foo::Bar) 00180 * @endcode 00181 * 00182 * @note you can safely use this macro regardless if the compiler supports partial specialisation. 00183 * If your compiler supports it, the macro will be expanded to @e nothing. 00184 * 00185 * @warning you have to call this macro @e outside any namespaces. 00186 * 00187 * @warning this exhaustive full specialisation @e might lead to an overflow of the compiler's 00188 * internal heap while building. You're warned! 00189 */ 00190 00191 #ifndef LASS_GUARDIAN_OF_INCLUSION_META_TYPE_TRAITS_H 00192 #define LASS_GUARDIAN_OF_INCLUSION_META_TYPE_TRAITS_H 00193 00194 #include "meta_common.h" 00195 #include "null_type.h" 00196 #include "meta_assert.h" 00197 00198 namespace lass 00199 { 00200 namespace meta 00201 { 00202 00203 #if !defined(LASS_NO_TEMPLATE_PARTIAL_SPECIALIZATION) 00204 00205 template <typename T> 00206 struct TypeTraits 00207 { 00208 private: 00209 00210 template <typename U> struct ConstTraits 00211 { 00212 enum { isConst = false }; 00213 typedef U TNonConst; 00214 typedef const U TConst; 00215 }; 00216 template <typename U> struct ConstTraits<const U> 00217 { 00218 enum { isConst = true }; 00219 typedef U TNonConst; 00220 typedef const U TConst; 00221 }; 00222 template <typename U> struct ConstTraits<U&> 00223 { 00224 enum { isConst = false }; 00225 typedef U& TNonConst; 00226 typedef const U& TConst; 00227 }; 00228 template <typename U> struct ConstTraits<const U&> 00229 { 00230 enum { isConst = true }; 00231 typedef U& TNonConst; 00232 typedef const U& TConst; 00233 }; 00234 00235 template <typename U> struct PointerTraits 00236 { 00237 enum { isPointer = false }; 00238 typedef NullType TPointee; 00239 }; 00240 template <typename U> struct PointerTraits<U*> 00241 { 00242 enum { isPointer = true }; 00243 typedef U TPointee; 00244 }; 00245 template <typename U> struct PointerTraits<U&> 00246 { 00247 enum { isPointer = false }; 00248 typedef NullType TPointee; 00249 }; 00250 template <typename U> struct PointerTraits<U*&> 00251 { 00252 enum { isPointer = true }; 00253 typedef U TPointee; 00254 }; 00255 00256 template <typename U> struct ReferenceTraits 00257 { 00258 enum { isReference = false }; 00259 typedef U TReferred; 00260 typedef U& TReference; 00261 }; 00262 template <typename U> struct ReferenceTraits<U&> 00263 { 00264 enum { isReference = true }; 00265 typedef U TReferred; 00266 typedef U& TReference; 00267 }; 00268 00269 typedef typename ConstTraits<T>::TNonConst TStripped; 00270 00271 public: 00272 00273 /** type of @a T itself 00274 */ 00275 typedef T Type; 00276 00277 /** is @c true if referred type of @a T is constant. */ 00278 enum { isConst = ConstTraits<T>::isConst }; 00279 /** strips @c const qualifier of refered type of @a T (but keeps reference if any). */ 00280 typedef typename ConstTraits<T>::TNonConst TNonConst; 00281 /** add @c const qualifier to referred type of @a T (but keeps reference if any). */ 00282 typedef typename ConstTraits<T>::TConst TConst; 00283 00284 /** is @c true if referred type of @a T is a pointer */ 00285 enum { isPointer = PointerTraits<TNonConst>::isPointer }; 00286 /** is type pointed to by referred type of @a T, NullType if not applyable. */ 00287 typedef typename PointerTraits<TNonConst>::TPointee TPointee; 00288 00289 /** is @c true if @a T is a reference*/ 00290 enum { isReference = ReferenceTraits<T>::isReference }; 00291 /** is type @a T refers to if @a T is a reference, is @a T otherwise*/ 00292 typedef typename ReferenceTraits<T>::TReferred TReferred; 00293 /** is a reference to @a T if @a T is @e not a reference, is @a T otherwise*/ 00294 typedef typename ReferenceTraits<T>::TReference TReference; 00295 00296 /** strips @c const qualifier of refered type of @a T but without keeping reference if any. */ 00297 typedef typename ConstTraits<typename ReferenceTraits<T>::TReferred>::TNonConst TStorage; 00298 }; 00299 00300 #define LASS_META_BROKEN_TYPE_TRAITS_SPECIALISATION(type) /**/ 00301 00302 #else 00303 00304 template <typename T> 00305 struct TypeTraits 00306 { 00307 LASS_META_ASSERT(false, lass_meta_TypeTraits_is_not_specialized_for_type); 00308 }; 00309 00310 #define LASS_META_BROKEN_TYPE_TRAITS_SPECIALISATION(type)\ 00311 namespace lass\ 00312 {\ 00313 namespace meta\ 00314 {\ 00315 template <>\ 00316 struct TypeTraits<type >\ 00317 {\ 00318 typedef type Type;\ 00319 enum { isConst = false };\ 00320 typedef type TNonConst;\ 00321 typedef const type TConst;\ 00322 enum { isPointer = false };\ 00323 typedef NullType TPointee;\ 00324 enum { isReference = false };\ 00325 typedef type TReferred;\ 00326 typedef type& TReference;\ 00327 typedef type TStorage;\ 00328 };\ 00329 template <>\ 00330 struct TypeTraits<const type >\ 00331 {\ 00332 typedef const type Type;\ 00333 enum { isConst = true };\ 00334 typedef type TNonConst;\ 00335 typedef const type TConst;\ 00336 enum { isPointer = false };\ 00337 typedef NullType TPointee;\ 00338 enum { isReference = false };\ 00339 typedef const type TReferred;\ 00340 typedef const type& TReference;\ 00341 typedef type TStorage;\ 00342 };\ 00343 template <>\ 00344 struct TypeTraits<type*>\ 00345 {\ 00346 typedef type* Type;\ 00347 enum { isConst = false };\ 00348 typedef type* TNonConst;\ 00349 typedef type* const TConst;\ 00350 enum { isPointer = true };\ 00351 typedef type TPointee;\ 00352 enum { isReference = false };\ 00353 typedef type* TReferred;\ 00354 typedef type*& TReference;\ 00355 typedef type* TStorage;\ 00356 };\ 00357 template <>\ 00358 struct TypeTraits<const type*>\ 00359 {\ 00360 typedef const type* Type;\ 00361 enum { isConst = false };\ 00362 typedef const type* TNonConst;\ 00363 typedef const type* const TConst;\ 00364 enum { isPointer = true };\ 00365 typedef const type TPointee;\ 00366 enum { isReference = false };\ 00367 typedef const type* TReferred;\ 00368 typedef const type*& TReference;\ 00369 typedef const type* TStorage;\ 00370 };\ 00371 template <>\ 00372 struct TypeTraits<type* const>\ 00373 {\ 00374 typedef type* const Type;\ 00375 enum { isConst = true };\ 00376 typedef type* TNonConst;\ 00377 typedef type* const TConst;\ 00378 enum { isPointer = true };\ 00379 typedef type TPointee;\ 00380 enum { isReference = false };\ 00381 typedef type* const TReferred;\ 00382 typedef type* const& TReference;\ 00383 typedef type* TStorage;\ 00384 };\ 00385 template <>\ 00386 struct TypeTraits<const type* const>\ 00387 {\ 00388 typedef const type* const Type;\ 00389 enum { isConst = true };\ 00390 typedef const type* TNonConst;\ 00391 typedef const type* const TConst;\ 00392 enum { isPointer = true };\ 00393 typedef const type TPointee;\ 00394 enum { isReference = false };\ 00395 typedef const type* const TReferred;\ 00396 typedef const type* const& TReference;\ 00397 typedef const type* TStorage;\ 00398 };\ 00399 template <>\ 00400 struct TypeTraits<type&>\ 00401 {\ 00402 typedef type& Type;\ 00403 enum { isConst = false };\ 00404 typedef type& TNonConst;\ 00405 typedef const type& TConst;\ 00406 enum { isPointer = false };\ 00407 typedef NullType TPointee;\ 00408 enum { isReference = true };\ 00409 typedef type TReferred;\ 00410 typedef type& TReference;\ 00411 typedef type TStorage;\ 00412 };\ 00413 template <>\ 00414 struct TypeTraits<const type&>\ 00415 {\ 00416 typedef const type& Type;\ 00417 enum { isConst = true };\ 00418 typedef type& TNonConst;\ 00419 typedef const type& TConst;\ 00420 enum { isPointer = false };\ 00421 typedef NullType TPointee;\ 00422 enum { isReference = true };\ 00423 typedef const type TReferred;\ 00424 typedef const type& TReference;\ 00425 typedef type TStorage;\ 00426 };\ 00427 template <>\ 00428 struct TypeTraits<type*&>\ 00429 {\ 00430 typedef type*& Type;\ 00431 enum { isConst = false };\ 00432 typedef type*& TNonConst;\ 00433 typedef type* const& TConst;\ 00434 enum { isPointer = true };\ 00435 typedef type TPointee;\ 00436 enum { isReference = true };\ 00437 typedef type* TReferred;\ 00438 typedef type*& TReference;\ 00439 typedef type* TStorage;\ 00440 };\ 00441 template <>\ 00442 struct TypeTraits<const type*&>\ 00443 {\ 00444 typedef const type*& Type;\ 00445 enum { isConst = false };\ 00446 typedef const type*& TNonConst;\ 00447 typedef const type* const& TConst;\ 00448 enum { isPointer = true };\ 00449 typedef const type TPointee;\ 00450 enum { isReference = true };\ 00451 typedef const type* TReferred;\ 00452 typedef const type*& TReference;\ 00453 typedef const type* TStorage;\ 00454 };\ 00455 template <>\ 00456 struct TypeTraits<type* const&>\ 00457 {\ 00458 typedef type* const& Type;\ 00459 enum { isConst = true };\ 00460 typedef type*& TNonConst;\ 00461 typedef type* const& TConst;\ 00462 enum { isPointer = true };\ 00463 typedef type TPointee;\ 00464 enum { isReference = true };\ 00465 typedef type* const TReferred;\ 00466 typedef type* const& TReference;\ 00467 typedef type* TStorage;\ 00468 };\ 00469 template <>\ 00470 struct TypeTraits<const type* const&>\ 00471 {\ 00472 typedef const type* const& Type;\ 00473 enum { isConst = true };\ 00474 typedef const type*& TNonConst;\ 00475 typedef const type* const& TConst;\ 00476 enum { isPointer = true };\ 00477 typedef const type TPointee;\ 00478 enum { isReference = true };\ 00479 typedef const type* const TReferred;\ 00480 typedef const type* const& TReference;\ 00481 typedef const type* TStorage;\ 00482 };\ 00483 }\ 00484 } 00485 00486 #endif 00487 00488 } 00489 00490 } 00491 00492 LASS_META_BROKEN_TYPE_TRAITS_SPECIALISATION(bool) 00493 LASS_META_BROKEN_TYPE_TRAITS_SPECIALISATION(char) 00494 LASS_META_BROKEN_TYPE_TRAITS_SPECIALISATION(wchar_t) 00495 LASS_META_BROKEN_TYPE_TRAITS_SPECIALISATION(signed char) 00496 LASS_META_BROKEN_TYPE_TRAITS_SPECIALISATION(signed short) 00497 LASS_META_BROKEN_TYPE_TRAITS_SPECIALISATION(signed int) 00498 LASS_META_BROKEN_TYPE_TRAITS_SPECIALISATION(signed long) 00499 LASS_META_BROKEN_TYPE_TRAITS_SPECIALISATION(signed __int64) 00500 LASS_META_BROKEN_TYPE_TRAITS_SPECIALISATION(unsigned char) 00501 LASS_META_BROKEN_TYPE_TRAITS_SPECIALISATION(unsigned short) 00502 LASS_META_BROKEN_TYPE_TRAITS_SPECIALISATION(unsigned int) 00503 LASS_META_BROKEN_TYPE_TRAITS_SPECIALISATION(unsigned long) 00504 LASS_META_BROKEN_TYPE_TRAITS_SPECIALISATION(unsigned __int64) 00505 LASS_META_BROKEN_TYPE_TRAITS_SPECIALISATION(float) 00506 LASS_META_BROKEN_TYPE_TRAITS_SPECIALISATION(double) 00507 LASS_META_BROKEN_TYPE_TRAITS_SPECIALISATION(long double) 00508 LASS_META_BROKEN_TYPE_TRAITS_SPECIALISATION(std::string) 00509 LASS_META_BROKEN_TYPE_TRAITS_SPECIALISATION(std::complex<float>) 00510 LASS_META_BROKEN_TYPE_TRAITS_SPECIALISATION(std::complex<double>) 00511 LASS_META_BROKEN_TYPE_TRAITS_SPECIALISATION(std::complex<long double>) 00512 00513 #endif 00514 00515 // EOF
Generated on Mon Nov 10 14:22:01 2008 for Library of Assembled Shared Sources by 1.5.7.1 |