QBitArray: replace the member operator~ with a hidden friend

Which takes the array to be inverted by value, so we get free move
semantics and allowing us to perform the negation in-place.

[ChangeLog][Potentially Source-Incompatible Changes] The bitwise AND,
OR, XOR, and NOT operator functions on QBitArray are now hidden
friends. This may cause source-incompatibility in unusual coding styles
(like 'array.operator~()') or with classes that have a casting 'operator
QBitArray()'.

Change-Id: I85b3fc2dd45c4693be13fffd1795ba1fbaf23769
Reviewed-by: Marc Mutz <marc.mutz@qt.io>
This commit is contained in:
Thiago Macieira 2023-11-08 10:44:39 -08:00
parent 9b176281df
commit db991cb4e1
4 changed files with 28 additions and 6 deletions

View File

@ -618,6 +618,13 @@ QStringView QXmlStreamAttributes::value(QLatin1StringView qualifiedName) const
#if QT_CORE_REMOVED_SINCE(6, 7) #if QT_CORE_REMOVED_SINCE(6, 7)
#include "qbitarray.h"
QBitArray QBitArray::operator~() const
{
return QBitArray(*this).inverted_inplace();
}
#include "qbytearray.h" #include "qbytearray.h"
QByteArray QByteArray::left(qsizetype len) const QByteArray QByteArray::left(qsizetype len) const

View File

@ -583,8 +583,9 @@ QBitArray &QBitArray::operator^=(const QBitArray &other)
} }
/*! /*!
Returns a bit array that contains the inverted bits of this bit \fn QBitArray QBitArray::operator~(QBitArray a)
array. Returns a bit array that contains the inverted bits of the bit
array \a a.
Example: Example:
\snippet code/src_corelib_tools_qbitarray.cpp 11 \snippet code/src_corelib_tools_qbitarray.cpp 11
@ -592,12 +593,19 @@ QBitArray &QBitArray::operator^=(const QBitArray &other)
\sa operator&(), operator|(), operator^() \sa operator&(), operator|(), operator^()
*/ */
QBitArray QBitArray::operator~() const Q_NEVER_INLINE QBitArray QBitArray::inverted_inplace() &&
{ {
qsizetype n = d.size(); qsizetype n = d.size();
QBitArray result(QByteArrayData(n, n)); uchar *dst = reinterpret_cast<uchar *>(data_ptr().data());
const uchar *src = reinterpret_cast<const uchar *>(data_ptr().data()); const uchar *src = dst;
uchar *dst = reinterpret_cast<uchar *>(result.data_ptr().data()); QBitArray result([&] {
if (d.isDetached() || n == 0)
return std::move(d.data_ptr()); // invert in-place
QByteArrayData tmp(n, n);
dst = reinterpret_cast<uchar *>(tmp.data());
return tmp;
}());
uchar bitdiff = 8; uchar bitdiff = 8;
if (n) if (n)

View File

@ -16,6 +16,8 @@ class Q_CORE_EXPORT QBitArray
friend Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QBitArray &); friend Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QBitArray &);
#endif #endif
friend Q_CORE_EXPORT size_t qHash(const QBitArray &key, size_t seed) noexcept; friend Q_CORE_EXPORT size_t qHash(const QBitArray &key, size_t seed) noexcept;
friend QBitArray operator~(QBitArray a)
{ return std::move(a).inverted_inplace(); }
QByteArray d; QByteArray d;
QBitArray(QByteArrayData &&dd) : d(std::move(dd)) {} QBitArray(QByteArrayData &&dd) : d(std::move(dd)) {}
@ -32,6 +34,8 @@ class Q_CORE_EXPORT QBitArray
return R{ ba.d[1 + byteIdx], uchar(1U << bitIdx) }; return R{ ba.d[1 + byteIdx], uchar(1U << bitIdx) };
} }
QBitArray inverted_inplace() &&;
public: public:
inline QBitArray() noexcept {} inline QBitArray() noexcept {}
explicit QBitArray(qsizetype size, bool val = false); explicit QBitArray(qsizetype size, bool val = false);
@ -78,7 +82,9 @@ public:
QBitArray &operator&=(const QBitArray &); QBitArray &operator&=(const QBitArray &);
QBitArray &operator|=(const QBitArray &); QBitArray &operator|=(const QBitArray &);
QBitArray &operator^=(const QBitArray &); QBitArray &operator^=(const QBitArray &);
#if QT_CORE_REMOVED_SINCE(6, 7)
QBitArray operator~() const; QBitArray operator~() const;
#endif
inline bool operator==(const QBitArray &other) const { return d == other.d; } inline bool operator==(const QBitArray &other) const { return d == other.d; }
inline bool operator!=(const QBitArray &other) const { return d != other.d; } inline bool operator!=(const QBitArray &other) const { return d != other.d; }

View File

@ -454,6 +454,7 @@ void tst_QBitArray::operator_neg()
input = ~input; input = ~input;
QCOMPARE(input, res); QCOMPARE(input, res);
QCOMPARE(~~input, res); // performs two in-place negations
} }
void tst_QBitArray::datastream_data() void tst_QBitArray::datastream_data()