qtypetraits.h: add is_signed/is_unsigned/not_/not_c predicates
[profile/ivi/qtbase.git] / src / corelib / global / qtypetraits.h
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Marc Mutz <marc.mutz@kdab.com>
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the QtCore module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia.  For licensing terms and
14 ** conditions see http://qt.digia.com/licensing.  For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file.  Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights.  These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file.  Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 // BEGIN Google Code
43
44 // Copyright (c) 2006, Google Inc.
45 // All rights reserved.
46 //
47 // Redistribution and use in source and binary forms, with or without
48 // modification, are permitted provided that the following conditions are
49 // met:
50 //
51 //     * Redistributions of source code must retain the above copyright
52 // notice, this list of conditions and the following disclaimer.
53 //     * Redistributions in binary form must reproduce the above
54 // copyright notice, this list of conditions and the following disclaimer
55 // in the documentation and/or other materials provided with the
56 // distribution.
57 //     * Neither the name of Google Inc. nor the names of its
58 // contributors may be used to endorse or promote products derived from
59 // this software without specific prior written permission.
60 //
61 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
62 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
63 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
64 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
65 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
66 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
67 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
68 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
69 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
70 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
71 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
72
73 // ----
74 //
75 // This code is compiled directly on many platforms, including client
76 // platforms like Windows, Mac, and embedded systems.  Before making
77 // any changes here, make sure that you're not breaking any platforms.
78 //
79 // Define a small subset of tr1 type traits. The traits we define are:
80 //   is_integral
81 //   is_floating_point
82 //   is_pointer
83 //   is_enum
84 //   is_reference
85 //   is_pod
86 //   has_trivial_constructor
87 //   has_trivial_copy
88 //   has_trivial_assign
89 //   has_trivial_destructor
90 //   remove_const
91 //   remove_volatile
92 //   remove_cv
93 //   remove_reference
94 //   add_reference
95 //   remove_pointer
96 //   is_same
97 //   is_convertible
98 // We can add more type traits as required.
99
100 // Changes from the original implementation:
101 //  - Move base types from template_util.h directly into this header.
102 //  - Use Qt macros for long long type differences on Windows.
103 //  - Enclose in QtPrivate namespace.
104
105 #ifndef QTYPETRAITS_H
106 #define QTYPETRAITS_H
107
108 #include <utility>                  // For pair
109 #include "QtCore/qglobal.h"
110
111 QT_BEGIN_HEADER
112 QT_BEGIN_NAMESPACE
113
114 namespace QtPrivate {
115
116 // Types small_ and big_ are guaranteed such that sizeof(small_) <
117 // sizeof(big_)
118 typedef char small_;
119
120 struct big_ {
121   char dummy[2];
122 };
123
124 // Identity metafunction.
125 template <class T>
126 struct identity_ {
127   typedef T type;
128 };
129
130 // integral_constant, defined in tr1, is a wrapper for an integer
131 // value. We don't really need this generality; we could get away
132 // with hardcoding the integer type to bool. We use the fully
133 // general integer_constant for compatibility with tr1.
134
135 template<class T, T v>
136 struct integral_constant {
137   static const T value = v;
138   typedef T value_type;
139   typedef integral_constant<T, v> type;
140 };
141
142 template <class T, T v> const T integral_constant<T, v>::value;
143
144
145 // Abbreviations: true_type and false_type are structs that represent boolean
146 // true and false values. Also define the boost::mpl versions of those names,
147 // true_ and false_.
148 typedef integral_constant<bool, true>  true_type;
149 typedef integral_constant<bool, false> false_type;
150 typedef true_type  true_;
151 typedef false_type false_;
152
153 // if_ is a templatized conditional statement.
154 // if_<cond, A, B> is a compile time evaluation of cond.
155 // if_<>::type contains A if cond is true, B otherwise.
156 template<bool cond, typename A, typename B>
157 struct if_{
158   typedef A type;
159 };
160
161 template<typename A, typename B>
162 struct if_<false, A, B> {
163   typedef B type;
164 };
165
166
167 // type_equals_ is a template type comparator, similar to Loki IsSameType.
168 // type_equals_<A, B>::value is true iff "A" is the same type as "B".
169 //
170 // New code should prefer base::is_same, defined in base/type_traits.h.
171 // It is functionally identical, but is_same is the standard spelling.
172 template<typename A, typename B>
173 struct type_equals_ : public false_ {
174 };
175
176 template<typename A>
177 struct type_equals_<A, A> : public true_ {
178 };
179
180 // and_ is a template && operator.
181 // and_<A, B>::value evaluates "A::value && B::value".
182 template<typename A, typename B>
183 struct and_ : public integral_constant<bool, (A::value && B::value)> {
184 };
185
186 // or_ is a template || operator.
187 // or_<A, B>::value evaluates "A::value || B::value".
188 template<typename A, typename B>
189 struct or_ : public integral_constant<bool, (A::value || B::value)> {
190 };
191
192 template <class T> struct is_integral;
193 template <class T> struct is_floating_point;
194 template <class T> struct is_pointer;
195 // MSVC can't compile this correctly, and neither can gcc 3.3.5 (at least)
196 #if !defined(_MSC_VER) && !(defined(__GNUC__) && __GNUC__ <= 3)
197 // is_enum uses is_convertible, which is not available on MSVC.
198 template <class T> struct is_enum;
199 #endif
200 template <class T> struct is_reference;
201 template <class T> struct is_pod;
202 template <class T> struct has_trivial_constructor;
203 template <class T> struct has_trivial_copy;
204 template <class T> struct has_trivial_assign;
205 template <class T> struct has_trivial_destructor;
206 template <class T> struct remove_const;
207 template <class T> struct remove_volatile;
208 template <class T> struct remove_cv;
209 template <class T> struct remove_reference;
210 template <class T> struct add_reference;
211 template <class T> struct remove_pointer;
212 template <class T, class U> struct is_same;
213 #if !defined(_MSC_VER) && !(defined(__GNUC__) && __GNUC__ <= 3)
214 template <class From, class To> struct is_convertible;
215 #endif
216
217 // is_integral is false except for the built-in integer types. A
218 // cv-qualified type is integral if and only if the underlying type is.
219 template <class T> struct is_integral : false_type { };
220 template<> struct is_integral<bool> : true_type { };
221 template<> struct is_integral<char> : true_type { };
222 template<> struct is_integral<unsigned char> : true_type { };
223 template<> struct is_integral<signed char> : true_type { };
224 #if defined(_MSC_VER)
225 // wchar_t is not by default a distinct type from unsigned short in
226 // Microsoft C.
227 // See http://msdn2.microsoft.com/en-us/library/dh8che7s(VS.80).aspx
228 template<> struct is_integral<__wchar_t> : true_type { };
229 #else
230 template<> struct is_integral<wchar_t> : true_type { };
231 #endif
232 template<> struct is_integral<short> : true_type { };
233 template<> struct is_integral<unsigned short> : true_type { };
234 template<> struct is_integral<int> : true_type { };
235 template<> struct is_integral<unsigned int> : true_type { };
236 template<> struct is_integral<long> : true_type { };
237 template<> struct is_integral<unsigned long> : true_type { };
238 #if defined(Q_OS_WIN) && !defined(Q_CC_GNU)
239 template<> struct is_integral<__int64> : true_type { };
240 template<> struct is_integral<unsigned __int64> : true_type { };
241 #else
242 template<> struct is_integral<long long> : true_type { };
243 template<> struct is_integral<unsigned long long> : true_type { };
244 #endif
245 template <class T> struct is_integral<const T> : is_integral<T> { };
246 template <class T> struct is_integral<volatile T> : is_integral<T> { };
247 template <class T> struct is_integral<const volatile T> : is_integral<T> { };
248
249 // is_floating_point is false except for the built-in floating-point types.
250 // A cv-qualified type is integral if and only if the underlying type is.
251 template <class T> struct is_floating_point : false_type { };
252 template<> struct is_floating_point<float> : true_type { };
253 template<> struct is_floating_point<double> : true_type { };
254 template<> struct is_floating_point<long double> : true_type { };
255 template <class T> struct is_floating_point<const T>
256     : is_floating_point<T> { };
257 template <class T> struct is_floating_point<volatile T>
258     : is_floating_point<T> { };
259 template <class T> struct is_floating_point<const volatile T>
260     : is_floating_point<T> { };
261
262 // is_pointer is false except for pointer types. A cv-qualified type (e.g.
263 // "int* const", as opposed to "int const*") is cv-qualified if and only if
264 // the underlying type is.
265 template <class T> struct is_pointer : false_type { };
266 template <class T> struct is_pointer<T*> : true_type { };
267 template <class T> struct is_pointer<const T> : is_pointer<T> { };
268 template <class T> struct is_pointer<volatile T> : is_pointer<T> { };
269 template <class T> struct is_pointer<const volatile T> : is_pointer<T> { };
270
271 #if !defined(_MSC_VER) && !(defined(__GNUC__) && __GNUC__ <= 3)
272
273 namespace internal {
274
275 template <class T> struct is_class_or_union {
276   template <class U> static small_ tester(void (U::*)());
277   template <class U> static big_ tester(...);
278   static const bool value = sizeof(tester<T>(0)) == sizeof(small_);
279 };
280
281 // is_convertible chokes if the first argument is an array. That's why
282 // we use add_reference here.
283 template <bool NotUnum, class T> struct is_enum_impl
284     : is_convertible<typename add_reference<T>::type, int> { };
285
286 template <class T> struct is_enum_impl<true, T> : false_type { };
287
288 }  // namespace internal
289
290 // Specified by TR1 [4.5.1] primary type categories.
291
292 // Implementation note:
293 //
294 // Each type is either void, integral, floating point, array, pointer,
295 // reference, member object pointer, member function pointer, enum,
296 // union or class. Out of these, only integral, floating point, reference,
297 // class and enum types are potentially convertible to int. Therefore,
298 // if a type is not a reference, integral, floating point or class and
299 // is convertible to int, it's a enum. Adding cv-qualification to a type
300 // does not change whether it's an enum.
301 //
302 // Is-convertible-to-int check is done only if all other checks pass,
303 // because it can't be used with some types (e.g. void or classes with
304 // inaccessible conversion operators).
305 template <class T> struct is_enum
306     : internal::is_enum_impl<
307           is_same<T, void>::value ||
308               is_integral<T>::value ||
309               is_floating_point<T>::value ||
310               is_reference<T>::value ||
311               internal::is_class_or_union<T>::value,
312           T> { };
313
314 template <class T> struct is_enum<const T> : is_enum<T> { };
315 template <class T> struct is_enum<volatile T> : is_enum<T> { };
316 template <class T> struct is_enum<const volatile T> : is_enum<T> { };
317
318 #endif
319
320 // is_reference is false except for reference types.
321 template<typename T> struct is_reference : false_type {};
322 template<typename T> struct is_reference<T&> : true_type {};
323
324
325 // We can't get is_pod right without compiler help, so fail conservatively.
326 // We will assume it's false except for arithmetic types, enumerations,
327 // pointers and cv-qualified versions thereof. Note that std::pair<T,U>
328 // is not a POD even if T and U are PODs.
329 template <class T> struct is_pod
330  : integral_constant<bool, (is_integral<T>::value ||
331                             is_floating_point<T>::value ||
332 #if !defined(_MSC_VER) && !(defined(__GNUC__) && __GNUC__ <= 3)
333                             // is_enum is not available on MSVC.
334                             is_enum<T>::value ||
335 #endif
336                             is_pointer<T>::value)> { };
337 template <class T> struct is_pod<const T> : is_pod<T> { };
338 template <class T> struct is_pod<volatile T> : is_pod<T> { };
339 template <class T> struct is_pod<const volatile T> : is_pod<T> { };
340
341
342 // We can't get has_trivial_constructor right without compiler help, so
343 // fail conservatively. We will assume it's false except for: (1) types
344 // for which is_pod is true. (2) std::pair of types with trivial
345 // constructors. (3) array of a type with a trivial constructor.
346 // (4) const versions thereof.
347 template <class T> struct has_trivial_constructor : is_pod<T> { };
348 template <class T, class U> struct has_trivial_constructor<std::pair<T, U> >
349   : integral_constant<bool,
350                       (has_trivial_constructor<T>::value &&
351                        has_trivial_constructor<U>::value)> { };
352 template <class A, int N> struct has_trivial_constructor<A[N]>
353   : has_trivial_constructor<A> { };
354 template <class T> struct has_trivial_constructor<const T>
355   : has_trivial_constructor<T> { };
356
357 // We can't get has_trivial_copy right without compiler help, so fail
358 // conservatively. We will assume it's false except for: (1) types
359 // for which is_pod is true. (2) std::pair of types with trivial copy
360 // constructors. (3) array of a type with a trivial copy constructor.
361 // (4) const versions thereof.
362 template <class T> struct has_trivial_copy : is_pod<T> { };
363 template <class T, class U> struct has_trivial_copy<std::pair<T, U> >
364   : integral_constant<bool,
365                       (has_trivial_copy<T>::value &&
366                        has_trivial_copy<U>::value)> { };
367 template <class A, int N> struct has_trivial_copy<A[N]>
368   : has_trivial_copy<A> { };
369 template <class T> struct has_trivial_copy<const T> : has_trivial_copy<T> { };
370
371 // We can't get has_trivial_assign right without compiler help, so fail
372 // conservatively. We will assume it's false except for: (1) types
373 // for which is_pod is true. (2) std::pair of types with trivial copy
374 // constructors. (3) array of a type with a trivial assign constructor.
375 template <class T> struct has_trivial_assign : is_pod<T> { };
376 template <class T, class U> struct has_trivial_assign<std::pair<T, U> >
377   : integral_constant<bool,
378                       (has_trivial_assign<T>::value &&
379                        has_trivial_assign<U>::value)> { };
380 template <class A, int N> struct has_trivial_assign<A[N]>
381   : has_trivial_assign<A> { };
382
383 // We can't get has_trivial_destructor right without compiler help, so
384 // fail conservatively. We will assume it's false except for: (1) types
385 // for which is_pod is true. (2) std::pair of types with trivial
386 // destructors. (3) array of a type with a trivial destructor.
387 // (4) const versions thereof.
388 template <class T> struct has_trivial_destructor : is_pod<T> { };
389 template <class T, class U> struct has_trivial_destructor<std::pair<T, U> >
390   : integral_constant<bool,
391                       (has_trivial_destructor<T>::value &&
392                        has_trivial_destructor<U>::value)> { };
393 template <class A, int N> struct has_trivial_destructor<A[N]>
394   : has_trivial_destructor<A> { };
395 template <class T> struct has_trivial_destructor<const T>
396   : has_trivial_destructor<T> { };
397
398 // Specified by TR1 [4.7.1]
399 template<typename T> struct remove_const { typedef T type; };
400 template<typename T> struct remove_const<T const> { typedef T type; };
401 template<typename T> struct remove_volatile { typedef T type; };
402 template<typename T> struct remove_volatile<T volatile> { typedef T type; };
403 template<typename T> struct remove_cv {
404   typedef typename remove_const<typename remove_volatile<T>::type>::type type;
405 };
406
407
408 // Specified by TR1 [4.7.2] Reference modifications.
409 template<typename T> struct remove_reference { typedef T type; };
410 template<typename T> struct remove_reference<T&> { typedef T type; };
411
412 template <typename T> struct add_reference { typedef T& type; };
413 template <typename T> struct add_reference<T&> { typedef T& type; };
414
415 // Specified by TR1 [4.7.4] Pointer modifications.
416 template<typename T> struct remove_pointer { typedef T type; };
417 template<typename T> struct remove_pointer<T*> { typedef T type; };
418 template<typename T> struct remove_pointer<T* const> { typedef T type; };
419 template<typename T> struct remove_pointer<T* volatile> { typedef T type; };
420 template<typename T> struct remove_pointer<T* const volatile> {
421   typedef T type; };
422
423 // Specified by TR1 [4.6] Relationships between types
424 template<typename T, typename U> struct is_same : public false_type { };
425 template<typename T> struct is_same<T, T> : public true_type { };
426
427 // Specified by TR1 [4.6] Relationships between types
428 #if !defined(_MSC_VER) && !(defined(__GNUC__) && __GNUC__ <= 3)
429 namespace internal {
430
431 // This class is an implementation detail for is_convertible, and you
432 // don't need to know how it works to use is_convertible. For those
433 // who care: we declare two different functions, one whose argument is
434 // of type To and one with a variadic argument list. We give them
435 // return types of different size, so we can use sizeof to trick the
436 // compiler into telling us which function it would have chosen if we
437 // had called it with an argument of type From.  See Alexandrescu's
438 // _Modern C++ Design_ for more details on this sort of trick.
439
440 template <typename From, typename To>
441 struct ConvertHelper {
442   static small_ Test(To);
443   static big_ Test(...);
444   static From Create();
445 };
446 }  // namespace internal
447
448 // Inherits from true_type if From is convertible to To, false_type otherwise.
449 template <typename From, typename To>
450 struct is_convertible
451     : integral_constant<bool,
452                         sizeof(internal::ConvertHelper<From, To>::Test(
453                                   internal::ConvertHelper<From, To>::Create()))
454                         == sizeof(small_)> {
455 };
456 #endif
457
458 // END Google Code
459
460 // a metafunction to invert an integral_constant:
461 template <typename T>
462 struct not_
463     : integral_constant<bool, !T::value> {};
464
465 // same, with a bool argument:
466 template <bool B>
467 struct not_c
468     : integral_constant<bool, !B> {};
469
470 // Checks whether a type is unsigned (T must be convertible to unsigned int):
471 template <typename T>
472 struct is_unsigned
473     : integral_constant<bool, (T(0) < T(-1))> {};
474
475 // Checks whether a type is signed (T must be convertible to int):
476 template <typename T>
477 struct is_signed
478     : not_< is_unsigned<T> > {};
479
480 Q_STATIC_ASSERT(( is_unsigned<quint8>::value));
481 Q_STATIC_ASSERT((!is_unsigned<qint8>::value));
482
483 Q_STATIC_ASSERT((!is_signed<quint8>::value));
484 Q_STATIC_ASSERT(( is_signed<qint8>::value));
485
486 Q_STATIC_ASSERT(( is_unsigned<quint16>::value));
487 Q_STATIC_ASSERT((!is_unsigned<qint16>::value));
488
489 Q_STATIC_ASSERT((!is_signed<quint16>::value));
490 Q_STATIC_ASSERT(( is_signed<qint16>::value));
491
492 Q_STATIC_ASSERT(( is_unsigned<quint32>::value));
493 Q_STATIC_ASSERT((!is_unsigned<qint32>::value));
494
495 Q_STATIC_ASSERT((!is_signed<quint32>::value));
496 Q_STATIC_ASSERT(( is_signed<qint32>::value));
497
498 Q_STATIC_ASSERT(( is_unsigned<quint64>::value));
499 Q_STATIC_ASSERT((!is_unsigned<qint64>::value));
500
501 Q_STATIC_ASSERT((!is_signed<quint64>::value));
502 Q_STATIC_ASSERT(( is_signed<qint64>::value));
503
504 } // namespace QtPrivate
505
506 QT_END_NAMESPACE
507 QT_END_HEADER
508
509 #endif  // QTYPETRAITS_H