OLD | NEW |
1 /* | 1 // Copyright 2017 The Chromium Authors. All rights reserved. |
2 * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved. | 2 // Use of this source code is governed by a BSD-style license that can be |
3 * Copyright (C) 2009, 2010 Google Inc. All rights reserved. | 3 // found in the LICENSE file. |
4 * | |
5 * This library is free software; you can redistribute it and/or | |
6 * modify it under the terms of the GNU Library General Public | |
7 * License as published by the Free Software Foundation; either | |
8 * version 2 of the License, or (at your option) any later version. | |
9 * | |
10 * This library is distributed in the hope that it will be useful, | |
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
13 * Library General Public License for more details. | |
14 * | |
15 * You should have received a copy of the GNU Library General Public License | |
16 * along with this library; see the file COPYING.LIB. If not, write to | |
17 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | |
18 * Boston, MA 02110-1301, USA. | |
19 * | |
20 */ | |
21 | 4 |
22 #ifndef TypeTraits_h | 5 #include "platform/wtf/TypeTraits.h" |
23 #define TypeTraits_h | |
24 | 6 |
25 #include <cstddef> | 7 // The contents of this header was moved to platform/wtf as part of |
26 #include <type_traits> | 8 // WTF migration project. See the following post for details: |
27 #include <utility> | 9 // https://groups.google.com/a/chromium.org/d/msg/blink-dev/tLdAZCTlcAA/bYXVT8gY
CAAJ |
28 | |
29 #include "wtf/Compiler.h" | |
30 | |
31 namespace WTF { | |
32 | |
33 // Returns a string that contains the type name of |T| as a substring. | |
34 template <typename T> | |
35 inline const char* getStringWithTypeName() { | |
36 return WTF_PRETTY_FUNCTION; | |
37 } | |
38 | |
39 template <typename T> | |
40 struct IsWeak { | |
41 static const bool value = false; | |
42 }; | |
43 | |
44 enum WeakHandlingFlag { | |
45 NoWeakHandlingInCollections, | |
46 WeakHandlingInCollections | |
47 }; | |
48 | |
49 template <typename T, typename From> | |
50 class IsAssignable { | |
51 typedef char YesType; | |
52 struct NoType { | |
53 char padding[8]; | |
54 }; | |
55 | |
56 template <typename T2, | |
57 typename From2, | |
58 typename = decltype(std::declval<T2&>() = std::declval<From2>())> | |
59 static YesType checkAssignability(int); | |
60 template <typename T2, typename From2> | |
61 static NoType checkAssignability(...); | |
62 | |
63 public: | |
64 static const bool value = | |
65 sizeof(checkAssignability<T, From>(0)) == sizeof(YesType); | |
66 }; | |
67 | |
68 template <typename T> | |
69 struct IsCopyAssignable { | |
70 static_assert(!std::is_reference<T>::value, "T must not be a reference."); | |
71 static const bool value = IsAssignable<T, const T&>::value; | |
72 }; | |
73 | |
74 template <typename T> | |
75 struct IsMoveAssignable { | |
76 static_assert(!std::is_reference<T>::value, "T must not be a reference."); | |
77 static const bool value = IsAssignable<T, T&&>::value; | |
78 }; | |
79 | |
80 template <typename T> | |
81 struct IsTriviallyCopyAssignable { | |
82 static const bool value = | |
83 __has_trivial_assign(T) && IsCopyAssignable<T>::value; | |
84 }; | |
85 | |
86 template <typename T> | |
87 struct IsTriviallyMoveAssignable { | |
88 // TODO(yutak): This isn't really correct, because __has_trivial_assign | |
89 // appears to look only at copy assignment. However, | |
90 // std::is_trivially_move_assignable isn't available at this moment, and | |
91 // there isn't a good way to write that ourselves. | |
92 // | |
93 // Here we use IsTriviallyCopyAssignable as a conservative approximation: if T | |
94 // is trivially copy assignable, T is trivially move assignable, too. This | |
95 // definition misses a case where T is trivially move-only assignable, but | |
96 // such cases should be rare. | |
97 static const bool value = IsTriviallyCopyAssignable<T>::value; | |
98 }; | |
99 | |
100 template <typename T> | |
101 class IsDestructible { | |
102 typedef char YesType; | |
103 struct NoType { | |
104 char padding[8]; | |
105 }; | |
106 | |
107 template <typename T2, typename = decltype(std::declval<T2>().~T2())> | |
108 static YesType checkDestructibility(int); | |
109 template <typename T2> | |
110 static NoType checkDestructibility(...); | |
111 | |
112 public: | |
113 static const bool value = | |
114 sizeof(checkDestructibility<T>(0)) == sizeof(YesType); | |
115 }; | |
116 | |
117 template <typename T> | |
118 struct IsTriviallyDefaultConstructible { | |
119 static const bool value = | |
120 __has_trivial_constructor(T) && std::is_constructible<T>::value; | |
121 }; | |
122 | |
123 template <typename T> | |
124 struct IsTriviallyDestructible { | |
125 static const bool value = | |
126 __has_trivial_destructor(T) && IsDestructible<T>::value; | |
127 }; | |
128 | |
129 template <typename T, typename U> | |
130 struct IsSubclass { | |
131 private: | |
132 typedef char YesType; | |
133 struct NoType { | |
134 char padding[8]; | |
135 }; | |
136 | |
137 static YesType subclassCheck(U*); | |
138 static NoType subclassCheck(...); | |
139 static T* t; | |
140 | |
141 public: | |
142 static const bool value = sizeof(subclassCheck(t)) == sizeof(YesType); | |
143 }; | |
144 | |
145 template <typename T, template <typename... V> class U> | |
146 struct IsSubclassOfTemplate { | |
147 private: | |
148 typedef char YesType; | |
149 struct NoType { | |
150 char padding[8]; | |
151 }; | |
152 | |
153 template <typename... W> | |
154 static YesType subclassCheck(U<W...>*); | |
155 static NoType subclassCheck(...); | |
156 static T* t; | |
157 | |
158 public: | |
159 static const bool value = sizeof(subclassCheck(t)) == sizeof(YesType); | |
160 }; | |
161 | |
162 template <typename T, template <typename V, size_t W> class U> | |
163 struct IsSubclassOfTemplateTypenameSize { | |
164 private: | |
165 typedef char YesType; | |
166 struct NoType { | |
167 char padding[8]; | |
168 }; | |
169 | |
170 template <typename X, size_t Y> | |
171 static YesType subclassCheck(U<X, Y>*); | |
172 static NoType subclassCheck(...); | |
173 static T* t; | |
174 | |
175 public: | |
176 static const bool value = sizeof(subclassCheck(t)) == sizeof(YesType); | |
177 }; | |
178 | |
179 template <typename T, template <typename V, size_t W, typename X> class U> | |
180 struct IsSubclassOfTemplateTypenameSizeTypename { | |
181 private: | |
182 typedef char YesType; | |
183 struct NoType { | |
184 char padding[8]; | |
185 }; | |
186 | |
187 template <typename Y, size_t Z, typename A> | |
188 static YesType subclassCheck(U<Y, Z, A>*); | |
189 static NoType subclassCheck(...); | |
190 static T* t; | |
191 | |
192 public: | |
193 static const bool value = sizeof(subclassCheck(t)) == sizeof(YesType); | |
194 }; | |
195 | |
196 template <typename T, template <class V> class OuterTemplate> | |
197 struct RemoveTemplate { | |
198 typedef T Type; | |
199 }; | |
200 | |
201 template <typename T, template <class V> class OuterTemplate> | |
202 struct RemoveTemplate<OuterTemplate<T>, OuterTemplate> { | |
203 typedef T Type; | |
204 }; | |
205 | |
206 #if (COMPILER(MSVC) || !GCC_VERSION_AT_LEAST(4, 9, 0)) && !COMPILER(CLANG) | |
207 // FIXME: MSVC bug workaround. Remove once MSVC STL is fixed. | |
208 // FIXME: GCC before 4.9.0 seems to have the same issue. | |
209 // C++ 2011 Spec (ISO/IEC 14882:2011(E)) 20.9.6.2 Table 51 states that | |
210 // the template parameters shall be a complete type if they are different types. | |
211 // However, MSVC checks for type completeness even if they are the same type. | |
212 // Here, we use a template specialization for same type case to allow incomplete | |
213 // types. | |
214 | |
215 template <typename T, typename U> | |
216 struct IsConvertible { | |
217 static const bool value = std::is_convertible<T, U>::value; | |
218 }; | |
219 | |
220 template <typename T> | |
221 struct IsConvertible<T, T> { | |
222 static const bool value = true; | |
223 }; | |
224 | |
225 #define EnsurePtrConvertibleArgDecl(From, To) \ | |
226 typename std::enable_if<WTF::IsConvertible<From*, To*>::value>::type* = \ | |
227 nullptr | |
228 #define EnsurePtrConvertibleArgDefn(From, To) \ | |
229 typename std::enable_if<WTF::IsConvertible<From*, To*>::value>::type* | |
230 #else | |
231 #define EnsurePtrConvertibleArgDecl(From, To) \ | |
232 typename std::enable_if<std::is_convertible<From*, To*>::value>::type* = \ | |
233 nullptr | |
234 #define EnsurePtrConvertibleArgDefn(From, To) \ | |
235 typename std::enable_if<std::is_convertible<From*, To*>::value>::type* | |
236 #endif | |
237 | |
238 } // namespace WTF | |
239 | |
240 namespace blink { | |
241 | |
242 class Visitor; | |
243 | |
244 } // namespace blink | |
245 | |
246 namespace WTF { | |
247 | |
248 template <typename T> | |
249 class IsTraceable { | |
250 typedef char YesType; | |
251 typedef struct NoType { char padding[8]; } NoType; | |
252 | |
253 // Note that this also checks if a superclass of V has a trace method. | |
254 template <typename V> | |
255 static YesType checkHasTraceMethod( | |
256 V* v, | |
257 blink::Visitor* p = nullptr, | |
258 typename std::enable_if< | |
259 std::is_same<decltype(v->trace(p)), void>::value>::type* g = nullptr); | |
260 template <typename V> | |
261 static NoType checkHasTraceMethod(...); | |
262 | |
263 public: | |
264 // We add sizeof(T) to both sides here, because we want it to fail for | |
265 // incomplete types. Otherwise it just assumes that incomplete types do not | |
266 // have a trace method, which may not be true. | |
267 static const bool value = sizeof(YesType) + sizeof(T) == | |
268 sizeof(checkHasTraceMethod<T>(nullptr)) + sizeof(T); | |
269 }; | |
270 | |
271 // Convenience template wrapping the IsTraceableInCollection template in | |
272 // Collection Traits. It helps make the code more readable. | |
273 template <typename Traits> | |
274 class IsTraceableInCollectionTrait { | |
275 public: | |
276 static const bool value = Traits::template IsTraceableInCollection<>::value; | |
277 }; | |
278 | |
279 template <typename T, typename U> | |
280 struct IsTraceable<std::pair<T, U>> { | |
281 static const bool value = IsTraceable<T>::value || IsTraceable<U>::value; | |
282 }; | |
283 | |
284 // This is used to check that DISALLOW_NEW_EXCEPT_PLACEMENT_NEW objects are not | |
285 // stored in off-heap Vectors, HashTables etc. | |
286 template <typename T> | |
287 struct AllowsOnlyPlacementNew { | |
288 private: | |
289 using YesType = char; | |
290 struct NoType { | |
291 char padding[8]; | |
292 }; | |
293 | |
294 template <typename U> | |
295 static YesType checkMarker(typename U::IsAllowOnlyPlacementNew*); | |
296 template <typename U> | |
297 static NoType checkMarker(...); | |
298 | |
299 public: | |
300 static const bool value = sizeof(checkMarker<T>(nullptr)) == sizeof(YesType); | |
301 }; | |
302 | |
303 template <typename T> | |
304 class IsGarbageCollectedType { | |
305 typedef char YesType; | |
306 typedef struct NoType { char padding[8]; } NoType; | |
307 | |
308 static_assert(sizeof(T), "T must be fully defined"); | |
309 | |
310 using NonConstType = typename std::remove_const<T>::type; | |
311 template <typename U> | |
312 static YesType checkGarbageCollectedType( | |
313 typename U::IsGarbageCollectedTypeMarker*); | |
314 template <typename U> | |
315 static NoType checkGarbageCollectedType(...); | |
316 | |
317 // Separately check for GarbageCollectedMixin, which declares a different | |
318 // marker typedef, to avoid resolution ambiguity for cases like | |
319 // IsGarbageCollectedType<B> over: | |
320 // | |
321 // class A : public GarbageCollected<A>, public GarbageCollectedMixin { | |
322 // USING_GARBAGE_COLLECTED_MIXIN(A); | |
323 // ... | |
324 // }; | |
325 // class B : public A, public GarbageCollectedMixin { ... }; | |
326 // | |
327 template <typename U> | |
328 static YesType checkGarbageCollectedMixinType( | |
329 typename U::IsGarbageCollectedMixinMarker*); | |
330 template <typename U> | |
331 static NoType checkGarbageCollectedMixinType(...); | |
332 | |
333 public: | |
334 static const bool value = | |
335 (sizeof(YesType) == | |
336 sizeof(checkGarbageCollectedType<NonConstType>(nullptr))) || | |
337 (sizeof(YesType) == | |
338 sizeof(checkGarbageCollectedMixinType<NonConstType>(nullptr))); | |
339 }; | |
340 | |
341 template <> | |
342 class IsGarbageCollectedType<void> { | |
343 public: | |
344 static const bool value = false; | |
345 }; | |
346 | |
347 template <typename T> | |
348 class IsPersistentReferenceType { | |
349 typedef char YesType; | |
350 typedef struct NoType { char padding[8]; } NoType; | |
351 | |
352 template <typename U> | |
353 static YesType checkPersistentReferenceType( | |
354 typename U::IsPersistentReferenceTypeMarker*); | |
355 template <typename U> | |
356 static NoType checkPersistentReferenceType(...); | |
357 | |
358 public: | |
359 static const bool value = | |
360 (sizeof(YesType) == sizeof(checkPersistentReferenceType<T>(nullptr))); | |
361 }; | |
362 | |
363 template <typename T, | |
364 bool = std::is_function<typename std::remove_const< | |
365 typename std::remove_pointer<T>::type>::type>::value || | |
366 std::is_void<typename std::remove_const< | |
367 typename std::remove_pointer<T>::type>::type>::value> | |
368 class IsPointerToGarbageCollectedType { | |
369 public: | |
370 static const bool value = false; | |
371 }; | |
372 | |
373 template <typename T> | |
374 class IsPointerToGarbageCollectedType<T*, false> { | |
375 public: | |
376 static const bool value = IsGarbageCollectedType<T>::value; | |
377 }; | |
378 | |
379 } // namespace WTF | |
380 | |
381 using WTF::IsGarbageCollectedType; | |
382 | |
383 #endif // TypeTraits_h | |
OLD | NEW |