92bd949570defc7a89d24af528c1a50dfef36dd1
[profile/ivi/qtbase.git] / src / corelib / global / qtypetraits.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 //
32 // This code is compiled directly on many platforms, including client
33 // platforms like Windows, Mac, and embedded systems.  Before making
34 // any changes here, make sure that you're not breaking any platforms.
35 //
36 // Define a small subset of tr1 type traits. The traits we define are:
37 //   is_integral
38 //   is_floating_point
39 //   is_pointer
40 //   is_enum
41 //   is_reference
42 //   is_pod
43 //   has_trivial_constructor
44 //   has_trivial_copy
45 //   has_trivial_assign
46 //   has_trivial_destructor
47 //   remove_const
48 //   remove_volatile
49 //   remove_cv
50 //   remove_reference
51 //   add_reference
52 //   remove_pointer
53 //   is_same
54 //   is_convertible
55 // We can add more type traits as required.
56
57 // Changes from the original implementation:
58 //  - Move base types from template_util.h directly into this header.
59 //  - Use Qt macros for long long type differences on Windows.
60 //  - Enclose in QtPrivate namespace.
61
62 #ifndef QTYPETRAITS_H
63 #define QTYPETRAITS_H
64
65 #include <utility>                  // For pair
66 #include "QtCore/qglobal.h"
67
68 QT_BEGIN_HEADER
69 QT_BEGIN_NAMESPACE
70
71 namespace QtPrivate {
72
73 // Types small_ and big_ are guaranteed such that sizeof(small_) <
74 // sizeof(big_)
75 typedef char small_;
76
77 struct big_ {
78   char dummy[2];
79 };
80
81 // Identity metafunction.
82 template <class T>
83 struct identity_ {
84   typedef T type;
85 };
86
87 // integral_constant, defined in tr1, is a wrapper for an integer
88 // value. We don't really need this generality; we could get away
89 // with hardcoding the integer type to bool. We use the fully
90 // general integer_constant for compatibility with tr1.
91
92 template<class T, T v>
93 struct integral_constant {
94   static const T value = v;
95   typedef T value_type;
96   typedef integral_constant<T, v> type;
97 };
98
99 template <class T, T v> const T integral_constant<T, v>::value;
100
101
102 // Abbreviations: true_type and false_type are structs that represent boolean
103 // true and false values. Also define the boost::mpl versions of those names,
104 // true_ and false_.
105 typedef integral_constant<bool, true>  true_type;
106 typedef integral_constant<bool, false> false_type;
107 typedef true_type  true_;
108 typedef false_type false_;
109
110 // if_ is a templatized conditional statement.
111 // if_<cond, A, B> is a compile time evaluation of cond.
112 // if_<>::type contains A if cond is true, B otherwise.
113 template<bool cond, typename A, typename B>
114 struct if_{
115   typedef A type;
116 };
117
118 template<typename A, typename B>
119 struct if_<false, A, B> {
120   typedef B type;
121 };
122
123
124 // type_equals_ is a template type comparator, similar to Loki IsSameType.
125 // type_equals_<A, B>::value is true iff "A" is the same type as "B".
126 //
127 // New code should prefer base::is_same, defined in base/type_traits.h.
128 // It is functionally identical, but is_same is the standard spelling.
129 template<typename A, typename B>
130 struct type_equals_ : public false_ {
131 };
132
133 template<typename A>
134 struct type_equals_<A, A> : public true_ {
135 };
136
137 // and_ is a template && operator.
138 // and_<A, B>::value evaluates "A::value && B::value".
139 template<typename A, typename B>
140 struct and_ : public integral_constant<bool, (A::value && B::value)> {
141 };
142
143 // or_ is a template || operator.
144 // or_<A, B>::value evaluates "A::value || B::value".
145 template<typename A, typename B>
146 struct or_ : public integral_constant<bool, (A::value || B::value)> {
147 };
148
149 template <class T> struct is_integral;
150 template <class T> struct is_floating_point;
151 template <class T> struct is_pointer;
152 // MSVC can't compile this correctly, and neither can gcc 3.3.5 (at least)
153 #if !defined(_MSC_VER) && !(defined(__GNUC__) && __GNUC__ <= 3)
154 // is_enum uses is_convertible, which is not available on MSVC.
155 template <class T> struct is_enum;
156 #endif
157 template <class T> struct is_reference;
158 template <class T> struct is_pod;
159 template <class T> struct has_trivial_constructor;
160 template <class T> struct has_trivial_copy;
161 template <class T> struct has_trivial_assign;
162 template <class T> struct has_trivial_destructor;
163 template <class T> struct remove_const;
164 template <class T> struct remove_volatile;
165 template <class T> struct remove_cv;
166 template <class T> struct remove_reference;
167 template <class T> struct add_reference;
168 template <class T> struct remove_pointer;
169 template <class T, class U> struct is_same;
170 #if !defined(_MSC_VER) && !(defined(__GNUC__) && __GNUC__ <= 3)
171 template <class From, class To> struct is_convertible;
172 #endif
173
174 // is_integral is false except for the built-in integer types. A
175 // cv-qualified type is integral if and only if the underlying type is.
176 template <class T> struct is_integral : false_type { };
177 template<> struct is_integral<bool> : true_type { };
178 template<> struct is_integral<char> : true_type { };
179 template<> struct is_integral<unsigned char> : true_type { };
180 template<> struct is_integral<signed char> : true_type { };
181 #if defined(_MSC_VER)
182 // wchar_t is not by default a distinct type from unsigned short in
183 // Microsoft C.
184 // See http://msdn2.microsoft.com/en-us/library/dh8che7s(VS.80).aspx
185 template<> struct is_integral<__wchar_t> : true_type { };
186 #else
187 template<> struct is_integral<wchar_t> : true_type { };
188 #endif
189 template<> struct is_integral<short> : true_type { };
190 template<> struct is_integral<unsigned short> : true_type { };
191 template<> struct is_integral<int> : true_type { };
192 template<> struct is_integral<unsigned int> : true_type { };
193 template<> struct is_integral<long> : true_type { };
194 template<> struct is_integral<unsigned long> : true_type { };
195 #if defined(Q_OS_WIN) && !defined(Q_CC_GNU)
196 template<> struct is_integral<__int64> : true_type { };
197 template<> struct is_integral<unsigned __int64> : true_type { };
198 #else
199 template<> struct is_integral<long long> : true_type { };
200 template<> struct is_integral<unsigned long long> : true_type { };
201 #endif
202 template <class T> struct is_integral<const T> : is_integral<T> { };
203 template <class T> struct is_integral<volatile T> : is_integral<T> { };
204 template <class T> struct is_integral<const volatile T> : is_integral<T> { };
205
206 // is_floating_point is false except for the built-in floating-point types.
207 // A cv-qualified type is integral if and only if the underlying type is.
208 template <class T> struct is_floating_point : false_type { };
209 template<> struct is_floating_point<float> : true_type { };
210 template<> struct is_floating_point<double> : true_type { };
211 template<> struct is_floating_point<long double> : true_type { };
212 template <class T> struct is_floating_point<const T>
213     : is_floating_point<T> { };
214 template <class T> struct is_floating_point<volatile T>
215     : is_floating_point<T> { };
216 template <class T> struct is_floating_point<const volatile T>
217     : is_floating_point<T> { };
218
219 // is_pointer is false except for pointer types. A cv-qualified type (e.g.
220 // "int* const", as opposed to "int const*") is cv-qualified if and only if
221 // the underlying type is.
222 template <class T> struct is_pointer : false_type { };
223 template <class T> struct is_pointer<T*> : true_type { };
224 template <class T> struct is_pointer<const T> : is_pointer<T> { };
225 template <class T> struct is_pointer<volatile T> : is_pointer<T> { };
226 template <class T> struct is_pointer<const volatile T> : is_pointer<T> { };
227
228 #if !defined(_MSC_VER) && !(defined(__GNUC__) && __GNUC__ <= 3)
229
230 namespace internal {
231
232 template <class T> struct is_class_or_union {
233   template <class U> static small_ tester(void (U::*)());
234   template <class U> static big_ tester(...);
235   static const bool value = sizeof(tester<T>(0)) == sizeof(small_);
236 };
237
238 // is_convertible chokes if the first argument is an array. That's why
239 // we use add_reference here.
240 template <bool NotUnum, class T> struct is_enum_impl
241     : is_convertible<typename add_reference<T>::type, int> { };
242
243 template <class T> struct is_enum_impl<true, T> : false_type { };
244
245 }  // namespace internal
246
247 // Specified by TR1 [4.5.1] primary type categories.
248
249 // Implementation note:
250 //
251 // Each type is either void, integral, floating point, array, pointer,
252 // reference, member object pointer, member function pointer, enum,
253 // union or class. Out of these, only integral, floating point, reference,
254 // class and enum types are potentially convertible to int. Therefore,
255 // if a type is not a reference, integral, floating point or class and
256 // is convertible to int, it's a enum. Adding cv-qualification to a type
257 // does not change whether it's an enum.
258 //
259 // Is-convertible-to-int check is done only if all other checks pass,
260 // because it can't be used with some types (e.g. void or classes with
261 // inaccessible conversion operators).
262 template <class T> struct is_enum
263     : internal::is_enum_impl<
264           is_same<T, void>::value ||
265               is_integral<T>::value ||
266               is_floating_point<T>::value ||
267               is_reference<T>::value ||
268               internal::is_class_or_union<T>::value,
269           T> { };
270
271 template <class T> struct is_enum<const T> : is_enum<T> { };
272 template <class T> struct is_enum<volatile T> : is_enum<T> { };
273 template <class T> struct is_enum<const volatile T> : is_enum<T> { };
274
275 #endif
276
277 // is_reference is false except for reference types.
278 template<typename T> struct is_reference : false_type {};
279 template<typename T> struct is_reference<T&> : true_type {};
280
281
282 // We can't get is_pod right without compiler help, so fail conservatively.
283 // We will assume it's false except for arithmetic types, enumerations,
284 // pointers and cv-qualified versions thereof. Note that std::pair<T,U>
285 // is not a POD even if T and U are PODs.
286 template <class T> struct is_pod
287  : integral_constant<bool, (is_integral<T>::value ||
288                             is_floating_point<T>::value ||
289 #if !defined(_MSC_VER) && !(defined(__GNUC__) && __GNUC__ <= 3)
290                             // is_enum is not available on MSVC.
291                             is_enum<T>::value ||
292 #endif
293                             is_pointer<T>::value)> { };
294 template <class T> struct is_pod<const T> : is_pod<T> { };
295 template <class T> struct is_pod<volatile T> : is_pod<T> { };
296 template <class T> struct is_pod<const volatile T> : is_pod<T> { };
297
298
299 // We can't get has_trivial_constructor right without compiler help, so
300 // fail conservatively. We will assume it's false except for: (1) types
301 // for which is_pod is true. (2) std::pair of types with trivial
302 // constructors. (3) array of a type with a trivial constructor.
303 // (4) const versions thereof.
304 template <class T> struct has_trivial_constructor : is_pod<T> { };
305 template <class T, class U> struct has_trivial_constructor<std::pair<T, U> >
306   : integral_constant<bool,
307                       (has_trivial_constructor<T>::value &&
308                        has_trivial_constructor<U>::value)> { };
309 template <class A, int N> struct has_trivial_constructor<A[N]>
310   : has_trivial_constructor<A> { };
311 template <class T> struct has_trivial_constructor<const T>
312   : has_trivial_constructor<T> { };
313
314 // We can't get has_trivial_copy right without compiler help, so fail
315 // conservatively. We will assume it's false except for: (1) types
316 // for which is_pod is true. (2) std::pair of types with trivial copy
317 // constructors. (3) array of a type with a trivial copy constructor.
318 // (4) const versions thereof.
319 template <class T> struct has_trivial_copy : is_pod<T> { };
320 template <class T, class U> struct has_trivial_copy<std::pair<T, U> >
321   : integral_constant<bool,
322                       (has_trivial_copy<T>::value &&
323                        has_trivial_copy<U>::value)> { };
324 template <class A, int N> struct has_trivial_copy<A[N]>
325   : has_trivial_copy<A> { };
326 template <class T> struct has_trivial_copy<const T> : has_trivial_copy<T> { };
327
328 // We can't get has_trivial_assign right without compiler help, so fail
329 // conservatively. We will assume it's false except for: (1) types
330 // for which is_pod is true. (2) std::pair of types with trivial copy
331 // constructors. (3) array of a type with a trivial assign constructor.
332 template <class T> struct has_trivial_assign : is_pod<T> { };
333 template <class T, class U> struct has_trivial_assign<std::pair<T, U> >
334   : integral_constant<bool,
335                       (has_trivial_assign<T>::value &&
336                        has_trivial_assign<U>::value)> { };
337 template <class A, int N> struct has_trivial_assign<A[N]>
338   : has_trivial_assign<A> { };
339
340 // We can't get has_trivial_destructor right without compiler help, so
341 // fail conservatively. We will assume it's false except for: (1) types
342 // for which is_pod is true. (2) std::pair of types with trivial
343 // destructors. (3) array of a type with a trivial destructor.
344 // (4) const versions thereof.
345 template <class T> struct has_trivial_destructor : is_pod<T> { };
346 template <class T, class U> struct has_trivial_destructor<std::pair<T, U> >
347   : integral_constant<bool,
348                       (has_trivial_destructor<T>::value &&
349                        has_trivial_destructor<U>::value)> { };
350 template <class A, int N> struct has_trivial_destructor<A[N]>
351   : has_trivial_destructor<A> { };
352 template <class T> struct has_trivial_destructor<const T>
353   : has_trivial_destructor<T> { };
354
355 // Specified by TR1 [4.7.1]
356 template<typename T> struct remove_const { typedef T type; };
357 template<typename T> struct remove_const<T const> { typedef T type; };
358 template<typename T> struct remove_volatile { typedef T type; };
359 template<typename T> struct remove_volatile<T volatile> { typedef T type; };
360 template<typename T> struct remove_cv {
361   typedef typename remove_const<typename remove_volatile<T>::type>::type type;
362 };
363
364
365 // Specified by TR1 [4.7.2] Reference modifications.
366 template<typename T> struct remove_reference { typedef T type; };
367 template<typename T> struct remove_reference<T&> { typedef T type; };
368
369 template <typename T> struct add_reference { typedef T& type; };
370 template <typename T> struct add_reference<T&> { typedef T& type; };
371
372 // Specified by TR1 [4.7.4] Pointer modifications.
373 template<typename T> struct remove_pointer { typedef T type; };
374 template<typename T> struct remove_pointer<T*> { typedef T type; };
375 template<typename T> struct remove_pointer<T* const> { typedef T type; };
376 template<typename T> struct remove_pointer<T* volatile> { typedef T type; };
377 template<typename T> struct remove_pointer<T* const volatile> {
378   typedef T type; };
379
380 // Specified by TR1 [4.6] Relationships between types
381 template<typename T, typename U> struct is_same : public false_type { };
382 template<typename T> struct is_same<T, T> : public true_type { };
383
384 // Specified by TR1 [4.6] Relationships between types
385 #if !defined(_MSC_VER) && !(defined(__GNUC__) && __GNUC__ <= 3)
386 namespace internal {
387
388 // This class is an implementation detail for is_convertible, and you
389 // don't need to know how it works to use is_convertible. For those
390 // who care: we declare two different functions, one whose argument is
391 // of type To and one with a variadic argument list. We give them
392 // return types of different size, so we can use sizeof to trick the
393 // compiler into telling us which function it would have chosen if we
394 // had called it with an argument of type From.  See Alexandrescu's
395 // _Modern C++ Design_ for more details on this sort of trick.
396
397 template <typename From, typename To>
398 struct ConvertHelper {
399   static small_ Test(To);
400   static big_ Test(...);
401   static From Create();
402 };
403 }  // namespace internal
404
405 // Inherits from true_type if From is convertible to To, false_type otherwise.
406 template <typename From, typename To>
407 struct is_convertible
408     : integral_constant<bool,
409                         sizeof(internal::ConvertHelper<From, To>::Test(
410                                   internal::ConvertHelper<From, To>::Create()))
411                         == sizeof(small_)> {
412 };
413 #endif
414
415 }
416
417 QT_END_NAMESPACE
418 QT_END_HEADER
419
420 #endif  // QTYPETRAITS_H