www.pudn.com > Loki.rar > TypeTraits.h


//////////////////////////////////////////////////////////////////////////////// 
// 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: May 19, 2002 
 
#ifndef TYPETRAITS_INC_ 
#define TYPETRAITS_INC_ 
 
#include "Typelist.h" 
 
namespace Loki 
{ 
//////////////////////////////////////////////////////////////////////////////// 
// class template IsCustomUnsignedInt 
// Offers a means to integrate nonstandard built-in unsigned integral types 
// (such as unsigned __int64 or unsigned long long int) with the TypeTraits  
//     class template defined below. 
// Invocation: IsCustomUnsignedInt where T is any type 
// Defines 'value', an enum that is 1 iff T is a custom built-in unsigned 
//     integral type 
// Specialize this class template for nonstandard unsigned integral types 
//     and define value = 1 in those specializations 
//////////////////////////////////////////////////////////////////////////////// 
 
    template  
    struct IsCustomUnsignedInt 
    { 
        enum { value = 0 }; 
    };         
 
//////////////////////////////////////////////////////////////////////////////// 
// class template IsCustomSignedInt 
// Offers a means to integrate nonstandard built-in unsigned integral types 
// (such as unsigned __int64 or unsigned long long int) with the TypeTraits  
//     class template defined below. 
// Invocation: IsCustomSignedInt where T is any type 
// Defines 'value', an enum that is 1 iff T is a custom built-in signed 
//     integral type 
// Specialize this class template for nonstandard unsigned integral types 
//     and define value = 1 in those specializations 
//////////////////////////////////////////////////////////////////////////////// 
 
    template  
    struct IsCustomSignedInt 
    { 
        enum { value = 0 }; 
    };         
 
//////////////////////////////////////////////////////////////////////////////// 
// class template IsCustomFloat 
// Offers a means to integrate nonstandard floating point types with the 
//     TypeTraits class template defined below. 
// Invocation: IsCustomFloat where T is any type 
// Defines 'value', an enum that is 1 iff T is a custom built-in 
//     floating point type 
// Specialize this class template for nonstandard unsigned integral types 
//     and define value = 1 in those specializations 
//////////////////////////////////////////////////////////////////////////////// 
 
    template  
    struct IsCustomFloat 
    { 
        enum { value = 0 }; 
    };         
 
//////////////////////////////////////////////////////////////////////////////// 
// Helper types for class template TypeTraits defined below 
//////////////////////////////////////////////////////////////////////////////// 
 
    namespace Private 
    { 
        typedef TYPELIST_4(unsigned char, unsigned short int, 
           unsigned int, unsigned long int) StdUnsignedInts; 
        typedef TYPELIST_4(signed char, short int, 
           int, long int) StdSignedInts; 
        typedef TYPELIST_3(bool, char, wchar_t) StdOtherInts; 
        typedef TYPELIST_3(float, double, long double) StdFloats; 
    } 
         
//////////////////////////////////////////////////////////////////////////////// 
// class template TypeTraits 
// Figures out various properties of any given type 
// Invocations (T is a type): 
// a) TypeTraits::isPointer 
// returns (at compile time) true if T is a pointer type 
// b) TypeTraits::PointeeType 
// returns the type to which T points is T is a pointer type, NullType otherwise 
// a) TypeTraits::isReference 
// returns (at compile time) true if T is a reference type 
// b) TypeTraits::ReferredType 
// returns the type to which T refers is T is a reference type, NullType 
// otherwise 
// c) TypeTraits::isMemberPointer 
// returns (at compile time) true if T is a pointer to member type 
// d) TypeTraits::isStdUnsignedInt 
// returns (at compile time) true if T is a standard unsigned integral type 
// e) TypeTraits::isStdSignedInt 
// returns (at compile time) true if T is a standard signed integral type 
// f) TypeTraits::isStdIntegral 
// returns (at compile time) true if T is a standard integral type 
// g) TypeTraits::isStdFloat 
// returns (at compile time) true if T is a standard floating-point type 
// h) TypeTraits::isStdArith 
// returns (at compile time) true if T is a standard arithmetic type 
// i) TypeTraits::isStdFundamental 
// returns (at compile time) true if T is a standard fundamental type 
// j) TypeTraits::isUnsignedInt 
// returns (at compile time) true if T is a unsigned integral type 
// k) TypeTraits::isSignedInt 
// returns (at compile time) true if T is a signed integral type 
// l) TypeTraits::isIntegral 
// returns (at compile time) true if T is a integral type 
// m) TypeTraits::isFloat 
// returns (at compile time) true if T is a floating-point type 
// n) TypeTraits::isArith 
// returns (at compile time) true if T is a arithmetic type 
// o) TypeTraits::isFundamental 
// returns (at compile time) true if T is a fundamental type 
// p) TypeTraits::ParameterType 
// returns the optimal type to be used as a parameter for functions that take Ts 
// q) TypeTraits::isConst 
// returns (at compile time) true if T is a const-qualified type 
// r) TypeTraits::NonConstType 
// removes the 'const' qualifier from T, if any 
// s) TypeTraits::isVolatile 
// returns (at compile time) true if T is a volatile-qualified type 
// t) TypeTraits::NonVolatileType 
// removes the 'volatile' qualifier from T, if any 
// u) TypeTraits::UnqualifiedType 
// removes both the 'const' and 'volatile' qualifiers from T, if any 
//////////////////////////////////////////////////////////////////////////////// 
 
    template  
    class TypeTraits 
    { 
        typedef char (&yes)[1]; 
        typedef char (&no) [2]; 
 
        template 
        static void vc7_need_this_for_is_array(Type2Type); 
 
        template 
        static yes is_reference(Type2Type); 
        static no  is_reference(...); 
 
        template 
        static yes is_pointer1(Type2Type); 
        static no  is_pointer1(...); 
 
        template 
        static yes is_pointer2(Type2Type); 
        static no  is_pointer2(...); 
 
        template 
        static yes is_pointer3(Type2Type); 
        static no  is_pointer3(...); 
 
        template 
        static yes is_pointer4(Type2Type); 
        static no  is_pointer4(...); 
 
        template 
        static yes is_pointer2member(Type2Type); 
        static no  is_pointer2member(...); 
 
        template 
        static yes is_array1(Type2Type); 
        static no  is_array1(...); 
 
        template 
        static yes is_array2(Type2Type); 
        static no  is_array2(...); 
 
        template 
        static yes is_const(Type2Type); 
        static no  is_const(...); 
 
        template 
        static yes is_volatile(Type2Type); 
        static no  is_volatile(...); 
 
    public:         
        // 
        // VC7 BUG - will not detect refernce to function 
        // 
        enum {  
            isReference =  
                sizeof(is_reference(Type2Type())) == sizeof(yes)  
        }; 
         
        // 
        // VC7 BUG - will not detect pointer to function 
        // 
        enum {  
            isPointer =  
                sizeof(is_pointer1(Type2Type())) == sizeof(yes) || 
                sizeof(is_pointer2(Type2Type())) == sizeof(yes) || 
                sizeof(is_pointer3(Type2Type())) == sizeof(yes) || 
                sizeof(is_pointer4(Type2Type())) == sizeof(yes) 
        }; 
         
        enum {  
            isMemberPointer =  
                sizeof(is_pointer2member(Type2Type())) == sizeof(yes) 
        }; 
     
        enum {  
            isArray = 
                sizeof(is_array1(Type2Type())) == sizeof(yes) || 
                sizeof(is_array2(Type2Type())) == sizeof(yes) 
        }; 
 
        enum {  
            isVoid =  
                SameType::value          || 
                SameType::value    || 
                SameType::value || 
                SameType::value 
        }; 
 
        enum { isStdUnsignedInt =  
            TL::IndexOf::value >= 0 }; 
        enum { isStdSignedInt =  
            TL::IndexOf::value >= 0 }; 
        enum { isStdIntegral = isStdUnsignedInt || isStdSignedInt || 
            TL::IndexOf::value >= 0 }; 
        enum { isStdFloat = TL::IndexOf::value >= 0 }; 
        enum { isStdArith = isStdIntegral || isStdFloat }; 
        enum { isStdFundamental = isStdArith || isStdFloat || isVoid }; 
             
        enum { isUnsignedInt = isStdUnsignedInt || IsCustomUnsignedInt::value }; 
        enum { isSignedInt = isStdSignedInt || IsCustomSignedInt::value }; 
        enum { isIntegral = isStdIntegral || isUnsignedInt || isSignedInt }; 
        enum { isFloat = isStdFloat || IsCustomFloat::value }; 
        enum { isArith = isIntegral || isFloat }; 
        enum { isFundamental = isStdFundamental || isArith || isFloat }; 
         
        enum {  
            isConst =  
                sizeof(is_const(Type2Type())) == sizeof(yes) 
        }; 
 
        enum {  
            isVolatile =  
                sizeof(is_volatile(Type2Type())) == sizeof(yes) 
        }; 
 
         
    private: 
        // is_scalar include functions types 
        struct is_scalar 
        { 
        private: 
            struct BoolConvert { BoolConvert(bool); }; 
 
            static yes check(BoolConvert); 
            static no  check(...); 
 
            struct NotScalar {}; 
 
            typedef typename Select 
            < 
                isVoid || isReference || isArray,  
                NotScalar, T 
            > 
            ::Result RetType; 
             
            static RetType& get(); 
 
        public: 
// 
// Ignore forcing value to bool 'true' or 'false' (performance warning) 
// 
#ifdef _MSC_VER 
#pragma warning (disable: 4800) 
#endif 
 
            enum { value = sizeof(check(get())) == sizeof(yes) }; 
 
#ifdef _MSC_VER 
#pragma warning (default: 4800) 
#endif 
        }; // is_scalar 
 
     
    private: 
        template 
        struct AdjReference 
        { 
            template 
            struct In { typedef U const & Result; }; 
        }; 
 
        template<> 
        struct AdjReference 
        { 
            template 
            struct In { typedef U Result; }; 
        }; 
 
        typedef typename AdjReference:: 
                template In::Result AdjType; 
 
    public:         
        enum { isScalar = is_scalar::value }; 
 
 
        typedef typename Select 
        < 
            isScalar || isArray, T, AdjType 
        > 
        ::Result ParameterType; 
         
        // 
        // We get is_class for free 
        // BUG - fails with functions types (ICE) and unknown size array 
        // (but works for other incomplete types) 
        // (the boost one (Paul Mensonides) is better) 
        // 
        enum { isClass =  
                !isScalar    &&  
                !isArray     &&  
                !isReference && 
                !isVoid  
        }; 
    }; 
} 
 
//////////////////////////////////////////////////////////////////////////////// 
// Change log: 
// June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!! 
// May  10, 2002: ported by Rani Sharoni to VC7 (RTM - 9466) 
//////////////////////////////////////////////////////////////////////////////// 
 
#endif // TYPETRAITS_INC_