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>
This commit is contained in:
Giuseppe D'Angelo 2020-01-03 17:18:02 +01:00
parent 990e2e4fb8
commit 889d40ebe2
59 changed files with 148 additions and 189 deletions

View File

@ -431,6 +431,51 @@ Q_DECL_UNUSED constexpr Deprecated_t Deprecated = {};
Q_DISABLE_COPY(Class) \
Q_DISABLE_MOVE(Class)
/*
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

View File

@ -102,8 +102,7 @@ public:
QDebug(const QDebug &o) : stream(o.stream) { ++stream->ref; }
QDebug(QDebug &&other) noexcept : stream{qExchange(other.stream, nullptr)} {}
inline QDebug &operator=(const QDebug &other);
QDebug &operator=(QDebug &&other) noexcept
{ QDebug{std::move(other)}.swap(*this); return *this; }
QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QDebug)
~QDebug();
inline void swap(QDebug &other) noexcept { qSwap(stream, other.stream); }

View File

@ -121,7 +121,7 @@ public:
~QDir();
QDir &operator=(const QDir &);
QDir &operator=(QDir &&other) noexcept { swap(other); return *this; }
QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(QDir)
void swap(QDir &other) noexcept
{ qSwap(d_ptr, other.d_ptr); }

View File

@ -79,7 +79,7 @@ public:
~QFileInfo();
QFileInfo &operator=(const QFileInfo &fileinfo);
QFileInfo &operator=(QFileInfo &&other) noexcept { swap(other); return *this; }
QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(QFileInfo)
void swap(QFileInfo &other) noexcept
{ qSwap(d_ptr, other.d_ptr); }

View File

@ -68,7 +68,7 @@ public:
QProcessEnvironment();
QProcessEnvironment(const QProcessEnvironment &other);
~QProcessEnvironment();
QProcessEnvironment &operator=(QProcessEnvironment && other) noexcept { swap(other); return *this; }
QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(QProcessEnvironment)
QProcessEnvironment &operator=(const QProcessEnvironment &other);
void swap(QProcessEnvironment &other) noexcept { qSwap(d, other.d); }

View File

@ -62,7 +62,7 @@ public:
~QStorageInfo();
QStorageInfo &operator=(const QStorageInfo &other);
QStorageInfo &operator=(QStorageInfo &&other) noexcept { swap(other); return *this; }
QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(QStorageInfo)
inline void swap(QStorageInfo &other) noexcept
{ qSwap(d, other.d); }

View File

@ -184,8 +184,7 @@ public:
#endif
QUrl(QUrl &&other) noexcept : d(other.d)
{ other.d = nullptr; }
inline QUrl &operator=(QUrl &&other) noexcept
{ qSwap(d, other.d); return *this; }
QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(QUrl)
~QUrl();
inline void swap(QUrl &other) noexcept { qSwap(d, other.d); }

View File

@ -67,7 +67,7 @@ public:
QUrlQuery(const QUrlQuery &other);
QUrlQuery &operator=(const QUrlQuery &other);
QUrlQuery &operator=(QUrlQuery &&other) noexcept { swap(other); return *this; }
QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(QUrlQuery)
~QUrlQuery();
bool operator==(const QUrlQuery &other) const;

View File

@ -220,9 +220,8 @@ public:
{ return !operator==(other); }
QPersistentModelIndex &operator=(const QPersistentModelIndex &other);
inline QPersistentModelIndex(QPersistentModelIndex &&other) noexcept
: d(other.d) { other.d = nullptr; }
inline QPersistentModelIndex &operator=(QPersistentModelIndex &&other) noexcept
{ qSwap(d, other.d); return *this; }
: d(qExchange(other.d, nullptr)) {}
QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(QPersistentModelIndex)
inline void swap(QPersistentModelIndex &other) noexcept { qSwap(d, other.d); }
bool operator==(const QModelIndex &other) const;
bool operator!=(const QModelIndex &other) const;

View File

@ -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); }

View File

@ -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();

View File

@ -1597,6 +1597,14 @@ bool QMetaObject::invokeMethodImpl(QObject *object, QtPrivate::QSlotObjectBase *
that \a o was pointing to.
*/
/*!
\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

View File

@ -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; }

View File

@ -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); }

View File

@ -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; }

View File

@ -78,7 +78,7 @@ public:
QMimeType();
QMimeType(const QMimeType &other);
QMimeType &operator=(const QMimeType &other);
QMimeType &operator=(QMimeType &&other) noexcept { swap(other); return *this; }
QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(QMimeType)
void swap(QMimeType &other) noexcept
{
qSwap(d, other.d);

View File

@ -185,12 +185,7 @@ public:
other.container = nullptr;
}
QCborValue &operator=(const QCborValue &other);
QCborValue &operator=(QCborValue &&other) noexcept
{
QCborValue tmp(std::move(other));
swap(tmp);
return *this;
}
QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QCborValue)
void swap(QCborValue &other) noexcept
{

View File

@ -170,8 +170,7 @@ public:
QByteArray &operator=(const char *str);
inline QByteArray(QByteArray && other) noexcept
{ qSwap(d, other.d); }
inline QByteArray &operator=(QByteArray &&other) noexcept
{ qSwap(d, other.d); return *this; }
QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(QByteArray)
inline void swap(QByteArray &other) noexcept
{ qSwap(d, other.d); }

View File

@ -57,8 +57,7 @@ public:
QCollatorSortKey(const QCollatorSortKey &other);
~QCollatorSortKey();
QCollatorSortKey &operator=(const QCollatorSortKey &other);
inline QCollatorSortKey &operator=(QCollatorSortKey &&other) noexcept
{ swap(other); return *this; }
QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(QCollatorSortKey)
void swap(QCollatorSortKey &other) noexcept
{ d.swap(other.d); }
@ -88,8 +87,7 @@ public:
QCollator &operator=(const QCollator &);
QCollator(QCollator &&other) noexcept
: d(other.d) { other.d = nullptr; }
QCollator &operator=(QCollator &&other) noexcept
{ swap(other); return *this; }
QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QCollator)
void swap(QCollator &other) noexcept
{ qSwap(d, other.d); }

View File

@ -944,7 +944,7 @@ public:
QLocale(Language language, Country country = AnyCountry);
QLocale(Language language, Script script, Country country);
QLocale(const QLocale &other);
QLocale &operator=(QLocale &&other) noexcept { swap(other); return *this; }
QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(QLocale)
QLocale &operator=(const QLocale &other);
~QLocale();

View File

@ -88,8 +88,7 @@ public:
QRegularExpression(const QRegularExpression &re);
~QRegularExpression();
QRegularExpression &operator=(const QRegularExpression &re);
QRegularExpression &operator=(QRegularExpression &&re) noexcept
{ d.swap(re.d); return *this; }
QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(QRegularExpression)
void swap(QRegularExpression &other) noexcept { d.swap(other.d); }

View File

@ -337,8 +337,7 @@ public:
QString &operator=(QLatin1String latin1);
inline QString(QString &&other) noexcept
{ qSwap(d, other.d); }
inline QString &operator=(QString &&other) noexcept
{ qSwap(d, other.d); return *this; }
QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(QString)
inline void swap(QString &other) noexcept { qSwap(d, other.d); }
inline qsizetype size() const { return d.size; }
inline qsizetype count() const { return d.size; }

View File

@ -83,8 +83,7 @@ public:
: m_sem(sem), m_n(n) {}
QSemaphoreReleaser(QSemaphoreReleaser &&other) noexcept
: m_sem(other.cancel()), m_n(other.m_n) {}
QSemaphoreReleaser &operator=(QSemaphoreReleaser &&other) noexcept
{ QSemaphoreReleaser moved(std::move(other)); swap(moved); return *this; }
QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QSemaphoreReleaser)
~QSemaphoreReleaser()
{

View File

@ -271,7 +271,7 @@ public:
QDateTime(QDateTime &&other) noexcept;
~QDateTime();
QDateTime &operator=(QDateTime &&other) noexcept { swap(other); return *this; }
QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(QDateTime)
QDateTime &operator=(const QDateTime &other) noexcept;
void swap(QDateTime &other) noexcept { qSwap(d.d, other.d.d); }

View File

@ -99,7 +99,7 @@ public:
~QTimeZone();
QTimeZone &operator=(const QTimeZone &other);
QTimeZone &operator=(QTimeZone &&other) noexcept { swap(other); return *this; }
QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(QTimeZone)
void swap(QTimeZone &other) noexcept
{ d.swap(other.d); }

View File

@ -101,12 +101,7 @@ public:
other.size = 0;
}
QArrayDataPointer &operator=(QArrayDataPointer &&other) noexcept
{
QArrayDataPointer moved(std::move(other));
swap(moved);
return *this;
}
QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QArrayDataPointer)
DataOps &operator*() noexcept
{

View File

@ -61,8 +61,7 @@ public:
QBitArray(const QBitArray &other) : d(other.d) {}
inline QBitArray &operator=(const QBitArray &other) { d = other.d; return *this; }
inline QBitArray(QBitArray &&other) noexcept : d(std::move(other.d)) {}
inline QBitArray &operator=(QBitArray &&other) noexcept
{ qSwap(d, other.d); return *this; }
QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(QBitArray)
inline void swap(QBitArray &other) noexcept { qSwap(d, other.d); }

View File

@ -72,7 +72,7 @@ public:
~QCommandLineOption();
QCommandLineOption &operator=(const QCommandLineOption &other);
QCommandLineOption &operator=(QCommandLineOption &&other) noexcept { swap(other); return *this; }
QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(QCommandLineOption)
void swap(QCommandLineOption &other) noexcept
{ qSwap(d, other.d); }

View File

@ -94,8 +94,7 @@ public:
inline bool isDetached() const { return d->ref.loadRelaxed() == 1; }
QContiguousCache<T> &operator=(const QContiguousCache<T> &other);
inline QContiguousCache<T> &operator=(QContiguousCache<T> &&other) noexcept
{ qSwap(d, other.d); return *this; }
QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(QContiguousCache)
inline void swap(QContiguousCache<T> &other) noexcept { qSwap(d, other.d); }
template <typename U = T>

View File

@ -80,8 +80,7 @@ public:
QEasingCurve &operator=(const QEasingCurve &other)
{ if ( this != &other ) { QEasingCurve copy(other); swap(copy); } return *this; }
QEasingCurve(QEasingCurve &&other) noexcept : d_ptr(other.d_ptr) { other.d_ptr = nullptr; }
QEasingCurve &operator=(QEasingCurve &&other) noexcept
{ qSwap(d_ptr, other.d_ptr); return *this; }
QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(QEasingCurve)
void swap(QEasingCurve &other) noexcept { qSwap(d_ptr, other.d_ptr); }

View File

@ -750,15 +750,7 @@ public:
: d(std::exchange(other.d, nullptr))
{
}
QHash &operator=(QHash &&other) noexcept(std::is_nothrow_destructible<Node>::value)
{
if (d != other.d) {
if (d && !d->ref.deref())
delete d;
d = std::exchange(other.d, nullptr);
}
return *this;
}
QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QHash)
#ifdef Q_QDOC
template <typename InputIterator>
QHash(InputIterator f, InputIterator l);

View File

@ -94,11 +94,7 @@ public:
{
other.headOffset = other.tailOffset = 0;
}
inline QRingChunk &operator=(QRingChunk &&other) noexcept
{
swap(other);
return *this;
}
QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(QRingChunk)
inline void swap(QRingChunk &other) noexcept
{

View File

@ -111,13 +111,8 @@ public:
}
return *this;
}
QSharedDataPointer(QSharedDataPointer &&o) noexcept : d(o.d) { o.d = nullptr; }
inline QSharedDataPointer<T> &operator=(QSharedDataPointer<T> &&other) noexcept
{
QSharedDataPointer moved(std::move(other));
swap(moved);
return *this;
}
QSharedDataPointer(QSharedDataPointer &&o) noexcept : d(qExchange(o.d, nullptr)) {}
QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QSharedDataPointer)
inline bool operator!() const { return !d; }
@ -216,13 +211,8 @@ public:
}
return *this;
}
inline QExplicitlySharedDataPointer(QExplicitlySharedDataPointer &&o) noexcept : d(o.d) { o.d = nullptr; }
inline QExplicitlySharedDataPointer<T> &operator=(QExplicitlySharedDataPointer<T> &&other) noexcept
{
QExplicitlySharedDataPointer moved(std::move(other));
swap(moved);
return *this;
}
inline QExplicitlySharedDataPointer(QExplicitlySharedDataPointer &&o) noexcept : d(qExchange(o.d, nullptr)) {}
QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QExplicitlySharedDataPointer)
inline bool operator!() const { return !d; }

View File

@ -333,12 +333,7 @@ public:
other.d = nullptr;
other.value = nullptr;
}
QSharedPointer &operator=(QSharedPointer &&other) noexcept
{
QSharedPointer moved(std::move(other));
swap(moved);
return *this;
}
QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QSharedPointer)
template <class X, IfCompatible<X> = true>
QSharedPointer(QSharedPointer<X> &&other) noexcept
@ -563,8 +558,7 @@ public:
other.d = nullptr;
other.value = nullptr;
}
QWeakPointer &operator=(QWeakPointer &&other) noexcept
{ QWeakPointer moved(std::move(other)); swap(moved); return *this; }
QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QWeakPointer)
QWeakPointer &operator=(const QWeakPointer &other) noexcept
{
QWeakPointer copy(other);

View File

@ -126,10 +126,11 @@ class QVersionNumber
other.dummy = 1;
}
SegmentStorage &operator=(SegmentStorage &&other) noexcept
QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(SegmentStorage)
void swap(SegmentStorage &other) noexcept
{
qSwap(dummy, other.dummy);
return *this;
}
explicit SegmentStorage(QList<int> &&seg)

View File

@ -62,14 +62,13 @@ public:
QIcon(const QPixmap &pixmap);
QIcon(const QIcon &other);
QIcon(QIcon &&other) noexcept
: d(other.d)
{ other.d = nullptr; }
: d(qExchange(other.d, nullptr))
{}
explicit QIcon(const QString &fileName); // file or resource name
explicit QIcon(QIconEngine *engine);
~QIcon();
QIcon &operator=(const QIcon &other);
inline QIcon &operator=(QIcon &&other) noexcept
{ swap(other); return *this; }
QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QIcon)
inline void swap(QIcon &other) noexcept
{ qSwap(d, other.d); }
bool operator==(const QIcon &) const = delete;

View File

@ -125,13 +125,12 @@ public:
QImage(const QImage &);
inline QImage(QImage &&other) noexcept
: QPaintDevice(), d(nullptr)
{ qSwap(d, other.d); }
: QPaintDevice(), d(qExchange(other.d, nullptr))
{}
~QImage();
QImage &operator=(const QImage &);
inline QImage &operator=(QImage &&other) noexcept
{ qSwap(d, other.d); return *this; }
QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QImage)
inline void swap(QImage &other) noexcept
{ qSwap(d, other.d); }

View File

@ -77,8 +77,7 @@ public:
void setBoundingRect(const QRect &r);
QPicture& operator=(const QPicture &p);
inline QPicture &operator=(QPicture &&other) noexcept
{ qSwap(d_ptr, other.d_ptr); return *this; }
QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(QPicture)
inline void swap(QPicture &other) noexcept
{ d_ptr.swap(other.d_ptr); }
void detach();

View File

@ -75,8 +75,7 @@ public:
~QPixmap();
QPixmap &operator=(const QPixmap &);
inline QPixmap &operator=(QPixmap &&other) noexcept
{ qSwap(data, other.data); return *this; }
QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QPixmap)
inline void swap(QPixmap &other) noexcept
{ qSwap(data, other.data); }
bool operator==(const QPixmap &) const = delete;

View File

@ -87,9 +87,8 @@ public:
QCursor(const QCursor &cursor);
~QCursor();
QCursor &operator=(const QCursor &cursor);
QCursor(QCursor &&other) noexcept : d(other.d) { other.d = nullptr; }
inline QCursor &operator=(QCursor &&other) noexcept
{ swap(other); return *this; }
QCursor(QCursor &&other) noexcept : d(qExchange(other.d, nullptr)) {}
QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QCursor)
void swap(QCursor &other) noexcept { qSwap(d, other.d); }

View File

@ -185,7 +185,7 @@ public:
operator QVariant() const;
QKeyCombination operator[](uint i) const;
QKeySequence &operator=(const QKeySequence &other);
QKeySequence &operator=(QKeySequence &&other) noexcept { swap(other); return *this; }
QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(QKeySequence)
void swap(QKeySequence &other) noexcept { qSwap(d, other.d); }
bool operator==(const QKeySequence &other) const;

View File

@ -68,12 +68,9 @@ public:
~QPalette();
QPalette &operator=(const QPalette &palette);
QPalette(QPalette &&other) noexcept
: d(other.d), data(other.data)
{ other.d = nullptr; }
inline QPalette &operator=(QPalette &&other) noexcept
{
swap(other); return *this;
}
: d(qExchange(other.d, nullptr)), data(other.data)
{}
QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(QPalette)
void swap(QPalette &other) noexcept
{

View File

@ -78,8 +78,7 @@ public:
~QBrush();
QBrush &operator=(const QBrush &brush);
inline QBrush &operator=(QBrush &&other) noexcept
{ qSwap(d, other.d); return *this; }
QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(QBrush)
inline void swap(QBrush &other) noexcept
{ qSwap(d, other.d); }

View File

@ -95,12 +95,7 @@ public:
QColorSpace(QColorSpace &&colorSpace) noexcept
: d_ptr(qExchange(colorSpace.d_ptr, nullptr))
{ }
QColorSpace &operator=(QColorSpace &&colorSpace) noexcept
{
// Make the deallocation of this->d_ptr happen in ~QColorSpace()
QColorSpace(std::move(colorSpace)).swap(*this);
return *this;
}
QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QColorSpace)
void swap(QColorSpace &colorSpace) noexcept
{ qSwap(d_ptr, colorSpace.d_ptr); }

View File

@ -64,11 +64,7 @@ public:
QColorTransform{other}.swap(*this);
return *this;
}
QColorTransform &operator=(QColorTransform &&other) noexcept
{
QColorTransform{std::move(other)}.swap(*this);
return *this;
}
QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QColorTransform)
void swap(QColorTransform &other) noexcept { qSwap(d, other.d); }

View File

@ -81,7 +81,7 @@ public:
const QMarginsF &margins, Unit units = Point,
const QMarginsF &minMargins = QMarginsF(0, 0, 0, 0));
QPageLayout(const QPageLayout &other);
QPageLayout &operator=(QPageLayout &&other) noexcept { swap(other); return *this; }
QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(QPageLayout)
QPageLayout &operator=(const QPageLayout &other);
~QPageLayout();

View File

@ -232,7 +232,7 @@ public:
const QString &name = QString(),
SizeMatchPolicy matchPolicy = FuzzyMatch);
QPageSize(const QPageSize &other);
QPageSize &operator=(QPageSize &&other) noexcept { swap(other); return *this; }
QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(QPageSize)
QPageSize &operator=(const QPageSize &other);
~QPageSize();

View File

@ -92,8 +92,7 @@ public:
explicit QPainterPath(const QPointF &startPoint);
QPainterPath(const QPainterPath &other);
QPainterPath &operator=(const QPainterPath &other);
inline QPainterPath &operator=(QPainterPath &&other) noexcept
{ qSwap(d_ptr, other.d_ptr); return *this; }
QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(QPainterPath)
~QPainterPath();
inline void swap(QPainterPath &other) noexcept { d_ptr.swap(other.d_ptr); }

View File

@ -71,9 +71,8 @@ public:
QPen &operator=(const QPen &pen) noexcept;
QPen(QPen &&other) noexcept
: d(other.d) { other.d = nullptr; }
QPen &operator=(QPen &&other) noexcept
{ qSwap(d, other.d); return *this; }
: d(qExchange(other.d, nullptr)) {}
QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(QPen)
void swap(QPen &other) noexcept { qSwap(d, other.d); }
Qt::PenStyle style() const;

View File

@ -70,12 +70,11 @@ public:
QRegion(const QPolygon &pa, Qt::FillRule fillRule = Qt::OddEvenFill);
QRegion(const QRegion &region);
QRegion(QRegion &&other) noexcept
: d(other.d) { other.d = const_cast<QRegionData*>(&shared_empty); }
: d(qExchange(other.d, const_cast<QRegionData*>(&shared_empty))) {}
QRegion(const QBitmap &bitmap);
~QRegion();
QRegion &operator=(const QRegion &);
inline QRegion &operator=(QRegion &&other) noexcept
{ qSwap(d, other.d); return *this; }
QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(QRegion);
inline void swap(QRegion &other) noexcept { qSwap(d, other.d); }
bool isEmpty() const;
bool isNull() const;

View File

@ -252,8 +252,7 @@ public:
bool operator<(const QFont &) const;
operator QVariant() const;
bool isCopyOf(const QFont &) const;
inline QFont &operator=(QFont &&other) noexcept
{ qSwap(d, other.d); qSwap(resolve_mask, other.resolve_mask); return *this; }
QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(QFont)
QString key() const;

View File

@ -304,14 +304,11 @@ public:
explicit Holder(void *p, qt_destroy_func_t d) : ptr(p), destroy_func(d) {}
~Holder() { if (ptr && destroy_func) destroy_func(ptr); }
Holder(Holder &&other) noexcept
: ptr(other.ptr),
destroy_func(other.destroy_func)
: ptr(qExchange(other.ptr, nullptr)),
destroy_func(qExchange(other.destroy_func, nullptr))
{
other.ptr = nullptr;
other.destroy_func = nullptr;
}
Holder &operator=(Holder &&other) noexcept
{ swap(other); return *this; }
QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(Holder)
void swap(Holder &other) noexcept
{

View File

@ -60,8 +60,7 @@ public:
~QFontMetrics();
QFontMetrics &operator=(const QFontMetrics &);
inline QFontMetrics &operator=(QFontMetrics &&other) noexcept
{ qSwap(d, other.d); return *this; }
QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(QFontMetrics)
void swap(QFontMetrics &other) noexcept
{ qSwap(d, other.d); }
@ -131,8 +130,7 @@ public:
QFontMetricsF &operator=(const QFontMetricsF &);
QFontMetricsF &operator=(const QFontMetrics &);
inline QFontMetricsF &operator=(QFontMetricsF &&other) noexcept
{ qSwap(d, other.d); return *this; }
QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(QFontMetricsF)
void swap(QFontMetricsF &other) noexcept { qSwap(d, other.d); }

View File

@ -66,7 +66,7 @@ public:
QGlyphRun();
QGlyphRun(const QGlyphRun &other);
QGlyphRun &operator=(QGlyphRun &&other) noexcept { swap(other); return *this; }
QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(QGlyphRun)
QGlyphRun &operator=(const QGlyphRun &other);
~QGlyphRun();

View File

@ -79,7 +79,7 @@ public:
qreal pixelSize,
QFont::HintingPreference hintingPreference = QFont::PreferDefaultHinting);
QRawFont(const QRawFont &other);
QRawFont &operator=(QRawFont &&other) noexcept { swap(other); return *this; }
QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(QRawFont)
QRawFont &operator=(const QRawFont &other);
~QRawFont();

View File

@ -64,7 +64,7 @@ public:
QStaticText();
explicit QStaticText(const QString &text);
QStaticText(const QStaticText &other);
QStaticText &operator=(QStaticText &&other) noexcept { swap(other); return *this; }
QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(QStaticText)
QStaticText &operator=(const QStaticText &);
~QStaticText();

View File

@ -73,7 +73,7 @@ public:
explicit QTextCursor(QTextFrame *frame);
explicit QTextCursor(const QTextBlock &block);
QTextCursor(const QTextCursor &cursor);
QTextCursor &operator=(QTextCursor &&other) noexcept { swap(other); return *this; }
QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(QTextCursor)
QTextCursor &operator=(const QTextCursor &other);
~QTextCursor();

View File

@ -109,7 +109,7 @@ public:
QOpenGLDebugMessage(const QOpenGLDebugMessage &debugMessage);
QOpenGLDebugMessage &operator=(const QOpenGLDebugMessage &debugMessage);
QOpenGLDebugMessage &operator=(QOpenGLDebugMessage &&other) noexcept { swap(other); return *this; }
QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(QOpenGLDebugMessage)
~QOpenGLDebugMessage();
void swap(QOpenGLDebugMessage &other) noexcept { qSwap(d, other.d); }

View File

@ -55,8 +55,7 @@ class Q_OPENGL_EXPORT QOpenGLPixelTransferOptions
public:
QOpenGLPixelTransferOptions();
QOpenGLPixelTransferOptions(const QOpenGLPixelTransferOptions &);
QOpenGLPixelTransferOptions &operator=(QOpenGLPixelTransferOptions &&other) noexcept
{ swap(other); return *this; }
QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(QOpenGLPixelTransferOptions)
QOpenGLPixelTransferOptions &operator=(const QOpenGLPixelTransferOptions &);
~QOpenGLPixelTransferOptions();