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