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