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
77template <typename T> inline T *qGetPtrHelper(T *ptr) noexcept { return ptr; }
78template <typename Ptr> inline auto qGetPtrHelper(Ptr &ptr) noexcept -> decltype(ptr.get())
79{ static_assert(noexcept(ptr.get()), "Smart d pointers for Q_DECLARE_PRIVATE must have noexcept get()"); return ptr.get(); }
80
81class QObject;
82class QObjectPrivate;
83namespace QtPrivate {
84 template <typename ObjPrivate> void assertObjectType(QObjectPrivate *d);
85 inline const QObject *getQObject(const QObjectPrivate *d);
86}
87
88#define Q_DECLARE_PRIVATE(Class) \
89 inline Class##Private* d_func() noexcept \
90 { Q_CAST_IGNORE_ALIGN(return reinterpret_cast<Class##Private *>(qGetPtrHelper(d_ptr));) } \
91 inline const Class##Private* d_func() const noexcept \
92 { Q_CAST_IGNORE_ALIGN(return reinterpret_cast<const Class##Private *>(qGetPtrHelper(d_ptr));) } \
93 friend class Class##Private;
94
95#define Q_DECLARE_PRIVATE_D(Dptr, Class) \
96 inline Class##Private* d_func() noexcept \
97 { Q_CAST_IGNORE_ALIGN(return reinterpret_cast<Class##Private *>(qGetPtrHelper(Dptr));) } \
98 inline const Class##Private* d_func() const noexcept \
99 { Q_CAST_IGNORE_ALIGN(return reinterpret_cast<const Class##Private *>(qGetPtrHelper(Dptr));) } \
100 friend class Class##Private;
101
102#define Q_DECLARE_PUBLIC(Class) \
103 inline Class* q_func() noexcept { return static_cast<Class *>(q_ptr); } \
104 inline const Class* q_func() const noexcept { return static_cast<const Class *>(q_ptr); } \
105 friend class Class; \
106 friend const QObject *QtPrivate::getQObject(const QObjectPrivate *d); \
107 template <typename ObjPrivate> friend void QtPrivate::assertObjectType(QObjectPrivate *d);
108
109#define Q_D(Class) Class##Private * const d = d_func()
110#define Q_Q(Class) Class * const q = q_func()
111
112/*
113 Specialize a shared type with:
114
115 Q_DECLARE_SHARED(type)
116
117 where 'type' is the name of the type to specialize. NOTE: shared
118 types must define a member-swap, and be defined in the same
119 namespace as Qt for this to work.
120*/
121
122#define Q_DECLARE_SHARED(TYPE) \
123Q_DECLARE_TYPEINFO(TYPE, Q_RELOCATABLE_TYPE); \
124inline void swap(TYPE &value1, TYPE &value2) \
125 noexcept(noexcept(value1.swap(value2))) \
126{ value1.swap(value2); }
127
128#endif // __cplusplus
129
130QT_END_NAMESPACE
131
132#endif // QTCLASSHELPERMACROS_H
133

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