Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qtclasshelpermacros.h
Go to the documentation of this file.
1// Copyright (C) 2022 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3// Qt-Security score:significant reason:default
4
5#ifndef QTCLASSHELPERMACROS_H
6#define QTCLASSHELPERMACROS_H
7
8#include <QtCore/qtconfigmacros.h>
9
10#if 0
11#pragma qt_class(QtClassHelperMacros)
12#pragma qt_sync_stop_processing
13#endif
14
15QT_BEGIN_NAMESPACE
16
17#if defined(__cplusplus)
18
19/*
20 Some classes do not permit copies to be made of an object. These
21 classes contains a private copy constructor and assignment
22 operator to disable copying (the compiler gives an error message).
23*/
24#define Q_DISABLE_COPY(Class)
25 Class(const Class &) = delete;
26 Class &operator=(const Class &) = delete;
27
28#define Q_DISABLE_COPY_MOVE(Class)
29 Q_DISABLE_COPY(Class)
30 Class(Class &&) = delete;
31 Class &operator=(Class &&) = delete;
32
33#define Q_DISABLE_COPY_X(Class, reason)
34 Class(const Class &) Q_DECL_EQ_DELETE_X(reason);
35 Class &operator=(const Class &) Q_DECL_EQ_DELETE_X(reason);
36
37#define Q_DISABLE_COPY_MOVE_X(Class, reason)
38 Q_DISABLE_COPY_X(Class, reason)
39 Class(Class &&) Q_DECL_EQ_DELETE_X(reason);
40 Class &operator=(Class &&) Q_DECL_EQ_DELETE_X(reason);
41
42/*
43 Implementing a move assignment operator using an established
44 technique (move-and-swap, pure swap) is just boilerplate.
45 Here's a couple of *private* macros for convenience.
46
47 To know which one to use:
48
49 * if you don't have a move constructor (*) => use pure swap;
50 * if you have a move constructor, then
51 * if your class holds just memory (no file handles, no user-defined
52 datatypes, etc.) => use pure swap;
53 * use move and swap.
54
55 The preference should always go for the move-and-swap one, as it
56 will deterministically destroy the data previously held in *this,
57 and not "dump" it in the moved-from object (which may then be alive
58 for longer).
59
60 The requirement for either macro is the presence of a member swap(),
61 which any value class that defines its own special member functions
62 should have anyhow.
63
64 (*) Many value classes in Qt do not have move constructors; mostly,
65 the implicitly shared classes using QSharedDataPointer and friends.
66 The reason is mostly historical: those classes require either an
67 out-of-line move constructor, which we could not provide before we
68 made C++11 mandatory (and that we don't like anyhow), or
69 an out-of-line dtor for the Q(E)DSP<Private> member (cf. QPixmap).
70
71 If you can however add a move constructor to a class lacking it,
72 consider doing so, then reevaluate which macro to choose.
73*/
74#define QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(Class)
75 Class &operator=(Class &&other) noexcept {
76 Class moved(std::move(other));
77 swap(moved);
78 return *this;
79 }
80
81#define QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(Class)
82 Class &operator=(Class &&other) noexcept {
83 swap(other);
84 return *this;
85 }
86
87/*
88 This macro defines the RO5 special member functions (destructor,
89 copy+move constructors and assignment operators) as defaulted.
90
91 Normally we don't use this macro if we're fine with these functions
92 to be public; we instead leave a comment in the class declaration,
93 something like:
94
95 // compiler-generated special member functions are fine!
96
97 In some cases a class may need to redeclare these functions, for
98 instance if it wants to change their accessibility. Since
99 defaulting all five is boilerplate, use this macro instead.
100
101 Note that the default constructor is not covered, and this macro
102 will prevent its automatic generation.
103*/
104
105#define QT_DECLARE_RO5_SMF_AS_DEFAULTED(Class)
106 ~Class() = default;
107 Class(const Class &) = default;
108 Class(Class &&) = default;
109 Class &operator=(const Class &) = default;
110 Class &operator=(Class &&) = default;
111
112/*
113 These macros can be used to define tag structs in the preferred way (ie.
114 with explicit default ctor).
115
116 The _STRUCT version only defines the tag type, no variable, while the
117 normal macro defines also a variable (and appends _t to the type name to
118 distinguish the two).
119
120 E.g. if we were std, we could use
121
122 QT_DEFINE_TAG(nullopt); // nullopt of type nullopt_t
123
124 The variable will be constexpr by default. If you want to make it static,
125 or inline, or both, prepend those keywords:
126
127 static QT_DEFINE_TAG(MyTag); // static constexpr
128 static inline QT_DEFINE_TAG(MyTag); // static inline constexpr
129*/
130#define QT_DEFINE_TAG_STRUCT(TAG)
131 struct TAG { explicit TAG () = default; }
132#define QT_DEFINE_TAG(TAG)
133 constexpr QT_DEFINE_TAG_STRUCT(TAG ## _t) TAG{}
134
135
136template <typename T> inline T *qGetPtrHelper(T *ptr) noexcept { return ptr; }
137template <typename Ptr> inline auto qGetPtrHelper(Ptr &ptr) noexcept -> decltype(ptr.get())
138{ static_assert(noexcept(ptr.get()), "Smart d pointers for Q_DECLARE_PRIVATE must have noexcept get()"); return ptr.get(); }
139
140class QObject;
141class QObjectPrivate;
142namespace QtPrivate {
143 template <typename ObjPrivate> void assertObjectType(QObjectPrivate *d);
144 inline const QObject *getQObject(const QObjectPrivate *d);
145}
146
147#define Q_DECLARE_PRIVATE(Class)
148 inline Class##Private* d_func() noexcept
149 { Q_CAST_IGNORE_ALIGN(return reinterpret_cast<Class##Private *>(qGetPtrHelper(d_ptr));) }
150 inline const Class##Private* d_func() const noexcept
151 { Q_CAST_IGNORE_ALIGN(return reinterpret_cast<const Class##Private *>(qGetPtrHelper(d_ptr));) }
152 friend class Class##Private;
153
154#define Q_DECLARE_PRIVATE_D(Dptr, Class)
155 inline Class##Private* d_func() noexcept
156 { Q_CAST_IGNORE_ALIGN(return reinterpret_cast<Class##Private *>(qGetPtrHelper(Dptr));) }
157 inline const Class##Private* d_func() const noexcept
158 { Q_CAST_IGNORE_ALIGN(return reinterpret_cast<const Class##Private *>(qGetPtrHelper(Dptr));) }
159 friend class Class##Private;
160
161#define Q_DECLARE_PUBLIC(Class)
162 inline Class* q_func() noexcept { return static_cast<Class *>(q_ptr); }
163 inline const Class* q_func() const noexcept { return static_cast<const Class *>(q_ptr); }
164 friend class Class;
165 friend const QObject *QtPrivate::getQObject(const QObjectPrivate *d);
166 template <typename ObjPrivate> friend void QtPrivate::assertObjectType(QObjectPrivate *d);
167
168#define Q_D(Class) Class##Private * const d = d_func()
169#define Q_Q(Class) Class * const q = q_func()
170
171/*
172 Specialize a shared type with:
173
174 Q_DECLARE_SHARED(type)
175
176 where 'type' is the name of the type to specialize. NOTE: shared
177 types must define a member-swap, and be defined in the same
178 namespace as Qt for this to work.
179
180 For types defined in a namespace within QT_NAMESPACE, use
181 Q_DECLARE_SHARED_NS/_EXT instead. The _NS macro needs to be placed
182 inside the nested namespace:
183
184 namespace ns {
185 // ~~~ type defined here ~~~
186 Q_DECLARE_SHARED_NS(ns, type)
187 }
188
189 while the _NS_EXT macro goes into the QT_NAMESPACE, outside any
190 nested namespaces:
191
192 namespace ns {
193 // ~~~ type defined here ~~~
194 }
195 Q_DECLARE_SHARED_NS_EXT(ns, type)
196
197 The latter then also works for more deeply-nested namespaces:
198
199 Q_DECLARE_SHARED_NS_EXT(ns1::ns2, type)
200
201 Q_DECLARE_SHARED_NS does, too, if all namespaces were opened in one statement:
202
203 namespace ns1::ns2 {
204 Q_DECLARE_SHARED_NS(ns1::ns2, type);
205 }
206*/
207
208#define Q_DECLARE_SHARED(TYPE) QT_DECLARE_ADL_SWAP
209 (TYPE) Q_DECLARE_TYPEINFO
210 (TYPE, Q_RELOCATABLE_TYPE); \
211/* end */
212
213#define Q_DECLARE_SHARED_NS(NS, TYPE) QT_DECLARE_ADL_SWAP
214 (TYPE) \
215}/* namespace NS */ Q_DECLARE_TYPEINFO
216 (NS :: TYPE, Q_RELOCATABLE_TYPE); namespace
217 NS { \
218/* end */
219
220#define Q_DECLARE_SHARED_NS_EXT(NS, TYPE) namespace
221 NS { QT_DECLARE_ADL_SWAP
222 (TYPE) \
223}/* namespace NS */ Q_DECLARE_TYPEINFO
224 (NS :: TYPE, Q_RELOCATABLE_TYPE); \
225/* end */
226
227#define QT_DECLARE_ADL_SWAP(TYPE) inline
228 void swap(TYPE &value1, TYPE &value2)
229 noexcept(noexcept(value1.swap(value2))) \
230{value1.swap(value2); }
231
232#endif // __cplusplus
233
234QT_END_NAMESPACE
235
236#endif // QTCLASSHELPERMACROS_H