diff options
author | Giuseppe D'Angelo <giuseppe.dangelo@kdab.com> | 2020-01-03 17:18:02 +0100 |
---|---|---|
committer | Giuseppe D'Angelo <giuseppe.dangelo@kdab.com> | 2020-10-03 11:47:17 +0200 |
commit | 889d40ebe2d9d0e92caea2749608720f7c088173 (patch) | |
tree | a68214fbf5a0dc9b1488e4ae79a499dabc1cc445 /src/corelib/kernel | |
parent | 990e2e4fb8ef546b89b5e83e659771edd5b4ed3e (diff) |
Centralize the implementation of move assignment operators
At the moment we have two main strategies for dealing with move
assignment in Qt:
1) move-and-swap, used by "containers" (in the broad sense): containers,
but also smart pointers and similar classes that can hold user-defined
types;
2) pure swap, used by containers that hold only memory (e.g. QString,
QByteArray, ...) as well as most implicitly shared datatypes.
Given the fact that a move assignment operator's code is just
boilerplate (whether it's move-and-swap or pure swap), provide two
_strictly internal_ macros to help write them, and apply the macros
across corelib and gui, porting away from the hand-rolled
implementations.
The rule of thumb when porting to the new macros is:
* Try to stick to the existing code behavior, unless broken
* if changing, then follow this checklist:
* if the class does not have a move constructor => pure swap
(but consider ADDING a move constructor, if possible!)
* if the class does have a move constructor, try to follow the
criteria above, namely:
* if the class holds only memory, pure swap;
* if the class may hold anything else but memory (file handles,
etc.), then move and swap.
Noteworthy details:
* some operators planned to be removed in Qt 6 were not ported;
* as drive-by, some move constructors were simplified to be using
qExchange(); others were outright broken and got fixed;
* some contained some more interesting code and were not touched.
Change-Id: Idaab3489247dcbabb6df3fa1e5286b69e1d372e9
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'src/corelib/kernel')
-rw-r--r-- | src/corelib/kernel/qbasictimer.h | 6 | ||||
-rw-r--r-- | src/corelib/kernel/qcore_mac_p.h | 37 | ||||
-rw-r--r-- | src/corelib/kernel/qmetaobject.cpp | 8 | ||||
-rw-r--r-- | src/corelib/kernel/qobjectdefs.h | 11 | ||||
-rw-r--r-- | src/corelib/kernel/qvariant.h | 3 | ||||
-rw-r--r-- | src/corelib/kernel/qwinregistry_p.h | 6 |
6 files changed, 31 insertions, 40 deletions
diff --git a/src/corelib/kernel/qbasictimer.h b/src/corelib/kernel/qbasictimer.h index b9bfd636bc..64a9acbe6e 100644 --- a/src/corelib/kernel/qbasictimer.h +++ b/src/corelib/kernel/qbasictimer.h @@ -61,11 +61,7 @@ public: : id{qExchange(other.id, 0)} {} - QBasicTimer& operator=(QBasicTimer &&other) noexcept - { - QBasicTimer{std::move(other)}.swap(*this); - return *this; - } + QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QBasicTimer) void swap(QBasicTimer &other) noexcept { qSwap(id, other.id); } diff --git a/src/corelib/kernel/qcore_mac_p.h b/src/corelib/kernel/qcore_mac_p.h index 2d33e2ca95..ef31b1928c 100644 --- a/src/corelib/kernel/qcore_mac_p.h +++ b/src/corelib/kernel/qcore_mac_p.h @@ -260,21 +260,12 @@ public: QAppleLogActivity(os_activity_t activity) : activity(activity) {} ~QAppleLogActivity() { if (activity) leave(); } - QAppleLogActivity(const QAppleLogActivity &) = delete; - QAppleLogActivity& operator=(const QAppleLogActivity &) = delete; + Q_DISABLE_COPY(QAppleLogActivity) QAppleLogActivity(QAppleLogActivity&& other) - : activity(other.activity), state(other.state) { other.activity = nullptr; } + : activity(qExchange(other.activity, nullptr)), state(other.state) {} - QAppleLogActivity& operator=(QAppleLogActivity &&other) - { - if (this != &other) { - activity = other.activity; - state = other.state; - other.activity = nullptr; - } - return *this; - } + QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QAppleLogActivity) QAppleLogActivity&& enter() { @@ -343,18 +334,14 @@ public: #endif QMacNotificationObserver(const QMacNotificationObserver& other) = delete; - QMacNotificationObserver(QMacNotificationObserver&& other) : observer(other.observer) { - other.observer = nullptr; - } + QMacNotificationObserver(QMacNotificationObserver&& other) : observer(qExchange(other.observer, nullptr)) {} QMacNotificationObserver &operator=(const QMacNotificationObserver& other) = delete; - QMacNotificationObserver &operator=(QMacNotificationObserver&& other) { - if (this != &other) { - remove(); - observer = other.observer; - other.observer = nullptr; - } - return *this; + QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QMacNotificationObserver) + + void swap(QMacNotificationObserver &other) noexcept + { + qSwap(observer, other.observer); } void remove(); @@ -397,11 +384,7 @@ public: return *this; } - QMacKeyValueObserver &operator=(QMacKeyValueObserver &&other) { - QMacKeyValueObserver tmp(std::move(other)); - swap(tmp, *this); - return *this; - } + QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QMacKeyValueObserver) void removeObserver(); diff --git a/src/corelib/kernel/qmetaobject.cpp b/src/corelib/kernel/qmetaobject.cpp index c537293347..3bb3e33465 100644 --- a/src/corelib/kernel/qmetaobject.cpp +++ b/src/corelib/kernel/qmetaobject.cpp @@ -1598,6 +1598,14 @@ bool QMetaObject::invokeMethodImpl(QObject *object, QtPrivate::QSlotObjectBase * */ /*! + \fn QMetaObject::Connection::swap(Connection &other) + \since 5.15 + + Swaps this Connection instance with \a other. This operation is very fast + and never fails. +*/ + +/*! \class QMetaMethod \inmodule QtCore diff --git a/src/corelib/kernel/qobjectdefs.h b/src/corelib/kernel/qobjectdefs.h index 16478d889f..38a87e2dcb 100644 --- a/src/corelib/kernel/qobjectdefs.h +++ b/src/corelib/kernel/qobjectdefs.h @@ -459,11 +459,16 @@ public: operator RestrictedBool() const { return d_ptr && isConnected_helper() ? &Connection::d_ptr : nullptr; } #endif - Connection(Connection &&o) noexcept : d_ptr(o.d_ptr) { o.d_ptr = nullptr; } - Connection &operator=(Connection &&other) noexcept - { qSwap(d_ptr, other.d_ptr); return *this; } + Connection(Connection &&o) noexcept : d_ptr(qExchange(o.d_ptr, nullptr)) {} + QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(Connection) + void swap(Connection &o) noexcept { qSwap(d_ptr, o.d_ptr); } }; +inline void swap(QMetaObject::Connection &lhs, QMetaObject::Connection &rhs) noexcept +{ + lhs.swap(rhs); +} + inline const QMetaObject *QMetaObject::superClass() const { return d.superdata; } diff --git a/src/corelib/kernel/qvariant.h b/src/corelib/kernel/qvariant.h index c28f841356..1bf904618f 100644 --- a/src/corelib/kernel/qvariant.h +++ b/src/corelib/kernel/qvariant.h @@ -234,8 +234,7 @@ class Q_CORE_EXPORT QVariant QVariant& operator=(const QVariant &other); inline QVariant(QVariant &&other) noexcept : d(other.d) { other.d = Private(); } - inline QVariant &operator=(QVariant &&other) noexcept - { QVariant moved(std::move(other)); swap(moved); return *this; } + QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QVariant) inline void swap(QVariant &other) noexcept { qSwap(d, other.d); } diff --git a/src/corelib/kernel/qwinregistry_p.h b/src/corelib/kernel/qwinregistry_p.h index d249a97988..a456292835 100644 --- a/src/corelib/kernel/qwinregistry_p.h +++ b/src/corelib/kernel/qwinregistry_p.h @@ -68,9 +68,9 @@ public: REGSAM permissions = KEY_READ, REGSAM access = 0); ~QWinRegistryKey(); - QWinRegistryKey(QWinRegistryKey &&other) noexcept { swap(other); } - QWinRegistryKey &operator=(QWinRegistryKey &&other) noexcept { swap(other); return *this; } - + QWinRegistryKey(QWinRegistryKey &&other) noexcept + : m_key(qExchange(other.m_key, nullptr)) {} + QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QWinRegistryKey) void swap(QWinRegistryKey &other) noexcept { qSwap(m_key, other.m_key); } bool isValid() const { return m_key != nullptr; } |