Qt 6.x
The Qt SDK
Loading...
Searching...
No Matches
qtypeinfo.h
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// Copyright (C) 2016 Intel Corporation.
3// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
4
5#ifndef QTYPEINFO_H
6#define QTYPEINFO_H
7
8#include <QtCore/qcompilerdetection.h>
9#include <QtCore/qcontainerfwd.h>
10
11#include <variant>
12#include <optional>
13#include <tuple>
14
16
17class QDebug;
18
19/*
20 QTypeInfo - type trait functionality
21*/
22
23namespace QtPrivate {
24
25template <typename T>
26inline constexpr bool qIsRelocatable = std::is_trivially_copyable_v<T> && std::is_trivially_destructible_v<T>;
27
28// Denotes types that are trivially default constructible, and for which
29// value-initialization can be achieved by filling their storage with 0 bits.
30// There is no type trait we can use for this, so we hardcode a list of
31// possibilities that we know are OK on the architectures that we support.
32// The most notable exception are pointers to data members, which for instance
33// on the Itanium ABI are initialized to -1.
34template <typename T>
35inline constexpr bool qIsValueInitializationBitwiseZero =
36 std::is_scalar_v<T> && !std::is_member_object_pointer_v<T>;
37
38}
39
40/*
41 The catch-all template.
42*/
43
44template <typename T>
46{
47public:
48 enum {
49 isPointer [[deprecated("Use std::is_pointer instead")]] = std::is_pointer_v<T>,
50 isIntegral [[deprecated("Use std::is_integral instead")]] = std::is_integral_v<T>,
51 isComplex = !std::is_trivial_v<T>,
52 isRelocatable = QtPrivate::qIsRelocatable<T>,
53 isValueInitializationBitwiseZero = QtPrivate::qIsValueInitializationBitwiseZero<T>,
54 };
55};
56
57template<>
59{
60public:
61 enum {
62 isPointer [[deprecated("Use std::is_pointer instead")]] = false,
63 isIntegral [[deprecated("Use std::is_integral instead")]] = false,
64 isComplex = false,
67 };
68};
69
90template <class T, class...Ts>
92{
93 static_assert(sizeof...(Ts) > 0);
94public:
95 static constexpr bool isComplex = ((QTypeInfo<Ts>::isComplex) || ...);
96 static constexpr bool isRelocatable = ((QTypeInfo<Ts>::isRelocatable) && ...);
97 [[deprecated("Use std::is_pointer instead")]] static constexpr bool isPointer = false;
98 [[deprecated("Use std::is_integral instead")]] static constexpr bool isIntegral = false;
99 static constexpr bool isValueInitializationBitwiseZero = false;
100};
101
102// QTypeInfo for std::pair:
103// std::pair is spec'ed to be struct { T1 first; T2 second; }, so, unlike tuple<>,
104// we _can_ specialize QTypeInfo for pair<>:
105template <class T1, class T2>
106class QTypeInfo<std::pair<T1, T2>> : public QTypeInfoMerger<std::pair<T1, T2>, T1, T2> {};
107
108#define Q_DECLARE_MOVABLE_CONTAINER(CONTAINER) \
109template <typename ...T> \
110class QTypeInfo<CONTAINER<T...>> \
111{ \
112public: \
113 enum { \
114 isPointer [[deprecated("Use std::is_pointer instead")]] = false, \
115 isIntegral [[deprecated("Use std::is_integral instead")]] = false, \
116 isComplex = true, \
117 isRelocatable = true, \
118 isValueInitializationBitwiseZero = false, \
119 }; \
120}
121
131
132#undef Q_DECLARE_MOVABLE_CONTAINER
133
134/*
135 Specialize a specific type with:
136
137 Q_DECLARE_TYPEINFO(type, flags);
138
139 where 'type' is the name of the type to specialize and 'flags' is
140 logically-OR'ed combination of the flags below.
141*/
142enum { /* TYPEINFO flags */
148};
149
150#define Q_DECLARE_TYPEINFO_BODY(TYPE, FLAGS) \
151class QTypeInfo<TYPE > \
152{ \
153public: \
154 enum { \
155 isComplex = (((FLAGS) & Q_PRIMITIVE_TYPE) == 0) && !std::is_trivial_v<TYPE>, \
156 isRelocatable = !isComplex || ((FLAGS) & Q_RELOCATABLE_TYPE) || QtPrivate::qIsRelocatable<TYPE>, \
157 isPointer [[deprecated("Use std::is_pointer instead")]] = std::is_pointer_v< TYPE >, \
158 isIntegral [[deprecated("Use std::is_integral instead")]] = std::is_integral< TYPE >::value, \
159 isValueInitializationBitwiseZero = QtPrivate::qIsValueInitializationBitwiseZero<TYPE>, \
160 }; \
161}
162
163#define Q_DECLARE_TYPEINFO(TYPE, FLAGS) \
164template<> \
165Q_DECLARE_TYPEINFO_BODY(TYPE, FLAGS)
166
167/* Specialize QTypeInfo for QFlags<T> */
168template<typename T> class QFlags;
169template<typename T>
171
172namespace QTypeTraits
173{
174
175/*
176 The templates below aim to find out whether one can safely instantiate an operator==() or
177 operator<() for a type.
178
179 This is tricky for containers, as most containers have unconstrained comparison operators, even though they
180 rely on the corresponding operators for its content.
181 This is especially true for all of the STL template classes that have a comparison operator defined, and
182 leads to the situation, that the compiler would try to instantiate the operator, and fail if any
183 of its template arguments does not have the operator implemented.
184
185 The code tries to cover the relevant cases for Qt and the STL, by checking (recusrsively) the value_type
186 of a container (if it exists), and checking the template arguments of pair, tuple and variant.
187*/
188namespace detail {
189
190// find out whether T is a conteiner
191// this is required to check the value type of containers for the existence of the comparison operator
192template <typename, typename = void>
193struct is_container : std::false_type {};
194template <typename T>
195struct is_container<T, std::void_t<
196 typename T::value_type,
197 std::is_convertible<decltype(std::declval<T>().begin() != std::declval<T>().end()), bool>
198>> : std::true_type {};
199
200
201// Checks the existence of the comparison operator for the class itself
204template <typename, typename = void>
205struct has_operator_equal : std::false_type {};
206template <typename T>
207struct has_operator_equal<T, std::void_t<decltype(bool(std::declval<const T&>() == std::declval<const T&>()))>>
208 : std::true_type {};
210
211// Two forward declarations
212template<typename T, bool = is_container<T>::value>
214template<typename T>
216
217// the entry point for the public method
218template<typename T>
220
221// if T isn't a container check if it's a tuple like object
222template<typename T, bool>
224// if T::value_type exists, check first T::value_type, then T itself
225template<typename T>
227 std::conjunction<
228 std::disjunction<
229 std::is_same<T, typename T::value_type>, // avoid endless recursion
230 expand_operator_equal<typename T::value_type>
231 >, expand_operator_equal_tuple<T>> {};
232
233// recursively check the template arguments of a tuple like object
234template<typename ...T>
235using expand_operator_equal_recursive = std::conjunction<expand_operator_equal<T>...>;
236
237template<typename T>
239template<typename T>
241template<typename T1, typename T2>
243template<typename ...T>
245template<typename ...T>
247
248// the same for operator<(), see above for explanations
249template <typename, typename = void>
250struct has_operator_less_than : std::false_type{};
251template <typename T>
252struct has_operator_less_than<T, std::void_t<decltype(bool(std::declval<const T&>() < std::declval<const T&>()))>>
253 : std::true_type{};
254
255template<typename T, bool = is_container<T>::value>
257template<typename T>
259
260template<typename T>
262
263template<typename T, bool>
265template<typename T>
267 std::conjunction<
268 std::disjunction<
269 std::is_same<T, typename T::value_type>,
270 expand_operator_less_than<typename T::value_type>
271 >, expand_operator_less_than_tuple<T>
272 > {};
273
274template<typename ...T>
275using expand_operator_less_than_recursive = std::conjunction<expand_operator_less_than<T>...>;
276
277template<typename T>
279template<typename T>
281template<typename T1, typename T2>
283template<typename ...T>
285template<typename ...T>
287
288}
289
290template<typename T, typename = void>
291struct is_dereferenceable : std::false_type {};
292
293template<typename T>
294struct is_dereferenceable<T, std::void_t<decltype(std::declval<T>().operator->())> >
295 : std::true_type {};
296
297template <typename T>
299
300template<typename T>
302template<typename T>
304
305template <typename Container, typename T>
306using has_operator_equal_container = std::disjunction<std::is_base_of<Container, T>, QTypeTraits::has_operator_equal<T>>;
307
308template<typename T>
310template<typename T>
312
313template <typename Container, typename T>
314using has_operator_less_than_container = std::disjunction<std::is_base_of<Container, T>, QTypeTraits::has_operator_less_than<T>>;
315
316template <typename ...T>
317using compare_eq_result = std::enable_if_t<std::conjunction_v<QTypeTraits::has_operator_equal<T>...>, bool>;
318
319template <typename Container, typename ...T>
320using compare_eq_result_container = std::enable_if_t<std::conjunction_v<QTypeTraits::has_operator_equal_container<Container, T>...>, bool>;
321
322template <typename ...T>
323using compare_lt_result = std::enable_if_t<std::conjunction_v<QTypeTraits::has_operator_less_than<T>...>, bool>;
324
325template <typename Container, typename ...T>
326using compare_lt_result_container = std::enable_if_t<std::conjunction_v<QTypeTraits::has_operator_less_than_container<Container, T>...>, bool>;
327
328namespace detail {
329
330template<typename T>
332template<typename T>
334
335}
336
337template <typename Stream, typename, typename = void>
338struct has_ostream_operator : std::false_type {};
339template <typename Stream, typename T>
340struct has_ostream_operator<Stream, T, std::void_t<decltype(detail::reference<Stream>() << detail::const_reference<T>())>>
341 : std::true_type {};
342template <typename Stream, typename T>
343inline constexpr bool has_ostream_operator_v = has_ostream_operator<Stream, T>::value;
344
345template <typename Stream, typename Container, typename T>
346using has_ostream_operator_container = std::disjunction<std::is_base_of<Container, T>, QTypeTraits::has_ostream_operator<Stream, T>>;
347
348template <typename Stream, typename, typename = void>
349struct has_istream_operator : std::false_type {};
350template <typename Stream, typename T>
351struct has_istream_operator<Stream, T, std::void_t<decltype(detail::reference<Stream>() >> detail::reference<T>())>>
352 : std::true_type {};
353template <typename Stream, typename T>
355template <typename Stream, typename Container, typename T>
356using has_istream_operator_container = std::disjunction<std::is_base_of<Container, T>, QTypeTraits::has_istream_operator<Stream, T>>;
357
358template <typename Stream, typename T>
359inline constexpr bool has_stream_operator_v = has_ostream_operator_v<Stream, T> && has_istream_operator_v<Stream, T>;
360
361}
362
363
365#endif // QTYPEINFO_H
\inmodule QtCore
\inmodule QtCore
Definition qhash.h:818
Definition qlist.h:74
Definition qmap.h:186
\inmodule QtCore
Definition qhash.h:1348
\inmodule QtCore
Definition qqueue.h:14
Definition qset.h:18
\inmodule QtCore
Definition qstack.h:13
\inmodule QtCore
Definition qtypeinfo.h:92
static constexpr bool isValueInitializationBitwiseZero
Definition qtypeinfo.h:99
static constexpr bool isIntegral
Definition qtypeinfo.h:98
static constexpr bool isPointer
Definition qtypeinfo.h:97
static constexpr bool isComplex
Definition qtypeinfo.h:95
static constexpr bool isRelocatable
Definition qtypeinfo.h:96
@ isValueInitializationBitwiseZero
Definition qtypeinfo.h:53
@ isRelocatable
Definition qtypeinfo.h:52
Combined button and popup list for selecting options.
const T & const_reference()
std::conjunction< expand_operator_less_than< T >... > expand_operator_less_than_recursive
Definition qtypeinfo.h:275
std::conjunction< expand_operator_equal< T >... > expand_operator_equal_recursive
Definition qtypeinfo.h:235
std::enable_if_t< std::conjunction_v< QTypeTraits::has_operator_equal< T >... >, bool > compare_eq_result
Definition qtypeinfo.h:317
constexpr bool is_dereferenceable_v
Definition qtypeinfo.h:298
constexpr bool has_operator_equal_v
Definition qtypeinfo.h:303
std::enable_if_t< std::conjunction_v< QTypeTraits::has_operator_equal_container< Container, T >... >, bool > compare_eq_result_container
Definition qtypeinfo.h:320
constexpr bool has_stream_operator_v
Definition qtypeinfo.h:359
std::enable_if_t< std::conjunction_v< QTypeTraits::has_operator_less_than_container< Container, T >... >, bool > compare_lt_result_container
Definition qtypeinfo.h:326
std::enable_if_t< std::conjunction_v< QTypeTraits::has_operator_less_than< T >... >, bool > compare_lt_result
Definition qtypeinfo.h:323
constexpr bool has_istream_operator_v
Definition qtypeinfo.h:354
std::disjunction< std::is_base_of< Container, T >, QTypeTraits::has_operator_equal< T > > has_operator_equal_container
Definition qtypeinfo.h:306
std::disjunction< std::is_base_of< Container, T >, QTypeTraits::has_operator_less_than< T > > has_operator_less_than_container
Definition qtypeinfo.h:314
std::disjunction< std::is_base_of< Container, T >, QTypeTraits::has_istream_operator< Stream, T > > has_istream_operator_container
Definition qtypeinfo.h:356
constexpr bool has_operator_less_than_v
Definition qtypeinfo.h:311
\macro QT_NAMESPACE
constexpr bool qIsRelocatable
Definition qtypeinfo.h:26
constexpr bool qIsValueInitializationBitwiseZero
Definition qtypeinfo.h:35
#define QT_WARNING_POP
#define QT_WARNING_DISABLE_FLOAT_COMPARE
#define QT_WARNING_PUSH
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter int const void return DBusMessageIter DBusMessageIter return DBusMessageIter void DBusMessageIter void int return DBusMessage DBusMessageIter return DBusMessageIter return DBusMessageIter DBusMessageIter const char const char const char const char return DBusMessage return DBusMessage const char return DBusMessage dbus_bool_t return DBusMessage dbus_uint32_t return DBusMessage void
@ Q_PRIMITIVE_TYPE
Definition qtypeinfo.h:144
@ Q_DUMMY_TYPE
Definition qtypeinfo.h:147
@ Q_RELOCATABLE_TYPE
Definition qtypeinfo.h:145
@ Q_COMPLEX_TYPE
Definition qtypeinfo.h:143
@ Q_MOVABLE_TYPE
Definition qtypeinfo.h:146
#define Q_DECLARE_MOVABLE_CONTAINER(CONTAINER)
Definition qtypeinfo.h:108
#define Q_DECLARE_TYPEINFO_BODY(TYPE, FLAGS)
Definition qtypeinfo.h:150
QVariant variant
[1]