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_