Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
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#include <type_traits>
15
17
18class QDebug;
19
20/*
21 QTypeInfo - type trait functionality
22*/
23
24namespace QtPrivate {
25
26// A trivially copyable class must also have a trivial, non-deleted
27// destructor [class.prop/1.3], CWG1734. Some implementations don't
28// check for a trivial destructor, because of backwards compatibility
29// with C++98's definition of trivial copyability.
30// Since trivial copiability has implications for the ABI, implementations
31// can't "just fix" their traits. So, although formally redundant, we
32// explicitly check for trivial destruction here.
33template <typename T>
34inline constexpr bool qIsRelocatable = std::is_trivially_copyable_v<T> && std::is_trivially_destructible_v<T>;
35
36// Denotes types that are trivially default constructible, and for which
37// value-initialization can be achieved by filling their storage with 0 bits.
38// There is no type trait we can use for this, so we hardcode a list of
39// possibilities that we know are OK on the architectures that we support.
40// The most notable exception are pointers to data members, which for instance
41// on the Itanium ABI are initialized to -1.
42template <typename T>
43inline constexpr bool qIsValueInitializationBitwiseZero =
44 std::is_scalar_v<T> && !std::is_member_object_pointer_v<T>;
45
46}
47
48/*
49 The catch-all template.
50*/
51
52template <typename T>
54{
55public:
56 enum {
57 isPointer [[deprecated("Use std::is_pointer instead")]] = std::is_pointer_v<T>,
58 isIntegral [[deprecated("Use std::is_integral instead")]] = std::is_integral_v<T>,
59 isComplex = !std::is_trivial_v<T>,
60 isRelocatable = QtPrivate::qIsRelocatable<T>,
61 isValueInitializationBitwiseZero = QtPrivate::qIsValueInitializationBitwiseZero<T>,
62 };
63};
64
65template<>
67{
68public:
69 enum {
70 isPointer [[deprecated("Use std::is_pointer instead")]] = false,
71 isIntegral [[deprecated("Use std::is_integral instead")]] = false,
72 isComplex = false,
75 };
76};
77
98template <class T, class...Ts>
100{
101 static_assert(sizeof...(Ts) > 0);
102public:
103 static constexpr bool isComplex = ((QTypeInfo<Ts>::isComplex) || ...);
104 static constexpr bool isRelocatable = ((QTypeInfo<Ts>::isRelocatable) && ...);
105 [[deprecated("Use std::is_pointer instead")]] static constexpr bool isPointer = false;
106 [[deprecated("Use std::is_integral instead")]] static constexpr bool isIntegral = false;
107 static constexpr bool isValueInitializationBitwiseZero = false;
108 static_assert(!isRelocatable ||
109 std::is_copy_constructible_v<T> ||
110 std::is_move_constructible_v<T>,
111 "All Ts... are Q_RELOCATABLE_TYPE, but T is neither copy- nor move-constructible, "
112 "so cannot be Q_RELOCATABLE_TYPE. Please mark T as Q_COMPLEX_TYPE manually.");
113};
114
115// QTypeInfo for std::pair:
116// std::pair is spec'ed to be struct { T1 first; T2 second; }, so, unlike tuple<>,
117// we _can_ specialize QTypeInfo for pair<>:
118template <class T1, class T2>
119class QTypeInfo<std::pair<T1, T2>> : public QTypeInfoMerger<std::pair<T1, T2>, T1, T2> {};
120
121#define Q_DECLARE_MOVABLE_CONTAINER(CONTAINER) \
122template <typename ...T> \
123class QTypeInfo<CONTAINER<T...>> \
124{ \
125public: \
126 enum { \
127 isPointer [[deprecated("Use std::is_pointer instead")]] = false, \
128 isIntegral [[deprecated("Use std::is_integral instead")]] = false, \
129 isComplex = true, \
130 isRelocatable = true, \
131 isValueInitializationBitwiseZero = false, \
132 }; \
133}
134
144
145#undef Q_DECLARE_MOVABLE_CONTAINER
146
147/*
148 Specialize a specific type with:
149
150 Q_DECLARE_TYPEINFO(type, flags);
151
152 where 'type' is the name of the type to specialize and 'flags' is
153 logically-OR'ed combination of the flags below.
154*/
155enum { /* TYPEINFO flags */
161};
162
163#define Q_DECLARE_TYPEINFO_BODY(TYPE, FLAGS) \
164class QTypeInfo<TYPE > \
165{ \
166public: \
167 enum { \
168 isComplex = (((FLAGS) & Q_PRIMITIVE_TYPE) == 0) && !std::is_trivial_v<TYPE>, \
169 isRelocatable = !isComplex || ((FLAGS) & Q_RELOCATABLE_TYPE) || QtPrivate::qIsRelocatable<TYPE>, \
170 isPointer [[deprecated("Use std::is_pointer instead")]] = std::is_pointer_v< TYPE >, \
171 isIntegral [[deprecated("Use std::is_integral instead")]] = std::is_integral< TYPE >::value, \
172 isValueInitializationBitwiseZero = QtPrivate::qIsValueInitializationBitwiseZero<TYPE>, \
173 }; \
174 static_assert(!isRelocatable || \
175 std::is_copy_constructible_v<TYPE > || \
176 std::is_move_constructible_v<TYPE >, \
177 #TYPE " is neither copy- nor move-constructible, so cannot be Q_RELOCATABLE_TYPE"); \
178}
179
180#define Q_DECLARE_TYPEINFO(TYPE, FLAGS) \
181template<> \
182Q_DECLARE_TYPEINFO_BODY(TYPE, FLAGS)
183
184/* Specialize QTypeInfo for QFlags<T> */
185template<typename T> class QFlags;
186template<typename T>
188
189namespace QTypeTraits
190{
191
192/*
193 The templates below aim to find out whether one can safely instantiate an operator==() or
194 operator<() for a type.
195
196 This is tricky for containers, as most containers have unconstrained comparison operators, even though they
197 rely on the corresponding operators for its content.
198 This is especially true for all of the STL template classes that have a comparison operator defined, and
199 leads to the situation, that the compiler would try to instantiate the operator, and fail if any
200 of its template arguments does not have the operator implemented.
201
202 The code tries to cover the relevant cases for Qt and the STL, by checking (recusrsively) the value_type
203 of a container (if it exists), and checking the template arguments of pair, tuple and variant.
204*/
205namespace detail {
206
207// find out whether T is a conteiner
208// this is required to check the value type of containers for the existence of the comparison operator
209template <typename, typename = void>
210struct is_container : std::false_type {};
211template <typename T>
212struct is_container<T, std::void_t<
213 typename T::value_type,
214 std::is_convertible<decltype(std::declval<T>().begin() != std::declval<T>().end()), bool>
215>> : std::true_type {};
216
217
218// Checks the existence of the comparison operator for the class itself
221template <typename, typename = void>
222struct has_operator_equal : std::false_type {};
223template <typename T>
224struct has_operator_equal<T, std::void_t<decltype(bool(std::declval<const T&>() == std::declval<const T&>()))>>
225 : std::true_type {};
227
228// Two forward declarations
229template<typename T, bool = is_container<T>::value>
231template<typename T>
233
234// the entry point for the public method
235template<typename T>
236using expand_operator_equal = expand_operator_equal_container<T>;
237
238// if T isn't a container check if it's a tuple like object
239template<typename T, bool>
241// if T::value_type exists, check first T::value_type, then T itself
242template<typename T>
244 std::conjunction<
245 std::disjunction<
246 std::is_same<T, typename T::value_type>, // avoid endless recursion
247 expand_operator_equal<typename T::value_type>
248 >, expand_operator_equal_tuple<T>> {};
249
250// recursively check the template arguments of a tuple like object
251template<typename ...T>
252using expand_operator_equal_recursive = std::conjunction<expand_operator_equal<T>...>;
253
254template<typename T>
256template<typename T>
258template<typename T1, typename T2>
260template<typename ...T>
262template<typename ...T>
264
265// the same for operator<(), see above for explanations
266template <typename, typename = void>
267struct has_operator_less_than : std::false_type{};
268template <typename T>
269struct has_operator_less_than<T, std::void_t<decltype(bool(std::declval<const T&>() < std::declval<const T&>()))>>
270 : std::true_type{};
271
272template<typename T, bool = is_container<T>::value>
274template<typename T>
276
277template<typename T>
278using expand_operator_less_than = expand_operator_less_than_container<T>;
279
280template<typename T, bool>
282template<typename T>
284 std::conjunction<
285 std::disjunction<
286 std::is_same<T, typename T::value_type>,
287 expand_operator_less_than<typename T::value_type>
288 >, expand_operator_less_than_tuple<T>
289 > {};
290
291template<typename ...T>
292using expand_operator_less_than_recursive = std::conjunction<expand_operator_less_than<T>...>;
293
294template<typename T>
296template<typename T>
298template<typename T1, typename T2>
300template<typename ...T>
302template<typename ...T>
304
305}
306
307template<typename T, typename = void>
308struct is_dereferenceable : std::false_type {};
309
310template<typename T>
311struct is_dereferenceable<T, std::void_t<decltype(std::declval<T>().operator->())> >
312 : std::true_type {};
313
314template <typename T>
316
317template<typename T>
319template<typename T>
321
322template <typename Container, typename T>
323using has_operator_equal_container = std::disjunction<std::is_base_of<Container, T>, QTypeTraits::has_operator_equal<T>>;
324
325template<typename T>
327template<typename T>
329
330template <typename Container, typename T>
331using has_operator_less_than_container = std::disjunction<std::is_base_of<Container, T>, QTypeTraits::has_operator_less_than<T>>;
332
333template <typename ...T>
334using compare_eq_result = std::enable_if_t<std::conjunction_v<QTypeTraits::has_operator_equal<T>...>, bool>;
335
336template <typename Container, typename ...T>
337using compare_eq_result_container = std::enable_if_t<std::conjunction_v<QTypeTraits::has_operator_equal_container<Container, T>...>, bool>;
338
339template <typename ...T>
340using compare_lt_result = std::enable_if_t<std::conjunction_v<QTypeTraits::has_operator_less_than<T>...>, bool>;
341
342template <typename Container, typename ...T>
343using compare_lt_result_container = std::enable_if_t<std::conjunction_v<QTypeTraits::has_operator_less_than_container<Container, T>...>, bool>;
344
345namespace detail {
346
347template<typename T>
349template<typename T>
351
352}
353
354template <typename Stream, typename, typename = void>
355struct has_ostream_operator : std::false_type {};
356template <typename Stream, typename T>
357struct has_ostream_operator<Stream, T, std::void_t<decltype(detail::reference<Stream>() << detail::const_reference<T>())>>
358 : std::true_type {};
359template <typename Stream, typename T>
360inline constexpr bool has_ostream_operator_v = has_ostream_operator<Stream, T>::value;
361
362template <typename Stream, typename Container, typename T>
363using has_ostream_operator_container = std::disjunction<std::is_base_of<Container, T>, QTypeTraits::has_ostream_operator<Stream, T>>;
364
365template <typename Stream, typename, typename = void>
366struct has_istream_operator : std::false_type {};
367template <typename Stream, typename T>
368struct has_istream_operator<Stream, T, std::void_t<decltype(detail::reference<Stream>() >> detail::reference<T>())>>
369 : std::true_type {};
370template <typename Stream, typename T>
372template <typename Stream, typename Container, typename T>
373using has_istream_operator_container = std::disjunction<std::is_base_of<Container, T>, QTypeTraits::has_istream_operator<Stream, T>>;
374
375template <typename Stream, typename T>
376inline constexpr bool has_stream_operator_v = has_ostream_operator_v<Stream, T> && has_istream_operator_v<Stream, T>;
377
378}
379
380
382#endif // QTYPEINFO_H
\inmodule QtCore
\inmodule QtCore
Definition qhash.h:820
Definition qlist.h:75
Definition qmap.h:187
\inmodule QtCore
Definition qhash.h:1425
\inmodule QtCore
Definition qqueue.h:14
Definition qset.h:18
\inmodule QtCore
Definition qstack.h:13
\inmodule QtCore
Definition qtypeinfo.h:100
static constexpr bool isValueInitializationBitwiseZero
Definition qtypeinfo.h:107
static constexpr bool isIntegral
Definition qtypeinfo.h:106
static constexpr bool isPointer
Definition qtypeinfo.h:105
static constexpr bool isComplex
Definition qtypeinfo.h:103
static constexpr bool isRelocatable
Definition qtypeinfo.h:104
@ isValueInitializationBitwiseZero
Definition qtypeinfo.h:61
@ isRelocatable
Definition qtypeinfo.h:60
Combined button and popup list for selecting options.
std::conjunction< expand_operator_equal< T >... > expand_operator_equal_recursive
Definition qtypeinfo.h:252
std::conjunction< expand_operator_less_than< T >... > expand_operator_less_than_recursive
Definition qtypeinfo.h:292
const T & const_reference()
constexpr bool is_dereferenceable_v
Definition qtypeinfo.h:315
constexpr bool has_operator_equal_v
Definition qtypeinfo.h:320
constexpr bool has_stream_operator_v
Definition qtypeinfo.h:376
std::disjunction< std::is_base_of< Container, T >, QTypeTraits::has_istream_operator< Stream, T > > has_istream_operator_container
Definition qtypeinfo.h:373
constexpr bool has_istream_operator_v
Definition qtypeinfo.h:371
std::disjunction< std::is_base_of< Container, T >, QTypeTraits::has_operator_equal< T > > has_operator_equal_container
Definition qtypeinfo.h:323
std::enable_if_t< std::conjunction_v< QTypeTraits::has_operator_equal< T >... >, bool > compare_eq_result
Definition qtypeinfo.h:334
std::disjunction< std::is_base_of< Container, T >, QTypeTraits::has_operator_less_than< T > > has_operator_less_than_container
Definition qtypeinfo.h:331
std::enable_if_t< std::conjunction_v< QTypeTraits::has_operator_equal_container< Container, T >... >, bool > compare_eq_result_container
Definition qtypeinfo.h:337
std::enable_if_t< std::conjunction_v< QTypeTraits::has_operator_less_than_container< Container, T >... >, bool > compare_lt_result_container
Definition qtypeinfo.h:343
std::enable_if_t< std::conjunction_v< QTypeTraits::has_operator_less_than< T >... >, bool > compare_lt_result
Definition qtypeinfo.h:340
constexpr bool has_operator_less_than_v
Definition qtypeinfo.h:328
\macro QT_NO_KEYWORDS >
constexpr bool qIsRelocatable
Definition qtypeinfo.h:34
constexpr bool qIsValueInitializationBitwiseZero
Definition qtypeinfo.h:43
#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:157
@ Q_DUMMY_TYPE
Definition qtypeinfo.h:160
@ Q_RELOCATABLE_TYPE
Definition qtypeinfo.h:158
@ Q_COMPLEX_TYPE
Definition qtypeinfo.h:156
@ Q_MOVABLE_TYPE
Definition qtypeinfo.h:159
#define Q_DECLARE_MOVABLE_CONTAINER(CONTAINER)
Definition qtypeinfo.h:121
#define Q_DECLARE_TYPEINFO_BODY(TYPE, FLAGS)
Definition qtypeinfo.h:163
QVariant variant
[1]