Tue, 06 Jan 2015 21:39:09 +0100
Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.
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"
14 /*
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.
18 */
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.
33 */
34 template<typename T, T Value>
35 struct IntegralConstant
36 {
37 static const T value = Value;
38 typedef T ValueType;
39 typedef IntegralConstant<T, Value> Type;
40 };
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 IsIntegralHelper : FalseType {};
55 template<> struct IsIntegralHelper<char> : TrueType {};
56 template<> struct IsIntegralHelper<signed char> : TrueType {};
57 template<> struct IsIntegralHelper<unsigned char> : TrueType {};
58 template<> struct IsIntegralHelper<short> : TrueType {};
59 template<> struct IsIntegralHelper<unsigned short> : TrueType {};
60 template<> struct IsIntegralHelper<int> : TrueType {};
61 template<> struct IsIntegralHelper<unsigned int> : TrueType {};
62 template<> struct IsIntegralHelper<long> : TrueType {};
63 template<> struct IsIntegralHelper<unsigned long> : TrueType {};
64 template<> struct IsIntegralHelper<long long> : TrueType {};
65 template<> struct IsIntegralHelper<unsigned long long> : TrueType {};
66 template<> struct IsIntegralHelper<bool> : TrueType {};
67 template<> struct IsIntegralHelper<wchar_t> : TrueType {};
68 #ifdef MOZ_CHAR16_IS_NOT_WCHAR
69 template<> struct IsIntegralHelper<char16_t> : TrueType {};
70 #endif
72 } /* namespace detail */
74 /**
75 * IsIntegral determines whether a type is an integral type.
76 *
77 * mozilla::IsIntegral<int>::value is true;
78 * mozilla::IsIntegral<unsigned short>::value is true;
79 * mozilla::IsIntegral<const long>::value is true;
80 * mozilla::IsIntegral<int*>::value is false;
81 * mozilla::IsIntegral<double>::value is false;
82 *
83 * Note that the behavior of IsIntegral on char16_t and char32_t is
84 * unspecified.
85 */
86 template<typename T>
87 struct IsIntegral : detail::IsIntegralHelper<typename RemoveCV<T>::Type>
88 {};
90 template<typename T, typename U>
91 struct IsSame;
93 namespace detail {
95 template<typename T>
96 struct IsFloatingPointHelper
97 : IntegralConstant<bool,
98 IsSame<T, float>::value ||
99 IsSame<T, double>::value ||
100 IsSame<T, long double>::value>
101 {};
103 } // namespace detail
105 /**
106 * IsFloatingPoint determines whether a type is a floating point type (float,
107 * double, long double).
108 *
109 * mozilla::IsFloatingPoint<int>::value is false;
110 * mozilla::IsFloatingPoint<const float>::value is true;
111 * mozilla::IsFloatingPoint<long double>::value is true;
112 * mozilla::IsFloatingPoint<double*>::value is false.
113 */
114 template<typename T>
115 struct IsFloatingPoint
116 : detail::IsFloatingPointHelper<typename RemoveCV<T>::Type>
117 {};
119 namespace detail {
121 template<typename T>
122 struct IsArrayHelper : FalseType {};
124 template<typename T, decltype(sizeof(1)) N>
125 struct IsArrayHelper<T[N]> : TrueType {};
127 template<typename T>
128 struct IsArrayHelper<T[]> : TrueType {};
130 } // namespace detail
132 /**
133 * IsArray determines whether a type is an array type, of known or unknown
134 * length.
135 *
136 * mozilla::IsArray<int>::value is false;
137 * mozilla::IsArray<int[]>::value is true;
138 * mozilla::IsArray<int[5]>::value is true.
139 */
140 template<typename T>
141 struct IsArray : detail::IsArrayHelper<typename RemoveCV<T>::Type>
142 {};
144 /**
145 * IsPointer determines whether a type is a pointer type (but not a pointer-to-
146 * member type).
147 *
148 * mozilla::IsPointer<struct S*>::value is true;
149 * mozilla::IsPointer<int**>::value is true;
150 * mozilla::IsPointer<void (*)(void)>::value is true;
151 * mozilla::IsPointer<int>::value is false;
152 * mozilla::IsPointer<struct S>::value is false.
153 */
154 template<typename T>
155 struct IsPointer : FalseType {};
157 template<typename T>
158 struct IsPointer<T*> : TrueType {};
160 /**
161 * IsLvalueReference determines whether a type is an lvalue reference.
162 *
163 * mozilla::IsLvalueReference<struct S*>::value is false;
164 * mozilla::IsLvalueReference<int**>::value is false;
165 * mozilla::IsLvalueReference<void (*)(void)>::value is false;
166 * mozilla::IsLvalueReference<int>::value is false;
167 * mozilla::IsLvalueReference<struct S>::value is false;
168 * mozilla::IsLvalueReference<struct S*&>::value is true;
169 * mozilla::IsLvalueReference<struct S&&>::value is false.
170 */
171 template<typename T>
172 struct IsLvalueReference : FalseType {};
174 template<typename T>
175 struct IsLvalueReference<T&> : TrueType {};
177 /**
178 * IsRvalueReference determines whether a type is an rvalue reference.
179 *
180 * mozilla::IsRvalueReference<struct S*>::value is false;
181 * mozilla::IsRvalueReference<int**>::value is false;
182 * mozilla::IsRvalueReference<void (*)(void)>::value is false;
183 * mozilla::IsRvalueReference<int>::value is false;
184 * mozilla::IsRvalueReference<struct S>::value is false;
185 * mozilla::IsRvalueReference<struct S*&>::value is false;
186 * mozilla::IsRvalueReference<struct S&&>::value is true.
187 */
188 template<typename T>
189 struct IsRvalueReference : FalseType {};
191 template<typename T>
192 struct IsRvalueReference<T&&> : TrueType {};
194 namespace detail {
196 // __is_enum is a supported extension across all of our supported compilers.
197 template<typename T>
198 struct IsEnumHelper
199 : IntegralConstant<bool, __is_enum(T)>
200 {};
202 } // namespace detail
204 /**
205 * IsEnum determines whether a type is an enum type.
206 *
207 * mozilla::IsEnum<enum S>::value is true;
208 * mozilla::IsEnum<enum S*>::value is false;
209 * mozilla::IsEnum<int>::value is false;
210 */
211 template<typename T>
212 struct IsEnum
213 : detail::IsEnumHelper<typename RemoveCV<T>::Type>
214 {};
216 namespace detail {
218 // __is_class is a supported extension across all of our supported compilers:
219 // http://llvm.org/releases/3.0/docs/ClangReleaseNotes.html
220 // http://gcc.gnu.org/onlinedocs/gcc-4.4.7/gcc/Type-Traits.html#Type-Traits
221 // http://msdn.microsoft.com/en-us/library/ms177194%28v=vs.100%29.aspx
222 template<typename T>
223 struct IsClassHelper
224 : IntegralConstant<bool, __is_class(T)>
225 {};
227 } // namespace detail
229 /**
230 * IsClass determines whether a type is a class type (but not a union).
231 *
232 * struct S {};
233 * union U {};
234 * mozilla::IsClass<int>::value is false;
235 * mozilla::IsClass<const S>::value is true;
236 * mozilla::IsClass<U>::value is false;
237 */
238 template<typename T>
239 struct IsClass
240 : detail::IsClassHelper<typename RemoveCV<T>::Type>
241 {};
243 /* 20.9.4.2 Composite type traits [meta.unary.comp] */
245 /**
246 * IsReference determines whether a type is an lvalue or rvalue reference.
247 *
248 * mozilla::IsReference<struct S*>::value is false;
249 * mozilla::IsReference<int**>::value is false;
250 * mozilla::IsReference<int&>::value is true;
251 * mozilla::IsReference<void (*)(void)>::value is false;
252 * mozilla::IsReference<const int&>::value is true;
253 * mozilla::IsReference<int>::value is false;
254 * mozilla::IsReference<struct S>::value is false;
255 * mozilla::IsReference<struct S&>::value is true;
256 * mozilla::IsReference<struct S*&>::value is true;
257 * mozilla::IsReference<struct S&&>::value is true.
258 */
259 template<typename T>
260 struct IsReference
261 : IntegralConstant<bool,
262 IsLvalueReference<T>::value || IsRvalueReference<T>::value>
263 {};
265 /**
266 * IsArithmetic determines whether a type is arithmetic. A type is arithmetic
267 * iff it is an integral type or a floating point type.
268 *
269 * mozilla::IsArithmetic<int>::value is true;
270 * mozilla::IsArithmetic<double>::value is true;
271 * mozilla::IsArithmetic<long double*>::value is false.
272 */
273 template<typename T>
274 struct IsArithmetic
275 : IntegralConstant<bool, IsIntegral<T>::value || IsFloatingPoint<T>::value>
276 {};
278 /* 20.9.4.3 Type properties [meta.unary.prop] */
280 /**
281 * IsConst determines whether a type is const or not.
282 *
283 * mozilla::IsConst<int>::value is false;
284 * mozilla::IsConst<void* const>::value is true;
285 * mozilla::IsConst<const char*>::value is false.
286 */
287 template<typename T>
288 struct IsConst : FalseType {};
290 template<typename T>
291 struct IsConst<const T> : TrueType {};
293 /**
294 * IsVolatile determines whether a type is volatile or not.
295 *
296 * mozilla::IsVolatile<int>::value is false;
297 * mozilla::IsVolatile<void* volatile>::value is true;
298 * mozilla::IsVolatile<volatile char*>::value is false.
299 */
300 template<typename T>
301 struct IsVolatile : FalseType {};
303 template<typename T>
304 struct IsVolatile<volatile T> : TrueType {};
306 /**
307 * Traits class for identifying POD types. Until C++11 there's no automatic
308 * way to detect PODs, so for the moment this is done manually. Users may
309 * define specializations of this class that inherit from mozilla::TrueType and
310 * mozilla::FalseType (or equivalently mozilla::IntegralConstant<bool, true or
311 * false>, or conveniently from mozilla::IsPod for composite types) as needed to
312 * ensure correct IsPod behavior.
313 */
314 template<typename T>
315 struct IsPod : public FalseType {};
317 template<> struct IsPod<char> : TrueType {};
318 template<> struct IsPod<signed char> : TrueType {};
319 template<> struct IsPod<unsigned char> : TrueType {};
320 template<> struct IsPod<short> : TrueType {};
321 template<> struct IsPod<unsigned short> : TrueType {};
322 template<> struct IsPod<int> : TrueType {};
323 template<> struct IsPod<unsigned int> : TrueType {};
324 template<> struct IsPod<long> : TrueType {};
325 template<> struct IsPod<unsigned long> : TrueType {};
326 template<> struct IsPod<long long> : TrueType {};
327 template<> struct IsPod<unsigned long long> : TrueType {};
328 template<> struct IsPod<bool> : TrueType {};
329 template<> struct IsPod<float> : TrueType {};
330 template<> struct IsPod<double> : TrueType {};
331 template<> struct IsPod<wchar_t> : TrueType {};
332 #ifdef MOZ_CHAR16_IS_NOT_WCHAR
333 template<> struct IsPod<char16_t> : TrueType {};
334 #endif
335 template<typename T> struct IsPod<T*> : TrueType {};
337 namespace detail {
339 // __is_empty is a supported extension across all of our supported compilers:
340 // http://llvm.org/releases/3.0/docs/ClangReleaseNotes.html
341 // http://gcc.gnu.org/onlinedocs/gcc-4.4.7/gcc/Type-Traits.html#Type-Traits
342 // http://msdn.microsoft.com/en-us/library/ms177194%28v=vs.100%29.aspx
343 template<typename T>
344 struct IsEmptyHelper
345 : IntegralConstant<bool, IsClass<T>::value && __is_empty(T)>
346 {};
348 } // namespace detail
350 /**
351 * IsEmpty determines whether a type is a class (but not a union) that is empty.
352 *
353 * A class is empty iff it and all its base classes have no non-static data
354 * members (except bit-fields of length 0) and no virtual member functions, and
355 * no base class is empty or a virtual base class.
356 *
357 * Intuitively, empty classes don't have any data that has to be stored in
358 * instances of those classes. (The size of the class must still be non-zero,
359 * because distinct array elements of any type must have different addresses.
360 * However, if the Empty Base Optimization is implemented by the compiler [most
361 * compilers implement it, and in certain cases C++11 requires it], the size of
362 * a class inheriting from an empty |Base| class need not be inflated by
363 * |sizeof(Base)|.) And intuitively, non-empty classes have data members and/or
364 * vtable pointers that must be stored in each instance for proper behavior.
365 *
366 * static_assert(!mozilla::IsEmpty<int>::value, "not a class => not empty");
367 * union U1 { int x; };
368 * static_assert(!mozilla::IsEmpty<U1>::value, "not a class => not empty");
369 * struct E1 {};
370 * struct E2 { int : 0 };
371 * struct E3 : E1 {};
372 * struct E4 : E2 {};
373 * static_assert(mozilla::IsEmpty<E1>::value &&
374 * mozilla::IsEmpty<E2>::value &&
375 * mozilla::IsEmpty<E3>::value &&
376 * mozilla::IsEmpty<E4>::value,
377 * "all empty");
378 * union U2 { E1 e1; };
379 * static_assert(!mozilla::IsEmpty<U2>::value, "not a class => not empty");
380 * struct NE1 { int x; };
381 * struct NE2 : virtual E1 {};
382 * struct NE3 : E2 { virtual ~NE3() {} };
383 * struct NE4 { virtual void f() {} };
384 * static_assert(!mozilla::IsEmpty<NE1>::value &&
385 * !mozilla::IsEmpty<NE2>::value &&
386 * !mozilla::IsEmpty<NE3>::value &&
387 * !mozilla::IsEmpty<NE4>::value,
388 * "all empty");
389 */
390 template<typename T>
391 struct IsEmpty : detail::IsEmptyHelper<typename RemoveCV<T>::Type>
392 {};
395 namespace detail {
397 template<typename T, bool = IsFloatingPoint<T>::value>
398 struct IsSignedHelper;
400 template<typename T>
401 struct IsSignedHelper<T, true> : TrueType {};
403 template<typename T>
404 struct IsSignedHelper<T, false>
405 : IntegralConstant<bool, IsArithmetic<T>::value && T(-1) < T(1)>
406 {};
408 } // namespace detail
410 /**
411 * IsSigned determines whether a type is a signed arithmetic type. |char| is
412 * considered a signed type if it has the same representation as |signed char|.
413 *
414 * Don't use this if the type might be user-defined! You might or might not get
415 * a compile error, depending.
416 *
417 * mozilla::IsSigned<int>::value is true;
418 * mozilla::IsSigned<const unsigned int>::value is false;
419 * mozilla::IsSigned<unsigned char>::value is false;
420 * mozilla::IsSigned<float>::value is true.
421 */
422 template<typename T>
423 struct IsSigned : detail::IsSignedHelper<T> {};
425 namespace detail {
427 template<typename T, bool = IsFloatingPoint<T>::value>
428 struct IsUnsignedHelper;
430 template<typename T>
431 struct IsUnsignedHelper<T, true> : FalseType {};
433 template<typename T>
434 struct IsUnsignedHelper<T, false>
435 : IntegralConstant<bool,
436 IsArithmetic<T>::value &&
437 (IsSame<typename RemoveCV<T>::Type, bool>::value ||
438 T(1) < T(-1))>
439 {};
441 } // namespace detail
443 /**
444 * IsUnsigned determines whether a type is an unsigned arithmetic type.
445 *
446 * Don't use this if the type might be user-defined! You might or might not get
447 * a compile error, depending.
448 *
449 * mozilla::IsUnsigned<int>::value is false;
450 * mozilla::IsUnsigned<const unsigned int>::value is true;
451 * mozilla::IsUnsigned<unsigned char>::value is true;
452 * mozilla::IsUnsigned<float>::value is false.
453 */
454 template<typename T>
455 struct IsUnsigned : detail::IsUnsignedHelper<T> {};
457 /* 20.9.5 Type property queries [meta.unary.prop.query] */
459 /* 20.9.6 Relationships between types [meta.rel] */
461 /**
462 * IsSame tests whether two types are the same type.
463 *
464 * mozilla::IsSame<int, int>::value is true;
465 * mozilla::IsSame<int*, int*>::value is true;
466 * mozilla::IsSame<int, unsigned int>::value is false;
467 * mozilla::IsSame<void, void>::value is true;
468 * mozilla::IsSame<const int, int>::value is false;
469 * mozilla::IsSame<struct S, struct S>::value is true.
470 */
471 template<typename T, typename U>
472 struct IsSame : FalseType {};
474 template<typename T>
475 struct IsSame<T, T> : TrueType {};
477 namespace detail {
479 #if defined(__GNUC__) || defined(__clang__) || defined(_MSC_VER)
481 template<class Base, class Derived>
482 struct BaseOfTester : IntegralConstant<bool, __is_base_of(Base, Derived)> {};
484 #else
486 // The trickery used to implement IsBaseOf here makes it possible to use it for
487 // the cases of private and multiple inheritance. This code was inspired by the
488 // sample code here:
489 //
490 // http://stackoverflow.com/questions/2910979/how-is-base-of-works
491 template<class Base, class Derived>
492 struct BaseOfHelper
493 {
494 public:
495 operator Base*() const;
496 operator Derived*();
497 };
499 template<class Base, class Derived>
500 struct BaseOfTester
501 {
502 private:
503 template<class T>
504 static char test(Derived*, T);
505 static int test(Base*, int);
507 public:
508 static const bool value =
509 sizeof(test(BaseOfHelper<Base, Derived>(), int())) == sizeof(char);
510 };
512 template<class Base, class Derived>
513 struct BaseOfTester<Base, const Derived>
514 {
515 private:
516 template<class T>
517 static char test(Derived*, T);
518 static int test(Base*, int);
520 public:
521 static const bool value =
522 sizeof(test(BaseOfHelper<Base, Derived>(), int())) == sizeof(char);
523 };
525 template<class Base, class Derived>
526 struct BaseOfTester<Base&, Derived&> : FalseType {};
528 template<class Type>
529 struct BaseOfTester<Type, Type> : TrueType {};
531 template<class Type>
532 struct BaseOfTester<Type, const Type> : TrueType {};
534 #endif
536 } /* namespace detail */
538 /*
539 * IsBaseOf allows to know whether a given class is derived from another.
540 *
541 * Consider the following class definitions:
542 *
543 * class A {};
544 * class B : public A {};
545 * class C {};
546 *
547 * mozilla::IsBaseOf<A, B>::value is true;
548 * mozilla::IsBaseOf<A, C>::value is false;
549 */
550 template<class Base, class Derived>
551 struct IsBaseOf
552 : IntegralConstant<bool, detail::BaseOfTester<Base, Derived>::value>
553 {};
555 namespace detail {
557 template<typename From, typename To>
558 struct ConvertibleTester
559 {
560 private:
561 static From create();
563 template<typename From1, typename To1>
564 static char test(To to);
566 template<typename From1, typename To1>
567 static int test(...);
569 public:
570 static const bool value =
571 sizeof(test<From, To>(create())) == sizeof(char);
572 };
574 } // namespace detail
576 /**
577 * IsConvertible determines whether a value of type From will implicitly convert
578 * to a value of type To. For example:
579 *
580 * struct A {};
581 * struct B : public A {};
582 * struct C {};
583 *
584 * mozilla::IsConvertible<A, A>::value is true;
585 * mozilla::IsConvertible<A*, A*>::value is true;
586 * mozilla::IsConvertible<B, A>::value is true;
587 * mozilla::IsConvertible<B*, A*>::value is true;
588 * mozilla::IsConvertible<C, A>::value is false;
589 * mozilla::IsConvertible<A, C>::value is false;
590 * mozilla::IsConvertible<A*, C*>::value is false;
591 * mozilla::IsConvertible<C*, A*>::value is false.
592 *
593 * For obscure reasons, you can't use IsConvertible when the types being tested
594 * are related through private inheritance, and you'll get a compile error if
595 * you try. Just don't do it!
596 */
597 template<typename From, typename To>
598 struct IsConvertible
599 : IntegralConstant<bool, detail::ConvertibleTester<From, To>::value>
600 {};
602 /* 20.9.7 Transformations between types [meta.trans] */
604 /* 20.9.7.1 Const-volatile modifications [meta.trans.cv] */
606 /**
607 * RemoveConst removes top-level const qualifications on a type.
608 *
609 * mozilla::RemoveConst<int>::Type is int;
610 * mozilla::RemoveConst<const int>::Type is int;
611 * mozilla::RemoveConst<const int*>::Type is const int*;
612 * mozilla::RemoveConst<int* const>::Type is int*.
613 */
614 template<typename T>
615 struct RemoveConst
616 {
617 typedef T Type;
618 };
620 template<typename T>
621 struct RemoveConst<const T>
622 {
623 typedef T Type;
624 };
626 /**
627 * RemoveVolatile removes top-level volatile qualifications on a type.
628 *
629 * mozilla::RemoveVolatile<int>::Type is int;
630 * mozilla::RemoveVolatile<volatile int>::Type is int;
631 * mozilla::RemoveVolatile<volatile int*>::Type is volatile int*;
632 * mozilla::RemoveVolatile<int* volatile>::Type is int*.
633 */
634 template<typename T>
635 struct RemoveVolatile
636 {
637 typedef T Type;
638 };
640 template<typename T>
641 struct RemoveVolatile<volatile T>
642 {
643 typedef T Type;
644 };
646 /**
647 * RemoveCV removes top-level const and volatile qualifications on a type.
648 *
649 * mozilla::RemoveCV<int>::Type is int;
650 * mozilla::RemoveCV<const int>::Type is int;
651 * mozilla::RemoveCV<volatile int>::Type is int;
652 * mozilla::RemoveCV<int* const volatile>::Type is int*.
653 */
654 template<typename T>
655 struct RemoveCV
656 {
657 typedef typename RemoveConst<typename RemoveVolatile<T>::Type>::Type Type;
658 };
660 /* 20.9.7.2 Reference modifications [meta.trans.ref] */
662 /**
663 * Converts reference types to the underlying types.
664 *
665 * mozilla::RemoveReference<T>::Type is T;
666 * mozilla::RemoveReference<T&>::Type is T;
667 * mozilla::RemoveReference<T&&>::Type is T;
668 */
670 template<typename T>
671 struct RemoveReference
672 {
673 typedef T Type;
674 };
676 template<typename T>
677 struct RemoveReference<T&>
678 {
679 typedef T Type;
680 };
682 template<typename T>
683 struct RemoveReference<T&&>
684 {
685 typedef T Type;
686 };
688 /* 20.9.7.3 Sign modifications [meta.trans.sign] */
690 template<bool B, typename T = void>
691 struct EnableIf;
693 template<bool Condition, typename A, typename B>
694 struct Conditional;
696 namespace detail {
698 template<bool MakeConst, typename T>
699 struct WithC : Conditional<MakeConst, const T, T>
700 {};
702 template<bool MakeVolatile, typename T>
703 struct WithV : Conditional<MakeVolatile, volatile T, T>
704 {};
707 template<bool MakeConst, bool MakeVolatile, typename T>
708 struct WithCV : WithC<MakeConst, typename WithV<MakeVolatile, T>::Type>
709 {};
711 template<typename T>
712 struct CorrespondingSigned;
714 template<>
715 struct CorrespondingSigned<char> { typedef signed char Type; };
716 template<>
717 struct CorrespondingSigned<unsigned char> { typedef signed char Type; };
718 template<>
719 struct CorrespondingSigned<unsigned short> { typedef short Type; };
720 template<>
721 struct CorrespondingSigned<unsigned int> { typedef int Type; };
722 template<>
723 struct CorrespondingSigned<unsigned long> { typedef long Type; };
724 template<>
725 struct CorrespondingSigned<unsigned long long> { typedef long long Type; };
727 template<typename T,
728 typename CVRemoved = typename RemoveCV<T>::Type,
729 bool IsSignedIntegerType = IsSigned<CVRemoved>::value &&
730 !IsSame<char, CVRemoved>::value>
731 struct MakeSigned;
733 template<typename T, typename CVRemoved>
734 struct MakeSigned<T, CVRemoved, true>
735 {
736 typedef T Type;
737 };
739 template<typename T, typename CVRemoved>
740 struct MakeSigned<T, CVRemoved, false>
741 : WithCV<IsConst<T>::value, IsVolatile<T>::value,
742 typename CorrespondingSigned<CVRemoved>::Type>
743 {};
745 } // namespace detail
747 /**
748 * MakeSigned produces the corresponding signed integer type for a given
749 * integral type T, with the const/volatile qualifiers of T. T must be a
750 * possibly-const/volatile-qualified integral type that isn't bool.
751 *
752 * If T is already a signed integer type (not including char!), then T is
753 * produced.
754 *
755 * Otherwise, if T is an unsigned integer type, the signed variety of T, with
756 * T's const/volatile qualifiers, is produced.
757 *
758 * Otherwise, the integral type of the same size as T, with the lowest rank,
759 * with T's const/volatile qualifiers, is produced. (This basically only acts
760 * to produce signed char when T = char.)
761 *
762 * mozilla::MakeSigned<unsigned long>::Type is signed long;
763 * mozilla::MakeSigned<volatile int>::Type is volatile int;
764 * mozilla::MakeSigned<const unsigned short>::Type is const signed short;
765 * mozilla::MakeSigned<const char>::Type is const signed char;
766 * mozilla::MakeSigned<bool> is an error;
767 * mozilla::MakeSigned<void*> is an error.
768 */
769 template<typename T>
770 struct MakeSigned
771 : EnableIf<IsIntegral<T>::value && !IsSame<bool, typename RemoveCV<T>::Type>::value,
772 typename detail::MakeSigned<T>
773 >::Type
774 {};
776 namespace detail {
778 template<typename T>
779 struct CorrespondingUnsigned;
781 template<>
782 struct CorrespondingUnsigned<char> { typedef unsigned char Type; };
783 template<>
784 struct CorrespondingUnsigned<signed char> { typedef unsigned char Type; };
785 template<>
786 struct CorrespondingUnsigned<short> { typedef unsigned short Type; };
787 template<>
788 struct CorrespondingUnsigned<int> { typedef unsigned int Type; };
789 template<>
790 struct CorrespondingUnsigned<long> { typedef unsigned long Type; };
791 template<>
792 struct CorrespondingUnsigned<long long> { typedef unsigned long long Type; };
795 template<typename T,
796 typename CVRemoved = typename RemoveCV<T>::Type,
797 bool IsUnsignedIntegerType = IsUnsigned<CVRemoved>::value &&
798 !IsSame<char, CVRemoved>::value>
799 struct MakeUnsigned;
801 template<typename T, typename CVRemoved>
802 struct MakeUnsigned<T, CVRemoved, true>
803 {
804 typedef T Type;
805 };
807 template<typename T, typename CVRemoved>
808 struct MakeUnsigned<T, CVRemoved, false>
809 : WithCV<IsConst<T>::value, IsVolatile<T>::value,
810 typename CorrespondingUnsigned<CVRemoved>::Type>
811 {};
813 } // namespace detail
815 /**
816 * MakeUnsigned produces the corresponding unsigned integer type for a given
817 * integral type T, with the const/volatile qualifiers of T. T must be a
818 * possibly-const/volatile-qualified integral type that isn't bool.
819 *
820 * If T is already an unsigned integer type (not including char!), then T is
821 * produced.
822 *
823 * Otherwise, if T is an signed integer type, the unsigned variety of T, with
824 * T's const/volatile qualifiers, is produced.
825 *
826 * Otherwise, the unsigned integral type of the same size as T, with the lowest
827 * rank, with T's const/volatile qualifiers, is produced. (This basically only
828 * acts to produce unsigned char when T = char.)
829 *
830 * mozilla::MakeUnsigned<signed long>::Type is unsigned long;
831 * mozilla::MakeUnsigned<volatile unsigned int>::Type is volatile unsigned int;
832 * mozilla::MakeUnsigned<const signed short>::Type is const unsigned short;
833 * mozilla::MakeUnsigned<const char>::Type is const unsigned char;
834 * mozilla::MakeUnsigned<bool> is an error;
835 * mozilla::MakeUnsigned<void*> is an error.
836 */
837 template<typename T>
838 struct MakeUnsigned
839 : EnableIf<IsIntegral<T>::value && !IsSame<bool, typename RemoveCV<T>::Type>::value,
840 typename detail::MakeUnsigned<T>
841 >::Type
842 {};
844 /* 20.9.7.4 Array modifications [meta.trans.arr] */
846 /* 20.9.7.5 Pointer modifications [meta.trans.ptr] */
848 /* 20.9.7.6 Other transformations [meta.trans.other] */
850 /**
851 * EnableIf is a struct containing a typedef of T if and only if B is true.
852 *
853 * mozilla::EnableIf<true, int>::Type is int;
854 * mozilla::EnableIf<false, int>::Type is a compile-time error.
855 *
856 * Use this template to implement SFINAE-style (Substitution Failure Is not An
857 * Error) requirements. For example, you might use it to impose a restriction
858 * on a template parameter:
859 *
860 * template<typename T>
861 * class PodVector // vector optimized to store POD (memcpy-able) types
862 * {
863 * EnableIf<IsPod<T>::value, T>::Type* vector;
864 * size_t length;
865 * ...
866 * };
867 */
868 template<bool B, typename T>
869 struct EnableIf
870 {};
872 template<typename T>
873 struct EnableIf<true, T>
874 {
875 typedef T Type;
876 };
878 /**
879 * Conditional selects a class between two, depending on a given boolean value.
880 *
881 * mozilla::Conditional<true, A, B>::Type is A;
882 * mozilla::Conditional<false, A, B>::Type is B;
883 */
884 template<bool Condition, typename A, typename B>
885 struct Conditional
886 {
887 typedef A Type;
888 };
890 template<class A, class B>
891 struct Conditional<false, A, B>
892 {
893 typedef B Type;
894 };
896 } /* namespace mozilla */
898 #endif /* mozilla_TypeTraits_h */