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 27 namespace 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 294 namespace blink { 295 296 class JSONValue; 297 298 } // namespace blink 299 300 namespace 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 311 template<typename T> 312 class 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(...); 324 public: 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. 333 template<typename Traits> 334 class ShouldBeTraced { 335 public: 336 static const bool value = Traits::template NeedsTracingLazily<>::value; 337 }; 338 339 template<typename T, typename U> 340 struct 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