summaryrefslogtreecommitdiffstats
path: root/src/corelib/global
diff options
context:
space:
mode:
authorSona Kurazyan <sona.kurazyan@qt.io>2022-08-12 16:36:54 +0200
committerSona Kurazyan <sona.kurazyan@qt.io>2022-08-19 14:19:24 +0200
commitc201c5aedfcb131d2ac829346812560509904c7d (patch)
tree09f2ed25e0721174429d69da43faf8c79ef61de4 /src/corelib/global
parent23ecaf897fad6e786d8e833695baecae148c739c (diff)
Extract header qtclasshelpermacros.h
Move the class helper macros from qglobal.h and Q_DECLARE_SHARED from qtypeinfo.h there. Task-number: QTBUG-99313 Change-Id: I8c8b6241a76916176a48c09fbaf4effc87683770 Reviewed-by: Edward Welbourne <edward.welbourne@qt.io> Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@gmx.de>
Diffstat (limited to 'src/corelib/global')
-rw-r--r--src/corelib/global/qglobal.cpp57
-rw-r--r--src/corelib/global/qglobal.h105
-rw-r--r--src/corelib/global/qtclasshelpermacros.h144
-rw-r--r--src/corelib/global/qtclasshelpermacros.qdoc59
-rw-r--r--src/corelib/global/qtypeinfo.h17
5 files changed, 204 insertions, 178 deletions
diff --git a/src/corelib/global/qglobal.cpp b/src/corelib/global/qglobal.cpp
index de28cd87af..5d9660830e 100644
--- a/src/corelib/global/qglobal.cpp
+++ b/src/corelib/global/qglobal.cpp
@@ -512,63 +512,6 @@ using namespace Qt::StringLiterals;
*/
/*!
- \macro Q_DISABLE_COPY(Class)
- \relates QObject
-
- Disables the use of copy constructors and assignment operators
- for the given \a Class.
-
- Instances of subclasses of QObject should not be thought of as
- values that can be copied or assigned, but as unique identities.
- This means that when you create your own subclass of QObject
- (director or indirect), you should \e not give it a copy constructor
- or an assignment operator. However, it may not enough to simply
- omit them from your class, because, if you mistakenly write some code
- that requires a copy constructor or an assignment operator (it's easy
- to do), your compiler will thoughtfully create it for you. You must
- do more.
-
- The curious user will have seen that the Qt classes derived
- from QObject typically include this macro in a private section:
-
- \snippet code/src_corelib_global_qglobal.cpp 43
-
- It declares a copy constructor and an assignment operator in the
- private section, so that if you use them by mistake, the compiler
- will report an error.
-
- \snippet code/src_corelib_global_qglobal.cpp 44
-
- But even this might not catch absolutely every case. You might be
- tempted to do something like this:
-
- \snippet code/src_corelib_global_qglobal.cpp 45
-
- First of all, don't do that. Most compilers will generate code that
- uses the copy constructor, so the privacy violation error will be
- reported, but your C++ compiler is not required to generate code for
- this statement in a specific way. It could generate code using
- \e{neither} the copy constructor \e{nor} the assignment operator we
- made private. In that case, no error would be reported, but your
- application would probably crash when you called a member function
- of \c{w}.
-
- \sa Q_DISABLE_COPY_MOVE
-*/
-
-/*!
- \macro Q_DISABLE_COPY_MOVE(Class)
- \relates QObject
-
- A convenience macro that disables the use of copy constructors, assignment
- operators, move constructors and move assignment operators for the given
- \a Class.
-
- \sa Q_DISABLE_COPY
- \since 5.13
-*/
-
-/*!
\macro Q_DECLARE_FLAGS(Flags, Enum)
\relates QFlags
diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h
index 13452bf22a..4329f9f093 100644
--- a/src/corelib/global/qglobal.h
+++ b/src/corelib/global/qglobal.h
@@ -46,6 +46,7 @@ inline void qt_noop(void) {}
#include <QtCore/qassert.h>
#include <QtCore/qtypes.h>
+#include <QtCore/qtclasshelpermacros.h>
/*
Avoid "unused parameter" warnings
@@ -56,65 +57,6 @@ inline void qt_noop(void) {}
QT_BEGIN_NAMESPACE
/*
- Some classes do not permit copies to be made of an object. These
- classes contains a private copy constructor and assignment
- operator to disable copying (the compiler gives an error message).
-*/
-#define Q_DISABLE_COPY(Class) \
- Class(const Class &) = delete;\
- Class &operator=(const Class &) = delete;
-
-#define Q_DISABLE_COPY_MOVE(Class) \
- Q_DISABLE_COPY(Class) \
- Class(Class &&) = delete; \
- Class &operator=(Class &&) = delete;
-
-/*
- Implementing a move assignment operator using an established
- technique (move-and-swap, pure swap) is just boilerplate.
- Here's a couple of *private* macros for convenience.
-
- To know which one to use:
-
- * if you don't have a move constructor (*) => use pure swap;
- * if you have a move constructor, then
- * if your class holds just memory (no file handles, no user-defined
- datatypes, etc.) => use pure swap;
- * use move and swap.
-
- The preference should always go for the move-and-swap one, as it
- will deterministically destroy the data previously held in *this,
- and not "dump" it in the moved-from object (which may then be alive
- for longer).
-
- The requirement for either macro is the presence of a member swap(),
- which any value class that defines its own special member functions
- should have anyhow.
-
- (*) Many value classes in Qt do not have move constructors; mostly,
- the implicitly shared classes using QSharedDataPointer and friends.
- The reason is mostly historical: those classes require either an
- out-of-line move constructor, which we could not provide before we
- made C++11 mandatory (and that we don't like anyhow), or
- an out-of-line dtor for the Q(E)DSP<Private> member (cf. QPixmap).
-
- If you can however add a move constructor to a class lacking it,
- consider doing so, then reevaluate which macro to choose.
-*/
-#define QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(Class) \
- Class &operator=(Class &&other) noexcept { \
- Class moved(std::move(other)); \
- swap(moved); \
- return *this; \
- }
-
-#define QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(Class) \
- Class &operator=(Class &&other) noexcept { \
- swap(other); \
- return *this; \
- }
-
-/*
No, this is not an evil backdoor. QT_BUILD_INTERNAL just exports more symbols
for Qt's internal unit tests. If you want slower loading times and more
symbols that can vanish from version to version, feel free to define QT_BUILD_INTERNAL.
@@ -244,26 +186,6 @@ typedef void (*QFunctionPointer)();
# define Q_UNIMPLEMENTED() qWarning("Unimplemented code.")
#endif
-/*
- Compilers which follow outdated template instantiation rules
- require a class to have a comparison operator to exist when
- a QList of this type is instantiated. It's not actually
- used in the list, though. Hence the dummy implementation.
- Just in case other code relies on it we better trigger a warning
- mandating a real implementation.
-*/
-
-#ifdef Q_FULL_TEMPLATE_INSTANTIATION
-# define Q_DUMMY_COMPARISON_OPERATOR(C) \
- bool operator==(const C&) const { \
- qWarning(#C"::operator==(const "#C"&) was called"); \
- return false; \
- }
-#else
-
-# define Q_DUMMY_COMPARISON_OPERATOR(C)
-#endif
-
QT_WARNING_PUSH
// warning: noexcept-expression evaluates to 'false' because of a call to 'void swap(..., ...)'
QT_WARNING_DISABLE_GCC("-Wnoexcept")
@@ -328,33 +250,8 @@ constexpr std::underlying_type_t<Enum> qToUnderlying(Enum e) noexcept
return static_cast<std::underlying_type_t<Enum>>(e);
}
-template <typename T> inline T *qGetPtrHelper(T *ptr) noexcept { return ptr; }
-template <typename Ptr> inline auto qGetPtrHelper(Ptr &ptr) noexcept -> decltype(ptr.get())
-{ static_assert(noexcept(ptr.get()), "Smart d pointers for Q_DECLARE_PRIVATE must have noexcept get()"); return ptr.get(); }
-
// The body must be a statement:
#define Q_CAST_IGNORE_ALIGN(body) QT_WARNING_PUSH QT_WARNING_DISABLE_GCC("-Wcast-align") body QT_WARNING_POP
-#define Q_DECLARE_PRIVATE(Class) \
- inline Class##Private* d_func() noexcept \
- { Q_CAST_IGNORE_ALIGN(return reinterpret_cast<Class##Private *>(qGetPtrHelper(d_ptr));) } \
- inline const Class##Private* d_func() const noexcept \
- { Q_CAST_IGNORE_ALIGN(return reinterpret_cast<const Class##Private *>(qGetPtrHelper(d_ptr));) } \
- friend class Class##Private;
-
-#define Q_DECLARE_PRIVATE_D(Dptr, Class) \
- inline Class##Private* d_func() noexcept \
- { Q_CAST_IGNORE_ALIGN(return reinterpret_cast<Class##Private *>(qGetPtrHelper(Dptr));) } \
- inline const Class##Private* d_func() const noexcept \
- { Q_CAST_IGNORE_ALIGN(return reinterpret_cast<const Class##Private *>(qGetPtrHelper(Dptr));) } \
- friend class Class##Private;
-
-#define Q_DECLARE_PUBLIC(Class) \
- inline Class* q_func() noexcept { return static_cast<Class *>(q_ptr); } \
- inline const Class* q_func() const noexcept { return static_cast<const Class *>(q_ptr); } \
- friend class Class;
-
-#define Q_D(Class) Class##Private * const d = d_func()
-#define Q_Q(Class) Class * const q = q_func()
#define QT_MODULE(x)
diff --git a/src/corelib/global/qtclasshelpermacros.h b/src/corelib/global/qtclasshelpermacros.h
new file mode 100644
index 0000000000..3c59404910
--- /dev/null
+++ b/src/corelib/global/qtclasshelpermacros.h
@@ -0,0 +1,144 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QTCLASSHELPERMACROS_H
+#define QTCLASSHELPERMACROS_H
+
+#include <QtCore/qtconfigmacros.h>
+
+#if 0
+#pragma qt_class(QtClassHelperMacros)
+#pragma qt_sync_stop_processing
+#endif
+
+QT_BEGIN_NAMESPACE
+
+#if defined(__cplusplus)
+
+/*
+ Some classes do not permit copies to be made of an object. These
+ classes contains a private copy constructor and assignment
+ operator to disable copying (the compiler gives an error message).
+*/
+#define Q_DISABLE_COPY(Class) \
+ Class(const Class &) = delete;\
+ Class &operator=(const Class &) = delete;
+
+#define Q_DISABLE_COPY_MOVE(Class) \
+ Q_DISABLE_COPY(Class) \
+ Class(Class &&) = delete; \
+ Class &operator=(Class &&) = delete;
+
+/*
+ Implementing a move assignment operator using an established
+ technique (move-and-swap, pure swap) is just boilerplate.
+ Here's a couple of *private* macros for convenience.
+
+ To know which one to use:
+
+ * if you don't have a move constructor (*) => use pure swap;
+ * if you have a move constructor, then
+ * if your class holds just memory (no file handles, no user-defined
+ datatypes, etc.) => use pure swap;
+ * use move and swap.
+
+ The preference should always go for the move-and-swap one, as it
+ will deterministically destroy the data previously held in *this,
+ and not "dump" it in the moved-from object (which may then be alive
+ for longer).
+
+ The requirement for either macro is the presence of a member swap(),
+ which any value class that defines its own special member functions
+ should have anyhow.
+
+ (*) Many value classes in Qt do not have move constructors; mostly,
+ the implicitly shared classes using QSharedDataPointer and friends.
+ The reason is mostly historical: those classes require either an
+ out-of-line move constructor, which we could not provide before we
+ made C++11 mandatory (and that we don't like anyhow), or
+ an out-of-line dtor for the Q(E)DSP<Private> member (cf. QPixmap).
+
+ If you can however add a move constructor to a class lacking it,
+ consider doing so, then reevaluate which macro to choose.
+*/
+#define QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(Class) \
+ Class &operator=(Class &&other) noexcept { \
+ Class moved(std::move(other)); \
+ swap(moved); \
+ return *this; \
+ }
+
+#define QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(Class) \
+ Class &operator=(Class &&other) noexcept { \
+ swap(other); \
+ return *this; \
+ }
+
+template <typename T> inline T *qGetPtrHelper(T *ptr) noexcept { return ptr; }
+template <typename Ptr> inline auto qGetPtrHelper(Ptr &ptr) noexcept -> decltype(ptr.get())
+{ static_assert(noexcept(ptr.get()), "Smart d pointers for Q_DECLARE_PRIVATE must have noexcept get()"); return ptr.get(); }
+
+#define Q_DECLARE_PRIVATE(Class) \
+ inline Class##Private* d_func() noexcept \
+ { Q_CAST_IGNORE_ALIGN(return reinterpret_cast<Class##Private *>(qGetPtrHelper(d_ptr));) } \
+ inline const Class##Private* d_func() const noexcept \
+ { Q_CAST_IGNORE_ALIGN(return reinterpret_cast<const Class##Private *>(qGetPtrHelper(d_ptr));) } \
+ friend class Class##Private;
+
+#define Q_DECLARE_PRIVATE_D(Dptr, Class) \
+ inline Class##Private* d_func() noexcept \
+ { Q_CAST_IGNORE_ALIGN(return reinterpret_cast<Class##Private *>(qGetPtrHelper(Dptr));) } \
+ inline const Class##Private* d_func() const noexcept \
+ { Q_CAST_IGNORE_ALIGN(return reinterpret_cast<const Class##Private *>(qGetPtrHelper(Dptr));) } \
+ friend class Class##Private;
+
+#define Q_DECLARE_PUBLIC(Class) \
+ inline Class* q_func() noexcept { return static_cast<Class *>(q_ptr); } \
+ inline const Class* q_func() const noexcept { return static_cast<const Class *>(q_ptr); } \
+ friend class Class;
+
+#define Q_D(Class) Class##Private * const d = d_func()
+#define Q_Q(Class) Class * const q = q_func()
+
+/*
+ Compilers which follow outdated template instantiation rules
+ require a class to have a comparison operator to exist when
+ a QList of this type is instantiated. It's not actually
+ used in the list, though. Hence the dummy implementation.
+ Just in case other code relies on it we better trigger a warning
+ mandating a real implementation.
+*/
+
+#ifdef Q_FULL_TEMPLATE_INSTANTIATION
+# define Q_DUMMY_COMPARISON_OPERATOR(C) \
+ bool operator==(const C&) const { \
+ qWarning(#C"::operator==(const "#C"&) was called"); \
+ return false; \
+ }
+#else
+
+# define Q_DUMMY_COMPARISON_OPERATOR(C)
+#endif
+
+/*
+ Specialize a shared type with:
+
+ Q_DECLARE_SHARED(type)
+
+ where 'type' is the name of the type to specialize. NOTE: shared
+ types must define a member-swap, and be defined in the same
+ namespace as Qt for this to work.
+*/
+
+#define Q_DECLARE_SHARED_IMPL(TYPE, FLAGS) \
+Q_DECLARE_TYPEINFO(TYPE, FLAGS); \
+inline void swap(TYPE &value1, TYPE &value2) \
+ noexcept(noexcept(value1.swap(value2))) \
+{ value1.swap(value2); }
+#define Q_DECLARE_SHARED(TYPE) Q_DECLARE_SHARED_IMPL(TYPE, Q_RELOCATABLE_TYPE)
+
+#endif // __cplusplus
+
+QT_END_NAMESPACE
+
+#endif // QTCLASSHELPERMACROS_H
diff --git a/src/corelib/global/qtclasshelpermacros.qdoc b/src/corelib/global/qtclasshelpermacros.qdoc
new file mode 100644
index 0000000000..50c8f6e8d9
--- /dev/null
+++ b/src/corelib/global/qtclasshelpermacros.qdoc
@@ -0,0 +1,59 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
+
+/*!
+ \macro Q_DISABLE_COPY(Class)
+ \relates QtClassHelperMacros
+
+ Disables the use of copy constructors and assignment operators
+ for the given \a Class.
+
+ Instances of subclasses of QObject should not be thought of as
+ values that can be copied or assigned, but as unique identities.
+ This means that when you create your own subclass of QObject
+ (director or indirect), you should \e not give it a copy constructor
+ or an assignment operator. However, it may not enough to simply
+ omit them from your class, because, if you mistakenly write some code
+ that requires a copy constructor or an assignment operator (it's easy
+ to do), your compiler will thoughtfully create it for you. You must
+ do more.
+
+ The curious user will have seen that the Qt classes derived
+ from QObject typically include this macro in a private section:
+
+ \snippet code/src_corelib_global_qglobal.cpp 43
+
+ It declares a copy constructor and an assignment operator in the
+ private section, so that if you use them by mistake, the compiler
+ will report an error.
+
+ \snippet code/src_corelib_global_qglobal.cpp 44
+
+ But even this might not catch absolutely every case. You might be
+ tempted to do something like this:
+
+ \snippet code/src_corelib_global_qglobal.cpp 45
+
+ First of all, don't do that. Most compilers will generate code that
+ uses the copy constructor, so the privacy violation error will be
+ reported, but your C++ compiler is not required to generate code for
+ this statement in a specific way. It could generate code using
+ \e{neither} the copy constructor \e{nor} the assignment operator we
+ made private. In that case, no error would be reported, but your
+ application would probably crash when you called a member function
+ of \c{w}.
+
+ \sa Q_DISABLE_COPY_MOVE
+*/
+
+/*!
+ \macro Q_DISABLE_COPY_MOVE(Class)
+ \relates QtClassHelperMacros
+
+ A convenience macro that disables the use of copy constructors, assignment
+ operators, move constructors and move assignment operators for the given
+ \a Class.
+
+ \sa Q_DISABLE_COPY
+ \since 5.13
+*/
diff --git a/src/corelib/global/qtypeinfo.h b/src/corelib/global/qtypeinfo.h
index 1938967a91..73bf6140c7 100644
--- a/src/corelib/global/qtypeinfo.h
+++ b/src/corelib/global/qtypeinfo.h
@@ -143,23 +143,6 @@ template<typename T> class QFlags;
template<typename T>
Q_DECLARE_TYPEINFO_BODY(QFlags<T>, Q_PRIMITIVE_TYPE);
-/*
- Specialize a shared type with:
-
- Q_DECLARE_SHARED(type)
-
- where 'type' is the name of the type to specialize. NOTE: shared
- types must define a member-swap, and be defined in the same
- namespace as Qt for this to work.
-*/
-
-#define Q_DECLARE_SHARED_IMPL(TYPE, FLAGS) \
-Q_DECLARE_TYPEINFO(TYPE, FLAGS); \
-inline void swap(TYPE &value1, TYPE &value2) \
- noexcept(noexcept(value1.swap(value2))) \
-{ value1.swap(value2); }
-#define Q_DECLARE_SHARED(TYPE) Q_DECLARE_SHARED_IMPL(TYPE, Q_RELOCATABLE_TYPE)
-
namespace QTypeTraits
{