|
Sierra Toolkit
Version of the Day
|
00001 // Copyright (c) 2006, Google Inc. 00002 // All rights reserved. 00003 // 00004 // Redistribution and use in source and binary forms, with or without 00005 // modification, are permitted provided that the following conditions are 00006 // met: 00007 // 00008 // * Redistributions of source code must retain the above copyright 00009 // notice, this list of conditions and the following disclaimer. 00010 // * Redistributions in binary form must reproduce the above 00011 // copyright notice, this list of conditions and the following disclaimer 00012 // in the documentation and/or other materials provided with the 00013 // distribution. 00014 // * Neither the name of Google Inc. nor the names of its 00015 // contributors may be used to endorse or promote products derived from 00016 // this software without specific prior written permission. 00017 // 00018 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 00019 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 00020 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 00021 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 00022 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 00023 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 00024 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 00025 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 00026 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00027 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 00028 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00029 00030 // ---- 00031 // Author: Matt Austern 00032 // 00033 // Define a small subset of tr1 type traits. The traits we define are: 00034 // is_integral 00035 // is_floating_point 00036 // is_pointer 00037 // is_enum 00038 // is_reference 00039 // is_pod 00040 // has_trivial_constructor 00041 // has_trivial_copy 00042 // has_trivial_assign 00043 // has_trivial_destructor 00044 // remove_const 00045 // remove_volatile 00046 // remove_cv 00047 // remove_reference 00048 // add_reference 00049 // remove_pointer 00050 // is_same 00051 // is_convertible 00052 // We can add more type traits as required. 00053 00054 #ifndef BASE_TYPE_TRAITS_H_ 00055 #define BASE_TYPE_TRAITS_H_ 00056 00057 #include <stk_util/util/sparseconfig.h> 00058 #include <utility> // For pair 00059 00060 _START_GOOGLE_NAMESPACE_ 00061 00062 // integral_constant, defined in tr1, is a wrapper for an integer 00063 // value. We don't really need this generality; we could get away 00064 // with hardcoding the integer type to bool. We use the fully 00065 // general integer_constant for compatibility with tr1. 00066 00067 template<class T, T v> 00068 struct integral_constant { 00069 static const T value = v; 00070 typedef T value_type; 00071 typedef integral_constant<T, v> type; 00072 }; 00073 00074 template <class T, T v> const T integral_constant<T, v>::value; 00075 00076 // Abbreviations: true_type and false_type are structs that represent 00077 // boolean true and false values. 00078 typedef integral_constant<bool, true> true_type; 00079 typedef integral_constant<bool, false> false_type; 00080 00081 // Types small_ and big_ are guaranteed such that sizeof(small_) < 00082 // sizeof(big_) 00083 typedef char small_; 00084 00085 struct big_ { 00086 char dummy[2]; 00087 }; 00088 00089 template <class T> struct is_integral; 00090 template <class T> struct is_floating_point; 00091 template <class T> struct is_pointer; 00092 // MSVC can't compile this correctly, and neither can gcc 3.3.5 (at least) 00093 #if !defined(_MSC_VER) && !(defined(__GNUC__) && __GNUC__ <= 3) 00094 // is_enum uses is_convertible, which is not available on MSVC. 00095 template <class T> struct is_enum; 00096 #endif 00097 template <class T> struct is_reference; 00098 template <class T> struct is_pod; 00099 template <class T> struct has_trivial_constructor; 00100 template <class T> struct has_trivial_copy; 00101 template <class T> struct has_trivial_assign; 00102 template <class T> struct has_trivial_destructor; 00103 template <class T> struct remove_const; 00104 template <class T> struct remove_volatile; 00105 template <class T> struct remove_cv; 00106 template <class T> struct remove_reference; 00107 template <class T> struct add_reference; 00108 template <class T> struct remove_pointer; 00109 template <class T, class U> struct is_same; 00110 #if !defined(_MSC_VER) && !(defined(__GNUC__) && __GNUC__ <= 3) 00111 template <class From, class To> struct is_convertible; 00112 #endif 00113 00114 // is_integral is false except for the built-in integer types. 00115 template <class T> struct is_integral : false_type { }; 00116 template<> struct is_integral<bool> : true_type { }; 00117 template<> struct is_integral<char> : true_type { }; 00118 template<> struct is_integral<unsigned char> : true_type { }; 00119 template<> struct is_integral<signed char> : true_type { }; 00120 #if defined(_MSC_VER) 00121 // wchar_t is not by default a distinct type from unsigned short in 00122 // Microsoft C. 00123 // See http://msdn2.microsoft.com/en-us/library/dh8che7s(VS.80).aspx 00124 template<> struct is_integral<__wchar_t> : true_type { }; 00125 #else 00126 template<> struct is_integral<wchar_t> : true_type { }; 00127 #endif 00128 template<> struct is_integral<short> : true_type { }; 00129 template<> struct is_integral<unsigned short> : true_type { }; 00130 template<> struct is_integral<int> : true_type { }; 00131 template<> struct is_integral<unsigned int> : true_type { }; 00132 template<> struct is_integral<long> : true_type { }; 00133 template<> struct is_integral<unsigned long> : true_type { }; 00134 #ifdef HAVE_LONG_LONG 00135 template<> struct is_integral<long long> : true_type { }; 00136 template<> struct is_integral<unsigned long long> : true_type { }; 00137 #endif 00138 00139 00140 // is_floating_point is false except for the built-in floating-point types. 00141 template <class T> struct is_floating_point : false_type { }; 00142 template<> struct is_floating_point<float> : true_type { }; 00143 template<> struct is_floating_point<double> : true_type { }; 00144 template<> struct is_floating_point<long double> : true_type { }; 00145 00146 00147 // is_pointer is false except for pointer types. 00148 template <class T> struct is_pointer : false_type { }; 00149 template <class T> struct is_pointer<T*> : true_type { }; 00150 00151 #if !defined(_MSC_VER) && !(defined(__GNUC__) && __GNUC__ <= 3) 00152 00153 namespace internal { 00154 00155 template <class T> struct is_class_or_union { 00156 template <class U> static small_ tester(void (U::*)()); 00157 template <class U> static big_ tester(...); 00158 static const bool value = sizeof(tester<T>(0)) == sizeof(small_); 00159 }; 00160 00161 // is_convertible chokes if the first argument is an array. That's why 00162 // we use add_reference here. 00163 template <bool NotUnum, class T> struct is_enum_impl 00164 : is_convertible<typename add_reference<T>::type, int> { }; 00165 00166 template <class T> struct is_enum_impl<true, T> : false_type { }; 00167 00168 } // namespace internal 00169 00170 // Specified by TR1 [4.5.1] primary type categories. 00171 00172 // Implementation note: 00173 // 00174 // Each type is either void, integral, floating point, array, pointer, 00175 // reference, member object pointer, member function pointer, enum, 00176 // union or class. Out of these, only integral, floating point, reference, 00177 // class and enum types are potentially convertible to int. Therefore, 00178 // if a type is not a reference, integral, floating point or class and 00179 // is convertible to int, it's a enum. 00180 // 00181 // Is-convertible-to-int check is done only if all other checks pass, 00182 // because it can't be used with some types (e.g. void or classes with 00183 // inaccessible conversion operators). 00184 template <class T> struct is_enum 00185 : internal::is_enum_impl< 00186 is_same<T, void>::value || 00187 is_integral<T>::value || 00188 is_floating_point<T>::value || 00189 is_reference<T>::value || 00190 internal::is_class_or_union<T>::value, 00191 T> { }; 00192 00193 template <class T> struct is_enum<const T> : is_enum<T> { }; 00194 template <class T> struct is_enum<volatile T> : is_enum<T> { }; 00195 template <class T> struct is_enum<const volatile T> : is_enum<T> { }; 00196 00197 #endif 00198 00199 // is_reference is false except for reference types. 00200 template<typename T> struct is_reference : false_type {}; 00201 template<typename T> struct is_reference<T&> : true_type {}; 00202 00203 00204 // We can't get is_pod right without compiler help, so fail conservatively. 00205 // We will assume it's false except for arithmetic types, enumerations, 00206 // pointers and const versions thereof. Note that std::pair is not a POD. 00207 template <class T> struct is_pod 00208 : integral_constant<bool, (is_integral<T>::value || 00209 is_floating_point<T>::value || 00210 #if !defined(_MSC_VER) && !(defined(__GNUC__) && __GNUC__ <= 3) 00211 // is_enum is not available on MSVC. 00212 is_enum<T>::value || 00213 #endif 00214 is_pointer<T>::value)> { }; 00215 template <class T> struct is_pod<const T> : is_pod<T> { }; 00216 00217 00218 // We can't get has_trivial_constructor right without compiler help, so 00219 // fail conservatively. We will assume it's false except for: (1) types 00220 // for which is_pod is true. (2) std::pair of types with trivial 00221 // constructors. (3) array of a type with a trivial constructor. 00222 // (4) const versions thereof. 00223 template <class T> struct has_trivial_constructor : is_pod<T> { }; 00224 template <class T, class U> struct has_trivial_constructor<std::pair<T, U> > 00225 : integral_constant<bool, 00226 (has_trivial_constructor<T>::value && 00227 has_trivial_constructor<U>::value)> { }; 00228 template <class A, int N> struct has_trivial_constructor<A[N]> 00229 : has_trivial_constructor<A> { }; 00230 template <class T> struct has_trivial_constructor<const T> 00231 : has_trivial_constructor<T> { }; 00232 00233 // We can't get has_trivial_copy right without compiler help, so fail 00234 // conservatively. We will assume it's false except for: (1) types 00235 // for which is_pod is true. (2) std::pair of types with trivial copy 00236 // constructors. (3) array of a type with a trivial copy constructor. 00237 // (4) const versions thereof. 00238 template <class T> struct has_trivial_copy : is_pod<T> { }; 00239 template <class T, class U> struct has_trivial_copy<std::pair<T, U> > 00240 : integral_constant<bool, 00241 (has_trivial_copy<T>::value && 00242 has_trivial_copy<U>::value)> { }; 00243 template <class A, int N> struct has_trivial_copy<A[N]> 00244 : has_trivial_copy<A> { }; 00245 template <class T> struct has_trivial_copy<const T> : has_trivial_copy<T> { }; 00246 00247 // We can't get has_trivial_assign right without compiler help, so fail 00248 // conservatively. We will assume it's false except for: (1) types 00249 // for which is_pod is true. (2) std::pair of types with trivial copy 00250 // constructors. (3) array of a type with a trivial assign constructor. 00251 template <class T> struct has_trivial_assign : is_pod<T> { }; 00252 template <class T, class U> struct has_trivial_assign<std::pair<T, U> > 00253 : integral_constant<bool, 00254 (has_trivial_assign<T>::value && 00255 has_trivial_assign<U>::value)> { }; 00256 template <class A, int N> struct has_trivial_assign<A[N]> 00257 : has_trivial_assign<A> { }; 00258 00259 // We can't get has_trivial_destructor right without compiler help, so 00260 // fail conservatively. We will assume it's false except for: (1) types 00261 // for which is_pod is true. (2) std::pair of types with trivial 00262 // destructors. (3) array of a type with a trivial destructor. 00263 // (4) const versions thereof. 00264 template <class T> struct has_trivial_destructor : is_pod<T> { }; 00265 template <class T, class U> struct has_trivial_destructor<std::pair<T, U> > 00266 : integral_constant<bool, 00267 (has_trivial_destructor<T>::value && 00268 has_trivial_destructor<U>::value)> { }; 00269 template <class A, int N> struct has_trivial_destructor<A[N]> 00270 : has_trivial_destructor<A> { }; 00271 template <class T> struct has_trivial_destructor<const T> 00272 : has_trivial_destructor<T> { }; 00273 00274 // Specified by TR1 [4.7.1] 00275 template<typename T> struct remove_const { typedef T type; }; 00276 template<typename T> struct remove_const<T const> { typedef T type; }; 00277 template<typename T> struct remove_volatile { typedef T type; }; 00278 template<typename T> struct remove_volatile<T volatile> { typedef T type; }; 00279 template<typename T> struct remove_cv { 00280 typedef typename remove_const<typename remove_volatile<T>::type>::type type; 00281 }; 00282 00283 00284 // Specified by TR1 [4.7.2] Reference modifications. 00285 template<typename T> struct remove_reference { typedef T type; }; 00286 template<typename T> struct remove_reference<T&> { typedef T type; }; 00287 00288 template <typename T> struct add_reference { typedef T& type; }; 00289 template <typename T> struct add_reference<T&> { typedef T& type; }; 00290 00291 // Specified by TR1 [4.7.4] Pointer modifications. 00292 template<typename T> struct remove_pointer { typedef T type; }; 00293 template<typename T> struct remove_pointer<T*> { typedef T type; }; 00294 template<typename T> struct remove_pointer<T* const> { typedef T type; }; 00295 template<typename T> struct remove_pointer<T* volatile> { typedef T type; }; 00296 template<typename T> struct remove_pointer<T* const volatile> { 00297 typedef T type; }; 00298 00299 // Specified by TR1 [4.6] Relationships between types 00300 template<typename T, typename U> struct is_same : public false_type { }; 00301 template<typename T> struct is_same<T, T> : public true_type { }; 00302 00303 // Specified by TR1 [4.6] Relationships between types 00304 #if !defined(_MSC_VER) && !(defined(__GNUC__) && __GNUC__ <= 3) 00305 namespace internal { 00306 00307 // This class is an implementation detail for is_convertible, and you 00308 // don't need to know how it works to use is_convertible. For those 00309 // who care: we declare two different functions, one whose argument is 00310 // of type To and one with a variadic argument list. We give them 00311 // return types of different size, so we can use sizeof to trick the 00312 // compiler into telling us which function it would have chosen if we 00313 // had called it with an argument of type From. See Alexandrescu's 00314 // _Modern C++ Design_ for more details on this sort of trick. 00315 00316 template <typename From, typename To> 00317 struct ConvertHelper { 00318 static small_ Test(To); 00319 static big_ Test(...); 00320 static From Create(); 00321 }; 00322 } // namespace internal 00323 00324 // Inherits from true_type if From is convertible to To, false_type otherwise. 00325 template <typename From, typename To> 00326 struct is_convertible 00327 : integral_constant<bool, 00328 sizeof(internal::ConvertHelper<From, To>::Test( 00329 internal::ConvertHelper<From, To>::Create())) 00330 == sizeof(small_)> { 00331 }; 00332 #endif 00333 00334 _END_GOOGLE_NAMESPACE_ 00335 00336 #endif // BASE_TYPE_TRAITS_H_