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.
20 /* 20.9.3 Helper classes [meta.help] */
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
;
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] */
43 * IsPointer determines whether a type is a pointer type (but not a pointer-to-
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.
53 struct IsPointer
: FalseType
{};
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] */
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.
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] */
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
{};
108 struct IsSame
<T
, T
> : TrueType
{};
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
116 // http://stackoverflow.com/questions/2910979/how-is-base-of-works
117 template<class Base
, class Derived
>
121 operator Base
*() const;
125 template<class Base
, class Derived
>
130 static char test(Derived
*, T
);
131 static int test(Base
*, int);
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
>
143 static char test(Derived
*, T
);
144 static int test(Base
*, int);
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
{};
155 struct BaseOfTester
<Type
, Type
> : TrueType
{};
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:
168 * class B : public A {};
171 * mozilla::IsBaseOf<A, B>::value is true;
172 * mozilla::IsBaseOf<A, C>::value is false;
174 template<class Base
, class Derived
>
176 : IntegralConstant
<bool, detail::BaseOfTester
<Base
, Derived
>::value
>
181 template<typename From
, typename To
>
182 struct ConvertibleTester
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(...);
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:
205 * struct B : public A {};
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
>
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;
258 template<bool B
, typename T
= void>
263 struct EnableIf
<true, T
>
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
>
280 template<class A
, class B
>
281 struct Conditional
<false, A
, B
>
286 } /* namespace mozilla */
288 #endif /* mozilla_TypeTraits_h_ */