// This file is part of the uSTL library, an STL implementation. // // Copyright (c) 2007 by Mike Sharov // // This implementation is adapted from the Loki library, distributed under // the MIT license with Copyright (c) 2001 by Andrei Alexandrescu. #pragma once #include "typelist.h" namespace ustl { namespace tm { //---------------------------------------------------------------------- // Type classes and type modifiers //---------------------------------------------------------------------- typedef tl::Seq::Type StdUnsignedInts; typedef tl::Seq::Type StdSignedInts; typedef tl::Seq::Type StdOtherInts; typedef tl::Seq::Type StdFloats; template struct Identity { typedef U Result; }; template struct AddPointer { typedef U* Result; }; template struct AddPointer { typedef U* Result; }; template struct AddReference { typedef U& Result; }; template struct AddReference { typedef U& Result; }; template <> struct AddReference { typedef NullType Result; }; template struct AddParameterType { typedef const U& Result; }; template struct AddParameterType { typedef U& Result; }; template <> struct AddParameterType { typedef NullType Result; }; template struct RemoveReference { typedef U Result; }; template struct RemoveReference { typedef U Result; }; #if HAVE_CPP11 template struct RemoveReference { typedef U Result; }; #endif template struct EnableIf { typedef void Result; }; template struct EnableIf { typedef T Result; }; //---------------------------------------------------------------------- // Function pointer testers //---------------------------------------------------------------------- // Macros expand to numerous parameters template struct IsFunctionPointerRaw { enum { result = false}; }; template struct IsMemberFunctionPointerRaw { enum { result = false}; }; #define TM_FPR_MAXN 9 #define TM_FPR_TYPE(n) PASTE(T,n) #define TM_FPR_TYPENAME(n) typename TM_FPR_TYPE(n) // First specialize for regular functions template struct IsFunctionPointerRaw {enum {result = true};}; #define TM_FPR_SPEC(n) \ template \ struct IsFunctionPointerRaw \ { enum { result = true }; } LIST (TM_FPR_MAXN, TM_FPR_SPEC, ;); // Then for those with an ellipsis argument template struct IsFunctionPointerRaw {enum {result = true};}; #define TM_FPR_SPEC_ELLIPSIS(n) \ template \ struct IsFunctionPointerRaw \ { enum { result = true }; } LIST (TM_FPR_MAXN, TM_FPR_SPEC_ELLIPSIS, ;); // Then for member function pointers template struct IsMemberFunctionPointerRaw { enum { result = true }; }; #define TM_MFPR_SPEC(n) \ template \ struct IsMemberFunctionPointerRaw \ { enum { result = true };}; LIST (TM_FPR_MAXN, TM_MFPR_SPEC, ;); // Then for member function pointers with an ellipsis argument template struct IsMemberFunctionPointerRaw { enum { result = true }; }; #define TM_MFPR_SPEC_ELLIPSIS(n) \ template \ struct IsMemberFunctionPointerRaw \ { enum { result = true }; }; LIST (TM_FPR_MAXN, TM_MFPR_SPEC_ELLIPSIS, ;); // Then for const member function pointers (getting tired yet?) template struct IsMemberFunctionPointerRaw { enum { result = true }; }; #define TM_CMFPR_SPEC(n) \ template \ struct IsMemberFunctionPointerRaw \ { enum { result = true };}; LIST (TM_FPR_MAXN, TM_CMFPR_SPEC, ;); // Finally for const member function pointers with an ellipsis argument (whew!) template struct IsMemberFunctionPointerRaw { enum { result = true }; }; #define TM_CMFPR_SPEC_ELLIPSIS(n) \ template \ struct IsMemberFunctionPointerRaw \ { enum { result = true }; }; LIST (TM_FPR_MAXN, TM_CMFPR_SPEC_ELLIPSIS, ;); #undef TM_FPR_SPEC #undef TM_FPR_SPEC_ELLIPSIS #undef TM_MFPR_SPEC #undef TM_MFPR_SPEC_ELLIPSIS #undef TM_CMFPR_SPEC #undef TM_CMFPR_SPEC_ELLIPSIS #undef TM_FPR_TYPENAME #undef TM_FPR_TYPE #undef TM_FPR_MAXN //---------------------------------------------------------------------- // Type traits template //---------------------------------------------------------------------- /// Figures out at compile time various properties of any given type /// Invocations (T is a type, TypeTraits::Propertie): /// /// - isPointer : returns true if T is a pointer type /// - PointeeType : returns the type to which T points if T is a pointer /// type, NullType otherwise /// - isReference : returns true if T is a reference type /// - isLValue : returns true if T is an lvalue /// - isRValue : returns true if T is an rvalue /// - ReferredType : returns the type to which T refers if T is a reference /// type, NullType otherwise /// - isMemberPointer : returns true if T is a pointer to member type /// - isStdUnsignedInt: returns true if T is a standard unsigned integral type /// - isStdSignedInt : returns true if T is a standard signed integral type /// - isStdIntegral : returns true if T is a standard integral type /// - isStdFloat : returns true if T is a standard floating-point type /// - isStdArith : returns true if T is a standard arithmetic type /// - isStdFundamental: returns true if T is a standard fundamental type /// - isUnsignedInt : returns true if T is a unsigned integral type /// - isSignedInt : returns true if T is a signed integral type /// - isIntegral : returns true if T is a integral type /// - isFloat : returns true if T is a floating-point type /// - isArith : returns true if T is a arithmetic type /// - isFundamental : returns true if T is a fundamental type /// - ParameterType : returns the optimal type to be used as a parameter for /// functions that take Ts /// - isConst : returns true if T is a const-qualified type /// - NonConstType : Type with removed 'const' qualifier from T, if any /// - isVolatile : returns true if T is a volatile-qualified type /// - NonVolatileType : Type with removed 'volatile' qualifier from T, if any /// - UnqualifiedType : Type with removed 'const' and 'volatile' qualifiers from /// T, if any /// - ConstParameterType: returns the optimal type to be used as a parameter /// for functions that take 'const T's /// template class TypeTraits { private: #define TMTT1 template struct #define TMTT2 template struct TMTT1 ReferenceTraits { enum { result = false, lvalue = true, rvalue = false }; typedef U ReferredType; }; TMTT1 ReferenceTraits { enum { result = true, lvalue = true, rvalue = false }; typedef U ReferredType; }; TMTT1 PointerTraits { enum { result = false }; typedef NullType PointeeType; }; TMTT1 PointerTraits { enum { result = true }; typedef U PointeeType; }; TMTT1 PointerTraits { enum { result = true }; typedef U PointeeType; }; TMTT1 PToMTraits { enum { result = false }; }; TMTT2 PToMTraits { enum { result = true }; }; TMTT2 PToMTraits { enum { result = true }; }; TMTT1 FunctionPointerTraits { enum { result = IsFunctionPointerRaw::result }; }; TMTT1 PToMFunctionTraits { enum { result = IsMemberFunctionPointerRaw::result }; }; TMTT1 UnConst { typedef U Result; enum { isConst = false }; }; TMTT1 UnConst { typedef U Result; enum { isConst = true }; }; TMTT1 UnConst { typedef U& Result; enum { isConst = true }; }; TMTT1 UnVolatile { typedef U Result; enum { isVolatile = false }; }; TMTT1 UnVolatile{ typedef U Result; enum { isVolatile = true }; }; TMTT1 UnVolatile {typedef U& Result;enum { isVolatile = true }; }; #if HAVE_CPP11 TMTT1 ReferenceTraits { enum { result = true, lvalue = false, rvalue = true }; typedef U ReferredType; }; TMTT1 PointerTraits { enum { result = true }; typedef U PointeeType; }; TMTT2 PToMTraits { enum { result = true }; }; TMTT1 UnConst { typedef U&& Result; enum { isConst = true }; }; TMTT1 UnVolatile {typedef U&& Result;enum { isVolatile = true }; }; #endif #undef TMTT2 #undef TMTT1 public: typedef typename UnConst::Result NonConstType; typedef typename UnVolatile::Result NonVolatileType; typedef typename UnVolatile::Result>::Result UnqualifiedType; typedef typename PointerTraits::PointeeType PointeeType; typedef typename ReferenceTraits::ReferredType ReferredType; enum { isConst = UnConst::isConst }; enum { isVolatile = UnVolatile::isVolatile }; enum { isReference = ReferenceTraits::result }; enum { isLValue = ReferenceTraits::lvalue }; enum { isRValue = ReferenceTraits::rvalue }; enum { isFunction = FunctionPointerTraits::Result >::result }; enum { isFunctionPointer = FunctionPointerTraits< typename ReferenceTraits::ReferredType >::result }; enum { isMemberFunctionPointer= PToMFunctionTraits< typename ReferenceTraits::ReferredType >::result }; enum { isMemberPointer = PToMTraits< typename ReferenceTraits::ReferredType >::result || isMemberFunctionPointer }; enum { isPointer = PointerTraits< typename ReferenceTraits::ReferredType >::result || isFunctionPointer }; enum { isStdUnsignedInt = tl::IndexOf::value >= 0 || tl::IndexOf::ReferredType>::value >= 0}; enum { isStdSignedInt = tl::IndexOf::value >= 0 || tl::IndexOf::ReferredType>::value >= 0}; enum { isStdIntegral = isStdUnsignedInt || isStdSignedInt || tl::IndexOf::value >= 0 || tl::IndexOf::ReferredType>::value >= 0}; enum { isStdFloat = tl::IndexOf::value >= 0 || tl::IndexOf::ReferredType>::value >= 0}; enum { isStdArith = isStdIntegral || isStdFloat }; enum { isStdFundamental = isStdArith || isStdFloat || Conversion::sameType }; enum { isUnsignedInt = isStdUnsignedInt }; enum { isUnsigned = isUnsignedInt || isPointer }; enum { isSignedInt = isStdSignedInt }; enum { isIntegral = isStdIntegral || isUnsignedInt || isSignedInt }; enum { isFloat = isStdFloat }; enum { isSigned = isSignedInt || isFloat }; enum { isArith = isIntegral || isFloat }; enum { isFundamental = isStdFundamental || isArith }; typedef typename Select::Result>::Result ParameterType; }; } // namespace tm } // namespace ustl