Version 7.6.3.2-android, tag libreoffice-7.6.3.2-android
[LibreOffice.git] / include / onlineupdate / mozilla / TypeTraits.h
blob7ca9d33158379c20aaa1c483331cf4766f02e2f6
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 "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.
20 #include <wchar.h>
22 namespace mozilla {
24 /* Forward declarations. */
26 template<typename> struct RemoveCV;
28 /* 20.9.3 Helper classes [meta.help] */
30 /**
31 * Helper class used as a base for various type traits, exposed publicly
32 * because <type_traits> exposes it as well.
34 template<typename T, T Value>
35 struct IntegralConstant
37 static const T value = Value;
38 typedef T ValueType;
39 typedef IntegralConstant<T, Value> Type;
42 /** Convenient aliases. */
43 typedef IntegralConstant<bool, true> TrueType;
44 typedef IntegralConstant<bool, false> FalseType;
46 /* 20.9.4 Unary type traits [meta.unary] */
48 /* 20.9.4.1 Primary type categories [meta.unary.cat] */
50 namespace detail {
52 template<typename T>
53 struct IsVoidHelper : FalseType {};
55 template<>
56 struct IsVoidHelper<void> : TrueType {};
58 } // namespace detail
60 /**
61 * IsVoid determines whether a type is void.
63 * mozilla::IsVoid<int>::value is false;
64 * mozilla::IsVoid<void>::value is true;
65 * mozilla::IsVoid<void*>::value is false;
66 * mozilla::IsVoid<volatile void>::value is true.
68 template<typename T>
69 struct IsVoid : detail::IsVoidHelper<typename RemoveCV<T>::Type> {};
71 namespace detail {
73 template <typename T>
74 struct IsIntegralHelper : FalseType {};
76 template<> struct IsIntegralHelper<char> : TrueType {};
77 template<> struct IsIntegralHelper<signed char> : TrueType {};
78 template<> struct IsIntegralHelper<unsigned char> : TrueType {};
79 template<> struct IsIntegralHelper<short> : TrueType {};
80 template<> struct IsIntegralHelper<unsigned short> : TrueType {};
81 template<> struct IsIntegralHelper<int> : TrueType {};
82 template<> struct IsIntegralHelper<unsigned int> : TrueType {};
83 template<> struct IsIntegralHelper<long> : TrueType {};
84 template<> struct IsIntegralHelper<unsigned long> : TrueType {};
85 template<> struct IsIntegralHelper<long long> : TrueType {};
86 template<> struct IsIntegralHelper<unsigned long long> : TrueType {};
87 template<> struct IsIntegralHelper<bool> : TrueType {};
88 template<> struct IsIntegralHelper<wchar_t> : TrueType {};
89 #ifdef MOZ_CHAR16_IS_NOT_WCHAR
90 template<> struct IsIntegralHelper<char16_t> : TrueType {};
91 #endif
93 } /* namespace detail */
95 /**
96 * IsIntegral determines whether a type is an integral type.
98 * mozilla::IsIntegral<int>::value is true;
99 * mozilla::IsIntegral<unsigned short>::value is true;
100 * mozilla::IsIntegral<const long>::value is true;
101 * mozilla::IsIntegral<int*>::value is false;
102 * mozilla::IsIntegral<double>::value is false;
104 * Note that the behavior of IsIntegral on char16_t and char32_t is
105 * unspecified.
107 template<typename T>
108 struct IsIntegral : detail::IsIntegralHelper<typename RemoveCV<T>::Type>
111 template<typename T, typename U>
112 struct IsSame;
114 namespace detail {
116 template<typename T>
117 struct IsFloatingPointHelper
118 : IntegralConstant<bool,
119 IsSame<T, float>::value ||
120 IsSame<T, double>::value ||
121 IsSame<T, long double>::value>
124 } // namespace detail
127 * IsFloatingPoint determines whether a type is a floating point type (float,
128 * double, long double).
130 * mozilla::IsFloatingPoint<int>::value is false;
131 * mozilla::IsFloatingPoint<const float>::value is true;
132 * mozilla::IsFloatingPoint<long double>::value is true;
133 * mozilla::IsFloatingPoint<double*>::value is false.
135 template<typename T>
136 struct IsFloatingPoint
137 : detail::IsFloatingPointHelper<typename RemoveCV<T>::Type>
140 namespace detail {
142 template<typename T>
143 struct IsArrayHelper : FalseType {};
145 template<typename T, decltype(sizeof(1)) N>
146 struct IsArrayHelper<T[N]> : TrueType {};
148 template<typename T>
149 struct IsArrayHelper<T[]> : TrueType {};
151 } // namespace detail
154 * IsArray determines whether a type is an array type, of known or unknown
155 * length.
157 * mozilla::IsArray<int>::value is false;
158 * mozilla::IsArray<int[]>::value is true;
159 * mozilla::IsArray<int[5]>::value is true.
161 template<typename T>
162 struct IsArray : detail::IsArrayHelper<typename RemoveCV<T>::Type>
165 namespace detail {
167 template<typename T>
168 struct IsPointerHelper : FalseType {};
170 template<typename T>
171 struct IsPointerHelper<T*> : TrueType {};
173 } // namespace detail
176 * IsPointer determines whether a type is a possibly-CV-qualified pointer type
177 * (but not a pointer-to-member type).
179 * mozilla::IsPointer<struct S*>::value is true;
180 * mozilla::IsPointer<int*>::value is true;
181 * mozilla::IsPointer<int**>::value is true;
182 * mozilla::IsPointer<const int*>::value is true;
183 * mozilla::IsPointer<int* const>::value is true;
184 * mozilla::IsPointer<int* volatile>::value is true;
185 * mozilla::IsPointer<void (*)(void)>::value is true;
186 * mozilla::IsPointer<int>::value is false;
187 * mozilla::IsPointer<struct S>::value is false.
188 * mozilla::IsPointer<int(struct S::*)>::value is false
190 template<typename T>
191 struct IsPointer : detail::IsPointerHelper<typename RemoveCV<T>::Type>
195 * IsLvalueReference determines whether a type is an lvalue reference.
197 * mozilla::IsLvalueReference<struct S*>::value is false;
198 * mozilla::IsLvalueReference<int**>::value is false;
199 * mozilla::IsLvalueReference<void (*)(void)>::value is false;
200 * mozilla::IsLvalueReference<int>::value is false;
201 * mozilla::IsLvalueReference<struct S>::value is false;
202 * mozilla::IsLvalueReference<struct S*&>::value is true;
203 * mozilla::IsLvalueReference<struct S&&>::value is false.
205 template<typename T>
206 struct IsLvalueReference : FalseType {};
208 template<typename T>
209 struct IsLvalueReference<T&> : TrueType {};
212 * IsRvalueReference determines whether a type is an rvalue reference.
214 * mozilla::IsRvalueReference<struct S*>::value is false;
215 * mozilla::IsRvalueReference<int**>::value is false;
216 * mozilla::IsRvalueReference<void (*)(void)>::value is false;
217 * mozilla::IsRvalueReference<int>::value is false;
218 * mozilla::IsRvalueReference<struct S>::value is false;
219 * mozilla::IsRvalueReference<struct S*&>::value is false;
220 * mozilla::IsRvalueReference<struct S&&>::value is true.
222 template<typename T>
223 struct IsRvalueReference : FalseType {};
225 template<typename T>
226 struct IsRvalueReference<T&&> : TrueType {};
228 namespace detail {
230 // __is_enum is a supported extension across all of our supported compilers.
231 template<typename T>
232 struct IsEnumHelper
233 : IntegralConstant<bool, __is_enum(T)>
236 } // namespace detail
239 * IsEnum determines whether a type is an enum type.
241 * mozilla::IsEnum<enum S>::value is true;
242 * mozilla::IsEnum<enum S*>::value is false;
243 * mozilla::IsEnum<int>::value is false;
245 template<typename T>
246 struct IsEnum
247 : detail::IsEnumHelper<typename RemoveCV<T>::Type>
250 namespace detail {
252 // __is_class is a supported extension across all of our supported compilers:
253 // http://llvm.org/releases/3.0/docs/ClangReleaseNotes.html
254 // http://gcc.gnu.org/onlinedocs/gcc-4.4.7/gcc/Type-Traits.html#Type-Traits
255 // http://msdn.microsoft.com/en-us/library/ms177194%28v=vs.100%29.aspx
256 template<typename T>
257 struct IsClassHelper
258 : IntegralConstant<bool, __is_class(T)>
261 } // namespace detail
264 * IsClass determines whether a type is a class type (but not a union).
266 * struct S {};
267 * union U {};
268 * mozilla::IsClass<int>::value is false;
269 * mozilla::IsClass<const S>::value is true;
270 * mozilla::IsClass<U>::value is false;
272 template<typename T>
273 struct IsClass
274 : detail::IsClassHelper<typename RemoveCV<T>::Type>
277 /* 20.9.4.2 Composite type traits [meta.unary.comp] */
280 * IsReference determines whether a type is an lvalue or rvalue reference.
282 * mozilla::IsReference<struct S*>::value is false;
283 * mozilla::IsReference<int**>::value is false;
284 * mozilla::IsReference<int&>::value is true;
285 * mozilla::IsReference<void (*)(void)>::value is false;
286 * mozilla::IsReference<const int&>::value is true;
287 * mozilla::IsReference<int>::value is false;
288 * mozilla::IsReference<struct S>::value is false;
289 * mozilla::IsReference<struct S&>::value is true;
290 * mozilla::IsReference<struct S*&>::value is true;
291 * mozilla::IsReference<struct S&&>::value is true.
293 template<typename T>
294 struct IsReference
295 : IntegralConstant<bool,
296 IsLvalueReference<T>::value || IsRvalueReference<T>::value>
300 * IsArithmetic determines whether a type is arithmetic. A type is arithmetic
301 * iff it is an integral type or a floating point type.
303 * mozilla::IsArithmetic<int>::value is true;
304 * mozilla::IsArithmetic<double>::value is true;
305 * mozilla::IsArithmetic<long double*>::value is false.
307 template<typename T>
308 struct IsArithmetic
309 : IntegralConstant<bool, IsIntegral<T>::value || IsFloatingPoint<T>::value>
312 /* 20.9.4.3 Type properties [meta.unary.prop] */
315 * IsConst determines whether a type is const or not.
317 * mozilla::IsConst<int>::value is false;
318 * mozilla::IsConst<void* const>::value is true;
319 * mozilla::IsConst<const char*>::value is false.
321 template<typename T>
322 struct IsConst : FalseType {};
324 template<typename T>
325 struct IsConst<const T> : TrueType {};
328 * IsVolatile determines whether a type is volatile or not.
330 * mozilla::IsVolatile<int>::value is false;
331 * mozilla::IsVolatile<void* volatile>::value is true;
332 * mozilla::IsVolatile<volatile char*>::value is false.
334 template<typename T>
335 struct IsVolatile : FalseType {};
337 template<typename T>
338 struct IsVolatile<volatile T> : TrueType {};
341 * Traits class for identifying POD types. Until C++11 there's no automatic
342 * way to detect PODs, so for the moment this is done manually. Users may
343 * define specializations of this class that inherit from mozilla::TrueType and
344 * mozilla::FalseType (or equivalently mozilla::IntegralConstant<bool, true or
345 * false>, or conveniently from mozilla::IsPod for composite types) as needed to
346 * ensure correct IsPod behavior.
348 template<typename T>
349 struct IsPod : public FalseType {};
351 template<> struct IsPod<char> : TrueType {};
352 template<> struct IsPod<signed char> : TrueType {};
353 template<> struct IsPod<unsigned char> : TrueType {};
354 template<> struct IsPod<short> : TrueType {};
355 template<> struct IsPod<unsigned short> : TrueType {};
356 template<> struct IsPod<int> : TrueType {};
357 template<> struct IsPod<unsigned int> : TrueType {};
358 template<> struct IsPod<long> : TrueType {};
359 template<> struct IsPod<unsigned long> : TrueType {};
360 template<> struct IsPod<long long> : TrueType {};
361 template<> struct IsPod<unsigned long long> : TrueType {};
362 template<> struct IsPod<bool> : TrueType {};
363 template<> struct IsPod<float> : TrueType {};
364 template<> struct IsPod<double> : TrueType {};
365 template<> struct IsPod<wchar_t> : TrueType {};
366 #ifdef MOZ_CHAR16_IS_NOT_WCHAR
367 template<> struct IsPod<char16_t> : TrueType {};
368 #endif
369 template<typename T> struct IsPod<T*> : TrueType {};
371 namespace detail {
373 // __is_empty is a supported extension across all of our supported compilers:
374 // http://llvm.org/releases/3.0/docs/ClangReleaseNotes.html
375 // http://gcc.gnu.org/onlinedocs/gcc-4.4.7/gcc/Type-Traits.html#Type-Traits
376 // http://msdn.microsoft.com/en-us/library/ms177194%28v=vs.100%29.aspx
377 template<typename T>
378 struct IsEmptyHelper
379 : IntegralConstant<bool, IsClass<T>::value && __is_empty(T)>
382 } // namespace detail
385 * IsEmpty determines whether a type is a class (but not a union) that is empty.
387 * A class is empty iff it and all its base classes have no non-static data
388 * members (except bit-fields of length 0) and no virtual member functions, and
389 * no base class is empty or a virtual base class.
391 * Intuitively, empty classes don't have any data that has to be stored in
392 * instances of those classes. (The size of the class must still be non-zero,
393 * because distinct array elements of any type must have different addresses.
394 * However, if the Empty Base Optimization is implemented by the compiler [most
395 * compilers implement it, and in certain cases C++11 requires it], the size of
396 * a class inheriting from an empty |Base| class need not be inflated by
397 * |sizeof(Base)|.) And intuitively, non-empty classes have data members and/or
398 * vtable pointers that must be stored in each instance for proper behavior.
400 * static_assert(!mozilla::IsEmpty<int>::value, "not a class => not empty");
401 * union U1 { int x; };
402 * static_assert(!mozilla::IsEmpty<U1>::value, "not a class => not empty");
403 * struct E1 {};
404 * struct E2 { int : 0 };
405 * struct E3 : E1 {};
406 * struct E4 : E2 {};
407 * static_assert(mozilla::IsEmpty<E1>::value &&
408 * mozilla::IsEmpty<E2>::value &&
409 * mozilla::IsEmpty<E3>::value &&
410 * mozilla::IsEmpty<E4>::value,
411 * "all empty");
412 * union U2 { E1 e1; };
413 * static_assert(!mozilla::IsEmpty<U2>::value, "not a class => not empty");
414 * struct NE1 { int x; };
415 * struct NE2 : virtual E1 {};
416 * struct NE3 : E2 { virtual ~NE3() {} };
417 * struct NE4 { virtual void f() {} };
418 * static_assert(!mozilla::IsEmpty<NE1>::value &&
419 * !mozilla::IsEmpty<NE2>::value &&
420 * !mozilla::IsEmpty<NE3>::value &&
421 * !mozilla::IsEmpty<NE4>::value,
422 * "all empty");
424 template<typename T>
425 struct IsEmpty : detail::IsEmptyHelper<typename RemoveCV<T>::Type>
429 namespace detail {
431 template<typename T,
432 bool = IsFloatingPoint<T>::value,
433 bool = IsIntegral<T>::value,
434 typename NoCV = typename RemoveCV<T>::Type>
435 struct IsSignedHelper;
437 // Floating point is signed.
438 template<typename T, typename NoCV>
439 struct IsSignedHelper<T, true, false, NoCV> : TrueType {};
441 // Integral is conditionally signed.
442 template<typename T, typename NoCV>
443 struct IsSignedHelper<T, false, true, NoCV>
444 : IntegralConstant<bool, bool(NoCV(-1) < NoCV(1))>
447 // Non-floating point, non-integral is not signed.
448 template<typename T, typename NoCV>
449 struct IsSignedHelper<T, false, false, NoCV> : FalseType {};
451 } // namespace detail
454 * IsSigned determines whether a type is a signed arithmetic type. |char| is
455 * considered a signed type if it has the same representation as |signed char|.
457 * mozilla::IsSigned<int>::value is true;
458 * mozilla::IsSigned<const unsigned int>::value is false;
459 * mozilla::IsSigned<unsigned char>::value is false;
460 * mozilla::IsSigned<float>::value is true.
462 template<typename T>
463 struct IsSigned : detail::IsSignedHelper<T> {};
465 namespace detail {
467 template<typename T,
468 bool = IsFloatingPoint<T>::value,
469 bool = IsIntegral<T>::value,
470 typename NoCV = typename RemoveCV<T>::Type>
471 struct IsUnsignedHelper;
473 // Floating point is not unsigned.
474 template<typename T, typename NoCV>
475 struct IsUnsignedHelper<T, true, false, NoCV> : FalseType {};
477 // Integral is conditionally unsigned.
478 template<typename T, typename NoCV>
479 struct IsUnsignedHelper<T, false, true, NoCV>
480 : IntegralConstant<bool,
481 (IsSame<NoCV, bool>::value || bool(NoCV(1) < NoCV(-1)))>
484 // Non-floating point, non-integral is not unsigned.
485 template<typename T, typename NoCV>
486 struct IsUnsignedHelper<T, false, false, NoCV> : FalseType {};
488 } // namespace detail
491 * IsUnsigned determines whether a type is an unsigned arithmetic type.
493 * mozilla::IsUnsigned<int>::value is false;
494 * mozilla::IsUnsigned<const unsigned int>::value is true;
495 * mozilla::IsUnsigned<unsigned char>::value is true;
496 * mozilla::IsUnsigned<float>::value is false.
498 template<typename T>
499 struct IsUnsigned : detail::IsUnsignedHelper<T> {};
501 /* 20.9.5 Type property queries [meta.unary.prop.query] */
503 /* 20.9.6 Relationships between types [meta.rel] */
506 * IsSame tests whether two types are the same type.
508 * mozilla::IsSame<int, int>::value is true;
509 * mozilla::IsSame<int*, int*>::value is true;
510 * mozilla::IsSame<int, unsigned int>::value is false;
511 * mozilla::IsSame<void, void>::value is true;
512 * mozilla::IsSame<const int, int>::value is false;
513 * mozilla::IsSame<struct S, struct S>::value is true.
515 template<typename T, typename U>
516 struct IsSame : FalseType {};
518 template<typename T>
519 struct IsSame<T, T> : TrueType {};
521 namespace detail {
523 #if defined(__GNUC__) || defined(__clang__) || defined(_MSC_VER)
525 template<class Base, class Derived>
526 struct BaseOfTester : IntegralConstant<bool, __is_base_of(Base, Derived)> {};
528 #else
530 // The trickery used to implement IsBaseOf here makes it possible to use it for
531 // the cases of private and multiple inheritance. This code was inspired by the
532 // sample code here:
534 // http://stackoverflow.com/questions/2910979/how-is-base-of-works
535 template<class Base, class Derived>
536 struct BaseOfHelper
538 public:
539 operator Base*() const;
540 operator Derived*();
543 template<class Base, class Derived>
544 struct BaseOfTester
546 private:
547 template<class T>
548 static char test(Derived*, T);
549 static int test(Base*, int);
551 public:
552 static const bool value =
553 sizeof(test(BaseOfHelper<Base, Derived>(), int())) == sizeof(char);
556 template<class Base, class Derived>
557 struct BaseOfTester<Base, const Derived>
559 private:
560 template<class T>
561 static char test(Derived*, T);
562 static int test(Base*, int);
564 public:
565 static const bool value =
566 sizeof(test(BaseOfHelper<Base, Derived>(), int())) == sizeof(char);
569 template<class Base, class Derived>
570 struct BaseOfTester<Base&, Derived&> : FalseType {};
572 template<class Type>
573 struct BaseOfTester<Type, Type> : TrueType {};
575 template<class Type>
576 struct BaseOfTester<Type, const Type> : TrueType {};
578 #endif
580 } /* namespace detail */
583 * IsBaseOf allows to know whether a given class is derived from another.
585 * Consider the following class definitions:
587 * class A {};
588 * class B : public A {};
589 * class C {};
591 * mozilla::IsBaseOf<A, B>::value is true;
592 * mozilla::IsBaseOf<A, C>::value is false;
594 template<class Base, class Derived>
595 struct IsBaseOf
596 : IntegralConstant<bool, detail::BaseOfTester<Base, Derived>::value>
599 namespace detail {
601 template<typename From, typename To>
602 struct ConvertibleTester
604 private:
605 static From create();
607 template<typename From1, typename To1>
608 static char test(To to);
610 template<typename From1, typename To1>
611 static int test(...);
613 public:
614 static const bool value =
615 sizeof(test<From, To>(create())) == sizeof(char);
618 } // namespace detail
621 * IsConvertible determines whether a value of type From will implicitly convert
622 * to a value of type To. For example:
624 * struct A {};
625 * struct B : public A {};
626 * struct C {};
628 * mozilla::IsConvertible<A, A>::value is true;
629 * mozilla::IsConvertible<A*, A*>::value is true;
630 * mozilla::IsConvertible<B, A>::value is true;
631 * mozilla::IsConvertible<B*, A*>::value is true;
632 * mozilla::IsConvertible<C, A>::value is false;
633 * mozilla::IsConvertible<A, C>::value is false;
634 * mozilla::IsConvertible<A*, C*>::value is false;
635 * mozilla::IsConvertible<C*, A*>::value is false.
637 * For obscure reasons, you can't use IsConvertible when the types being tested
638 * are related through private inheritance, and you'll get a compile error if
639 * you try. Just don't do it!
641 * Note - we need special handling for void, which ConvertibleTester doesn't
642 * handle. The void handling here doesn't handle const/volatile void correctly,
643 * which could be easily fixed if the need arises.
645 template<typename From, typename To>
646 struct IsConvertible
647 : IntegralConstant<bool, detail::ConvertibleTester<From, To>::value>
650 template<typename B>
651 struct IsConvertible<void, B>
652 : IntegralConstant<bool, IsVoid<B>::value>
655 template<typename A>
656 struct IsConvertible<A, void>
657 : IntegralConstant<bool, IsVoid<A>::value>
660 template<>
661 struct IsConvertible<void, void>
662 : TrueType
665 /* 20.9.7 Transformations between types [meta.trans] */
667 /* 20.9.7.1 Const-volatile modifications [meta.trans.cv] */
670 * RemoveConst removes top-level const qualifications on a type.
672 * mozilla::RemoveConst<int>::Type is int;
673 * mozilla::RemoveConst<const int>::Type is int;
674 * mozilla::RemoveConst<const int*>::Type is const int*;
675 * mozilla::RemoveConst<int* const>::Type is int*.
677 template<typename T>
678 struct RemoveConst
680 typedef T Type;
683 template<typename T>
684 struct RemoveConst<const T>
686 typedef T Type;
690 * RemoveVolatile removes top-level volatile qualifications on a type.
692 * mozilla::RemoveVolatile<int>::Type is int;
693 * mozilla::RemoveVolatile<volatile int>::Type is int;
694 * mozilla::RemoveVolatile<volatile int*>::Type is volatile int*;
695 * mozilla::RemoveVolatile<int* volatile>::Type is int*.
697 template<typename T>
698 struct RemoveVolatile
700 typedef T Type;
703 template<typename T>
704 struct RemoveVolatile<volatile T>
706 typedef T Type;
710 * RemoveCV removes top-level const and volatile qualifications on a type.
712 * mozilla::RemoveCV<int>::Type is int;
713 * mozilla::RemoveCV<const int>::Type is int;
714 * mozilla::RemoveCV<volatile int>::Type is int;
715 * mozilla::RemoveCV<int* const volatile>::Type is int*.
717 template<typename T>
718 struct RemoveCV
720 typedef typename RemoveConst<typename RemoveVolatile<T>::Type>::Type Type;
723 /* 20.9.7.2 Reference modifications [meta.trans.ref] */
726 * Converts reference types to the underlying types.
728 * mozilla::RemoveReference<T>::Type is T;
729 * mozilla::RemoveReference<T&>::Type is T;
730 * mozilla::RemoveReference<T&&>::Type is T;
733 template<typename T>
734 struct RemoveReference
736 typedef T Type;
739 template<typename T>
740 struct RemoveReference<T&>
742 typedef T Type;
745 template<typename T>
746 struct RemoveReference<T&&>
748 typedef T Type;
751 template<bool Condition, typename A, typename B>
752 struct Conditional;
754 namespace detail {
756 enum Voidness { TIsVoid, TIsNotVoid };
758 template<typename T, Voidness V = IsVoid<T>::value ? TIsVoid : TIsNotVoid>
759 struct AddLvalueReferenceHelper;
761 template<typename T>
762 struct AddLvalueReferenceHelper<T, TIsVoid>
764 typedef void Type;
767 template<typename T>
768 struct AddLvalueReferenceHelper<T, TIsNotVoid>
770 typedef T& Type;
773 } // namespace detail
776 * AddLvalueReference adds an lvalue & reference to T if one isn't already
777 * present. (Note: adding an lvalue reference to an rvalue && reference in
778 * essence replaces the && with a &&, per C+11 reference collapsing rules. For
779 * example, int&& would become int&.)
781 * The final computed type will only *not* be an lvalue reference if T is void.
783 * mozilla::AddLvalueReference<int>::Type is int&;
784 * mozilla::AddLvalueRference<volatile int&>::Type is volatile int&;
785 * mozilla::AddLvalueReference<void*>::Type is void*&;
786 * mozilla::AddLvalueReference<void>::Type is void;
787 * mozilla::AddLvalueReference<struct S&&>::Type is struct S&.
789 template<typename T>
790 struct AddLvalueReference
791 : detail::AddLvalueReferenceHelper<T>
794 namespace detail {
796 template<typename T, Voidness V = IsVoid<T>::value ? TIsVoid : TIsNotVoid>
797 struct AddRvalueReferenceHelper;
799 template<typename T>
800 struct AddRvalueReferenceHelper<T, TIsVoid>
802 typedef void Type;
805 template<typename T>
806 struct AddRvalueReferenceHelper<T, TIsNotVoid>
808 typedef T&& Type;
811 } // namespace detail
814 * AddRvalueReference adds an rvalue && reference to T if one isn't already
815 * present. (Note: adding an rvalue reference to an lvalue & reference in
816 * essence keeps the &, per C+11 reference collapsing rules. For example,
817 * int& would remain int&.)
819 * The final computed type will only *not* be a reference if T is void.
821 * mozilla::AddRvalueReference<int>::Type is int&&;
822 * mozilla::AddRvalueRference<volatile int&>::Type is volatile int&;
823 * mozilla::AddRvalueRference<const int&&>::Type is const int&&;
824 * mozilla::AddRvalueReference<void*>::Type is void*&&;
825 * mozilla::AddRvalueReference<void>::Type is void;
826 * mozilla::AddRvalueReference<struct S&>::Type is struct S&.
828 template<typename T>
829 struct AddRvalueReference
830 : detail::AddRvalueReferenceHelper<T>
833 /* 20.2.4 Function template declval [declval] */
836 * DeclVal simplifies the definition of expressions which occur as unevaluated
837 * operands. It converts T to a reference type, making it possible to use in
838 * decltype expressions even if T does not have a default constructor, e.g.:
839 * decltype(DeclVal<TWithNoDefaultConstructor>().foo())
841 template<typename T>
842 typename AddRvalueReference<T>::Type DeclVal();
844 /* 20.9.7.3 Sign modifications [meta.trans.sign] */
846 template<bool B, typename T = void>
847 struct EnableIf;
849 namespace detail {
851 template<bool MakeConst, typename T>
852 struct WithC : Conditional<MakeConst, const T, T>
855 template<bool MakeVolatile, typename T>
856 struct WithV : Conditional<MakeVolatile, volatile T, T>
860 template<bool MakeConst, bool MakeVolatile, typename T>
861 struct WithCV : WithC<MakeConst, typename WithV<MakeVolatile, T>::Type>
864 template<typename T>
865 struct CorrespondingSigned;
867 template<>
868 struct CorrespondingSigned<char> { typedef signed char Type; };
869 template<>
870 struct CorrespondingSigned<unsigned char> { typedef signed char Type; };
871 template<>
872 struct CorrespondingSigned<unsigned short> { typedef short Type; };
873 template<>
874 struct CorrespondingSigned<unsigned int> { typedef int Type; };
875 template<>
876 struct CorrespondingSigned<unsigned long> { typedef long Type; };
877 template<>
878 struct CorrespondingSigned<unsigned long long> { typedef long long Type; };
880 template<typename T,
881 typename CVRemoved = typename RemoveCV<T>::Type,
882 bool IsSignedIntegerType = IsSigned<CVRemoved>::value &&
883 !IsSame<char, CVRemoved>::value>
884 struct MakeSigned;
886 template<typename T, typename CVRemoved>
887 struct MakeSigned<T, CVRemoved, true>
889 typedef T Type;
892 template<typename T, typename CVRemoved>
893 struct MakeSigned<T, CVRemoved, false>
894 : WithCV<IsConst<T>::value, IsVolatile<T>::value,
895 typename CorrespondingSigned<CVRemoved>::Type>
898 } // namespace detail
901 * MakeSigned produces the corresponding signed integer type for a given
902 * integral type T, with the const/volatile qualifiers of T. T must be a
903 * possibly-const/volatile-qualified integral type that isn't bool.
905 * If T is already a signed integer type (not including char!), then T is
906 * produced.
908 * Otherwise, if T is an unsigned integer type, the signed variety of T, with
909 * T's const/volatile qualifiers, is produced.
911 * Otherwise, the integral type of the same size as T, with the lowest rank,
912 * with T's const/volatile qualifiers, is produced. (This basically only acts
913 * to produce signed char when T = char.)
915 * mozilla::MakeSigned<unsigned long>::Type is signed long;
916 * mozilla::MakeSigned<volatile int>::Type is volatile int;
917 * mozilla::MakeSigned<const unsigned short>::Type is const signed short;
918 * mozilla::MakeSigned<const char>::Type is const signed char;
919 * mozilla::MakeSigned<bool> is an error;
920 * mozilla::MakeSigned<void*> is an error.
922 template<typename T>
923 struct MakeSigned
924 : EnableIf<IsIntegral<T>::value &&
925 !IsSame<bool, typename RemoveCV<T>::Type>::value,
926 typename detail::MakeSigned<T>
927 >::Type
930 namespace detail {
932 template<typename T>
933 struct CorrespondingUnsigned;
935 template<>
936 struct CorrespondingUnsigned<char> { typedef unsigned char Type; };
937 template<>
938 struct CorrespondingUnsigned<signed char> { typedef unsigned char Type; };
939 template<>
940 struct CorrespondingUnsigned<short> { typedef unsigned short Type; };
941 template<>
942 struct CorrespondingUnsigned<int> { typedef unsigned int Type; };
943 template<>
944 struct CorrespondingUnsigned<long> { typedef unsigned long Type; };
945 template<>
946 struct CorrespondingUnsigned<long long> { typedef unsigned long long Type; };
949 template<typename T,
950 typename CVRemoved = typename RemoveCV<T>::Type,
951 bool IsUnsignedIntegerType = IsUnsigned<CVRemoved>::value &&
952 !IsSame<char, CVRemoved>::value>
953 struct MakeUnsigned;
955 template<typename T, typename CVRemoved>
956 struct MakeUnsigned<T, CVRemoved, true>
958 typedef T Type;
961 template<typename T, typename CVRemoved>
962 struct MakeUnsigned<T, CVRemoved, false>
963 : WithCV<IsConst<T>::value, IsVolatile<T>::value,
964 typename CorrespondingUnsigned<CVRemoved>::Type>
967 } // namespace detail
970 * MakeUnsigned produces the corresponding unsigned integer type for a given
971 * integral type T, with the const/volatile qualifiers of T. T must be a
972 * possibly-const/volatile-qualified integral type that isn't bool.
974 * If T is already an unsigned integer type (not including char!), then T is
975 * produced.
977 * Otherwise, if T is a signed integer type, the unsigned variety of T, with
978 * T's const/volatile qualifiers, is produced.
980 * Otherwise, the unsigned integral type of the same size as T, with the lowest
981 * rank, with T's const/volatile qualifiers, is produced. (This basically only
982 * acts to produce unsigned char when T = char.)
984 * mozilla::MakeUnsigned<signed long>::Type is unsigned long;
985 * mozilla::MakeUnsigned<volatile unsigned int>::Type is volatile unsigned int;
986 * mozilla::MakeUnsigned<const signed short>::Type is const unsigned short;
987 * mozilla::MakeUnsigned<const char>::Type is const unsigned char;
988 * mozilla::MakeUnsigned<bool> is an error;
989 * mozilla::MakeUnsigned<void*> is an error.
991 template<typename T>
992 struct MakeUnsigned
993 : EnableIf<IsIntegral<T>::value &&
994 !IsSame<bool, typename RemoveCV<T>::Type>::value,
995 typename detail::MakeUnsigned<T>
996 >::Type
999 /* 20.9.7.4 Array modifications [meta.trans.arr] */
1002 * RemoveExtent produces either the type of the elements of the array T, or T
1003 * itself.
1005 * mozilla::RemoveExtent<int>::Type is int;
1006 * mozilla::RemoveExtent<const int[]>::Type is const int;
1007 * mozilla::RemoveExtent<volatile int[5]>::Type is volatile int;
1008 * mozilla::RemoveExtent<long[][17]>::Type is long[17].
1010 template<typename T>
1011 struct RemoveExtent
1013 typedef T Type;
1016 template<typename T>
1017 struct RemoveExtent<T[]>
1019 typedef T Type;
1022 template<typename T, decltype(sizeof(1)) N>
1023 struct RemoveExtent<T[N]>
1025 typedef T Type;
1028 /* 20.9.7.5 Pointer modifications [meta.trans.ptr] */
1030 namespace detail {
1032 template<typename T, typename CVRemoved>
1033 struct RemovePointerHelper
1035 typedef T Type;
1038 template<typename T, typename Pointee>
1039 struct RemovePointerHelper<T, Pointee*>
1041 typedef Pointee Type;
1044 } // namespace detail
1047 * Produces the pointed-to type if a pointer is provided, else returns the input
1048 * type. Note that this does not dereference pointer-to-member pointers.
1050 * struct S { bool m; void f(); };
1051 * mozilla::RemovePointer<int>::Type is int;
1052 * mozilla::RemovePointer<int*>::Type is int;
1053 * mozilla::RemovePointer<int* const>::Type is int;
1054 * mozilla::RemovePointer<int* volatile>::Type is int;
1055 * mozilla::RemovePointer<const long*>::Type is const long;
1056 * mozilla::RemovePointer<void* const>::Type is void;
1057 * mozilla::RemovePointer<void (S::*)()>::Type is void (S::*)();
1058 * mozilla::RemovePointer<void (*)()>::Type is void();
1059 * mozilla::RemovePointer<bool S::*>::Type is bool S::*.
1061 template<typename T>
1062 struct RemovePointer
1063 : detail::RemovePointerHelper<T, typename RemoveCV<T>::Type>
1066 /* 20.9.7.6 Other transformations [meta.trans.other] */
1069 * EnableIf is a struct containing a typedef of T if and only if B is true.
1071 * mozilla::EnableIf<true, int>::Type is int;
1072 * mozilla::EnableIf<false, int>::Type is a compile-time error.
1074 * Use this template to implement SFINAE-style (Substitution Failure Is not An
1075 * Error) requirements. For example, you might use it to impose a restriction
1076 * on a template parameter:
1078 * template<typename T>
1079 * class PodVector // vector optimized to store POD (memcpy-able) types
1081 * EnableIf<IsPod<T>::value, T>::Type* vector;
1082 * size_t length;
1083 * ...
1084 * };
1086 template<bool B, typename T>
1087 struct EnableIf
1090 template<typename T>
1091 struct EnableIf<true, T>
1093 typedef T Type;
1097 * Conditional selects a class between two, depending on a given boolean value.
1099 * mozilla::Conditional<true, A, B>::Type is A;
1100 * mozilla::Conditional<false, A, B>::Type is B;
1102 template<bool Condition, typename A, typename B>
1103 struct Conditional
1105 typedef A Type;
1108 template<class A, class B>
1109 struct Conditional<false, A, B>
1111 typedef B Type;
1114 } /* namespace mozilla */
1116 #endif /* mozilla_TypeTraits_h */