This repository has been archived by the owner on Aug 4, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathTypeTraits.h
176 lines (153 loc) · 4.15 KB
/
TypeTraits.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/* Template-based metaprogramming and type-testing facilities. */
#ifndef mozilla_TypeTraits_h_
#define mozilla_TypeTraits_h_
namespace mozilla {
namespace detail {
/**
* The trickery used to implement IsBaseOf here makes it possible to use it for
* the cases of private and multiple inheritance. This code was inspired by the
* sample code here:
*
* http://stackoverflow.com/questions/2910979/how-is-base-of-works
*/
template<class Base, class Derived>
class IsBaseOfHelper
{
public:
operator Base*() const;
operator Derived*();
};
} /* namespace detail */
/*
* IsBaseOf allows to know whether a given class is derived from another.
*
* Consider the following class definitions:
*
* class A {};
* class B : public A {};
* class C {};
*
* mozilla::IsBaseOf<A, B>::value is true;
* mozilla::IsBaseOf<A, C>::value is false;
*/
template<class Base, class Derived>
class IsBaseOf
{
private:
template<class T>
static char test(Derived*, T);
static int test(Base*, int);
public:
static const bool value =
sizeof(test(detail::IsBaseOfHelper<Base, Derived>(), int())) == sizeof(char);
};
template<class Base, class Derived>
class IsBaseOf<Base, const Derived>
{
private:
template<class T>
static char test(Derived*, T);
static int test(Base*, int);
public:
static const bool value =
sizeof(test(detail::IsBaseOfHelper<Base, Derived>(), int())) == sizeof(char);
};
template<class Base, class Derived>
class IsBaseOf<Base&, Derived&>
{
public:
static const bool value = false;
};
template<class Type>
class IsBaseOf<Type, Type>
{
public:
static const bool value = true;
};
template<class Type>
class IsBaseOf<Type, const Type>
{
public:
static const bool value = true;
};
/*
* IsConvertible determines whether a value of type From will implicitly convert
* to a value of type To. For example:
*
* struct A {};
* struct B : public A {};
* struct C {};
*
* mozilla::IsConvertible<A, A>::value is true;
* mozilla::IsConvertible<A*, A*>::value is true;
* mozilla::IsConvertible<B, A>::value is true;
* mozilla::IsConvertible<B*, A*>::value is true;
* mozilla::IsConvertible<C, A>::value is false;
* mozilla::IsConvertible<A, C>::value is false;
* mozilla::IsConvertible<A*, C*>::value is false;
* mozilla::IsConvertible<C*, A*>::value is false.
*
* For obscure reasons, you can't use IsConvertible when the types being tested
* are related through private inheritance, and you'll get a compile error if
* you try. Just don't do it!
*/
template<typename From, typename To>
struct IsConvertible
{
private:
static From create();
template<typename From1, typename To1>
static char test(To to);
template<typename From1, typename To1>
static int test(...);
public:
static const bool value =
sizeof(test<From, To>(create())) == sizeof(char);
};
/*
* Conditional selects a class between two, depending on a given boolean value.
*
* mozilla::Conditional<true, A, B>::Type is A;
* mozilla::Conditional<false, A, B>::Type is B;
*/
template<bool condition, class A, class B>
struct Conditional
{
typedef A Type;
};
template<class A, class B>
struct Conditional<false, A, B>
{
typedef B Type;
};
/*
* EnableIf is a struct containing a typedef of T if and only if B is true.
*
* mozilla::EnableIf<true, int>::Type is int;
* mozilla::EnableIf<false, int>::Type is a compile-time error.
*
* Use this template to implement SFINAE-style (Substitution Failure Is not An
* Error) requirements. For example, you might use it to impose a restriction
* on a template parameter:
*
* template<typename T>
* class PodVector // vector optimized to store POD (memcpy-able) types
* {
* EnableIf<IsPodType<T>, T>::Type* vector;
* size_t length;
* ...
* };
*/
template<bool B, typename T = void>
struct EnableIf
{};
template<typename T>
struct EnableIf<true, T>
{
typedef T Type;
};
} /* namespace mozilla */
#endif /* mozilla_TypeTraits_h_ */