1 /*
2 * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
3 * Copyright (C) 2009, 2010 Google Inc. All rights reserved.
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
22#ifndef TypeTraits_h
23#define TypeTraits_h
24
25#include <utility>
26
27namespace WTF {
28
29    // The following are provided in this file:
30    //
31    //   IsInteger<T>::value
32    //   IsPod<T>::value, see the definition for a note about its limitations
33    //   IsConvertibleToInteger<T>::value
34    //
35    //   IsArray<T>::value
36    //
37    //   IsSameType<T, U>::value
38    //
39    //   RemovePointer<T>::Type
40    //   RemoveReference<T>::Type
41    //   RemoveConst<T>::Type
42    //   RemoveVolatile<T>::Type
43    //   RemoveConstVolatile<T>::Type
44    //   RemoveExtent<T>::Type
45    //
46    //   COMPILE_ASSERT's in TypeTraits.cpp illustrate their usage and what they do.
47
48    template<bool Predicate, class T = void> struct EnableIf;
49    template<class T> struct EnableIf<true, T> { typedef T Type; };
50
51    template<typename T> struct IsInteger           { static const bool value = false; };
52    template<> struct IsInteger<bool>               { static const bool value = true; };
53    template<> struct IsInteger<char>               { static const bool value = true; };
54    template<> struct IsInteger<signed char>        { static const bool value = true; };
55    template<> struct IsInteger<unsigned char>      { static const bool value = true; };
56    template<> struct IsInteger<short>              { static const bool value = true; };
57    template<> struct IsInteger<unsigned short>     { static const bool value = true; };
58    template<> struct IsInteger<int>                { static const bool value = true; };
59    template<> struct IsInteger<unsigned int>       { static const bool value = true; };
60    template<> struct IsInteger<long>               { static const bool value = true; };
61    template<> struct IsInteger<unsigned long>      { static const bool value = true; };
62    template<> struct IsInteger<long long>          { static const bool value = true; };
63    template<> struct IsInteger<unsigned long long> { static const bool value = true; };
64#if !COMPILER(MSVC) || defined(_NATIVE_WCHAR_T_DEFINED)
65    template<> struct IsInteger<wchar_t>            { static const bool value = true; };
66#endif
67
68    template<typename T> struct IsFloatingPoint     { static const bool value = false; };
69    template<> struct IsFloatingPoint<float>        { static const bool value = true; };
70    template<> struct IsFloatingPoint<double>       { static const bool value = true; };
71    template<> struct IsFloatingPoint<long double>  { static const bool value = true; };
72
73    template<typename T> struct IsArithmetic        { static const bool value = IsInteger<T>::value || IsFloatingPoint<T>::value; };
74
75    template<typename T> struct IsWeak              { static const bool value = false; };
76
77    enum WeakHandlingFlag {
78        NoWeakHandlingInCollections,
79        WeakHandlingInCollections
80    };
81
82    // IsPod is misnamed as it doesn't cover all plain old data (pod) types.
83    // Specifically, it doesn't allow for enums or for structs.
84    template <typename T> struct IsPod              { static const bool value = IsArithmetic<T>::value; };
85    template <typename P> struct IsPod<P*>          { static const bool value = true; };
86
87    template<typename T> class IsConvertibleToInteger {
88        // Avoid "possible loss of data" warning when using Microsoft's C++ compiler
89        // by not converting int's to doubles.
90        template<bool performCheck, typename U> class IsConvertibleToDouble;
91        template<typename U> class IsConvertibleToDouble<false, U> {
92        public:
93            static const bool value = false;
94        };
95
96        template<typename U> class IsConvertibleToDouble<true, U> {
97            typedef char YesType;
98            struct NoType {
99                char padding[8];
100            };
101
102            static YesType floatCheck(long double);
103            static NoType floatCheck(...);
104            static T& t;
105        public:
106            static const bool value = sizeof(floatCheck(t)) == sizeof(YesType);
107        };
108
109    public:
110        static const bool value = IsInteger<T>::value || IsConvertibleToDouble<!IsInteger<T>::value, T>::value;
111    };
112
113    template<typename From, typename To> class IsPointerConvertible {
114        typedef char YesType;
115        struct NoType {
116            char padding[8];
117        };
118
119        static YesType convertCheck(To* x);
120        static NoType convertCheck(...);
121    public:
122        enum {
123            Value = (sizeof(YesType) == sizeof(convertCheck(static_cast<From*>(0))))
124        };
125    };
126
127    template <class T> struct IsArray {
128        static const bool value = false;
129    };
130
131    template <class T> struct IsArray<T[]> {
132        static const bool value = true;
133    };
134
135    template <class T, size_t N> struct IsArray<T[N]> {
136        static const bool value = true;
137    };
138
139
140    template <typename T, typename U> struct IsSameType {
141        static const bool value = false;
142    };
143
144    template <typename T> struct IsSameType<T, T> {
145        static const bool value = true;
146    };
147
148    template <typename T, typename U> class IsSubclass {
149        typedef char YesType;
150        struct NoType {
151            char padding[8];
152        };
153
154        static YesType subclassCheck(U*);
155        static NoType subclassCheck(...);
156        static T* t;
157    public:
158        static const bool value = sizeof(subclassCheck(t)) == sizeof(YesType);
159    };
160
161    template <typename T, template<class V> class U> class IsSubclassOfTemplate {
162        typedef char YesType;
163        struct NoType {
164            char padding[8];
165        };
166
167        template<typename W> static YesType subclassCheck(U<W>*);
168        static NoType subclassCheck(...);
169        static T* t;
170    public:
171        static const bool value = sizeof(subclassCheck(t)) == sizeof(YesType);
172    };
173
174    template <typename T, template<typename V, size_t W> class U> class IsSubclassOfTemplateTypenameSize {
175        typedef char YesType;
176        struct NoType {
177            char padding[8];
178        };
179
180        template<typename X, size_t Y> static YesType subclassCheck(U<X, Y>*);
181        static NoType subclassCheck(...);
182        static T* t;
183    public:
184        static const bool value = sizeof(subclassCheck(t)) == sizeof(YesType);
185    };
186
187    template <typename T, template<typename V, size_t W, typename X> class U> class IsSubclassOfTemplateTypenameSizeTypename {
188        typedef char YesType;
189        struct NoType {
190            char padding[8];
191        };
192
193        template<typename Y, size_t Z, typename A> static YesType subclassCheck(U<Y, Z, A>*);
194        static NoType subclassCheck(...);
195        static T* t;
196    public:
197        static const bool value = sizeof(subclassCheck(t)) == sizeof(YesType);
198    };
199
200    template <typename T, template<class A, class B, class C> class U> class IsSubclassOfTemplate3 {
201        typedef char YesType;
202        struct NoType {
203            char padding[8];
204        };
205
206        template<typename D, typename E, typename F> static YesType subclassCheck(U<D, E, F>*);
207        static NoType subclassCheck(...);
208        static T* t;
209    public:
210        static const bool value = sizeof(subclassCheck(t)) == sizeof(YesType);
211    };
212
213    template <typename T, template<class A, class B, class C, class D, class E> class U> class IsSubclassOfTemplate5 {
214        typedef char YesType;
215        struct NoType {
216            char padding[8];
217        };
218
219        template<typename F, typename G, typename H, typename I, typename J> static YesType subclassCheck(U<F, G, H, I, J>*);
220        static NoType subclassCheck(...);
221        static T* t;
222    public:
223        static const bool value = sizeof(subclassCheck(t)) == sizeof(YesType);
224    };
225
226    template <typename T, template <class V> class OuterTemplate> struct RemoveTemplate {
227        typedef T Type;
228    };
229
230    template <typename T, template <class V> class OuterTemplate> struct RemoveTemplate<OuterTemplate<T>, OuterTemplate> {
231        typedef T Type;
232    };
233
234    template <typename T> struct RemoveConst {
235        typedef T Type;
236    };
237
238    template <typename T> struct RemoveConst<const T> {
239        typedef T Type;
240    };
241
242    template <typename T> struct RemoveVolatile {
243        typedef T Type;
244    };
245
246    template <typename T> struct RemoveVolatile<volatile T> {
247        typedef T Type;
248    };
249
250    template <typename T> struct RemoveConstVolatile {
251        typedef typename RemoveVolatile<typename RemoveConst<T>::Type>::Type Type;
252    };
253
254    template <typename T> struct RemovePointer {
255        typedef T Type;
256    };
257
258    template <typename T> struct RemovePointer<T*> {
259        typedef T Type;
260    };
261
262    template <typename T> struct RemoveReference {
263        typedef T Type;
264    };
265
266    template <typename T> struct RemoveReference<T&> {
267        typedef T Type;
268    };
269
270    template <typename T> struct RemoveExtent {
271        typedef T Type;
272    };
273
274    template <typename T> struct RemoveExtent<T[]> {
275        typedef T Type;
276    };
277
278    template <typename T, size_t N> struct RemoveExtent<T[N]> {
279        typedef T Type;
280    };
281
282    // Determines whether this type has a vtable.
283    template <typename T> struct IsPolymorphic {
284        static const bool value = __is_polymorphic(T);
285    };
286
287#define EnsurePtrConvertibleArgDecl(From, To) \
288    typename WTF::EnableIf<WTF::IsPointerConvertible<From, To>::Value, bool>::Type = true
289#define EnsurePtrConvertibleArgDefn(From, To) \
290    typename WTF::EnableIf<WTF::IsPointerConvertible<From, To>::Value, bool>::Type
291
292} // namespace WTF
293
294namespace blink {
295
296class JSONValue;
297
298} // namespace blink
299
300namespace WTF {
301
302    // FIXME: Disable pointer conversion checking against JSONValue.
303    // The current CodeGeneratorInspector.py generates code which upcasts to JSONValue from undefined types.
304    template<typename From> class IsPointerConvertible<From, blink::JSONValue> {
305    public:
306        enum {
307            Value = true
308        };
309    };
310
311template<typename T>
312class NeedsTracing {
313    typedef char YesType;
314    typedef struct NoType {
315        char padding[8];
316    } NoType;
317#if COMPILER(MSVC)
318    template<typename V> static YesType checkHasTraceMethod(char[&V::trace != 0]);
319#else
320    template<size_t> struct HasMethod;
321    template<typename V> static YesType checkHasTraceMethod(HasMethod<sizeof(&V::trace)>*);
322#endif // COMPILER(MSVC)
323    template<typename V> static NoType checkHasTraceMethod(...);
324public:
325    // We add sizeof(T) to both sides here, because we want it to fail for
326    // incomplete types. Otherwise it just assumes that incomplete types do not
327    // have a trace method, which may not be true.
328    static const bool value = sizeof(YesType) + sizeof(T) == sizeof(checkHasTraceMethod<T>(0)) + sizeof(T);
329};
330
331// Convenience template wrapping the NeedsTracingLazily template in
332// Collection Traits. It helps make the code more readable.
333template<typename Traits>
334class ShouldBeTraced {
335public:
336    static const bool value = Traits::template NeedsTracingLazily<>::value;
337};
338
339template<typename T, typename U>
340struct NeedsTracing<std::pair<T, U> > {
341    static const bool value = NeedsTracing<T>::value || NeedsTracing<U>::value || IsWeak<T>::value || IsWeak<U>::value;
342};
343
344} // namespace WTF
345
346#endif // TypeTraits_h
347