Sierra Toolkit Version of the Day
type_traits_google.h
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_
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines