PixelLightAPI  .
TypeTraits.h
Go to the documentation of this file.
00001 /*********************************************************\
00002  *  File: TypeTraits.h                                   *
00003  *
00004  *  Copyright (C) 2002-2012 The PixelLight Team (http://www.pixellight.org/)
00005  *
00006  *  This file is part of PixelLight.
00007  *
00008  *  PixelLight is free software: you can redistribute it and/or modify
00009  *  it under the terms of the GNU Lesser General Public License as published by
00010  *  the Free Software Foundation, either version 3 of the License, or
00011  *  (at your option) any later version.
00012  *
00013  *  PixelLight is distributed in the hope that it will be useful,
00014  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00016  *  GNU Lesser General Public License for more details.
00017  *
00018  *  You should have received a copy of the GNU Lesser General Public License
00019  *  along with PixelLight. If not, see <http://www.gnu.org/licenses/>.
00020 \*********************************************************/
00021 
00022 
00023 #ifndef __PLCORE_TYPETRAITS_H__
00024 #define __PLCORE_TYPETRAITS_H__
00025 #pragma once
00026 
00027 
00028 //[-------------------------------------------------------]
00029 //[ Includes                                              ]
00030 //[-------------------------------------------------------]
00031 #include "PLCore/Base/Type/EnumType.h"
00032 #include "PLCore/Base/Tools/CompileError.h"
00033 
00034 
00035 //[-------------------------------------------------------]
00036 //[ Namespace                                             ]
00037 //[-------------------------------------------------------]
00038 namespace PLCore {
00039 
00040 
00041 //[-------------------------------------------------------]
00042 //[ Types                                                 ]
00043 //[-------------------------------------------------------]
00044 /**
00045 *  @brief
00046 *    Type that is not used
00047 */
00048 class NullType {
00049 };
00050 
00051 /**
00052 *  @brief
00053 *    Type that is considered invalid (unknown type)
00054 */
00055 template <typename T>
00056 class InvalidType {
00057 };
00058 
00059 
00060 //[-------------------------------------------------------]
00061 //[ Helper classes                                        ]
00062 //[-------------------------------------------------------]
00063 /**
00064 *  @brief
00065 *    Class representing 'true' in templates
00066 */
00067 class TrueType {
00068 };
00069 
00070 /**
00071 *  @brief
00072 *    Class representing 'false' in templates
00073 */
00074 class FalseType {
00075 };
00076 
00077 /**
00078 *  @brief
00079 *    Conversion helper class
00080 */
00081 struct ConversionHelper
00082 {
00083     template <typename T> ConversionHelper(const volatile T&);
00084     template <typename T> ConversionHelper(T&);
00085 };
00086 
00087 
00088 //[-------------------------------------------------------]
00089 //[ Generic templates                                     ]
00090 //[-------------------------------------------------------]
00091 /**
00092 *  @brief
00093 *    Template to specialize another template only if two types are equal
00094 *
00095 *  @param[in] T1
00096 *    First compared type
00097 *  @param[in] T2
00098 *    Second compared type
00099 *  @param[in] TMPL
00100 *    Class template
00101 *  @param[in] TYPE
00102 *    Template argument for class template
00103 */
00104 // Implementation for T1 != T2
00105 template <typename T1, typename T2, template <typename T> class TMPL, typename TYPE>
00106 class SpecializeIfEqual {
00107     public:
00108         typedef FalseType Type;
00109 };
00110 
00111 // Implementation for T1 == T2
00112 template <typename T1, template <typename T> class TMPL, typename TYPE>
00113 class SpecializeIfEqual<T1, T1, TMPL, TYPE> {
00114     public:
00115         typedef TMPL<TYPE> Type;
00116 };
00117 
00118 /**
00119 *  @brief
00120 *    Choose type based on condition
00121 *
00122 *  @param[in] CHECK
00123 *    Condition
00124 *  @param[in] TYPE
00125 *    Type to return if condition is true
00126 *  @param[in] REST
00127 *    ChooseType that contains the rest of the decision if condition is false
00128 */
00129 // Generic
00130 template <bool CHECK, typename TYPE, typename REST>
00131 struct ChooseType {
00132 };
00133 
00134 // Implementation for CHECK == true
00135 template <typename TYPE, typename REST>
00136 struct ChooseType<true, TYPE, REST> {
00137     typedef TYPE Type;
00138 };
00139 
00140 // Implementation for CHECK == false
00141 template <typename TYPE, typename REST>
00142 struct ChooseType<false, TYPE, REST> {
00143     typedef typename REST::Type Type;
00144 };
00145 
00146 /**
00147 *  @brief
00148 *    Boolean operation: OR
00149 *
00150 *  @param[in] T1
00151 *    First class
00152 *  @param[in] T2
00153 *    Second class
00154 *
00155 *  @remarks
00156 *    The value of Value will contain the result of (T1::Value || T2::Value)
00157 */
00158 template <typename T1, typename T2>
00159 struct BooleanOr {
00160     static const bool Value = (T1::Value || T2::Value);
00161 };
00162 
00163 /**
00164 *  @brief
00165 *    Boolean operation: AND
00166 *
00167 *  @param[in] T1
00168 *    First class
00169 *  @param[in] T2
00170 *    Second class
00171 *
00172 *  @remarks
00173 *    The value of Value will contain the result of (T1::Value && T2::Value)
00174 */
00175 template <typename T1, typename T2>
00176 struct BooleanAnd {
00177     static const bool Value = (T1::Value && T2::Value);
00178 };
00179 
00180 /**
00181 *  @brief
00182 *    Boolean operation: NOT
00183 *
00184 *  @param[in] T
00185 *    Class
00186 *
00187 *  @remarks
00188 *    The value of Value will contain the result of (!T::Value)
00189 */
00190 template <typename T>
00191 struct BooleanNot {
00192     static const bool Value = (!T::Value);
00193 };
00194 
00195 
00196 //[-------------------------------------------------------]
00197 //[ Type traits                                           ]
00198 //[-------------------------------------------------------]
00199 /**
00200 *  @brief
00201 *    Class that recognizes integral types
00202 *
00203 *  @remarks
00204 *    This class can be used to check if a given data type is an integer-type.
00205 *    Examples:
00206 *    - IntegralType<long> ::IsIntegral => 1
00207 *    - IntegralType<long> ::Type       => long
00208 *    - IntegralType<float>::IsIntegral => 0
00209 *    - IntegralType<float>::Type       => NullType
00210 */
00211 template <typename T>
00212 class IntegralType {
00213     public:
00214         enum { IsIntegral = 0 };
00215         typedef NullType Type;
00216 };
00217 
00218 template <>
00219 class IntegralType<uint8> {
00220     public:
00221         enum { IsIntegral = 1 };
00222         typedef uint8 Type;
00223 };
00224 
00225 template <>
00226 class IntegralType<uint16> {
00227     public:
00228         enum { IsIntegral = 1 };
00229         typedef uint16 Type;
00230 };
00231 
00232 template <>
00233 class IntegralType<uint32> {
00234     public:
00235         enum { IsIntegral = 1 };
00236         typedef uint32 Type;
00237 };
00238 
00239 template <>
00240 class IntegralType<int8> {
00241     public:
00242         enum { IsIntegral = 1 };
00243         typedef int8 Type;
00244 };
00245 
00246 template <>
00247 class IntegralType<int16> {
00248     public:
00249         enum { IsIntegral = 1 };
00250         typedef int16 Type;
00251 };
00252 
00253 template <>
00254 class IntegralType<int32> {
00255     public:
00256         enum { IsIntegral = 1 };
00257         typedef int32 Type;
00258 };
00259 
00260 /**
00261 *  @brief
00262 *    Check if two types are equal
00263 *
00264 *  @param[in] T1
00265 *    First type
00266 *  @param[in] T2
00267 *    Second type
00268 *
00269 *  @remarks
00270 *    If (From) and (To) are equal, the value of Value is 'true', else 'false'
00271 */
00272 // Implementation for T1 != T2
00273 template<typename T1, typename T2>
00274 struct IsEqual
00275 {
00276     static const bool Value = false;
00277 };
00278 
00279 // Implementation for T1 == T2
00280 template<typename T>
00281 struct IsEqual<T, T>
00282 {
00283     static const bool Value = true;
00284 };
00285 
00286 
00287 /**
00288 *  @brief
00289 *    Check if two types are convertible
00290 *
00291 *  @param[in] From
00292 *    First type
00293 *  @param[in] To
00294 *    Second type
00295 *
00296 *  @remarks
00297 *    If (From) can be converted to (To), the value of Value is 'true', else 'false'
00298 */
00299 template<typename From, typename To>
00300 struct IsConvertible
00301 {
00302     private:
00303         typedef char                          one_byte;
00304         typedef struct { char two_chars[2]; } two_bytes;
00305 
00306     private:
00307         static one_byte  test(const To&, int);
00308         static two_bytes test(ConversionHelper, ...);
00309 
00310     public:
00311         static const bool Value = sizeof(test(*(static_cast<From*>(nullptr)), 0)) == 1;
00312 
00313 
00314 };
00315 
00316 /**
00317 *  @brief
00318 *    Check if one type is a base type of another
00319 *
00320 *  @param[in] Class
00321 *    First type
00322 *  @param[in] Base
00323 *    Second type
00324 *
00325 *  @remarks
00326 *    If Base is a base class of Class (and Base and Class are NOT equal), the value of Value is 'true', else 'false'
00327 */
00328 template<typename Class, typename Base>
00329 struct IsBaseClass
00330 {
00331     static const bool Value = BooleanAnd< IsConvertible<Class, Base>, BooleanNot< IsEqual<Class, Base> > >::Value;
00332 };
00333 
00334 /**
00335 *  @brief
00336 *    Check if a type is an enum
00337 *
00338 *  @param[in] T
00339 *    Type
00340 *
00341 *  @remarks
00342 *    If T is an enum type, the value of Value is 'true', else 'false'
00343 */
00344 template<typename T>
00345 struct IsEnum
00346 {
00347     static const bool Value = IsConvertible<T, int>::Value;
00348 };
00349 
00350 template<typename T>
00351 struct IsEnum< InvalidType<T> >
00352 {
00353     static const bool Value = false;
00354 };
00355 
00356 /**
00357 *  @brief
00358 *    Classify a type (check if it is a class, an enum, etc.)
00359 *
00360 *  @param[in] T
00361 *    Type
00362 */
00363 template <typename T>
00364 struct TypeClassification {
00365     static const bool Value = IsEnum<T>::Value; /**< 'true' if T is an enum */
00366 };
00367 
00368 /**
00369 *  @brief
00370 *    Get representative type for non-default types
00371 *
00372 *  @param[in] T
00373 *    Type
00374 *
00375 *  @remarks
00376 *    Type will be defined as:
00377 *    - int             (if T is an enum)
00378 *    - InvalidType<T>  (otherwise)
00379 */
00380 template <typename T>
00381 struct CheckType {
00382     typedef typename ChooseType< TypeClassification<T>::Value, PLCore::EnumTypePlain<T>,
00383                         ChooseType< true, InvalidType<T>, InvalidType<T> >
00384                      >::Type Type;
00385 };
00386 
00387 /**
00388 *  @brief
00389 *    Check if a class is derived from another class and issue an error if not
00390 *
00391 *  @param[in] Class
00392 *    Class
00393 *  @param[in] Base
00394 *    Base class
00395 *
00396 *  @remarks
00397 *    Will issue a compiler error if Class is not derived from Base
00398 */
00399 // Implementation for 'true' (no error)
00400 template <bool Condition, typename Class, typename Base>
00401 struct CheckBaseClassBool {
00402     // No error
00403     static void Error() {
00404     }
00405 };
00406 
00407 // Implementation for 'false' (no error)
00408 template <typename Class, typename Base>
00409 struct CheckBaseClassBool<false, Class, Base> {
00410     // Create error
00411     static void Error() {
00412         PLCORE_ERROR(Not_A_Base_Class)
00413     }
00414 };
00415 
00416 // Generic implementation
00417 template <typename Class, typename Base>
00418 struct CheckBaseClass {
00419     typedef CheckBaseClassBool< IsBaseClass<Class, Base>::Value, Class, Base > Type;
00420 };
00421 
00422 
00423 //[-------------------------------------------------------]
00424 //[ Namespace                                             ]
00425 //[-------------------------------------------------------]
00426 } // PLCore
00427 
00428 
00429 #endif // __PLCORE_TYPETRAITS_H__


PixelLight PixelLight 0.9.11-R1
Copyright (C) 2002-2012 by The PixelLight Team
Last modified Thu Feb 23 2012 14:09:01
The content of this PixelLight document is published under the
Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported