Sierra Toolkit  Version of the Day
type_traits_google.h
1 // Copyright (c) 2006, Google Inc.
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are
6 // met:
7 //
8 // * Redistributions of source code must retain the above copyright
9 // notice, this list of conditions and the following disclaimer.
10 // * Redistributions in binary form must reproduce the above
11 // copyright notice, this list of conditions and the following disclaimer
12 // in the documentation and/or other materials provided with the
13 // distribution.
14 // * Neither the name of Google Inc. nor the names of its
15 // contributors may be used to endorse or promote products derived from
16 // this software without specific prior written permission.
17 //
18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 
30 // ----
31 // Author: Matt Austern
32 //
33 // Define a small subset of tr1 type traits. The traits we define are:
34 // is_integral
35 // is_floating_point
36 // is_pointer
37 // is_enum
38 // is_reference
39 // is_pod
40 // has_trivial_constructor
41 // has_trivial_copy
42 // has_trivial_assign
43 // has_trivial_destructor
44 // remove_const
45 // remove_volatile
46 // remove_cv
47 // remove_reference
48 // add_reference
49 // remove_pointer
50 // is_same
51 // is_convertible
52 // We can add more type traits as required.
53 
54 #ifndef BASE_TYPE_TRAITS_H_
55 #define BASE_TYPE_TRAITS_H_
56 
57 #include <stk_util/util/sparseconfig.h>
58 #include <utility> // For pair
59 
60 _START_GOOGLE_NAMESPACE_
61 
62 // integral_constant, defined in tr1, is a wrapper for an integer
63 // value. We don't really need this generality; we could get away
64 // with hardcoding the integer type to bool. We use the fully
65 // general integer_constant for compatibility with tr1.
66 
67 template<class T, T v>
68 struct integral_constant {
69  static const T value = v;
70  typedef T value_type;
71  typedef integral_constant<T, v> type;
72 };
73 
74 template <class T, T v> const T integral_constant<T, v>::value;
75 
76 // Abbreviations: true_type and false_type are structs that represent
77 // boolean true and false values.
78 typedef integral_constant<bool, true> true_type;
79 typedef integral_constant<bool, false> false_type;
80 
81 // Types small_ and big_ are guaranteed such that sizeof(small_) <
82 // sizeof(big_)
83 typedef char small_;
84 
85 struct big_ {
86  char dummy[2];
87 };
88 
89 template <class T> struct is_integral;
90 template <class T> struct is_floating_point;
91 template <class T> struct is_pointer;
92 // MSVC can't compile this correctly, and neither can gcc 3.3.5 (at least)
93 #if !defined(_MSC_VER) && !(defined(__GNUC__) && __GNUC__ <= 3)
94 // is_enum uses is_convertible, which is not available on MSVC.
95 template <class T> struct is_enum;
96 #endif
97 template <class T> struct is_reference;
98 template <class T> struct is_pod;
99 template <class T> struct has_trivial_constructor;
100 template <class T> struct has_trivial_copy;
101 template <class T> struct has_trivial_assign;
102 template <class T> struct has_trivial_destructor;
103 template <class T> struct remove_const;
104 template <class T> struct remove_volatile;
105 template <class T> struct remove_cv;
106 template <class T> struct remove_reference;
107 template <class T> struct add_reference;
108 template <class T> struct remove_pointer;
109 template <class T, class U> struct is_same;
110 #if !defined(_MSC_VER) && !(defined(__GNUC__) && __GNUC__ <= 3)
111 template <class From, class To> struct is_convertible;
112 #endif
113 
114 // is_integral is false except for the built-in integer types.
115 template <class T> struct is_integral : false_type { };
116 template<> struct is_integral<bool> : true_type { };
117 template<> struct is_integral<char> : true_type { };
118 template<> struct is_integral<unsigned char> : true_type { };
119 template<> struct is_integral<signed char> : true_type { };
120 #if defined(_MSC_VER)
121 // wchar_t is not by default a distinct type from unsigned short in
122 // Microsoft C.
123 // See http://msdn2.microsoft.com/en-us/library/dh8che7s(VS.80).aspx
124 template<> struct is_integral<__wchar_t> : true_type { };
125 #else
126 template<> struct is_integral<wchar_t> : true_type { };
127 #endif
128 template<> struct is_integral<short> : true_type { };
129 template<> struct is_integral<unsigned short> : true_type { };
130 template<> struct is_integral<int> : true_type { };
131 template<> struct is_integral<unsigned int> : true_type { };
132 template<> struct is_integral<long> : true_type { };
133 template<> struct is_integral<unsigned long> : true_type { };
134 #ifdef HAVE_LONG_LONG
135 template<> struct is_integral<long long> : true_type { };
136 template<> struct is_integral<unsigned long long> : true_type { };
137 #endif
138 
139 
140 // is_floating_point is false except for the built-in floating-point types.
141 template <class T> struct is_floating_point : false_type { };
142 template<> struct is_floating_point<float> : true_type { };
143 template<> struct is_floating_point<double> : true_type { };
144 template<> struct is_floating_point<long double> : true_type { };
145 
146 
147 // is_pointer is false except for pointer types.
148 template <class T> struct is_pointer : false_type { };
149 template <class T> struct is_pointer<T*> : true_type { };
150 
151 #if !defined(_MSC_VER) && !(defined(__GNUC__) && __GNUC__ <= 3)
152 
153 namespace internal {
154 
155 template <class T> struct is_class_or_union {
156  template <class U> static small_ tester(void (U::*)());
157  template <class U> static big_ tester(...);
158  static const bool value = sizeof(tester<T>(0)) == sizeof(small_);
159 };
160 
161 // is_convertible chokes if the first argument is an array. That's why
162 // we use add_reference here.
163 template <bool NotUnum, class T> struct is_enum_impl
164  : is_convertible<typename add_reference<T>::type, int> { };
165 
166 template <class T> struct is_enum_impl<true, T> : false_type { };
167 
168 } // namespace internal
169 
170 // Specified by TR1 [4.5.1] primary type categories.
171 
172 // Implementation note:
173 //
174 // Each type is either void, integral, floating point, array, pointer,
175 // reference, member object pointer, member function pointer, enum,
176 // union or class. Out of these, only integral, floating point, reference,
177 // class and enum types are potentially convertible to int. Therefore,
178 // if a type is not a reference, integral, floating point or class and
179 // is convertible to int, it's a enum.
180 //
181 // Is-convertible-to-int check is done only if all other checks pass,
182 // because it can't be used with some types (e.g. void or classes with
183 // inaccessible conversion operators).
184 template <class T> struct is_enum
185  : internal::is_enum_impl<
186  is_same<T, void>::value ||
187  is_integral<T>::value ||
188  is_floating_point<T>::value ||
189  is_reference<T>::value ||
190  internal::is_class_or_union<T>::value,
191  T> { };
192 
193 template <class T> struct is_enum<const T> : is_enum<T> { };
194 template <class T> struct is_enum<volatile T> : is_enum<T> { };
195 template <class T> struct is_enum<const volatile T> : is_enum<T> { };
196 
197 #endif
198 
199 // is_reference is false except for reference types.
200 template<typename T> struct is_reference : false_type {};
201 template<typename T> struct is_reference<T&> : true_type {};
202 
203 
204 // We can't get is_pod right without compiler help, so fail conservatively.
205 // We will assume it's false except for arithmetic types, enumerations,
206 // pointers and const versions thereof. Note that std::pair is not a POD.
207 template <class T> struct is_pod
208  : integral_constant<bool, (is_integral<T>::value ||
209  is_floating_point<T>::value ||
210 #if !defined(_MSC_VER) && !(defined(__GNUC__) && __GNUC__ <= 3)
211  // is_enum is not available on MSVC.
212  is_enum<T>::value ||
213 #endif
214  is_pointer<T>::value)> { };
215 template <class T> struct is_pod<const T> : is_pod<T> { };
216 
217 
218 // We can't get has_trivial_constructor right without compiler help, so
219 // fail conservatively. We will assume it's false except for: (1) types
220 // for which is_pod is true. (2) std::pair of types with trivial
221 // constructors. (3) array of a type with a trivial constructor.
222 // (4) const versions thereof.
223 template <class T> struct has_trivial_constructor : is_pod<T> { };
224 template <class T, class U> struct has_trivial_constructor<std::pair<T, U> >
225  : integral_constant<bool,
226  (has_trivial_constructor<T>::value &&
227  has_trivial_constructor<U>::value)> { };
228 template <class A, int N> struct has_trivial_constructor<A[N]>
229  : has_trivial_constructor<A> { };
230 template <class T> struct has_trivial_constructor<const T>
231  : has_trivial_constructor<T> { };
232 
233 // We can't get has_trivial_copy right without compiler help, so fail
234 // conservatively. We will assume it's false except for: (1) types
235 // for which is_pod is true. (2) std::pair of types with trivial copy
236 // constructors. (3) array of a type with a trivial copy constructor.
237 // (4) const versions thereof.
238 template <class T> struct has_trivial_copy : is_pod<T> { };
239 template <class T, class U> struct has_trivial_copy<std::pair<T, U> >
240  : integral_constant<bool,
241  (has_trivial_copy<T>::value &&
242  has_trivial_copy<U>::value)> { };
243 template <class A, int N> struct has_trivial_copy<A[N]>
244  : has_trivial_copy<A> { };
245 template <class T> struct has_trivial_copy<const T> : has_trivial_copy<T> { };
246 
247 // We can't get has_trivial_assign right without compiler help, so fail
248 // conservatively. We will assume it's false except for: (1) types
249 // for which is_pod is true. (2) std::pair of types with trivial copy
250 // constructors. (3) array of a type with a trivial assign constructor.
251 template <class T> struct has_trivial_assign : is_pod<T> { };
252 template <class T, class U> struct has_trivial_assign<std::pair<T, U> >
253  : integral_constant<bool,
254  (has_trivial_assign<T>::value &&
255  has_trivial_assign<U>::value)> { };
256 template <class A, int N> struct has_trivial_assign<A[N]>
257  : has_trivial_assign<A> { };
258 
259 // We can't get has_trivial_destructor right without compiler help, so
260 // fail conservatively. We will assume it's false except for: (1) types
261 // for which is_pod is true. (2) std::pair of types with trivial
262 // destructors. (3) array of a type with a trivial destructor.
263 // (4) const versions thereof.
264 template <class T> struct has_trivial_destructor : is_pod<T> { };
265 template <class T, class U> struct has_trivial_destructor<std::pair<T, U> >
266  : integral_constant<bool,
267  (has_trivial_destructor<T>::value &&
268  has_trivial_destructor<U>::value)> { };
269 template <class A, int N> struct has_trivial_destructor<A[N]>
270  : has_trivial_destructor<A> { };
271 template <class T> struct has_trivial_destructor<const T>
272  : has_trivial_destructor<T> { };
273 
274 // Specified by TR1 [4.7.1]
275 template<typename T> struct remove_const { typedef T type; };
276 template<typename T> struct remove_const<T const> { typedef T type; };
277 template<typename T> struct remove_volatile { typedef T type; };
278 template<typename T> struct remove_volatile<T volatile> { typedef T type; };
279 template<typename T> struct remove_cv {
280  typedef typename remove_const<typename remove_volatile<T>::type>::type type;
281 };
282 
283 
284 // Specified by TR1 [4.7.2] Reference modifications.
285 template<typename T> struct remove_reference { typedef T type; };
286 template<typename T> struct remove_reference<T&> { typedef T type; };
287 
288 template <typename T> struct add_reference { typedef T& type; };
289 template <typename T> struct add_reference<T&> { typedef T& type; };
290 
291 // Specified by TR1 [4.7.4] Pointer modifications.
292 template<typename T> struct remove_pointer { typedef T type; };
293 template<typename T> struct remove_pointer<T*> { typedef T type; };
294 template<typename T> struct remove_pointer<T* const> { typedef T type; };
295 template<typename T> struct remove_pointer<T* volatile> { typedef T type; };
296 template<typename T> struct remove_pointer<T* const volatile> {
297  typedef T type; };
298 
299 // Specified by TR1 [4.6] Relationships between types
300 template<typename T, typename U> struct is_same : public false_type { };
301 template<typename T> struct is_same<T, T> : public true_type { };
302 
303 // Specified by TR1 [4.6] Relationships between types
304 #if !defined(_MSC_VER) && !(defined(__GNUC__) && __GNUC__ <= 3)
305 namespace internal {
306 
307 // This class is an implementation detail for is_convertible, and you
308 // don't need to know how it works to use is_convertible. For those
309 // who care: we declare two different functions, one whose argument is
310 // of type To and one with a variadic argument list. We give them
311 // return types of different size, so we can use sizeof to trick the
312 // compiler into telling us which function it would have chosen if we
313 // had called it with an argument of type From. See Alexandrescu's
314 // _Modern C++ Design_ for more details on this sort of trick.
315 
316 template <typename From, typename To>
317 struct ConvertHelper {
318  static small_ Test(To);
319  static big_ Test(...);
320  static From Create();
321 };
322 } // namespace internal
323 
324 // Inherits from true_type if From is convertible to To, false_type otherwise.
325 template <typename From, typename To>
326 struct is_convertible
327  : integral_constant<bool,
328  sizeof(internal::ConvertHelper<From, To>::Test(
329  internal::ConvertHelper<From, To>::Create()))
330  == sizeof(small_)> {
331 };
332 #endif
333 
334 _END_GOOGLE_NAMESPACE_
335 
336 #endif // BASE_TYPE_TRAITS_H_