/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- *//* vim: set ts=8 sts=2 et sw=2 tw=80: *//* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. *//* Template-based metaprogramming and type-testing facilities. */#ifndef mozilla_TypeTraits_h#define mozilla_TypeTraits_h#include"mozilla/Types.h"/* * These traits are approximate copies of the traits and semantics from C++11's * <type_traits> header. Don't add traits not in that header! When all * platforms provide that header, we can convert all users and remove this one. */#include<wchar.h>namespacemozilla{/* Forward declarations. */template<typename>structRemoveCV;/* 20.9.3 Helper classes [meta.help] *//** * Helper class used as a base for various type traits, exposed publicly * because <type_traits> exposes it as well. */template<typenameT,TValue>structIntegralConstant{staticconstTvalue=Value;typedefTValueType;typedefIntegralConstant<T,Value>Type;};/** Convenient aliases. */typedefIntegralConstant<bool,true>TrueType;typedefIntegralConstant<bool,false>FalseType;/* 20.9.4 Unary type traits [meta.unary] *//* 20.9.4.1 Primary type categories [meta.unary.cat] */namespacedetail{template<typenameT>structIsVoidHelper:FalseType{};template<>structIsVoidHelper<void>:TrueType{};}// namespace detail/** * IsVoid determines whether a type is void. * * mozilla::IsVoid<int>::value is false; * mozilla::IsVoid<void>::value is true; * mozilla::IsVoid<void*>::value is false; * mozilla::IsVoid<volatile void>::value is true. */template<typenameT>structIsVoid:detail::IsVoidHelper<typenameRemoveCV<T>::Type>{};namespacedetail{template<typenameT>structIsIntegralHelper:FalseType{};template<>structIsIntegralHelper<char>:TrueType{};template<>structIsIntegralHelper<signedchar>:TrueType{};template<>structIsIntegralHelper<unsignedchar>:TrueType{};template<>structIsIntegralHelper<short>:TrueType{};template<>structIsIntegralHelper<unsignedshort>:TrueType{};template<>structIsIntegralHelper<int>:TrueType{};template<>structIsIntegralHelper<unsignedint>:TrueType{};template<>structIsIntegralHelper<long>:TrueType{};template<>structIsIntegralHelper<unsignedlong>:TrueType{};template<>structIsIntegralHelper<longlong>:TrueType{};template<>structIsIntegralHelper<unsignedlonglong>:TrueType{};template<>structIsIntegralHelper<bool>:TrueType{};template<>structIsIntegralHelper<wchar_t>:TrueType{};#ifdef MOZ_CHAR16_IS_NOT_WCHARtemplate<>structIsIntegralHelper<char16_t>:TrueType{};#endif}/* namespace detail *//** * IsIntegral determines whether a type is an integral type. * * mozilla::IsIntegral<int>::value is true; * mozilla::IsIntegral<unsigned short>::value is true; * mozilla::IsIntegral<const long>::value is true; * mozilla::IsIntegral<int*>::value is false; * mozilla::IsIntegral<double>::value is false; * * Note that the behavior of IsIntegral on char16_t and char32_t is * unspecified. */template<typenameT>structIsIntegral:detail::IsIntegralHelper<typenameRemoveCV<T>::Type>{};template<typenameT,typenameU>structIsSame;namespacedetail{template<typenameT>structIsFloatingPointHelper:IntegralConstant<bool,IsSame<T,float>::value||IsSame<T,double>::value||IsSame<T,longdouble>::value>{};}// namespace detail/** * IsFloatingPoint determines whether a type is a floating point type (float, * double, long double). * * mozilla::IsFloatingPoint<int>::value is false; * mozilla::IsFloatingPoint<const float>::value is true; * mozilla::IsFloatingPoint<long double>::value is true; * mozilla::IsFloatingPoint<double*>::value is false. */template<typenameT>structIsFloatingPoint:detail::IsFloatingPointHelper<typenameRemoveCV<T>::Type>{};namespacedetail{template<typenameT>structIsArrayHelper:FalseType{};template<typenameT,decltype(sizeof(1))N>structIsArrayHelper<T[N]>:TrueType{};template<typenameT>structIsArrayHelper<T[]>:TrueType{};}// namespace detail/** * IsArray determines whether a type is an array type, of known or unknown * length. * * mozilla::IsArray<int>::value is false; * mozilla::IsArray<int[]>::value is true; * mozilla::IsArray<int[5]>::value is true. */template<typenameT>structIsArray:detail::IsArrayHelper<typenameRemoveCV<T>::Type>{};/** * IsPointer determines whether a type is a pointer type (but not a pointer-to- * member type). * * mozilla::IsPointer<struct S*>::value is true; * mozilla::IsPointer<int**>::value is true; * mozilla::IsPointer<void (*)(void)>::value is true; * mozilla::IsPointer<int>::value is false; * mozilla::IsPointer<struct S>::value is false. */template<typenameT>structIsPointer:FalseType{};template<typenameT>structIsPointer<T*>:TrueType{};/** * IsLvalueReference determines whether a type is an lvalue reference. * * mozilla::IsLvalueReference<struct S*>::value is false; * mozilla::IsLvalueReference<int**>::value is false; * mozilla::IsLvalueReference<void (*)(void)>::value is false; * mozilla::IsLvalueReference<int>::value is false; * mozilla::IsLvalueReference<struct S>::value is false; * mozilla::IsLvalueReference<struct S*&>::value is true; * mozilla::IsLvalueReference<struct S&&>::value is false. */template<typenameT>structIsLvalueReference:FalseType{};template<typenameT>structIsLvalueReference<T&>:TrueType{};/** * IsRvalueReference determines whether a type is an rvalue reference. * * mozilla::IsRvalueReference<struct S*>::value is false; * mozilla::IsRvalueReference<int**>::value is false; * mozilla::IsRvalueReference<void (*)(void)>::value is false; * mozilla::IsRvalueReference<int>::value is false; * mozilla::IsRvalueReference<struct S>::value is false; * mozilla::IsRvalueReference<struct S*&>::value is false; * mozilla::IsRvalueReference<struct S&&>::value is true. */template<typenameT>structIsRvalueReference:FalseType{};template<typenameT>structIsRvalueReference<T&&>:TrueType{};namespacedetail{// __is_enum is a supported extension across all of our supported compilers.template<typenameT>structIsEnumHelper:IntegralConstant<bool,__is_enum(T)>{};}// namespace detail/** * IsEnum determines whether a type is an enum type. * * mozilla::IsEnum<enum S>::value is true; * mozilla::IsEnum<enum S*>::value is false; * mozilla::IsEnum<int>::value is false; */template<typenameT>structIsEnum:detail::IsEnumHelper<typenameRemoveCV<T>::Type>{};namespacedetail{// __is_class is a supported extension across all of our supported compilers:// http://llvm.org/releases/3.0/docs/ClangReleaseNotes.html// http://gcc.gnu.org/onlinedocs/gcc-4.4.7/gcc/Type-Traits.html#Type-Traits// http://msdn.microsoft.com/en-us/library/ms177194%28v=vs.100%29.aspxtemplate<typenameT>structIsClassHelper:IntegralConstant<bool,__is_class(T)>{};}// namespace detail/** * IsClass determines whether a type is a class type (but not a union). * * struct S {}; * union U {}; * mozilla::IsClass<int>::value is false; * mozilla::IsClass<const S>::value is true; * mozilla::IsClass<U>::value is false; */template<typenameT>structIsClass:detail::IsClassHelper<typenameRemoveCV<T>::Type>{};/* 20.9.4.2 Composite type traits [meta.unary.comp] *//** * IsReference determines whether a type is an lvalue or rvalue reference. * * mozilla::IsReference<struct S*>::value is false; * mozilla::IsReference<int**>::value is false; * mozilla::IsReference<int&>::value is true; * mozilla::IsReference<void (*)(void)>::value is false; * mozilla::IsReference<const int&>::value is true; * mozilla::IsReference<int>::value is false; * mozilla::IsReference<struct S>::value is false; * mozilla::IsReference<struct S&>::value is true; * mozilla::IsReference<struct S*&>::value is true; * mozilla::IsReference<struct S&&>::value is true. */template<typenameT>structIsReference:IntegralConstant<bool,IsLvalueReference<T>::value||IsRvalueReference<T>::value>{};/** * IsArithmetic determines whether a type is arithmetic. A type is arithmetic * iff it is an integral type or a floating point type. * * mozilla::IsArithmetic<int>::value is true; * mozilla::IsArithmetic<double>::value is true; * mozilla::IsArithmetic<long double*>::value is false. */template<typenameT>structIsArithmetic:IntegralConstant<bool,IsIntegral<T>::value||IsFloatingPoint<T>::value>{};/* 20.9.4.3 Type properties [meta.unary.prop] *//** * IsConst determines whether a type is const or not. * * mozilla::IsConst<int>::value is false; * mozilla::IsConst<void* const>::value is true; * mozilla::IsConst<const char*>::value is false. */template<typenameT>structIsConst:FalseType{};template<typenameT>structIsConst<constT>:TrueType{};/** * IsVolatile determines whether a type is volatile or not. * * mozilla::IsVolatile<int>::value is false; * mozilla::IsVolatile<void* volatile>::value is true; * mozilla::IsVolatile<volatile char*>::value is false. */template<typenameT>structIsVolatile:FalseType{};template<typenameT>structIsVolatile<volatileT>:TrueType{};/** * Traits class for identifying POD types. Until C++11 there's no automatic * way to detect PODs, so for the moment this is done manually. Users may * define specializations of this class that inherit from mozilla::TrueType and * mozilla::FalseType (or equivalently mozilla::IntegralConstant<bool, true or * false>, or conveniently from mozilla::IsPod for composite types) as needed to * ensure correct IsPod behavior. */template<typenameT>structIsPod:publicFalseType{};template<>structIsPod<char>:TrueType{};template<>structIsPod<signedchar>:TrueType{};template<>structIsPod<unsignedchar>:TrueType{};template<>structIsPod<short>:TrueType{};template<>structIsPod<unsignedshort>:TrueType{};template<>structIsPod<int>:TrueType{};template<>structIsPod<unsignedint>:TrueType{};template<>structIsPod<long>:TrueType{};template<>structIsPod<unsignedlong>:TrueType{};template<>structIsPod<longlong>:TrueType{};template<>structIsPod<unsignedlonglong>:TrueType{};template<>structIsPod<bool>:TrueType{};template<>structIsPod<float>:TrueType{};template<>structIsPod<double>:TrueType{};template<>structIsPod<wchar_t>:TrueType{};#ifdef MOZ_CHAR16_IS_NOT_WCHARtemplate<>structIsPod<char16_t>:TrueType{};#endiftemplate<typenameT>structIsPod<T*>:TrueType{};namespacedetail{// __is_empty is a supported extension across all of our supported compilers:// http://llvm.org/releases/3.0/docs/ClangReleaseNotes.html// http://gcc.gnu.org/onlinedocs/gcc-4.4.7/gcc/Type-Traits.html#Type-Traits// http://msdn.microsoft.com/en-us/library/ms177194%28v=vs.100%29.aspxtemplate<typenameT>structIsEmptyHelper:IntegralConstant<bool,IsClass<T>::value&&__is_empty(T)>{};}// namespace detail/** * IsEmpty determines whether a type is a class (but not a union) that is empty. * * A class is empty iff it and all its base classes have no non-static data * members (except bit-fields of length 0) and no virtual member functions, and * no base class is empty or a virtual base class. * * Intuitively, empty classes don't have any data that has to be stored in * instances of those classes. (The size of the class must still be non-zero, * because distinct array elements of any type must have different addresses. * However, if the Empty Base Optimization is implemented by the compiler [most * compilers implement it, and in certain cases C++11 requires it], the size of * a class inheriting from an empty |Base| class need not be inflated by * |sizeof(Base)|.) And intuitively, non-empty classes have data members and/or * vtable pointers that must be stored in each instance for proper behavior. * * static_assert(!mozilla::IsEmpty<int>::value, "not a class => not empty"); * union U1 { int x; }; * static_assert(!mozilla::IsEmpty<U1>::value, "not a class => not empty"); * struct E1 {}; * struct E2 { int : 0 }; * struct E3 : E1 {}; * struct E4 : E2 {}; * static_assert(mozilla::IsEmpty<E1>::value && * mozilla::IsEmpty<E2>::value && * mozilla::IsEmpty<E3>::value && * mozilla::IsEmpty<E4>::value, * "all empty"); * union U2 { E1 e1; }; * static_assert(!mozilla::IsEmpty<U2>::value, "not a class => not empty"); * struct NE1 { int x; }; * struct NE2 : virtual E1 {}; * struct NE3 : E2 { virtual ~NE3() {} }; * struct NE4 { virtual void f() {} }; * static_assert(!mozilla::IsEmpty<NE1>::value && * !mozilla::IsEmpty<NE2>::value && * !mozilla::IsEmpty<NE3>::value && * !mozilla::IsEmpty<NE4>::value, * "all empty"); */template<typenameT>structIsEmpty:detail::IsEmptyHelper<typenameRemoveCV<T>::Type>{};namespacedetail{template<typenameT,bool=IsFloatingPoint<T>::value,bool=IsIntegral<T>::value,typenameNoCV=typenameRemoveCV<T>::Type>structIsSignedHelper;// Floating point is signed.template<typenameT,typenameNoCV>structIsSignedHelper<T,true,false,NoCV>:TrueType{};// Integral is conditionally signed.template<typenameT,typenameNoCV>structIsSignedHelper<T,false,true,NoCV>:IntegralConstant<bool,bool(NoCV(-1)<NoCV(1))>{};// Non-floating point, non-integral is not signed.template<typenameT,typenameNoCV>structIsSignedHelper<T,false,false,NoCV>:FalseType{};}// namespace detail/** * IsSigned determines whether a type is a signed arithmetic type. |char| is * considered a signed type if it has the same representation as |signed char|. * * mozilla::IsSigned<int>::value is true; * mozilla::IsSigned<const unsigned int>::value is false; * mozilla::IsSigned<unsigned char>::value is false; * mozilla::IsSigned<float>::value is true. */template<typenameT>structIsSigned:detail::IsSignedHelper<T>{};namespacedetail{template<typenameT,bool=IsFloatingPoint<T>::value,bool=IsIntegral<T>::value,typenameNoCV=typenameRemoveCV<T>::Type>structIsUnsignedHelper;// Floating point is not unsigned.template<typenameT,typenameNoCV>structIsUnsignedHelper<T,true,false,NoCV>:FalseType{};// Integral is conditionally unsigned.template<typenameT,typenameNoCV>structIsUnsignedHelper<T,false,true,NoCV>:IntegralConstant<bool,(IsSame<NoCV,bool>::value||bool(NoCV(1)<NoCV(-1)))>{};// Non-floating point, non-integral is not unsigned.template<typenameT,typenameNoCV>structIsUnsignedHelper<T,false,false,NoCV>:FalseType{};}// namespace detail/** * IsUnsigned determines whether a type is an unsigned arithmetic type. * * mozilla::IsUnsigned<int>::value is false; * mozilla::IsUnsigned<const unsigned int>::value is true; * mozilla::IsUnsigned<unsigned char>::value is true; * mozilla::IsUnsigned<float>::value is false. */template<typenameT>structIsUnsigned:detail::IsUnsignedHelper<T>{};/* 20.9.5 Type property queries [meta.unary.prop.query] *//* 20.9.6 Relationships between types [meta.rel] *//** * IsSame tests whether two types are the same type. * * mozilla::IsSame<int, int>::value is true; * mozilla::IsSame<int*, int*>::value is true; * mozilla::IsSame<int, unsigned int>::value is false; * mozilla::IsSame<void, void>::value is true; * mozilla::IsSame<const int, int>::value is false; * mozilla::IsSame<struct S, struct S>::value is true. */template<typenameT,typenameU>structIsSame:FalseType{};template<typenameT>structIsSame<T,T>:TrueType{};namespacedetail{#if defined(__GNUC__) || defined(__clang__) || defined(_MSC_VER)template<classBase,classDerived>structBaseOfTester:IntegralConstant<bool,__is_base_of(Base,Derived)>{};#else// The trickery used to implement IsBaseOf here makes it possible to use it for// the cases of private and multiple inheritance. This code was inspired by the// sample code here://// http://stackoverflow.com/questions/2910979/how-is-base-of-workstemplate<classBase,classDerived>structBaseOfHelper{public:operatorBase*()const;operatorDerived*();};template<classBase,classDerived>structBaseOfTester{private:template<classT>staticchartest(Derived*,T);staticinttest(Base*,int);public:staticconstboolvalue=sizeof(test(BaseOfHelper<Base,Derived>(),int()))==sizeof(char);};template<classBase,classDerived>structBaseOfTester<Base,constDerived>{private:template<classT>staticchartest(Derived*,T);staticinttest(Base*,int);public:staticconstboolvalue=sizeof(test(BaseOfHelper<Base,Derived>(),int()))==sizeof(char);};template<classBase,classDerived>structBaseOfTester<Base&,Derived&>:FalseType{};template<classType>structBaseOfTester<Type,Type>:TrueType{};template<classType>structBaseOfTester<Type,constType>:TrueType{};#endif}/* namespace detail *//* * IsBaseOf allows to know whether a given class is derived from another. * * Consider the following class definitions: * * class A {}; * class B : public A {}; * class C {}; * * mozilla::IsBaseOf<A, B>::value is true; * mozilla::IsBaseOf<A, C>::value is false; */template<classBase,classDerived>structIsBaseOf:IntegralConstant<bool,detail::BaseOfTester<Base,Derived>::value>{};namespacedetail{template<typenameFrom,typenameTo>structConvertibleTester{private:staticFromcreate();template<typenameFrom1,typenameTo1>staticchartest(Toto);template<typenameFrom1,typenameTo1>staticinttest(...);public:staticconstboolvalue=sizeof(test<From,To>(create()))==sizeof(char);};}// namespace detail/** * IsConvertible determines whether a value of type From will implicitly convert * to a value of type To. For example: * * struct A {}; * struct B : public A {}; * struct C {}; * * mozilla::IsConvertible<A, A>::value is true; * mozilla::IsConvertible<A*, A*>::value is true; * mozilla::IsConvertible<B, A>::value is true; * mozilla::IsConvertible<B*, A*>::value is true; * mozilla::IsConvertible<C, A>::value is false; * mozilla::IsConvertible<A, C>::value is false; * mozilla::IsConvertible<A*, C*>::value is false; * mozilla::IsConvertible<C*, A*>::value is false. * * For obscure reasons, you can't use IsConvertible when the types being tested * are related through private inheritance, and you'll get a compile error if * you try. Just don't do it! */template<typenameFrom,typenameTo>structIsConvertible:IntegralConstant<bool,detail::ConvertibleTester<From,To>::value>{};/* 20.9.7 Transformations between types [meta.trans] *//* 20.9.7.1 Const-volatile modifications [meta.trans.cv] *//** * RemoveConst removes top-level const qualifications on a type. * * mozilla::RemoveConst<int>::Type is int; * mozilla::RemoveConst<const int>::Type is int; * mozilla::RemoveConst<const int*>::Type is const int*; * mozilla::RemoveConst<int* const>::Type is int*. */template<typenameT>structRemoveConst{typedefTType;};template<typenameT>structRemoveConst<constT>{typedefTType;};/** * RemoveVolatile removes top-level volatile qualifications on a type. * * mozilla::RemoveVolatile<int>::Type is int; * mozilla::RemoveVolatile<volatile int>::Type is int; * mozilla::RemoveVolatile<volatile int*>::Type is volatile int*; * mozilla::RemoveVolatile<int* volatile>::Type is int*. */template<typenameT>structRemoveVolatile{typedefTType;};template<typenameT>structRemoveVolatile<volatileT>{typedefTType;};/** * RemoveCV removes top-level const and volatile qualifications on a type. * * mozilla::RemoveCV<int>::Type is int; * mozilla::RemoveCV<const int>::Type is int; * mozilla::RemoveCV<volatile int>::Type is int; * mozilla::RemoveCV<int* const volatile>::Type is int*. */template<typenameT>structRemoveCV{typedeftypenameRemoveConst<typenameRemoveVolatile<T>::Type>::TypeType;};/* 20.9.7.2 Reference modifications [meta.trans.ref] *//** * Converts reference types to the underlying types. * * mozilla::RemoveReference<T>::Type is T; * mozilla::RemoveReference<T&>::Type is T; * mozilla::RemoveReference<T&&>::Type is T; */template<typenameT>structRemoveReference{typedefTType;};template<typenameT>structRemoveReference<T&>{typedefTType;};template<typenameT>structRemoveReference<T&&>{typedefTType;};template<boolCondition,typenameA,typenameB>structConditional;namespacedetail{enumVoidness{TIsVoid,TIsNotVoid};template<typenameT,VoidnessV=IsVoid<T>::value?TIsVoid:TIsNotVoid>structAddLvalueReferenceHelper;template<typenameT>structAddLvalueReferenceHelper<T,TIsVoid>{typedefvoidType;};template<typenameT>structAddLvalueReferenceHelper<T,TIsNotVoid>{typedefT&Type;};}// namespace detail/** * AddLvalueReference adds an lvalue & reference to T if one isn't already * present. (Note: adding an lvalue reference to an rvalue && reference in * essence replaces the && with a &&, per C+11 reference collapsing rules. For * example, int&& would become int&.) * * The final computed type will only *not* be an lvalue reference if T is void. * * mozilla::AddLvalueReference<int>::Type is int&; * mozilla::AddLvalueRference<volatile int&>::Type is volatile int&; * mozilla::AddLvalueReference<void*>::Type is void*&; * mozilla::AddLvalueReference<void>::Type is void; * mozilla::AddLvalueReference<struct S&&>::Type is struct S&. */template<typenameT>structAddLvalueReference:detail::AddLvalueReferenceHelper<T>{};/* 20.9.7.3 Sign modifications [meta.trans.sign] */template<boolB,typenameT=void>structEnableIf;namespacedetail{template<boolMakeConst,typenameT>structWithC:Conditional<MakeConst,constT,T>{};template<boolMakeVolatile,typenameT>structWithV:Conditional<MakeVolatile,volatileT,T>{};template<boolMakeConst,boolMakeVolatile,typenameT>structWithCV:WithC<MakeConst,typenameWithV<MakeVolatile,T>::Type>{};template<typenameT>structCorrespondingSigned;template<>structCorrespondingSigned<char>{typedefsignedcharType;};template<>structCorrespondingSigned<unsignedchar>{typedefsignedcharType;};template<>structCorrespondingSigned<unsignedshort>{typedefshortType;};template<>structCorrespondingSigned<unsignedint>{typedefintType;};template<>structCorrespondingSigned<unsignedlong>{typedeflongType;};template<>structCorrespondingSigned<unsignedlonglong>{typedeflonglongType;};template<typenameT,typenameCVRemoved=typenameRemoveCV<T>::Type,boolIsSignedIntegerType=IsSigned<CVRemoved>::value&&!IsSame<char,CVRemoved>::value>structMakeSigned;template<typenameT,typenameCVRemoved>structMakeSigned<T,CVRemoved,true>{typedefTType;};template<typenameT,typenameCVRemoved>structMakeSigned<T,CVRemoved,false>:WithCV<IsConst<T>::value,IsVolatile<T>::value,typenameCorrespondingSigned<CVRemoved>::Type>{};}// namespace detail/** * MakeSigned produces the corresponding signed integer type for a given * integral type T, with the const/volatile qualifiers of T. T must be a * possibly-const/volatile-qualified integral type that isn't bool. * * If T is already a signed integer type (not including char!), then T is * produced. * * Otherwise, if T is an unsigned integer type, the signed variety of T, with * T's const/volatile qualifiers, is produced. * * Otherwise, the integral type of the same size as T, with the lowest rank, * with T's const/volatile qualifiers, is produced. (This basically only acts * to produce signed char when T = char.) * * mozilla::MakeSigned<unsigned long>::Type is signed long; * mozilla::MakeSigned<volatile int>::Type is volatile int; * mozilla::MakeSigned<const unsigned short>::Type is const signed short; * mozilla::MakeSigned<const char>::Type is const signed char; * mozilla::MakeSigned<bool> is an error; * mozilla::MakeSigned<void*> is an error. */template<typenameT>structMakeSigned:EnableIf<IsIntegral<T>::value&&!IsSame<bool,typenameRemoveCV<T>::Type>::value,typenamedetail::MakeSigned<T>>::Type{};namespacedetail{template<typenameT>structCorrespondingUnsigned;template<>structCorrespondingUnsigned<char>{typedefunsignedcharType;};template<>structCorrespondingUnsigned<signedchar>{typedefunsignedcharType;};template<>structCorrespondingUnsigned<short>{typedefunsignedshortType;};template<>structCorrespondingUnsigned<int>{typedefunsignedintType;};template<>structCorrespondingUnsigned<long>{typedefunsignedlongType;};template<>structCorrespondingUnsigned<longlong>{typedefunsignedlonglongType;};template<typenameT,typenameCVRemoved=typenameRemoveCV<T>::Type,boolIsUnsignedIntegerType=IsUnsigned<CVRemoved>::value&&!IsSame<char,CVRemoved>::value>structMakeUnsigned;template<typenameT,typenameCVRemoved>structMakeUnsigned<T,CVRemoved,true>{typedefTType;};template<typenameT,typenameCVRemoved>structMakeUnsigned<T,CVRemoved,false>:WithCV<IsConst<T>::value,IsVolatile<T>::value,typenameCorrespondingUnsigned<CVRemoved>::Type>{};}// namespace detail/** * MakeUnsigned produces the corresponding unsigned integer type for a given * integral type T, with the const/volatile qualifiers of T. T must be a * possibly-const/volatile-qualified integral type that isn't bool. * * If T is already an unsigned integer type (not including char!), then T is * produced. * * Otherwise, if T is an signed integer type, the unsigned variety of T, with * T's const/volatile qualifiers, is produced. * * Otherwise, the unsigned integral type of the same size as T, with the lowest * rank, with T's const/volatile qualifiers, is produced. (This basically only * acts to produce unsigned char when T = char.) * * mozilla::MakeUnsigned<signed long>::Type is unsigned long; * mozilla::MakeUnsigned<volatile unsigned int>::Type is volatile unsigned int; * mozilla::MakeUnsigned<const signed short>::Type is const unsigned short; * mozilla::MakeUnsigned<const char>::Type is const unsigned char; * mozilla::MakeUnsigned<bool> is an error; * mozilla::MakeUnsigned<void*> is an error. */template<typenameT>structMakeUnsigned:EnableIf<IsIntegral<T>::value&&!IsSame<bool,typenameRemoveCV<T>::Type>::value,typenamedetail::MakeUnsigned<T>>::Type{};/* 20.9.7.4 Array modifications [meta.trans.arr] *//** * RemoveExtent produces either the type of the elements of the array T, or T * itself. * * mozilla::RemoveExtent<int>::Type is int; * mozilla::RemoveExtent<const int[]>::Type is const int; * mozilla::RemoveExtent<volatile int[5]>::Type is volatile int; * mozilla::RemoveExtent<long[][17]>::Type is long[17]. */template<typenameT>structRemoveExtent{typedefTType;};template<typenameT>structRemoveExtent<T[]>{typedefTType;};template<typenameT,decltype(sizeof(1))N>structRemoveExtent<T[N]>{typedefTType;};/* 20.9.7.5 Pointer modifications [meta.trans.ptr] *//* 20.9.7.6 Other transformations [meta.trans.other] *//** * EnableIf is a struct containing a typedef of T if and only if B is true. * * mozilla::EnableIf<true, int>::Type is int; * mozilla::EnableIf<false, int>::Type is a compile-time error. * * Use this template to implement SFINAE-style (Substitution Failure Is not An * Error) requirements. For example, you might use it to impose a restriction * on a template parameter: * * template<typename T> * class PodVector // vector optimized to store POD (memcpy-able) types * { * EnableIf<IsPod<T>::value, T>::Type* vector; * size_t length; * ... * }; */template<boolB,typenameT>structEnableIf{};template<typenameT>structEnableIf<true,T>{typedefTType;};/** * Conditional selects a class between two, depending on a given boolean value. * * mozilla::Conditional<true, A, B>::Type is A; * mozilla::Conditional<false, A, B>::Type is B; */template<boolCondition,typenameA,typenameB>structConditional{typedefAType;};template<classA,classB>structConditional<false,A,B>{typedefBType;};}/* namespace mozilla */#endif /* mozilla_TypeTraits_h */