QtBase  v6.3.1
qtypeinfo.h
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 The Qt Company Ltd.
4 ** Copyright (C) 2016 Intel Corporation.
5 ** Contact: https://www.qt.io/licensing/
6 **
7 ** This file is part of the QtCore module of the Qt Toolkit.
8 **
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** Commercial License Usage
11 ** Licensees holding valid commercial Qt licenses may use this file in
12 ** accordance with the commercial license agreement provided with the
13 ** Software or, alternatively, in accordance with the terms contained in
14 ** a written agreement between you and The Qt Company. For licensing terms
15 ** and conditions see https://www.qt.io/terms-conditions. For further
16 ** information use the contact form at https://www.qt.io/contact-us.
17 **
18 ** GNU Lesser General Public License Usage
19 ** Alternatively, this file may be used under the terms of the GNU Lesser
20 ** General Public License version 3 as published by the Free Software
21 ** Foundation and appearing in the file LICENSE.LGPL3 included in the
22 ** packaging of this file. Please review the following information to
23 ** ensure the GNU Lesser General Public License version 3 requirements
24 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
25 **
26 ** GNU General Public License Usage
27 ** Alternatively, this file may be used under the terms of the GNU
28 ** General Public License version 2.0 or (at your option) the GNU General
29 ** Public license version 3 or any later version approved by the KDE Free
30 ** Qt Foundation. The licenses are as published by the Free Software
31 ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
32 ** included in the packaging of this file. Please review the following
33 ** information to ensure the GNU General Public License requirements will
34 ** be met: https://www.gnu.org/licenses/gpl-2.0.html and
35 ** https://www.gnu.org/licenses/gpl-3.0.html.
36 **
37 ** $QT_END_LICENSE$
38 **
39 ****************************************************************************/
40 
41 #include <QtCore/qglobal.h>
42 #include <QtCore/qcontainerfwd.h>
43 #include <variant>
44 #include <optional>
45 #include <tuple>
46 
47 #ifndef QTYPEINFO_H
48 #define QTYPEINFO_H
49 
51 
52 class QDebug;
53 
54 /*
55  QTypeInfo - type trait functionality
56 */
57 
58 template <typename T>
59 inline constexpr bool qIsRelocatable = std::is_trivially_copyable_v<T> && std::is_trivially_destructible_v<T>;
60 
61 /*
62  The catch-all template.
63 */
64 
65 template <typename T>
66 class QTypeInfo
67 {
68 public:
69  enum {
70  isPointer = std::is_pointer_v<T>,
71  isIntegral = std::is_integral_v<T>,
72  isComplex = !std::is_trivial_v<T>,
73  isRelocatable = qIsRelocatable<T>,
74  };
75 };
76 
77 template<>
79 {
80 public:
81  enum {
82  isPointer = false,
83  isIntegral = false,
84  isComplex = false,
85  isRelocatable = false,
86  };
87 };
88 
109 template <class T, class...Ts>
111 {
112  static_assert(sizeof...(Ts) > 0);
113 public:
114  static constexpr bool isComplex = ((QTypeInfo<Ts>::isComplex) || ...);
115  static constexpr bool isRelocatable = ((QTypeInfo<Ts>::isRelocatable) && ...);
116  static constexpr bool isPointer = false;
117  static constexpr bool isIntegral = false;
118 };
119 
120 #define Q_DECLARE_MOVABLE_CONTAINER(CONTAINER) \
121 template <typename ...T> \
122 class QTypeInfo<CONTAINER<T...>> \
123 { \
124 public: \
125  enum { \
126  isPointer = false, \
127  isIntegral = false, \
128  isComplex = true, \
129  isRelocatable = true, \
130  }; \
131 }
132 
142 
143 #undef Q_DECLARE_MOVABLE_CONTAINER
144 
145 /*
146  Specialize a specific type with:
147 
148  Q_DECLARE_TYPEINFO(type, flags);
149 
150  where 'type' is the name of the type to specialize and 'flags' is
151  logically-OR'ed combination of the flags below.
152 */
153 enum { /* TYPEINFO flags */
159 };
160 
161 #define Q_DECLARE_TYPEINFO_BODY(TYPE, FLAGS) \
162 class QTypeInfo<TYPE > \
163 { \
164 public: \
165  enum { \
166  isComplex = (((FLAGS) & Q_PRIMITIVE_TYPE) == 0) && !std::is_trivial_v<TYPE>, \
167  isRelocatable = !isComplex || ((FLAGS) & Q_RELOCATABLE_TYPE) || qIsRelocatable<TYPE>, \
168  isPointer = false, \
169  isIntegral = std::is_integral< TYPE >::value, \
170  }; \
171 }
172 
173 #define Q_DECLARE_TYPEINFO(TYPE, FLAGS) \
174 template<> \
175 Q_DECLARE_TYPEINFO_BODY(TYPE, FLAGS)
176 
177 /* Specialize QTypeInfo for QFlags<T> */
178 template<typename T> class QFlags;
179 template<typename T>
181 
182 /*
183  Specialize a shared type with:
184 
185  Q_DECLARE_SHARED(type)
186 
187  where 'type' is the name of the type to specialize. NOTE: shared
188  types must define a member-swap, and be defined in the same
189  namespace as Qt for this to work.
190 */
191 
192 #define Q_DECLARE_SHARED_IMPL(TYPE, FLAGS) \
193 Q_DECLARE_TYPEINFO(TYPE, FLAGS); \
194 inline void swap(TYPE &value1, TYPE &value2) \
195  noexcept(noexcept(value1.swap(value2))) \
196 { value1.swap(value2); }
197 #define Q_DECLARE_SHARED(TYPE) Q_DECLARE_SHARED_IMPL(TYPE, Q_RELOCATABLE_TYPE)
198 
199 namespace QTypeTraits
200 {
201 
202 /*
203  The templates below aim to find out whether one can safely instantiate an operator==() or
204  operator<() for a type.
205 
206  This is tricky for containers, as most containers have unconstrained comparison operators, even though they
207  rely on the corresponding operators for its content.
208  This is especially true for all of the STL template classes that have a comparison operator defined, and
209  leads to the situation, that the compiler would try to instantiate the operator, and fail if any
210  of its template arguments does not have the operator implemented.
211 
212  The code tries to cover the relevant cases for Qt and the STL, by checking (recusrsively) the value_type
213  of a container (if it exists), and checking the template arguments of pair, tuple and variant.
214 */
215 namespace detail {
216 
217 // find out whether T is a conteiner
218 // this is required to check the value type of containers for the existence of the comparison operator
219 template <typename, typename = void>
220 struct is_container : std::false_type {};
221 template <typename T>
222 struct is_container<T, std::void_t<
223  typename T::value_type,
224  std::is_convertible<decltype(std::declval<T>().begin() != std::declval<T>().end()), bool>
225 >> : std::true_type {};
226 
227 
228 // Checks the existence of the comparison operator for the class itself
231 template <typename, typename = void>
232 struct has_operator_equal : std::false_type {};
233 template <typename T>
234 struct has_operator_equal<T, std::void_t<decltype(bool(std::declval<const T&>() == std::declval<const T&>()))>>
235  : std::true_type {};
237 
238 // Two forward declarations
241 template<typename T>
243 
244 // the entry point for the public method
245 template<typename T>
247 
248 // if T isn't a container check if it's a tuple like object
249 template<typename T, bool>
251 // if T::value_type exists, check first T::value_type, then T itself
252 template<typename T>
254  std::conjunction<
255  std::disjunction<
256  std::is_same<T, typename T::value_type>, // avoid endless recursion
257  expand_operator_equal<typename T::value_type>
258  >, expand_operator_equal_tuple<T>> {};
259 
260 // recursively check the template arguments of a tuple like object
261 template<typename ...T>
262 using expand_operator_equal_recursive = std::conjunction<expand_operator_equal<T>...>;
263 
264 template<typename T>
266 template<typename T>
268 template<typename T1, typename T2>
270 template<typename ...T>
272 template<typename ...T>
274 
275 // the same for operator<(), see above for explanations
276 template <typename, typename = void>
277 struct has_operator_less_than : std::false_type{};
278 template <typename T>
279 struct has_operator_less_than<T, std::void_t<decltype(bool(std::declval<const T&>() < std::declval<const T&>()))>>
280  : std::true_type{};
281 
284 template<typename T>
286 
287 template<typename T>
289 
290 template<typename T, bool>
292 template<typename T>
294  std::conjunction<
295  std::disjunction<
296  std::is_same<T, typename T::value_type>,
297  expand_operator_less_than<typename T::value_type>
298  >, expand_operator_less_than_tuple<T>
299  > {};
300 
301 template<typename ...T>
302 using expand_operator_less_than_recursive = std::conjunction<expand_operator_less_than<T>...>;
303 
304 template<typename T>
306 template<typename T>
308 template<typename T1, typename T2>
310 template<typename ...T>
312 template<typename ...T>
314 
315 }
316 
317 template<typename T, typename = void>
318 struct is_dereferenceable : std::false_type {};
319 
320 template<typename T>
321 struct is_dereferenceable<T, std::void_t<decltype(std::declval<T>().operator->())> >
322  : std::true_type {};
323 
324 template <typename T>
326 
327 template<typename T>
329 template<typename T>
331 
332 template <typename Container, typename T>
333 using has_operator_equal_container = std::disjunction<std::is_base_of<Container, T>, QTypeTraits::has_operator_equal<T>>;
334 
335 template<typename T>
337 template<typename T>
339 
340 template <typename Container, typename T>
341 using has_operator_less_than_container = std::disjunction<std::is_base_of<Container, T>, QTypeTraits::has_operator_less_than<T>>;
342 
343 template <typename ...T>
344 using compare_eq_result = std::enable_if_t<std::conjunction_v<QTypeTraits::has_operator_equal<T>...>, bool>;
345 
346 template <typename Container, typename ...T>
347 using compare_eq_result_container = std::enable_if_t<std::conjunction_v<QTypeTraits::has_operator_equal_container<Container, T>...>, bool>;
348 
349 template <typename ...T>
350 using compare_lt_result = std::enable_if_t<std::conjunction_v<QTypeTraits::has_operator_less_than<T>...>, bool>;
351 
352 template <typename Container, typename ...T>
353 using compare_lt_result_container = std::enable_if_t<std::conjunction_v<QTypeTraits::has_operator_less_than_container<Container, T>...>, bool>;
354 
355 namespace detail {
356 
357 template<typename T>
359 template<typename T>
361 
362 }
363 
364 template <typename Stream, typename, typename = void>
365 struct has_ostream_operator : std::false_type {};
366 template <typename Stream, typename T>
367 struct has_ostream_operator<Stream, T, std::void_t<decltype(detail::reference<Stream>() << detail::const_reference<T>())>>
368  : std::true_type {};
369 template <typename Stream, typename T>
370 inline constexpr bool has_ostream_operator_v = has_ostream_operator<Stream, T>::value;
371 
372 template <typename Stream, typename Container, typename T>
373 using has_ostream_operator_container = std::disjunction<std::is_base_of<Container, T>, QTypeTraits::has_ostream_operator<Stream, T>>;
374 
375 template <typename Stream, typename, typename = void>
376 struct has_istream_operator : std::false_type {};
377 template <typename Stream, typename T>
378 struct has_istream_operator<Stream, T, std::void_t<decltype(detail::reference<Stream>() >> detail::reference<T>())>>
379  : std::true_type {};
380 template <typename Stream, typename T>
382 template <typename Stream, typename Container, typename T>
383 using has_istream_operator_container = std::disjunction<std::is_base_of<Container, T>, QTypeTraits::has_istream_operator<Stream, T>>;
384 
385 template <typename Stream, typename T>
386 inline constexpr bool has_stream_operator_v = has_ostream_operator_v<Stream, T> && has_istream_operator_v<Stream, T>;
387 
388 }
389 
390 
392 #endif // QTYPEINFO_H
#define value
[5]
Definition: qcache.h:50
The QDebug class provides an output stream for debugging information.
Definition: qdebug.h:65
The QFlags class provides a type-safe way of storing OR-combinations of enum values.
Definition: qflags.h:89
The QHash class is a template class that provides a hash-table-based dictionary.
Definition: qhash.h:773
Definition: qlist.h:108
Definition: qmap.h:222
The QMultiHash class is a convenience QHash subclass that provides multi-valued hashes.
Definition: qhash.h:1293
The QQueue class is a generic container that provides a queue.
Definition: qqueue.h:50
Definition: qset.h:54
The QStack class is a template class that provides a stack.
Definition: qstack.h:49
@ isPointer
Definition: qtypeinfo.h:70
@ isComplex
Definition: qtypeinfo.h:72
@ isRelocatable
Definition: qtypeinfo.h:73
@ isIntegral
Definition: qtypeinfo.h:71
static constexpr bool isIntegral
Definition: qtypeinfo.h:117
static constexpr bool isPointer
Definition: qtypeinfo.h:116
static constexpr bool isComplex
Definition: qtypeinfo.h:114
static constexpr bool isRelocatable
Definition: qtypeinfo.h:115
#define T(x)
Definition: main.cpp:42
#define true
Definition: ftrandom.c:51
std::conjunction< expand_operator_less_than< T >... > expand_operator_less_than_recursive
Definition: qtypeinfo.h:302
std::conjunction< expand_operator_equal< T >... > expand_operator_equal_recursive
Definition: qtypeinfo.h:262
const T & const_reference()
std::enable_if_t< std::conjunction_v< QTypeTraits::has_operator_equal< T >... >, bool > compare_eq_result
Definition: qtypeinfo.h:344
constexpr bool is_dereferenceable_v
Definition: qtypeinfo.h:325
constexpr bool has_operator_equal_v
Definition: qtypeinfo.h:330
std::enable_if_t< std::conjunction_v< QTypeTraits::has_operator_equal_container< Container, T >... >, bool > compare_eq_result_container
Definition: qtypeinfo.h:347
constexpr bool has_stream_operator_v
Definition: qtypeinfo.h:386
std::enable_if_t< std::conjunction_v< QTypeTraits::has_operator_less_than_container< Container, T >... >, bool > compare_lt_result_container
Definition: qtypeinfo.h:353
std::enable_if_t< std::conjunction_v< QTypeTraits::has_operator_less_than< T >... >, bool > compare_lt_result
Definition: qtypeinfo.h:350
constexpr bool has_istream_operator_v
Definition: qtypeinfo.h:381
std::disjunction< std::is_base_of< Container, T >, QTypeTraits::has_operator_equal< T > > has_operator_equal_container
Definition: qtypeinfo.h:333
std::disjunction< std::is_base_of< Container, T >, QTypeTraits::has_operator_less_than< T > > has_operator_less_than_container
Definition: qtypeinfo.h:341
std::disjunction< std::is_base_of< Container, T >, QTypeTraits::has_istream_operator< Stream, T > > has_istream_operator_container
Definition: qtypeinfo.h:383
constexpr bool has_operator_less_than_v
Definition: qtypeinfo.h:338
Definition: qfloat16.h:381
void
Definition: png.h:1080
#define QT_WARNING_POP
#define QT_WARNING_DISABLE_FLOAT_COMPARE
#define QT_WARNING_PUSH
@ Q_PRIMITIVE_TYPE
Definition: qtypeinfo.h:155
@ Q_DUMMY_TYPE
Definition: qtypeinfo.h:158
@ Q_RELOCATABLE_TYPE
Definition: qtypeinfo.h:156
@ Q_COMPLEX_TYPE
Definition: qtypeinfo.h:154
@ Q_MOVABLE_TYPE
Definition: qtypeinfo.h:157
#define Q_DECLARE_MOVABLE_CONTAINER(CONTAINER)
Definition: qtypeinfo.h:120
#define Q_DECLARE_TYPEINFO_BODY(TYPE, FLAGS)
Definition: qtypeinfo.h:161
constexpr bool qIsRelocatable
Definition: qtypeinfo.h:59
QVariant variant
[1]
Definition: main.cpp:38