QVariant: make many more QtCore types nothrow-copyable

All of those are implicitly-shared Qt data types whose copy constructors
can't throw and have wide contracts (there aren't even any assertions
for validity in any of them). These are all types with a QVariant
implicit constructor, except for QCborValue, which is updated on this
list so QJsonValue (which has a QVariant constructor) is also
legitimately noexcept.

To ensure we haven't made a mistake, the Private constructor checks
again.

Change-Id: I3859764fed084846bcb0fffd17044d8319a45e1f
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
This commit is contained in:
Thiago Macieira 2022-07-22 17:23:08 -07:00
parent 3fcb0237dc
commit e9c9e9225c
18 changed files with 71 additions and 94 deletions

View File

@ -1837,7 +1837,7 @@ QUrl::QUrl() : d(nullptr)
/*! /*!
Constructs a copy of \a other. Constructs a copy of \a other.
*/ */
QUrl::QUrl(const QUrl &other) : d(other.d) QUrl::QUrl(const QUrl &other) noexcept : d(other.d)
{ {
if (d) if (d)
d->ref.ref(); d->ref.ref();
@ -3227,7 +3227,7 @@ bool QUrl::operator !=(const QUrl &url) const
/*! /*!
Assigns the specified \a url to this object. Assigns the specified \a url to this object.
*/ */
QUrl &QUrl::operator =(const QUrl &url) QUrl &QUrl::operator =(const QUrl &url) noexcept
{ {
if (!d) { if (!d) {
if (url.d) { if (url.d) {

View File

@ -143,8 +143,8 @@ public:
#endif #endif
QUrl(); QUrl();
QUrl(const QUrl &copy); QUrl(const QUrl &copy) noexcept;
QUrl &operator =(const QUrl &copy); QUrl &operator =(const QUrl &copy) noexcept;
#ifdef QT_NO_URL_CAST_FROM_STRING #ifdef QT_NO_URL_CAST_FROM_STRING
explicit QUrl(const QString &url, ParsingMode mode = TolerantMode); explicit QUrl(const QString &url, ParsingMode mode = TolerantMode);
#else #else

View File

@ -335,13 +335,21 @@ template <typename T> inline
QVariant::Private::Private(std::piecewise_construct_t, const T &t) QVariant::Private::Private(std::piecewise_construct_t, const T &t)
: is_shared(!CanUseInternalSpace<T>), is_null(std::is_same_v<T, std::nullptr_t>) : is_shared(!CanUseInternalSpace<T>), is_null(std::is_same_v<T, std::nullptr_t>)
{ {
// confirm noexceptness
static constexpr bool isNothrowQVariantConstructible = noexcept(QVariant(t));
static constexpr bool isNothrowCopyConstructible = std::is_nothrow_copy_constructible_v<T>;
static constexpr bool isNothrowCopyAssignable = std::is_nothrow_copy_assignable_v<T>;
const QtPrivate::QMetaTypeInterface *iface = QtPrivate::qMetaTypeInterfaceForType<T>(); const QtPrivate::QMetaTypeInterface *iface = QtPrivate::qMetaTypeInterfaceForType<T>();
Q_ASSERT((quintptr(iface) & 0x3) == 0); Q_ASSERT((quintptr(iface) & 0x3) == 0);
packedType = quintptr(iface) >> 2; packedType = quintptr(iface) >> 2;
if constexpr (CanUseInternalSpace<T>) { if constexpr (CanUseInternalSpace<T>) {
static_assert(isNothrowQVariantConstructible == isNothrowCopyConstructible);
static_assert(isNothrowQVariantConstructible == isNothrowCopyAssignable);
new (data.data) T(t); new (data.data) T(t);
} else { } else {
static_assert(!isNothrowQVariantConstructible); // we allocate memory, even if T doesn't
data.shared = QVariant::PrivateShared::create(QtPrivate::qMetaTypeInterfaceForType<T>()); data.shared = QVariant::PrivateShared::create(QtPrivate::qMetaTypeInterfaceForType<T>());
new (data.shared->data()) T(t); new (data.shared->data()) T(t);
} }
@ -705,7 +713,7 @@ QVariant::QVariant(const QVariant &p)
*/ */
/*! /*!
\fn QVariant::QVariant(const QBitArray &val) \fn QVariant::QVariant(const QBitArray &val) noexcept
Constructs a new variant with a bitarray value, \a val. Constructs a new variant with a bitarray value, \a val.
*/ */
@ -759,7 +767,7 @@ QVariant::QVariant(const QVariant &p)
*/ */
/*! /*!
\fn QVariant::QVariant(const QUrl &val) \fn QVariant::QVariant(const QUrl &val) noexcept
Constructs a new variant with a url value of \a val. Constructs a new variant with a url value of \a val.
*/ */
@ -821,13 +829,13 @@ QVariant::QVariant(const QVariant &p)
*/ */
/*! /*!
\fn QVariant::QVariant(const QLocale &l) \fn QVariant::QVariant(const QLocale &l) noexcept
Constructs a new variant with a locale value, \a l. Constructs a new variant with a locale value, \a l.
*/ */
/*! /*!
\fn QVariant::QVariant(const QRegularExpression &re) \fn QVariant::QVariant(const QRegularExpression &re) noexcept
\since 5.0 \since 5.0
@ -876,7 +884,7 @@ QVariant::QVariant(double val) noexcept : d(std::piecewise_construct_t{}, val) {
QVariant::QVariant(float val) noexcept : d(std::piecewise_construct_t{}, val) {} QVariant::QVariant(float val) noexcept : d(std::piecewise_construct_t{}, val) {}
QVariant::QVariant(const QByteArray &val) noexcept : d(std::piecewise_construct_t{}, val) {} QVariant::QVariant(const QByteArray &val) noexcept : d(std::piecewise_construct_t{}, val) {}
QVariant::QVariant(const QBitArray &val) : d(std::piecewise_construct_t{}, val) {} QVariant::QVariant(const QBitArray &val) noexcept : d(std::piecewise_construct_t{}, val) {}
QVariant::QVariant(const QString &val) noexcept : d(std::piecewise_construct_t{}, val) {} QVariant::QVariant(const QString &val) noexcept : d(std::piecewise_construct_t{}, val) {}
QVariant::QVariant(QChar val) noexcept : d(std::piecewise_construct_t{}, val) {} QVariant::QVariant(QChar val) noexcept : d(std::piecewise_construct_t{}, val) {}
QVariant::QVariant(const QStringList &val) noexcept : d(std::piecewise_construct_t{}, val) {} QVariant::QVariant(const QStringList &val) noexcept : d(std::piecewise_construct_t{}, val) {}
@ -913,17 +921,19 @@ QVariant::QVariant(QSizeF s) noexcept(Private::FitsInInternalSize<sizeof(qreal)
: d(std::piecewise_construct_t{}, s) {} : d(std::piecewise_construct_t{}, s) {}
#endif #endif
#ifndef QT_BOOTSTRAPPED #ifndef QT_BOOTSTRAPPED
QVariant::QVariant(const QUrl &u) : d(std::piecewise_construct_t{}, u) {} QVariant::QVariant(const QUrl &u) noexcept : d(std::piecewise_construct_t{}, u) {}
#endif #endif
QVariant::QVariant(const QLocale &l) : d(std::piecewise_construct_t{}, l) {} QVariant::QVariant(const QLocale &l) noexcept : d(std::piecewise_construct_t{}, l) {}
#if QT_CONFIG(regularexpression) #if QT_CONFIG(regularexpression)
QVariant::QVariant(const QRegularExpression &re) : d(std::piecewise_construct_t{}, re) {} QVariant::QVariant(const QRegularExpression &re) noexcept : d(std::piecewise_construct_t{}, re) {}
#endif // QT_CONFIG(regularexpression) #endif // QT_CONFIG(regularexpression)
QVariant::QVariant(QUuid uuid) noexcept(Private::FitsInInternalSize<16>) : d(std::piecewise_construct_t{}, uuid) {} QVariant::QVariant(QUuid uuid) noexcept(Private::FitsInInternalSize<16>) : d(std::piecewise_construct_t{}, uuid) {}
#ifndef QT_BOOTSTRAPPED #ifndef QT_BOOTSTRAPPED
QVariant::QVariant(const QJsonValue &jsonValue) : d(std::piecewise_construct_t{}, jsonValue) {} QVariant::QVariant(const QJsonValue &jsonValue) noexcept(Private::FitsInInternalSize<sizeof(CborValueStandIn)>)
QVariant::QVariant(const QJsonObject &jsonObject) : d(std::piecewise_construct_t{}, jsonObject) {} : d(std::piecewise_construct_t{}, jsonValue)
QVariant::QVariant(const QJsonArray &jsonArray) : d(std::piecewise_construct_t{}, jsonArray) {} { static_assert(sizeof(CborValueStandIn) == sizeof(QJsonValue)); }
QVariant::QVariant(const QJsonObject &jsonObject) noexcept : d(std::piecewise_construct_t{}, jsonObject) {}
QVariant::QVariant(const QJsonArray &jsonArray) noexcept : d(std::piecewise_construct_t{}, jsonArray) {}
QVariant::QVariant(const QJsonDocument &jsonDocument) : d(std::piecewise_construct_t{}, jsonDocument) {} QVariant::QVariant(const QJsonDocument &jsonDocument) : d(std::piecewise_construct_t{}, jsonDocument) {}
#endif // QT_BOOTSTRAPPED #endif // QT_BOOTSTRAPPED
#if QT_CONFIG(itemmodel) #if QT_CONFIG(itemmodel)

View File

@ -56,6 +56,7 @@ inline T qvariant_cast(const QVariant &);
class Q_CORE_EXPORT QVariant class Q_CORE_EXPORT QVariant
{ {
struct CborValueStandIn { qint64 n; void *c; int t; };
public: public:
struct PrivateShared struct PrivateShared
{ {
@ -206,7 +207,7 @@ public:
QVariant(float f) noexcept; QVariant(float f) noexcept;
QVariant(const QByteArray &bytearray) noexcept; QVariant(const QByteArray &bytearray) noexcept;
QVariant(const QBitArray &bitarray); QVariant(const QBitArray &bitarray) noexcept;
QVariant(const QString &string) noexcept; QVariant(const QString &string) noexcept;
QVariant(const QStringList &stringlist) noexcept; QVariant(const QStringList &stringlist) noexcept;
QVariant(QChar qchar) noexcept; QVariant(QChar qchar) noexcept;
@ -226,19 +227,19 @@ public:
QVariant(QRect rect) noexcept(Private::FitsInInternalSize<sizeof(int) * 4>); QVariant(QRect rect) noexcept(Private::FitsInInternalSize<sizeof(int) * 4>);
QVariant(QRectF rect) noexcept(Private::FitsInInternalSize<sizeof(qreal) * 4>); QVariant(QRectF rect) noexcept(Private::FitsInInternalSize<sizeof(qreal) * 4>);
#endif #endif
QVariant(const QLocale &locale); QVariant(const QLocale &locale) noexcept;
#if QT_CONFIG(regularexpression) #if QT_CONFIG(regularexpression)
QVariant(const QRegularExpression &re); QVariant(const QRegularExpression &re) noexcept;
#endif // QT_CONFIG(regularexpression) #endif // QT_CONFIG(regularexpression)
#if QT_CONFIG(easingcurve) #if QT_CONFIG(easingcurve)
QVariant(const QEasingCurve &easing); QVariant(const QEasingCurve &easing);
#endif #endif
QVariant(QUuid uuid) noexcept(Private::FitsInInternalSize<16>); QVariant(QUuid uuid) noexcept(Private::FitsInInternalSize<16>);
#ifndef QT_BOOTSTRAPPED #ifndef QT_BOOTSTRAPPED
QVariant(const QUrl &url); QVariant(const QUrl &url) noexcept;
QVariant(const QJsonValue &jsonValue); QVariant(const QJsonValue &jsonValue) noexcept(Private::FitsInInternalSize<sizeof(CborValueStandIn)>);
QVariant(const QJsonObject &jsonObject); QVariant(const QJsonObject &jsonObject) noexcept;
QVariant(const QJsonArray &jsonArray); QVariant(const QJsonArray &jsonArray) noexcept;
QVariant(const QJsonDocument &jsonDocument); QVariant(const QJsonDocument &jsonDocument);
#endif // QT_BOOTSTRAPPED #endif // QT_BOOTSTRAPPED
#if QT_CONFIG(itemmodel) #if QT_CONFIG(itemmodel)

View File

@ -1805,7 +1805,7 @@ QCborValue::QCborValue(QCborTag tag, const QCborValue &tv)
/*! /*!
Copies the contents of \a other into this object. Copies the contents of \a other into this object.
*/ */
QCborValue::QCborValue(const QCborValue &other) QCborValue::QCborValue(const QCborValue &other) noexcept
: n(other.n), container(other.container), t(other.t) : n(other.n), container(other.container), t(other.t)
{ {
if (container) if (container)
@ -1899,7 +1899,7 @@ void QCborValue::dispose()
/*! /*!
Replaces the contents of this QCborObject with a copy of \a other. Replaces the contents of this QCborObject with a copy of \a other.
*/ */
QCborValue &QCborValue::operator=(const QCborValue &other) QCborValue &QCborValue::operator=(const QCborValue &other) noexcept
{ {
n = other.n; n = other.n;
assignContainer(container, other.container); assignContainer(container, other.container);

View File

@ -139,12 +139,12 @@ public:
// make sure const char* doesn't go call the bool constructor // make sure const char* doesn't go call the bool constructor
QCborValue(const void *) = delete; QCborValue(const void *) = delete;
QCborValue(const QCborValue &other); QCborValue(const QCborValue &other) noexcept;
QCborValue(QCborValue &&other) noexcept QCborValue(QCborValue &&other) noexcept
: n(other.n), container(qExchange(other.container, nullptr)), t(qExchange(other.t, Undefined)) : n(other.n), container(qExchange(other.container, nullptr)), t(qExchange(other.t, Undefined))
{ {
} }
QCborValue &operator=(const QCborValue &other); QCborValue &operator=(const QCborValue &other) noexcept;
QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QCborValue) QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QCborValue)
void swap(QCborValue &other) noexcept void swap(QCborValue &other) noexcept

View File

@ -138,11 +138,13 @@ QJsonArray::QJsonArray(std::initializer_list<QJsonValue> args)
Since QJsonArray is implicitly shared, the copy is shallow Since QJsonArray is implicitly shared, the copy is shallow
as long as the object doesn't get modified. as long as the object doesn't get modified.
*/ */
QJsonArray::QJsonArray(const QJsonArray &other) QJsonArray::QJsonArray(const QJsonArray &other) noexcept = default;
{
a = other.a;
}
/*!
\since 5.10
Move-constructs a QJsonArray from \a other.
*/
QJsonArray::QJsonArray(QJsonArray &&other) noexcept QJsonArray::QJsonArray(QJsonArray &&other) noexcept
: a(other.a) : a(other.a)
{ {
@ -152,18 +154,7 @@ QJsonArray::QJsonArray(QJsonArray &&other) noexcept
/*! /*!
Assigns \a other to this array. Assigns \a other to this array.
*/ */
QJsonArray &QJsonArray::operator =(const QJsonArray &other) QJsonArray &QJsonArray::operator =(const QJsonArray &other) noexcept = default;
{
a = other.a;
return *this;
}
/*!
\fn QJsonArray::QJsonArray(QJsonArray &&other)
\since 5.10
Move-constructs a QJsonArray from \a other.
*/
/*! /*!
\fn QJsonArray &QJsonArray::operator =(QJsonArray &&other) \fn QJsonArray &QJsonArray::operator =(QJsonArray &&other)

View File

@ -23,8 +23,8 @@ public:
~QJsonArray(); ~QJsonArray();
QJsonArray(const QJsonArray &other); QJsonArray(const QJsonArray &other) noexcept;
QJsonArray &operator =(const QJsonArray &other); QJsonArray &operator =(const QJsonArray &other) noexcept;
QJsonArray(QJsonArray &&other) noexcept; QJsonArray(QJsonArray &&other) noexcept;

View File

@ -122,11 +122,13 @@ QJsonObject::QJsonObject(std::initializer_list<QPair<QString, QJsonValue> > args
Since QJsonObject is implicitly shared, the copy is shallow Since QJsonObject is implicitly shared, the copy is shallow
as long as the object does not get modified. as long as the object does not get modified.
*/ */
QJsonObject::QJsonObject(const QJsonObject &other) QJsonObject::QJsonObject(const QJsonObject &other) noexcept = default;
{
o = other.o;
}
/*!
\since 5.10
Move-constructs a QJsonObject from \a other.
*/
QJsonObject::QJsonObject(QJsonObject &&other) noexcept QJsonObject::QJsonObject(QJsonObject &&other) noexcept
: o(other.o) : o(other.o)
{ {
@ -136,18 +138,8 @@ QJsonObject::QJsonObject(QJsonObject &&other) noexcept
/*! /*!
Assigns \a other to this object. Assigns \a other to this object.
*/ */
QJsonObject &QJsonObject::operator =(const QJsonObject &other) QJsonObject &QJsonObject::operator =(const QJsonObject &other) noexcept = default;
{
o = other.o;
return *this;
}
/*!
\fn QJsonObject::QJsonObject(QJsonObject &&other)
\since 5.10
Move-constructs a QJsonObject from \a other.
*/
/*! /*!
\fn QJsonObject &QJsonObject::operator =(QJsonObject &&other) \fn QJsonObject &QJsonObject::operator =(QJsonObject &&other)

View File

@ -25,8 +25,8 @@ public:
~QJsonObject(); ~QJsonObject();
QJsonObject(const QJsonObject &other); QJsonObject(const QJsonObject &other) noexcept;
QJsonObject &operator =(const QJsonObject &other); QJsonObject &operator =(const QJsonObject &other) noexcept;
QJsonObject(QJsonObject &&other) noexcept; QJsonObject(QJsonObject &&other) noexcept;

View File

@ -247,15 +247,12 @@ QJsonValue::~QJsonValue() = default;
/*! /*!
Creates a copy of \a other. Creates a copy of \a other.
*/ */
QJsonValue::QJsonValue(const QJsonValue &other) QJsonValue::QJsonValue(const QJsonValue &other) noexcept = default;
: value(other.value)
{
}
/*! /*!
Assigns the value stored in \a other to this object. Assigns the value stored in \a other to this object.
*/ */
QJsonValue &QJsonValue::operator =(const QJsonValue &other) QJsonValue &QJsonValue::operator =(const QJsonValue &other) noexcept
{ {
QJsonValue copy(other); QJsonValue copy(other);
swap(copy); swap(copy);

View File

@ -51,8 +51,8 @@ public:
~QJsonValue(); ~QJsonValue();
QJsonValue(const QJsonValue &other); QJsonValue(const QJsonValue &other) noexcept;
QJsonValue &operator =(const QJsonValue &other); QJsonValue &operator =(const QJsonValue &other) noexcept;
QJsonValue(QJsonValue &&other) noexcept; QJsonValue(QJsonValue &&other) noexcept;

View File

@ -1072,10 +1072,7 @@ QLocale::QLocale(Language language, Script script, Territory territory)
Constructs a QLocale object as a copy of \a other. Constructs a QLocale object as a copy of \a other.
*/ */
QLocale::QLocale(const QLocale &other) QLocale::QLocale(const QLocale &other) noexcept = default;
{
d = other.d;
}
/*! /*!
Destructor Destructor
@ -1090,11 +1087,7 @@ QLocale::~QLocale()
to this QLocale object. to this QLocale object.
*/ */
QLocale &QLocale::operator=(const QLocale &other) QLocale &QLocale::operator=(const QLocale &other) noexcept = default;
{
d = other.d;
return *this;
}
/*! /*!
\internal \internal

View File

@ -896,9 +896,9 @@ public:
explicit QLocale(QStringView name); explicit QLocale(QStringView name);
QLocale(Language language, Territory territory); QLocale(Language language, Territory territory);
QLocale(Language language, Script script = AnyScript, Territory territory = AnyTerritory); QLocale(Language language, Script script = AnyScript, Territory territory = AnyTerritory);
QLocale(const QLocale &other); QLocale(const QLocale &other) noexcept;
QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(QLocale) QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(QLocale)
QLocale &operator=(const QLocale &other); QLocale &operator=(const QLocale &other) noexcept;
~QLocale(); ~QLocale();
void swap(QLocale &other) noexcept { d.swap(other.d); } void swap(QLocale &other) noexcept { d.swap(other.d); }

View File

@ -1354,10 +1354,7 @@ QRegularExpression::QRegularExpression(const QString &pattern, PatternOptions op
\sa operator=() \sa operator=()
*/ */
QRegularExpression::QRegularExpression(const QRegularExpression &re) QRegularExpression::QRegularExpression(const QRegularExpression &re) noexcept = default;
: d(re.d)
{
}
/*! /*!
\fn QRegularExpression::QRegularExpression(QRegularExpression &&re) \fn QRegularExpression::QRegularExpression(QRegularExpression &&re)
@ -1386,11 +1383,7 @@ QT_DEFINE_QESDP_SPECIALIZATION_DTOR(QRegularExpressionPrivate)
Assigns the regular expression \a re to this object, and returns a reference Assigns the regular expression \a re to this object, and returns a reference
to the copy. Both the pattern and the pattern options are copied. to the copy. Both the pattern and the pattern options are copied.
*/ */
QRegularExpression &QRegularExpression::operator=(const QRegularExpression &re) QRegularExpression &QRegularExpression::operator=(const QRegularExpression &re) noexcept = default;
{
d = re.d;
return *this;
}
/*! /*!
\fn void QRegularExpression::swap(QRegularExpression &other) \fn void QRegularExpression::swap(QRegularExpression &other)

View File

@ -50,10 +50,10 @@ public:
QRegularExpression(); QRegularExpression();
explicit QRegularExpression(const QString &pattern, PatternOptions options = NoPatternOption); explicit QRegularExpression(const QString &pattern, PatternOptions options = NoPatternOption);
QRegularExpression(const QRegularExpression &re); QRegularExpression(const QRegularExpression &re) noexcept;
QRegularExpression(QRegularExpression &&re) = default; QRegularExpression(QRegularExpression &&re) = default;
~QRegularExpression(); ~QRegularExpression();
QRegularExpression &operator=(const QRegularExpression &re); QRegularExpression &operator=(const QRegularExpression &re) noexcept;
QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(QRegularExpression) QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(QRegularExpression)
void swap(QRegularExpression &other) noexcept { d.swap(other.d); } void swap(QRegularExpression &other) noexcept { d.swap(other.d); }

View File

@ -453,7 +453,7 @@ quint32 QBitArray::toUInt32(QSysInfo::Endian endianness, bool *ok) const noexcep
\overload \overload
*/ */
/*! \fn QBitArray::QBitArray(const QBitArray &other) /*! \fn QBitArray::QBitArray(const QBitArray &other) noexcept
Constructs a copy of \a other. Constructs a copy of \a other.
@ -465,7 +465,7 @@ quint32 QBitArray::toUInt32(QSysInfo::Endian endianness, bool *ok) const noexcep
\sa operator=() \sa operator=()
*/ */
/*! \fn QBitArray &QBitArray::operator=(const QBitArray &other) /*! \fn QBitArray &QBitArray::operator=(const QBitArray &other) noexcept
Assigns \a other to this bit array and returns a reference to Assigns \a other to this bit array and returns a reference to
this bit array. this bit array.

View File

@ -21,8 +21,8 @@ class Q_CORE_EXPORT QBitArray
public: public:
inline QBitArray() noexcept {} inline QBitArray() noexcept {}
explicit QBitArray(qsizetype size, bool val = false); explicit QBitArray(qsizetype size, bool val = false);
QBitArray(const QBitArray &other) : d(other.d) {} QBitArray(const QBitArray &other) noexcept : d(other.d) {}
inline QBitArray &operator=(const QBitArray &other) { d = other.d; return *this; } inline QBitArray &operator=(const QBitArray &other) noexcept { d = other.d; return *this; }
inline QBitArray(QBitArray &&other) noexcept : d(std::move(other.d)) {} inline QBitArray(QBitArray &&other) noexcept : d(std::move(other.d)) {}
QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(QBitArray) QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(QBitArray)