Home | History | Annotate | Download | only in base
      1 // Copyright (c) 2006-2009 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 // This code is compiled directly on many platforms, including client
      6 // platforms like Windows, Mac, and embedded systems.  Before making
      7 // any changes here, make sure that you're not breaking any platforms.
      8 //
      9 //
     10 // Define a small subset of tr1 type traits. The traits we define are:
     11 //   is_integral
     12 //   is_floating_point
     13 //   is_pointer
     14 //   is_reference
     15 //   is_pod
     16 //   has_trivial_constructor
     17 //   has_trivial_copy
     18 //   has_trivial_assign
     19 //   has_trivial_destructor
     20 //   remove_const
     21 //   remove_volatile
     22 //   remove_cv
     23 //   remove_reference
     24 //   remove_pointer
     25 //   is_convertible
     26 // We can add more type traits as required.
     27 
     28 #ifndef BASE_TYPE_TRAITS_H_
     29 #define BASE_TYPE_TRAITS_H_
     30 
     31 #include "base/template_util.h"     // For true_type and false_type
     32 #include <utility>                  // For pair
     33 
     34 namespace base {
     35 
     36 // is_integral is false except for the built-in integer types.
     37 template <class T> struct is_integral : false_type { };
     38 template<> struct is_integral<bool> : true_type { };
     39 template<> struct is_integral<char> : true_type { };
     40 template<> struct is_integral<unsigned char> : true_type { };
     41 template<> struct is_integral<signed char> : true_type { };
     42 #if defined(_MSC_VER)
     43 // wchar_t is not by default a distinct type from unsigned short in
     44 // Microsoft C.
     45 // See http://msdn2.microsoft.com/en-us/library/dh8che7s(VS.80).aspx
     46 template<> struct is_integral<__wchar_t> : true_type { };
     47 #else
     48 template<> struct is_integral<wchar_t> : true_type { };
     49 #endif
     50 template<> struct is_integral<short> : true_type { };
     51 template<> struct is_integral<unsigned short> : true_type { };
     52 template<> struct is_integral<int> : true_type { };
     53 template<> struct is_integral<unsigned int> : true_type { };
     54 template<> struct is_integral<long> : true_type { };
     55 template<> struct is_integral<unsigned long> : true_type { };
     56 template<> struct is_integral<long long> : true_type { };
     57 template<> struct is_integral<unsigned long long> : true_type { };
     58 
     59 
     60 // is_floating_point is false except for the built-in floating-point types.
     61 template <class T> struct is_floating_point : false_type { };
     62 template<> struct is_floating_point<float> : true_type { };
     63 template<> struct is_floating_point<double> : true_type { };
     64 template<> struct is_floating_point<long double> : true_type { };
     65 
     66 
     67 // is_pointer is false except for pointer types.
     68 template <class T> struct is_pointer : false_type { };
     69 template <class T> struct is_pointer<T*> : true_type { };
     70 
     71 
     72 // is_reference is false except for reference types.
     73 template<typename T> struct is_reference : false_type {};
     74 template<typename T> struct is_reference<T&> : true_type {};
     75 
     76 
     77 // We can't get is_pod right without compiler help, so fail conservatively.
     78 // We will assume it's false except for arithmetic types and pointers,
     79 // and const versions thereof. Note that std::pair is not a POD.
     80 template <class T> struct is_pod
     81  : integral_constant<bool, (is_integral<T>::value ||
     82                             is_floating_point<T>::value ||
     83                             is_pointer<T>::value)> { };
     84 template <class T> struct is_pod<const T> : is_pod<T> { };
     85 
     86 
     87 // We can't get has_trivial_constructor right without compiler help, so
     88 // fail conservatively. We will assume it's false except for: (1) types
     89 // for which is_pod is true. (2) std::pair of types with trivial
     90 // constructors. (3) array of a type with a trivial constructor.
     91 // (4) const versions thereof.
     92 template <class T> struct has_trivial_constructor : is_pod<T> { };
     93 template <class T, class U> struct has_trivial_constructor<std::pair<T, U> >
     94   : integral_constant<bool,
     95                       (has_trivial_constructor<T>::value &&
     96                        has_trivial_constructor<U>::value)> { };
     97 template <class A, int N> struct has_trivial_constructor<A[N]>
     98   : has_trivial_constructor<A> { };
     99 template <class T> struct has_trivial_constructor<const T>
    100   : has_trivial_constructor<T> { };
    101 
    102 // We can't get has_trivial_copy right without compiler help, so fail
    103 // conservatively. We will assume it's false except for: (1) types
    104 // for which is_pod is true. (2) std::pair of types with trivial copy
    105 // constructors. (3) array of a type with a trivial copy constructor.
    106 // (4) const versions thereof.
    107 template <class T> struct has_trivial_copy : is_pod<T> { };
    108 template <class T, class U> struct has_trivial_copy<std::pair<T, U> >
    109   : integral_constant<bool,
    110                       (has_trivial_copy<T>::value &&
    111                        has_trivial_copy<U>::value)> { };
    112 template <class A, int N> struct has_trivial_copy<A[N]>
    113   : has_trivial_copy<A> { };
    114 template <class T> struct has_trivial_copy<const T> : has_trivial_copy<T> { };
    115 
    116 // We can't get has_trivial_assign right without compiler help, so fail
    117 // conservatively. We will assume it's false except for: (1) types
    118 // for which is_pod is true. (2) std::pair of types with trivial copy
    119 // constructors. (3) array of a type with a trivial assign constructor.
    120 template <class T> struct has_trivial_assign : is_pod<T> { };
    121 template <class T, class U> struct has_trivial_assign<std::pair<T, U> >
    122   : integral_constant<bool,
    123                       (has_trivial_assign<T>::value &&
    124                        has_trivial_assign<U>::value)> { };
    125 template <class A, int N> struct has_trivial_assign<A[N]>
    126   : has_trivial_assign<A> { };
    127 
    128 // We can't get has_trivial_destructor right without compiler help, so
    129 // fail conservatively. We will assume it's false except for: (1) types
    130 // for which is_pod is true. (2) std::pair of types with trivial
    131 // destructors. (3) array of a type with a trivial destructor.
    132 // (4) const versions thereof.
    133 template <class T> struct has_trivial_destructor : is_pod<T> { };
    134 template <class T, class U> struct has_trivial_destructor<std::pair<T, U> >
    135   : integral_constant<bool,
    136                       (has_trivial_destructor<T>::value &&
    137                        has_trivial_destructor<U>::value)> { };
    138 template <class A, int N> struct has_trivial_destructor<A[N]>
    139   : has_trivial_destructor<A> { };
    140 template <class T> struct has_trivial_destructor<const T>
    141   : has_trivial_destructor<T> { };
    142 
    143 // Specified by TR1 [4.7.1]
    144 template<typename T> struct remove_const { typedef T type; };
    145 template<typename T> struct remove_const<T const> { typedef T type; };
    146 template<typename T> struct remove_volatile { typedef T type; };
    147 template<typename T> struct remove_volatile<T volatile> { typedef T type; };
    148 template<typename T> struct remove_cv {
    149   typedef typename remove_const<typename remove_volatile<T>::type>::type type;
    150 };
    151 
    152 
    153 // Specified by TR1 [4.7.2]
    154 template<typename T> struct remove_reference { typedef T type; };
    155 template<typename T> struct remove_reference<T&> { typedef T type; };
    156 
    157 // Specified by TR1 [4.7.4] Pointer modifications.
    158 template<typename T> struct remove_pointer { typedef T type; };
    159 template<typename T> struct remove_pointer<T*> { typedef T type; };
    160 template<typename T> struct remove_pointer<T* const> { typedef T type; };
    161 template<typename T> struct remove_pointer<T* volatile> { typedef T type; };
    162 template<typename T> struct remove_pointer<T* const volatile> {
    163   typedef T type; };
    164 
    165 // Specified by TR1 [4.6] Relationships between types
    166 #ifndef _MSC_VER
    167 namespace internal {
    168 
    169 // This class is an implementation detail for is_convertible, and you
    170 // don't need to know how it works to use is_convertible. For those
    171 // who care: we declare two different functions, one whose argument is
    172 // of type To and one with a variadic argument list. We give them
    173 // return types of different size, so we can use sizeof to trick the
    174 // compiler into telling us which function it would have chosen if we
    175 // had called it with an argument of type From.  See Alexandrescu's
    176 // _Modern C++ Design_ for more details on this sort of trick.
    177 
    178 template <typename From, typename To>
    179 struct ConvertHelper {
    180   static small_ Test(To);
    181   static big_ Test(...);
    182   static From Create();
    183 };
    184 }  // namespace internal
    185 
    186 // Inherits from true_type if From is convertible to To, false_type otherwise.
    187 template <typename From, typename To>
    188 struct is_convertible
    189     : integral_constant<bool,
    190                         sizeof(internal::ConvertHelper<From, To>::Test(
    191                                   internal::ConvertHelper<From, To>::Create()))
    192                         == sizeof(small_)> {
    193 };
    194 #endif
    195 
    196 } // Close namespace base
    197 
    198 #endif  // BASE_TYPE_TRAITS_H_
    199