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

Provided by KDAB

Privacy Policy
Learn Advanced QML with KDAB
Find out more

source code of qtbase/src/corelib/global/qtclasshelpermacros.h