1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 /* Template-based metaprogramming and type-testing facilities. */
9 #ifndef mozilla_TypeTraits_h
10 #define mozilla_TypeTraits_h
12 #include "mozilla/Types.h"
15 * These traits are approximate copies of the traits and semantics from C++11's
16 * <type_traits> header. Don't add traits not in that header! When all
17 * platforms provide that header, we can convert all users and remove this one.
24 /* Forward declarations. */
26 template<typename
> struct RemoveCV
;
27 template<typename
> struct AddRvalueReference
;
29 /* 20.2.4 Function template declval [declval] */
32 * DeclVal simplifies the definition of expressions which occur as unevaluated
33 * operands. It converts T to a reference type, making it possible to use in
34 * decltype expressions even if T does not have a default constructor, e.g.:
35 * decltype(DeclVal<TWithNoDefaultConstructor>().foo())
38 typename AddRvalueReference
<T
>::Type
DeclVal();
40 /* 20.9.3 Helper classes [meta.help] */
43 * Helper class used as a base for various type traits, exposed publicly
44 * because <type_traits> exposes it as well.
46 template<typename T
, T Value
>
47 struct IntegralConstant
49 static constexpr T value
= Value
;
51 typedef IntegralConstant
<T
, Value
> Type
;
54 /** Convenient aliases. */
55 typedef IntegralConstant
<bool, true> TrueType
;
56 typedef IntegralConstant
<bool, false> FalseType
;
58 /* 20.9.4 Unary type traits [meta.unary] */
60 /* 20.9.4.1 Primary type categories [meta.unary.cat] */
65 struct IsVoidHelper
: FalseType
{};
68 struct IsVoidHelper
<void> : TrueType
{};
73 * IsVoid determines whether a type is void.
75 * mozilla::IsVoid<int>::value is false;
76 * mozilla::IsVoid<void>::value is true;
77 * mozilla::IsVoid<void*>::value is false;
78 * mozilla::IsVoid<volatile void>::value is true.
81 struct IsVoid
: detail::IsVoidHelper
<typename RemoveCV
<T
>::Type
> {};
86 struct IsIntegralHelper
: FalseType
{};
88 template<> struct IsIntegralHelper
<char> : TrueType
{};
89 template<> struct IsIntegralHelper
<signed char> : TrueType
{};
90 template<> struct IsIntegralHelper
<unsigned char> : TrueType
{};
91 template<> struct IsIntegralHelper
<short> : TrueType
{};
92 template<> struct IsIntegralHelper
<unsigned short> : TrueType
{};
93 template<> struct IsIntegralHelper
<int> : TrueType
{};
94 template<> struct IsIntegralHelper
<unsigned int> : TrueType
{};
95 template<> struct IsIntegralHelper
<long> : TrueType
{};
96 template<> struct IsIntegralHelper
<unsigned long> : TrueType
{};
97 template<> struct IsIntegralHelper
<long long> : TrueType
{};
98 template<> struct IsIntegralHelper
<unsigned long long> : TrueType
{};
99 template<> struct IsIntegralHelper
<bool> : TrueType
{};
100 template<> struct IsIntegralHelper
<wchar_t> : TrueType
{};
101 template<> struct IsIntegralHelper
<char16_t
> : TrueType
{};
103 } /* namespace detail */
106 * IsIntegral determines whether a type is an integral type.
108 * mozilla::IsIntegral<int>::value is true;
109 * mozilla::IsIntegral<unsigned short>::value is true;
110 * mozilla::IsIntegral<const long>::value is true;
111 * mozilla::IsIntegral<int*>::value is false;
112 * mozilla::IsIntegral<double>::value is false;
115 struct IsIntegral
: detail::IsIntegralHelper
<typename RemoveCV
<T
>::Type
>
118 template<typename T
, typename U
>
124 struct IsFloatingPointHelper
125 : IntegralConstant
<bool,
126 IsSame
<T
, float>::value
||
127 IsSame
<T
, double>::value
||
128 IsSame
<T
, long double>::value
>
131 } // namespace detail
134 * IsFloatingPoint determines whether a type is a floating point type (float,
135 * double, long double).
137 * mozilla::IsFloatingPoint<int>::value is false;
138 * mozilla::IsFloatingPoint<const float>::value is true;
139 * mozilla::IsFloatingPoint<long double>::value is true;
140 * mozilla::IsFloatingPoint<double*>::value is false.
143 struct IsFloatingPoint
144 : detail::IsFloatingPointHelper
<typename RemoveCV
<T
>::Type
>
150 struct IsArrayHelper
: FalseType
{};
152 template<typename T
, decltype(sizeof(1)) N
>
153 struct IsArrayHelper
<T
[N
]> : TrueType
{};
156 struct IsArrayHelper
<T
[]> : TrueType
{};
158 } // namespace detail
161 * IsArray determines whether a type is an array type, of known or unknown
164 * mozilla::IsArray<int>::value is false;
165 * mozilla::IsArray<int[]>::value is true;
166 * mozilla::IsArray<int[5]>::value is true.
169 struct IsArray
: detail::IsArrayHelper
<typename RemoveCV
<T
>::Type
>
182 template<typename Result
, typename
... ArgTypes
>
183 struct IsFunPtr
<Result(*)(ArgTypes
...)>
187 }; // namespace detail
190 * IsFunction determines whether a type is a function type. Function pointers
191 * don't qualify here--only the type of an actual function symbol. We do not
192 * correctly handle varags function types because of a bug in MSVC.
194 * Given the function:
197 * mozilla::IsFunction<void(int)> is true;
198 * mozilla::IsFunction<void(*)(int)> is false;
199 * mozilla::IsFunction<decltype(f)> is true.
203 : public detail::IsFunPtr
<typename RemoveCV
<T
>::Type
*>
209 struct IsPointerHelper
: FalseType
{};
212 struct IsPointerHelper
<T
*> : TrueType
{};
214 } // namespace detail
217 * IsPointer determines whether a type is a possibly-CV-qualified pointer type
218 * (but not a pointer-to-member type).
220 * mozilla::IsPointer<struct S*>::value is true;
221 * mozilla::IsPointer<int*>::value is true;
222 * mozilla::IsPointer<int**>::value is true;
223 * mozilla::IsPointer<const int*>::value is true;
224 * mozilla::IsPointer<int* const>::value is true;
225 * mozilla::IsPointer<int* volatile>::value is true;
226 * mozilla::IsPointer<void (*)(void)>::value is true;
227 * mozilla::IsPointer<int>::value is false;
228 * mozilla::IsPointer<struct S>::value is false.
229 * mozilla::IsPointer<int(struct S::*)>::value is false
232 struct IsPointer
: detail::IsPointerHelper
<typename RemoveCV
<T
>::Type
>
236 * IsLvalueReference determines whether a type is an lvalue reference.
238 * mozilla::IsLvalueReference<struct S*>::value is false;
239 * mozilla::IsLvalueReference<int**>::value is false;
240 * mozilla::IsLvalueReference<void (*)(void)>::value is false;
241 * mozilla::IsLvalueReference<int>::value is false;
242 * mozilla::IsLvalueReference<struct S>::value is false;
243 * mozilla::IsLvalueReference<struct S*&>::value is true;
244 * mozilla::IsLvalueReference<struct S&&>::value is false.
247 struct IsLvalueReference
: FalseType
{};
250 struct IsLvalueReference
<T
&> : TrueType
{};
253 * IsRvalueReference determines whether a type is an rvalue reference.
255 * mozilla::IsRvalueReference<struct S*>::value is false;
256 * mozilla::IsRvalueReference<int**>::value is false;
257 * mozilla::IsRvalueReference<void (*)(void)>::value is false;
258 * mozilla::IsRvalueReference<int>::value is false;
259 * mozilla::IsRvalueReference<struct S>::value is false;
260 * mozilla::IsRvalueReference<struct S*&>::value is false;
261 * mozilla::IsRvalueReference<struct S&&>::value is true.
264 struct IsRvalueReference
: FalseType
{};
267 struct IsRvalueReference
<T
&&> : TrueType
{};
271 // __is_enum is a supported extension across all of our supported compilers.
274 : IntegralConstant
<bool, __is_enum(T
)>
277 } // namespace detail
280 * IsEnum determines whether a type is an enum type.
282 * mozilla::IsEnum<enum S>::value is true;
283 * mozilla::IsEnum<enum S*>::value is false;
284 * mozilla::IsEnum<int>::value is false;
288 : detail::IsEnumHelper
<typename RemoveCV
<T
>::Type
>
293 // __is_class is a supported extension across all of our supported compilers:
294 // http://llvm.org/releases/3.0/docs/ClangReleaseNotes.html
295 // http://gcc.gnu.org/onlinedocs/gcc-4.4.7/gcc/Type-Traits.html#Type-Traits
296 // http://msdn.microsoft.com/en-us/library/ms177194%28v=vs.100%29.aspx
299 : IntegralConstant
<bool, __is_class(T
)>
302 } // namespace detail
305 * IsClass determines whether a type is a class type (but not a union).
309 * mozilla::IsClass<int>::value is false;
310 * mozilla::IsClass<const S>::value is true;
311 * mozilla::IsClass<U>::value is false;
315 : detail::IsClassHelper
<typename RemoveCV
<T
>::Type
>
318 /* 20.9.4.2 Composite type traits [meta.unary.comp] */
321 * IsReference determines whether a type is an lvalue or rvalue reference.
323 * mozilla::IsReference<struct S*>::value is false;
324 * mozilla::IsReference<int**>::value is false;
325 * mozilla::IsReference<int&>::value is true;
326 * mozilla::IsReference<void (*)(void)>::value is false;
327 * mozilla::IsReference<const int&>::value is true;
328 * mozilla::IsReference<int>::value is false;
329 * mozilla::IsReference<struct S>::value is false;
330 * mozilla::IsReference<struct S&>::value is true;
331 * mozilla::IsReference<struct S*&>::value is true;
332 * mozilla::IsReference<struct S&&>::value is true.
336 : IntegralConstant
<bool,
337 IsLvalueReference
<T
>::value
|| IsRvalueReference
<T
>::value
>
341 * IsArithmetic determines whether a type is arithmetic. A type is arithmetic
342 * iff it is an integral type or a floating point type.
344 * mozilla::IsArithmetic<int>::value is true;
345 * mozilla::IsArithmetic<double>::value is true;
346 * mozilla::IsArithmetic<long double*>::value is false.
350 : IntegralConstant
<bool, IsIntegral
<T
>::value
|| IsFloatingPoint
<T
>::value
>
356 struct IsMemberPointerHelper
: FalseType
{};
358 template<typename T
, typename U
>
359 struct IsMemberPointerHelper
<T
U::*> : TrueType
{};
361 } // namespace detail
364 * IsMemberPointer determines whether a type is pointer to non-static member
365 * object or a pointer to non-static member function.
367 * mozilla::IsMemberPointer<int(cls::*)>::value is true
368 * mozilla::IsMemberPointer<int*>::value is false
371 struct IsMemberPointer
372 : detail::IsMemberPointerHelper
<typename RemoveCV
<T
>::Type
>
376 * IsScalar determines whether a type is a scalar type.
378 * mozilla::IsScalar<int>::value is true
379 * mozilla::IsScalar<int*>::value is true
380 * mozilla::IsScalar<cls>::value is false
384 : IntegralConstant
<bool, IsArithmetic
<T
>::value
|| IsEnum
<T
>::value
||
385 IsPointer
<T
>::value
|| IsMemberPointer
<T
>::value
>
388 /* 20.9.4.3 Type properties [meta.unary.prop] */
391 * IsConst determines whether a type is const or not.
393 * mozilla::IsConst<int>::value is false;
394 * mozilla::IsConst<void* const>::value is true;
395 * mozilla::IsConst<const char*>::value is false.
398 struct IsConst
: FalseType
{};
401 struct IsConst
<const T
> : TrueType
{};
404 * IsVolatile determines whether a type is volatile or not.
406 * mozilla::IsVolatile<int>::value is false;
407 * mozilla::IsVolatile<void* volatile>::value is true;
408 * mozilla::IsVolatile<volatile char*>::value is false.
411 struct IsVolatile
: FalseType
{};
414 struct IsVolatile
<volatile T
> : TrueType
{};
417 * Traits class for identifying POD types. Until C++11 there's no automatic
418 * way to detect PODs, so for the moment this is done manually. Users may
419 * define specializations of this class that inherit from mozilla::TrueType and
420 * mozilla::FalseType (or equivalently mozilla::IntegralConstant<bool, true or
421 * false>, or conveniently from mozilla::IsPod for composite types) as needed to
422 * ensure correct IsPod behavior.
425 struct IsPod
: public FalseType
{};
427 template<> struct IsPod
<char> : TrueType
{};
428 template<> struct IsPod
<signed char> : TrueType
{};
429 template<> struct IsPod
<unsigned char> : TrueType
{};
430 template<> struct IsPod
<short> : TrueType
{};
431 template<> struct IsPod
<unsigned short> : TrueType
{};
432 template<> struct IsPod
<int> : TrueType
{};
433 template<> struct IsPod
<unsigned int> : TrueType
{};
434 template<> struct IsPod
<long> : TrueType
{};
435 template<> struct IsPod
<unsigned long> : TrueType
{};
436 template<> struct IsPod
<long long> : TrueType
{};
437 template<> struct IsPod
<unsigned long long> : TrueType
{};
438 template<> struct IsPod
<bool> : TrueType
{};
439 template<> struct IsPod
<float> : TrueType
{};
440 template<> struct IsPod
<double> : TrueType
{};
441 template<> struct IsPod
<wchar_t> : TrueType
{};
442 template<> struct IsPod
<char16_t
> : TrueType
{};
443 template<typename T
> struct IsPod
<T
*> : TrueType
{};
447 // __is_empty is a supported extension across all of our supported compilers:
448 // http://llvm.org/releases/3.0/docs/ClangReleaseNotes.html
449 // http://gcc.gnu.org/onlinedocs/gcc-4.4.7/gcc/Type-Traits.html#Type-Traits
450 // http://msdn.microsoft.com/en-us/library/ms177194%28v=vs.100%29.aspx
453 : IntegralConstant
<bool, IsClass
<T
>::value
&& __is_empty(T
)>
456 } // namespace detail
459 * IsEmpty determines whether a type is a class (but not a union) that is empty.
461 * A class is empty iff it and all its base classes have no non-static data
462 * members (except bit-fields of length 0) and no virtual member functions, and
463 * no base class is empty or a virtual base class.
465 * Intuitively, empty classes don't have any data that has to be stored in
466 * instances of those classes. (The size of the class must still be non-zero,
467 * because distinct array elements of any type must have different addresses.
468 * However, if the Empty Base Optimization is implemented by the compiler [most
469 * compilers implement it, and in certain cases C++11 requires it], the size of
470 * a class inheriting from an empty |Base| class need not be inflated by
471 * |sizeof(Base)|.) And intuitively, non-empty classes have data members and/or
472 * vtable pointers that must be stored in each instance for proper behavior.
474 * static_assert(!mozilla::IsEmpty<int>::value, "not a class => not empty");
475 * union U1 { int x; };
476 * static_assert(!mozilla::IsEmpty<U1>::value, "not a class => not empty");
478 * struct E2 { int : 0 };
481 * static_assert(mozilla::IsEmpty<E1>::value &&
482 * mozilla::IsEmpty<E2>::value &&
483 * mozilla::IsEmpty<E3>::value &&
484 * mozilla::IsEmpty<E4>::value,
486 * union U2 { E1 e1; };
487 * static_assert(!mozilla::IsEmpty<U2>::value, "not a class => not empty");
488 * struct NE1 { int x; };
489 * struct NE2 : virtual E1 {};
490 * struct NE3 : E2 { virtual ~NE3() {} };
491 * struct NE4 { virtual void f() {} };
492 * static_assert(!mozilla::IsEmpty<NE1>::value &&
493 * !mozilla::IsEmpty<NE2>::value &&
494 * !mozilla::IsEmpty<NE3>::value &&
495 * !mozilla::IsEmpty<NE4>::value,
499 struct IsEmpty
: detail::IsEmptyHelper
<typename RemoveCV
<T
>::Type
>
506 bool = IsFloatingPoint
<T
>::value
,
507 bool = IsIntegral
<T
>::value
,
508 typename NoCV
= typename RemoveCV
<T
>::Type
>
509 struct IsSignedHelper
;
511 // Floating point is signed.
512 template<typename T
, typename NoCV
>
513 struct IsSignedHelper
<T
, true, false, NoCV
> : TrueType
{};
515 // Integral is conditionally signed.
516 template<typename T
, typename NoCV
>
517 struct IsSignedHelper
<T
, false, true, NoCV
>
518 : IntegralConstant
<bool, bool(NoCV(-1) < NoCV(1))>
521 // Non-floating point, non-integral is not signed.
522 template<typename T
, typename NoCV
>
523 struct IsSignedHelper
<T
, false, false, NoCV
> : FalseType
{};
525 } // namespace detail
528 * IsSigned determines whether a type is a signed arithmetic type. |char| is
529 * considered a signed type if it has the same representation as |signed char|.
531 * mozilla::IsSigned<int>::value is true;
532 * mozilla::IsSigned<const unsigned int>::value is false;
533 * mozilla::IsSigned<unsigned char>::value is false;
534 * mozilla::IsSigned<float>::value is true.
537 struct IsSigned
: detail::IsSignedHelper
<T
> {};
542 bool = IsFloatingPoint
<T
>::value
,
543 bool = IsIntegral
<T
>::value
,
544 typename NoCV
= typename RemoveCV
<T
>::Type
>
545 struct IsUnsignedHelper
;
547 // Floating point is not unsigned.
548 template<typename T
, typename NoCV
>
549 struct IsUnsignedHelper
<T
, true, false, NoCV
> : FalseType
{};
551 // Integral is conditionally unsigned.
552 template<typename T
, typename NoCV
>
553 struct IsUnsignedHelper
<T
, false, true, NoCV
>
554 : IntegralConstant
<bool,
555 (IsSame
<NoCV
, bool>::value
|| bool(NoCV(1) < NoCV(-1)))>
558 // Non-floating point, non-integral is not unsigned.
559 template<typename T
, typename NoCV
>
560 struct IsUnsignedHelper
<T
, false, false, NoCV
> : FalseType
{};
562 } // namespace detail
565 * IsUnsigned determines whether a type is an unsigned arithmetic type.
567 * mozilla::IsUnsigned<int>::value is false;
568 * mozilla::IsUnsigned<const unsigned int>::value is true;
569 * mozilla::IsUnsigned<unsigned char>::value is true;
570 * mozilla::IsUnsigned<float>::value is false.
573 struct IsUnsigned
: detail::IsUnsignedHelper
<T
> {};
577 struct DoIsDefaultConstructibleImpl
579 template<typename T
, typename
= decltype(T())>
580 static TrueType
test(int);
582 static FalseType
test(...);
586 struct IsDefaultConstructibleImpl
: public DoIsDefaultConstructibleImpl
588 typedef decltype(test
<T
>(0)) Type
;
591 } // namespace detail
594 * IsDefaultConstructible determines whether a type has a public default
597 * struct S0 {}; // Implicit default constructor.
598 * struct S1 { S1(); };
599 * struct S2 { explicit S2(int); }; // No implicit default constructor when
600 * // another one is present.
601 * struct S3 { S3() = delete; };
602 * class C4 { C4(); }; // Default constructor is private.
604 * mozilla::IsDefaultConstructible<int>::value is true;
605 * mozilla::IsDefaultConstructible<S0>::value is true;
606 * mozilla::IsDefaultConstructible<S1>::value is true;
607 * mozilla::IsDefaultConstructible<S2>::value is false;
608 * mozilla::IsDefaultConstructible<S3>::value is false;
609 * mozilla::IsDefaultConstructible<S4>::value is false.
612 struct IsDefaultConstructible
613 : public detail::IsDefaultConstructibleImpl
<T
>::Type
618 struct DoIsDestructibleImpl
620 template<typename T
, typename
= decltype(DeclVal
<T
&>().~T())>
621 static TrueType
test(int);
623 static FalseType
test(...);
627 struct IsDestructibleImpl
: public DoIsDestructibleImpl
629 typedef decltype(test
<T
>(0)) Type
;
632 } // namespace detail
635 * IsDestructible determines whether a type has a public destructor.
637 * struct S0 {}; // Implicit default destructor.
638 * struct S1 { ~S1(); };
639 * class C2 { ~C2(); }; // private destructor.
641 * mozilla::IsDestructible<S0>::value is true;
642 * mozilla::IsDestructible<S1>::value is true;
643 * mozilla::IsDestructible<C2>::value is false.
646 struct IsDestructible
: public detail::IsDestructibleImpl
<T
>::Type
{};
648 /* 20.9.5 Type property queries [meta.unary.prop.query] */
650 /* 20.9.6 Relationships between types [meta.rel] */
653 * IsSame tests whether two types are the same type.
655 * mozilla::IsSame<int, int>::value is true;
656 * mozilla::IsSame<int*, int*>::value is true;
657 * mozilla::IsSame<int, unsigned int>::value is false;
658 * mozilla::IsSame<void, void>::value is true;
659 * mozilla::IsSame<const int, int>::value is false;
660 * mozilla::IsSame<struct S, struct S>::value is true.
662 template<typename T
, typename U
>
663 struct IsSame
: FalseType
{};
666 struct IsSame
<T
, T
> : TrueType
{};
670 #if defined(__GNUC__) || defined(__clang__) || defined(_MSC_VER)
672 template<class Base
, class Derived
>
673 struct BaseOfTester
: IntegralConstant
<bool, __is_base_of(Base
, Derived
)> {};
677 // The trickery used to implement IsBaseOf here makes it possible to use it for
678 // the cases of private and multiple inheritance. This code was inspired by the
681 // http://stackoverflow.com/questions/2910979/how-is-base-of-works
682 template<class Base
, class Derived
>
686 operator Base
*() const;
690 template<class Base
, class Derived
>
695 static char test(Derived
*, T
);
696 static int test(Base
*, int);
699 static const bool value
=
700 sizeof(test(BaseOfHelper
<Base
, Derived
>(), int())) == sizeof(char);
703 template<class Base
, class Derived
>
704 struct BaseOfTester
<Base
, const Derived
>
708 static char test(Derived
*, T
);
709 static int test(Base
*, int);
712 static const bool value
=
713 sizeof(test(BaseOfHelper
<Base
, Derived
>(), int())) == sizeof(char);
716 template<class Base
, class Derived
>
717 struct BaseOfTester
<Base
&, Derived
&> : FalseType
{};
720 struct BaseOfTester
<Type
, Type
> : TrueType
{};
723 struct BaseOfTester
<Type
, const Type
> : TrueType
{};
727 } /* namespace detail */
730 * IsBaseOf allows to know whether a given class is derived from another.
732 * Consider the following class definitions:
735 * class B : public A {};
738 * mozilla::IsBaseOf<A, B>::value is true;
739 * mozilla::IsBaseOf<A, C>::value is false;
741 template<class Base
, class Derived
>
743 : IntegralConstant
<bool, detail::BaseOfTester
<Base
, Derived
>::value
>
748 template<typename From
, typename To
>
749 struct ConvertibleTester
752 template<typename To1
>
753 static char test_helper(To1
);
755 template<typename From1
, typename To1
>
756 static decltype(test_helper
<To1
>(DeclVal
<From1
>())) test(int);
758 template<typename From1
, typename To1
>
759 static int test(...);
762 static const bool value
=
763 sizeof(test
<From
, To
>(0)) == sizeof(char);
766 } // namespace detail
769 * IsConvertible determines whether a value of type From will implicitly convert
770 * to a value of type To. For example:
773 * struct B : public A {};
776 * mozilla::IsConvertible<A, A>::value is true;
777 * mozilla::IsConvertible<A*, A*>::value is true;
778 * mozilla::IsConvertible<B, A>::value is true;
779 * mozilla::IsConvertible<B*, A*>::value is true;
780 * mozilla::IsConvertible<C, A>::value is false;
781 * mozilla::IsConvertible<A, C>::value is false;
782 * mozilla::IsConvertible<A*, C*>::value is false;
783 * mozilla::IsConvertible<C*, A*>::value is false.
785 * For obscure reasons, you can't use IsConvertible when the types being tested
786 * are related through private inheritance, and you'll get a compile error if
787 * you try. Just don't do it!
789 * Note - we need special handling for void, which ConvertibleTester doesn't
790 * handle. The void handling here doesn't handle const/volatile void correctly,
791 * which could be easily fixed if the need arises.
793 template<typename From
, typename To
>
795 : IntegralConstant
<bool, detail::ConvertibleTester
<From
, To
>::value
>
799 struct IsConvertible
<void, B
>
800 : IntegralConstant
<bool, IsVoid
<B
>::value
>
804 struct IsConvertible
<A
, void>
805 : IntegralConstant
<bool, IsVoid
<A
>::value
>
809 struct IsConvertible
<void, void>
813 /* 20.9.7 Transformations between types [meta.trans] */
815 /* 20.9.7.1 Const-volatile modifications [meta.trans.cv] */
818 * RemoveConst removes top-level const qualifications on a type.
820 * mozilla::RemoveConst<int>::Type is int;
821 * mozilla::RemoveConst<const int>::Type is int;
822 * mozilla::RemoveConst<const int*>::Type is const int*;
823 * mozilla::RemoveConst<int* const>::Type is int*.
832 struct RemoveConst
<const T
>
838 * RemoveVolatile removes top-level volatile qualifications on a type.
840 * mozilla::RemoveVolatile<int>::Type is int;
841 * mozilla::RemoveVolatile<volatile int>::Type is int;
842 * mozilla::RemoveVolatile<volatile int*>::Type is volatile int*;
843 * mozilla::RemoveVolatile<int* volatile>::Type is int*.
846 struct RemoveVolatile
852 struct RemoveVolatile
<volatile T
>
858 * RemoveCV removes top-level const and volatile qualifications on a type.
860 * mozilla::RemoveCV<int>::Type is int;
861 * mozilla::RemoveCV<const int>::Type is int;
862 * mozilla::RemoveCV<volatile int>::Type is int;
863 * mozilla::RemoveCV<int* const volatile>::Type is int*.
868 typedef typename RemoveConst
<typename RemoveVolatile
<T
>::Type
>::Type Type
;
871 /* 20.9.7.2 Reference modifications [meta.trans.ref] */
874 * Converts reference types to the underlying types.
876 * mozilla::RemoveReference<T>::Type is T;
877 * mozilla::RemoveReference<T&>::Type is T;
878 * mozilla::RemoveReference<T&&>::Type is T;
882 struct RemoveReference
888 struct RemoveReference
<T
&>
894 struct RemoveReference
<T
&&>
899 template<bool Condition
, typename A
, typename B
>
904 enum Voidness
{ TIsVoid
, TIsNotVoid
};
906 template<typename T
, Voidness V
= IsVoid
<T
>::value
? TIsVoid
: TIsNotVoid
>
907 struct AddLvalueReferenceHelper
;
910 struct AddLvalueReferenceHelper
<T
, TIsVoid
>
916 struct AddLvalueReferenceHelper
<T
, TIsNotVoid
>
921 } // namespace detail
924 * AddLvalueReference adds an lvalue & reference to T if one isn't already
925 * present. (Note: adding an lvalue reference to an rvalue && reference in
926 * essence replaces the && with a &&, per C+11 reference collapsing rules. For
927 * example, int&& would become int&.)
929 * The final computed type will only *not* be an lvalue reference if T is void.
931 * mozilla::AddLvalueReference<int>::Type is int&;
932 * mozilla::AddLvalueRference<volatile int&>::Type is volatile int&;
933 * mozilla::AddLvalueReference<void*>::Type is void*&;
934 * mozilla::AddLvalueReference<void>::Type is void;
935 * mozilla::AddLvalueReference<struct S&&>::Type is struct S&.
938 struct AddLvalueReference
939 : detail::AddLvalueReferenceHelper
<T
>
944 template<typename T
, Voidness V
= IsVoid
<T
>::value
? TIsVoid
: TIsNotVoid
>
945 struct AddRvalueReferenceHelper
;
948 struct AddRvalueReferenceHelper
<T
, TIsVoid
>
954 struct AddRvalueReferenceHelper
<T
, TIsNotVoid
>
959 } // namespace detail
962 * AddRvalueReference adds an rvalue && reference to T if one isn't already
963 * present. (Note: adding an rvalue reference to an lvalue & reference in
964 * essence keeps the &, per C+11 reference collapsing rules. For example,
965 * int& would remain int&.)
967 * The final computed type will only *not* be a reference if T is void.
969 * mozilla::AddRvalueReference<int>::Type is int&&;
970 * mozilla::AddRvalueRference<volatile int&>::Type is volatile int&;
971 * mozilla::AddRvalueRference<const int&&>::Type is const int&&;
972 * mozilla::AddRvalueReference<void*>::Type is void*&&;
973 * mozilla::AddRvalueReference<void>::Type is void;
974 * mozilla::AddRvalueReference<struct S&>::Type is struct S&.
977 struct AddRvalueReference
978 : detail::AddRvalueReferenceHelper
<T
>
981 /* 20.9.7.3 Sign modifications [meta.trans.sign] */
983 template<bool B
, typename T
= void>
988 template<bool MakeConst
, typename T
>
989 struct WithC
: Conditional
<MakeConst
, const T
, T
>
992 template<bool MakeVolatile
, typename T
>
993 struct WithV
: Conditional
<MakeVolatile
, volatile T
, T
>
997 template<bool MakeConst
, bool MakeVolatile
, typename T
>
998 struct WithCV
: WithC
<MakeConst
, typename WithV
<MakeVolatile
, T
>::Type
>
1001 template<typename T
>
1002 struct CorrespondingSigned
;
1005 struct CorrespondingSigned
<char> { typedef signed char Type
; };
1007 struct CorrespondingSigned
<unsigned char> { typedef signed char Type
; };
1009 struct CorrespondingSigned
<unsigned short> { typedef short Type
; };
1011 struct CorrespondingSigned
<unsigned int> { typedef int Type
; };
1013 struct CorrespondingSigned
<unsigned long> { typedef long Type
; };
1015 struct CorrespondingSigned
<unsigned long long> { typedef long long Type
; };
1017 template<typename T
,
1018 typename CVRemoved
= typename RemoveCV
<T
>::Type
,
1019 bool IsSignedIntegerType
= IsSigned
<CVRemoved
>::value
&&
1020 !IsSame
<char, CVRemoved
>::value
>
1023 template<typename T
, typename CVRemoved
>
1024 struct MakeSigned
<T
, CVRemoved
, true>
1029 template<typename T
, typename CVRemoved
>
1030 struct MakeSigned
<T
, CVRemoved
, false>
1031 : WithCV
<IsConst
<T
>::value
, IsVolatile
<T
>::value
,
1032 typename CorrespondingSigned
<CVRemoved
>::Type
>
1035 } // namespace detail
1038 * MakeSigned produces the corresponding signed integer type for a given
1039 * integral type T, with the const/volatile qualifiers of T. T must be a
1040 * possibly-const/volatile-qualified integral type that isn't bool.
1042 * If T is already a signed integer type (not including char!), then T is
1045 * Otherwise, if T is an unsigned integer type, the signed variety of T, with
1046 * T's const/volatile qualifiers, is produced.
1048 * Otherwise, the integral type of the same size as T, with the lowest rank,
1049 * with T's const/volatile qualifiers, is produced. (This basically only acts
1050 * to produce signed char when T = char.)
1052 * mozilla::MakeSigned<unsigned long>::Type is signed long;
1053 * mozilla::MakeSigned<volatile int>::Type is volatile int;
1054 * mozilla::MakeSigned<const unsigned short>::Type is const signed short;
1055 * mozilla::MakeSigned<const char>::Type is const signed char;
1056 * mozilla::MakeSigned<bool> is an error;
1057 * mozilla::MakeSigned<void*> is an error.
1059 template<typename T
>
1061 : EnableIf
<IsIntegral
<T
>::value
&&
1062 !IsSame
<bool, typename RemoveCV
<T
>::Type
>::value
,
1063 typename
detail::MakeSigned
<T
>
1069 template<typename T
>
1070 struct CorrespondingUnsigned
;
1073 struct CorrespondingUnsigned
<char> { typedef unsigned char Type
; };
1075 struct CorrespondingUnsigned
<signed char> { typedef unsigned char Type
; };
1077 struct CorrespondingUnsigned
<short> { typedef unsigned short Type
; };
1079 struct CorrespondingUnsigned
<int> { typedef unsigned int Type
; };
1081 struct CorrespondingUnsigned
<long> { typedef unsigned long Type
; };
1083 struct CorrespondingUnsigned
<long long> { typedef unsigned long long Type
; };
1086 template<typename T
,
1087 typename CVRemoved
= typename RemoveCV
<T
>::Type
,
1088 bool IsUnsignedIntegerType
= IsUnsigned
<CVRemoved
>::value
&&
1089 !IsSame
<char, CVRemoved
>::value
>
1090 struct MakeUnsigned
;
1092 template<typename T
, typename CVRemoved
>
1093 struct MakeUnsigned
<T
, CVRemoved
, true>
1098 template<typename T
, typename CVRemoved
>
1099 struct MakeUnsigned
<T
, CVRemoved
, false>
1100 : WithCV
<IsConst
<T
>::value
, IsVolatile
<T
>::value
,
1101 typename CorrespondingUnsigned
<CVRemoved
>::Type
>
1104 } // namespace detail
1107 * MakeUnsigned produces the corresponding unsigned integer type for a given
1108 * integral type T, with the const/volatile qualifiers of T. T must be a
1109 * possibly-const/volatile-qualified integral type that isn't bool.
1111 * If T is already an unsigned integer type (not including char!), then T is
1114 * Otherwise, if T is an signed integer type, the unsigned variety of T, with
1115 * T's const/volatile qualifiers, is produced.
1117 * Otherwise, the unsigned integral type of the same size as T, with the lowest
1118 * rank, with T's const/volatile qualifiers, is produced. (This basically only
1119 * acts to produce unsigned char when T = char.)
1121 * mozilla::MakeUnsigned<signed long>::Type is unsigned long;
1122 * mozilla::MakeUnsigned<volatile unsigned int>::Type is volatile unsigned int;
1123 * mozilla::MakeUnsigned<const signed short>::Type is const unsigned short;
1124 * mozilla::MakeUnsigned<const char>::Type is const unsigned char;
1125 * mozilla::MakeUnsigned<bool> is an error;
1126 * mozilla::MakeUnsigned<void*> is an error.
1128 template<typename T
>
1130 : EnableIf
<IsIntegral
<T
>::value
&&
1131 !IsSame
<bool, typename RemoveCV
<T
>::Type
>::value
,
1132 typename
detail::MakeUnsigned
<T
>
1136 /* 20.9.7.4 Array modifications [meta.trans.arr] */
1139 * RemoveExtent produces either the type of the elements of the array T, or T
1142 * mozilla::RemoveExtent<int>::Type is int;
1143 * mozilla::RemoveExtent<const int[]>::Type is const int;
1144 * mozilla::RemoveExtent<volatile int[5]>::Type is volatile int;
1145 * mozilla::RemoveExtent<long[][17]>::Type is long[17].
1147 template<typename T
>
1153 template<typename T
>
1154 struct RemoveExtent
<T
[]>
1159 template<typename T
, decltype(sizeof(1)) N
>
1160 struct RemoveExtent
<T
[N
]>
1165 /* 20.9.7.5 Pointer modifications [meta.trans.ptr] */
1169 template<typename T
, typename CVRemoved
>
1170 struct RemovePointerHelper
1175 template<typename T
, typename Pointee
>
1176 struct RemovePointerHelper
<T
, Pointee
*>
1178 typedef Pointee Type
;
1181 } // namespace detail
1184 * Produces the pointed-to type if a pointer is provided, else returns the input
1185 * type. Note that this does not dereference pointer-to-member pointers.
1187 * struct S { bool m; void f(); };
1188 * mozilla::RemovePointer<int>::Type is int;
1189 * mozilla::RemovePointer<int*>::Type is int;
1190 * mozilla::RemovePointer<int* const>::Type is int;
1191 * mozilla::RemovePointer<int* volatile>::Type is int;
1192 * mozilla::RemovePointer<const long*>::Type is const long;
1193 * mozilla::RemovePointer<void* const>::Type is void;
1194 * mozilla::RemovePointer<void (S::*)()>::Type is void (S::*)();
1195 * mozilla::RemovePointer<void (*)()>::Type is void();
1196 * mozilla::RemovePointer<bool S::*>::Type is bool S::*.
1198 template<typename T
>
1199 struct RemovePointer
1200 : detail::RemovePointerHelper
<T
, typename RemoveCV
<T
>::Type
>
1204 * Converts T& to T*. Otherwise returns T* given T. Note that C++17 wants
1205 * std::add_pointer to work differently for function types. We don't implement
1206 * that behavior here.
1208 * mozilla::AddPointer<int> is int*;
1209 * mozilla::AddPointer<int*> is int**;
1210 * mozilla::AddPointer<int&> is int*;
1211 * mozilla::AddPointer<int* const> is int** const.
1213 template<typename T
>
1216 typedef typename RemoveReference
<T
>::Type
* Type
;
1219 /* 20.9.7.6 Other transformations [meta.trans.other] */
1222 * EnableIf is a struct containing a typedef of T if and only if B is true.
1224 * mozilla::EnableIf<true, int>::Type is int;
1225 * mozilla::EnableIf<false, int>::Type is a compile-time error.
1227 * Use this template to implement SFINAE-style (Substitution Failure Is not An
1228 * Error) requirements. For example, you might use it to impose a restriction
1229 * on a template parameter:
1231 * template<typename T>
1232 * class PodVector // vector optimized to store POD (memcpy-able) types
1234 * EnableIf<IsPod<T>::value, T>::Type* vector;
1239 template<bool B
, typename T
>
1243 template<typename T
>
1244 struct EnableIf
<true, T
>
1250 * Conditional selects a class between two, depending on a given boolean value.
1252 * mozilla::Conditional<true, A, B>::Type is A;
1253 * mozilla::Conditional<false, A, B>::Type is B;
1255 template<bool Condition
, typename A
, typename B
>
1261 template<class A
, class B
>
1262 struct Conditional
<false, A
, B
>
1269 template<typename U
,
1270 bool IsArray
= IsArray
<U
>::value
,
1271 bool IsFunction
= IsFunction
<U
>::value
>
1272 struct DecaySelector
;
1274 template<typename U
>
1275 struct DecaySelector
<U
, false, false>
1277 typedef typename RemoveCV
<U
>::Type Type
;
1280 template<typename U
>
1281 struct DecaySelector
<U
, true, false>
1283 typedef typename RemoveExtent
<U
>::Type
* Type
;
1286 template<typename U
>
1287 struct DecaySelector
<U
, false, true>
1289 typedef typename AddPointer
<U
>::Type Type
;
1292 }; // namespace detail
1295 * Strips const/volatile off a type and decays it from an lvalue to an
1296 * rvalue. So function types are converted to function pointers, arrays to
1297 * pointers, and references are removed.
1299 * mozilla::Decay<int>::Type is int
1300 * mozilla::Decay<int&>::Type is int
1301 * mozilla::Decay<int&&>::Type is int
1302 * mozilla::Decay<const int&>::Type is int
1303 * mozilla::Decay<int[2]>::Type is int*
1304 * mozilla::Decay<int(int)>::Type is int(*)(int)
1306 template<typename T
>
1308 : public detail::DecaySelector
<typename RemoveReference
<T
>::Type
>
1312 } /* namespace mozilla */
1314 #endif /* mozilla_TypeTraits_h */