Home | History | Annotate | Download | only in wtf
      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