Bug 856434: Bug 837035 didn't create the TransportFlow for DataChannels. Passes...
[gecko.git] / mfbt / TypeTraits.h
blob661912e1163826274f8d7e9809441e6f8d537580
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 /* Template-based metaprogramming and type-testing facilities. */
7 #ifndef mozilla_TypeTraits_h_
8 #define mozilla_TypeTraits_h_
11 * These traits are approximate copies of the traits and semantics from C++11's
12 * <type_traits> header. Don't add traits not in that header! When all
13 * platforms provide that header, we can convert all users and remove this one.
16 #include <wchar.h>
18 namespace mozilla {
20 /* 20.9.3 Helper classes [meta.help] */
22 /**
23 * Helper class used as a base for various type traits, exposed publicly
24 * because <type_traits> exposes it as well.
26 template<typename T, T Value>
27 struct IntegralConstant
29 static const T value = Value;
30 typedef T ValueType;
31 typedef IntegralConstant<T, Value> Type;
34 /** Convenient aliases. */
35 typedef IntegralConstant<bool, true> TrueType;
36 typedef IntegralConstant<bool, false> FalseType;
38 /* 20.9.4 Unary type traits [meta.unary] */
40 /* 20.9.4.1 Primary type categories [meta.unary.cat] */
42 /**
43 * IsPointer determines whether a type is a pointer type (but not a pointer-to-
44 * member type).
46 * mozilla::IsPointer<struct S*>::value is true;
47 * mozilla::IsPointer<int**>::value is true;
48 * mozilla::IsPointer<void (*)(void)>::value is true;
49 * mozilla::IsPointer<int>::value is false;
50 * mozilla::IsPointer<struct S>::value is false.
52 template<typename T>
53 struct IsPointer : FalseType {};
55 template<typename T>
56 struct IsPointer<T*> : TrueType {};
58 /* 20.9.4.2 Composite type traits [meta.unary.comp] */
60 /* 20.9.4.3 Type properties [meta.unary.prop] */
62 /**
63 * Traits class for identifying POD types. Until C++11 there's no automatic
64 * way to detect PODs, so for the moment this is done manually. Users may
65 * define specializations of this class that inherit from mozilla::TrueType and
66 * mozilla::FalseType (or equivalently mozilla::IntegralConstant<bool, true or
67 * false>, or conveniently from mozilla::IsPod for composite types) as needed to
68 * ensure correct IsPod behavior.
70 template<typename T>
71 struct IsPod : public FalseType {};
73 template<> struct IsPod<char> : TrueType {};
74 template<> struct IsPod<signed char> : TrueType {};
75 template<> struct IsPod<unsigned char> : TrueType {};
76 template<> struct IsPod<short> : TrueType {};
77 template<> struct IsPod<unsigned short> : TrueType {};
78 template<> struct IsPod<int> : TrueType {};
79 template<> struct IsPod<unsigned int> : TrueType {};
80 template<> struct IsPod<long> : TrueType {};
81 template<> struct IsPod<unsigned long> : TrueType {};
82 template<> struct IsPod<long long> : TrueType {};
83 template<> struct IsPod<unsigned long long> : TrueType {};
84 template<> struct IsPod<bool> : TrueType {};
85 template<> struct IsPod<float> : TrueType {};
86 template<> struct IsPod<double> : TrueType {};
87 template<> struct IsPod<wchar_t> : TrueType {};
88 template<typename T> struct IsPod<T*> : TrueType {};
90 /* 20.9.5 Type property queries [meta.unary.prop.query] */
92 /* 20.9.6 Relationships between types [meta.rel] */
94 /**
95 * IsSame tests whether two types are the same type.
97 * mozilla::IsSame<int, int>::value is true;
98 * mozilla::IsSame<int*, int*>::value is true;
99 * mozilla::IsSame<int, unsigned int>::value is false;
100 * mozilla::IsSame<void, void>::value is true;
101 * mozilla::IsSame<const int, int>::value is false;
102 * mozilla::IsSame<struct S, struct S>::value is true.
104 template<typename T, typename U>
105 struct IsSame : FalseType {};
107 template<typename T>
108 struct IsSame<T, T> : TrueType {};
110 namespace detail {
112 // The trickery used to implement IsBaseOf here makes it possible to use it for
113 // the cases of private and multiple inheritance. This code was inspired by the
114 // sample code here:
116 // http://stackoverflow.com/questions/2910979/how-is-base-of-works
117 template<class Base, class Derived>
118 struct BaseOfHelper
120 public:
121 operator Base*() const;
122 operator Derived*();
125 template<class Base, class Derived>
126 struct BaseOfTester
128 private:
129 template<class T>
130 static char test(Derived*, T);
131 static int test(Base*, int);
133 public:
134 static const bool value =
135 sizeof(test(BaseOfHelper<Base, Derived>(), int())) == sizeof(char);
138 template<class Base, class Derived>
139 struct BaseOfTester<Base, const Derived>
141 private:
142 template<class T>
143 static char test(Derived*, T);
144 static int test(Base*, int);
146 public:
147 static const bool value =
148 sizeof(test(BaseOfHelper<Base, Derived>(), int())) == sizeof(char);
151 template<class Base, class Derived>
152 struct BaseOfTester<Base&, Derived&> : FalseType {};
154 template<class Type>
155 struct BaseOfTester<Type, Type> : TrueType {};
157 template<class Type>
158 struct BaseOfTester<Type, const Type> : TrueType {};
160 } /* namespace detail */
163 * IsBaseOf allows to know whether a given class is derived from another.
165 * Consider the following class definitions:
167 * class A {};
168 * class B : public A {};
169 * class C {};
171 * mozilla::IsBaseOf<A, B>::value is true;
172 * mozilla::IsBaseOf<A, C>::value is false;
174 template<class Base, class Derived>
175 struct IsBaseOf
176 : IntegralConstant<bool, detail::BaseOfTester<Base, Derived>::value>
179 namespace detail {
181 template<typename From, typename To>
182 struct ConvertibleTester
184 private:
185 static From create();
187 template<typename From1, typename To1>
188 static char test(To to);
190 template<typename From1, typename To1>
191 static int test(...);
193 public:
194 static const bool value =
195 sizeof(test<From, To>(create())) == sizeof(char);
198 } // namespace detail
201 * IsConvertible determines whether a value of type From will implicitly convert
202 * to a value of type To. For example:
204 * struct A {};
205 * struct B : public A {};
206 * struct C {};
208 * mozilla::IsConvertible<A, A>::value is true;
209 * mozilla::IsConvertible<A*, A*>::value is true;
210 * mozilla::IsConvertible<B, A>::value is true;
211 * mozilla::IsConvertible<B*, A*>::value is true;
212 * mozilla::IsConvertible<C, A>::value is false;
213 * mozilla::IsConvertible<A, C>::value is false;
214 * mozilla::IsConvertible<A*, C*>::value is false;
215 * mozilla::IsConvertible<C*, A*>::value is false.
217 * For obscure reasons, you can't use IsConvertible when the types being tested
218 * are related through private inheritance, and you'll get a compile error if
219 * you try. Just don't do it!
221 template<typename From, typename To>
222 struct IsConvertible
223 : IntegralConstant<bool, detail::ConvertibleTester<From, To>::value>
226 /* 20.9.7 Transformations between types [meta.trans] */
228 /* 20.9.7.1 Const-volatile modifications [meta.trans.cv] */
230 /* 20.9.7.2 Reference modifications [meta.trans.ref] */
232 /* 20.9.7.3 Sign modifications [meta.trans.sign] */
234 /* 20.9.7.4 Array modifications [meta.trans.arr] */
236 /* 20.9.7.5 Pointer modifications [meta.trans.ptr] */
238 /* 20.9.7.6 Other transformations [meta.trans.other] */
241 * EnableIf is a struct containing a typedef of T if and only if B is true.
243 * mozilla::EnableIf<true, int>::Type is int;
244 * mozilla::EnableIf<false, int>::Type is a compile-time error.
246 * Use this template to implement SFINAE-style (Substitution Failure Is not An
247 * Error) requirements. For example, you might use it to impose a restriction
248 * on a template parameter:
250 * template<typename T>
251 * class PodVector // vector optimized to store POD (memcpy-able) types
253 * EnableIf<IsPod<T>::value, T>::Type* vector;
254 * size_t length;
255 * ...
256 * };
258 template<bool B, typename T = void>
259 struct EnableIf
262 template<typename T>
263 struct EnableIf<true, T>
265 typedef T Type;
269 * Conditional selects a class between two, depending on a given boolean value.
271 * mozilla::Conditional<true, A, B>::Type is A;
272 * mozilla::Conditional<false, A, B>::Type is B;
274 template<bool Condition, typename A, typename B>
275 struct Conditional
277 typedef A Type;
280 template<class A, class B>
281 struct Conditional<false, A, B>
283 typedef B Type;
286 } /* namespace mozilla */
288 #endif /* mozilla_TypeTraits_h_ */