summaryrefslogtreecommitdiffstats
path: root/src/corelib/tools
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib/tools')
-rw-r--r--src/corelib/tools/qalgorithms.qdoc23
-rw-r--r--src/corelib/tools/qarraydata.cpp31
-rw-r--r--src/corelib/tools/qarraydata.h130
-rw-r--r--src/corelib/tools/qarraydataops.h1653
-rw-r--r--src/corelib/tools/qarraydatapointer.h169
-rw-r--r--src/corelib/tools/qbitarray.cpp151
-rw-r--r--src/corelib/tools/qbitarray.h93
-rw-r--r--src/corelib/tools/qcache.h62
-rw-r--r--src/corelib/tools/qcache.qdoc14
-rw-r--r--src/corelib/tools/qcommandlineoption.h2
-rw-r--r--src/corelib/tools/qcommandlineparser.cpp2
-rw-r--r--src/corelib/tools/qcontainerfwd.h34
-rw-r--r--src/corelib/tools/qcontainertools_impl.h19
-rw-r--r--src/corelib/tools/qcontiguouscache.cpp26
-rw-r--r--src/corelib/tools/qcontiguouscache.h9
-rw-r--r--src/corelib/tools/qcryptographichash.cpp63
-rw-r--r--src/corelib/tools/qcryptographichash.h2
-rw-r--r--src/corelib/tools/qduplicatetracker_p.h4
-rw-r--r--src/corelib/tools/qeasingcurve.cpp47
-rw-r--r--src/corelib/tools/qeasingcurve.h11
-rw-r--r--src/corelib/tools/qflatmap_p.h2
-rw-r--r--src/corelib/tools/qfreelist.cpp6
-rw-r--r--src/corelib/tools/qfreelist_p.h5
-rw-r--r--src/corelib/tools/qhash.cpp74
-rw-r--r--src/corelib/tools/qhash.h255
-rw-r--r--src/corelib/tools/qhashfunctions.h6
-rw-r--r--src/corelib/tools/qiterator.h76
-rw-r--r--src/corelib/tools/qiterator.qdoc284
-rw-r--r--src/corelib/tools/qline.cpp39
-rw-r--r--src/corelib/tools/qline.h37
-rw-r--r--src/corelib/tools/qlist.h619
-rw-r--r--src/corelib/tools/qlist.qdoc275
-rw-r--r--src/corelib/tools/qmakearray_p.h8
-rw-r--r--src/corelib/tools/qmap.h182
-rw-r--r--src/corelib/tools/qmap.qdoc51
-rw-r--r--src/corelib/tools/qmargins.cpp34
-rw-r--r--src/corelib/tools/qmargins.h119
-rw-r--r--src/corelib/tools/qmessageauthenticationcode.cpp41
-rw-r--r--src/corelib/tools/qmessageauthenticationcode.h2
-rw-r--r--src/corelib/tools/qmultimap.qdoc90
-rw-r--r--src/corelib/tools/qoffsetstringarray_p.h9
-rw-r--r--src/corelib/tools/qpair.qdoc16
-rw-r--r--src/corelib/tools/qpoint.cpp82
-rw-r--r--src/corelib/tools/qpoint.h308
-rw-r--r--src/corelib/tools/qrect.cpp28
-rw-r--r--src/corelib/tools/qrect.h113
-rw-r--r--src/corelib/tools/qringbuffer_p.h6
-rw-r--r--src/corelib/tools/qscopedpointer.cpp28
-rw-r--r--src/corelib/tools/qscopedpointer.h99
-rw-r--r--src/corelib/tools/qscopedpointer_p.h148
-rw-r--r--src/corelib/tools/qscopedvaluerollback.h18
-rw-r--r--src/corelib/tools/qscopeguard.h13
-rw-r--r--src/corelib/tools/qset.h3
-rw-r--r--src/corelib/tools/qset.qdoc287
-rw-r--r--src/corelib/tools/qshareddata.cpp97
-rw-r--r--src/corelib/tools/qshareddata.h312
-rw-r--r--src/corelib/tools/qshareddata_impl.h11
-rw-r--r--src/corelib/tools/qsharedpointer.h2
-rw-r--r--src/corelib/tools/qsharedpointer_impl.h178
-rw-r--r--src/corelib/tools/qsize.cpp57
-rw-r--r--src/corelib/tools/qsize.h184
-rw-r--r--src/corelib/tools/qtaggedpointer.qdoc24
-rw-r--r--src/corelib/tools/qtimeline.cpp4
-rw-r--r--src/corelib/tools/qtools_p.h3
-rw-r--r--src/corelib/tools/qvarlengtharray.h255
-rw-r--r--src/corelib/tools/qvarlengtharray.qdoc6
-rw-r--r--src/corelib/tools/qversionnumber.cpp24
-rw-r--r--src/corelib/tools/qversionnumber.h181
-rw-r--r--src/corelib/tools/tools.pri1
69 files changed, 3046 insertions, 4201 deletions
diff --git a/src/corelib/tools/qalgorithms.qdoc b/src/corelib/tools/qalgorithms.qdoc
index f94a6856da..4249cad72e 100644
--- a/src/corelib/tools/qalgorithms.qdoc
+++ b/src/corelib/tools/qalgorithms.qdoc
@@ -47,8 +47,7 @@
meet a certain set of requirements.
Different algorithms can have different requirements for the
- iterators they accept. For example, qFill() accepts two
- \l {forward iterators}. The iterator types required are specified
+ iterators they accept. The iterator types required are specified
for each algorithm. If an iterator of the wrong type is passed (for
example, if QList::ConstIterator is passed as an
\l {Output Iterators}{output iterator}), you will always get a
@@ -63,21 +62,7 @@
The generic algorithms can be used on other container classes
than those provided by Qt and STL. The syntax of STL-style
iterators is modeled after C++ pointers, so it's possible to use
- plain arrays as containers and plain pointers as iterators. A
- common idiom is to use qBinaryFind() together with two static
- arrays: one that contains a list of keys, and another that
- contains a list of associated values. For example, the following
- code will look up an HTML entity (e.g., \c &) in the \c
- name_table array and return the corresponding Unicode value from
- the \c value_table if the entity is recognized:
-
- \snippet code/doc_src_qalgorithms.cpp 2
-
- This kind of code is for advanced users only; for most
- applications, a QMap- or QHash-based approach would work just as
- well:
-
- \snippet code/doc_src_qalgorithms.cpp 3
+ plain arrays as containers and plain pointers as iterators.
\section1 Types of Iterators
@@ -156,7 +141,7 @@
Exchanges the values of variables \a var1 and \a var2.
Example:
- \snippet code/doc_src_qalgorithms.cpp 10
+ \snippet code/doc_src_qalgorithms.cpp 0
*/
/*!
@@ -168,7 +153,7 @@
example, \c{QWidget *}).
Example:
- \snippet code/doc_src_qalgorithms.cpp 23
+ \snippet code/doc_src_qalgorithms.cpp 1
Notice that qDeleteAll() doesn't remove the items from the
container; it merely calls \c delete on them. In the example
diff --git a/src/corelib/tools/qarraydata.cpp b/src/corelib/tools/qarraydata.cpp
index ab4a0f8af6..5feb1ac8f6 100644
--- a/src/corelib/tools/qarraydata.cpp
+++ b/src/corelib/tools/qarraydata.cpp
@@ -159,12 +159,12 @@ static inline qsizetype reserveExtraBytes(qsizetype allocSize)
return allocSize;
}
-static inline qsizetype calculateBlockSize(qsizetype &capacity, qsizetype objectSize, qsizetype headerSize, uint options)
+static inline qsizetype calculateBlockSize(qsizetype &capacity, qsizetype objectSize, qsizetype headerSize, QArrayData::AllocationOption option)
{
// Calculate the byte size
// allocSize = objectSize * capacity + headerSize, but checked for overflow
// plus padded to grow in size
- if (options & (QArrayData::GrowsForward | QArrayData::GrowsBackwards)) {
+ if (option == QArrayData::Grow) {
auto r = qCalculateGrowingBlockSize(capacity, objectSize, headerSize);
capacity = r.elementCount;
return r.size;
@@ -173,19 +173,19 @@ static inline qsizetype calculateBlockSize(qsizetype &capacity, qsizetype object
}
}
-static QArrayData *allocateData(qsizetype allocSize, uint options)
+static QArrayData *allocateData(qsizetype allocSize)
{
QArrayData *header = static_cast<QArrayData *>(::malloc(size_t(allocSize)));
if (header) {
header->ref_.storeRelaxed(1);
- header->flags = options;
+ header->flags = 0;
header->alloc = 0;
}
return header;
}
void *QArrayData::allocate(QArrayData **dptr, qsizetype objectSize, qsizetype alignment,
- qsizetype capacity, ArrayOptions options) noexcept
+ qsizetype capacity, QArrayData::AllocationOption option) noexcept
{
Q_ASSERT(dptr);
// Alignment is a power of two
@@ -208,14 +208,14 @@ void *QArrayData::allocate(QArrayData **dptr, qsizetype objectSize, qsizetype al
}
Q_ASSERT(headerSize > 0);
- qsizetype allocSize = calculateBlockSize(capacity, objectSize, headerSize, options);
+ qsizetype allocSize = calculateBlockSize(capacity, objectSize, headerSize, option);
allocSize = reserveExtraBytes(allocSize);
if (Q_UNLIKELY(allocSize < 0)) { // handle overflow. cannot allocate reliably
*dptr = nullptr;
return nullptr;
}
- QArrayData *header = allocateData(allocSize, options);
+ QArrayData *header = allocateData(allocSize);
void *data = nullptr;
if (header) {
// find where offset should point to so that data() is aligned to alignment bytes
@@ -229,13 +229,17 @@ void *QArrayData::allocate(QArrayData **dptr, qsizetype objectSize, qsizetype al
QPair<QArrayData *, void *>
QArrayData::reallocateUnaligned(QArrayData *data, void *dataPointer,
- qsizetype objectSize, qsizetype capacity, ArrayOptions options) noexcept
+ qsizetype objectSize, qsizetype capacity, AllocationOption option) noexcept
{
Q_ASSERT(!data || !data->isShared());
- qsizetype headerSize = sizeof(QArrayData);
- qsizetype allocSize = calculateBlockSize(capacity, objectSize, headerSize, options);
- qptrdiff offset = dataPointer ? reinterpret_cast<char *>(dataPointer) - reinterpret_cast<char *>(data) : headerSize;
+ const qsizetype headerSize = sizeof(QArrayData);
+ qsizetype allocSize = calculateBlockSize(capacity, objectSize, headerSize, option);
+ const qptrdiff offset = dataPointer
+ ? reinterpret_cast<char *>(dataPointer) - reinterpret_cast<char *>(data)
+ : headerSize;
+ Q_ASSERT(offset > 0);
+ Q_ASSERT(offset <= allocSize); // equals when all free space is at the beginning
allocSize = reserveExtraBytes(allocSize);
if (Q_UNLIKELY(allocSize < 0)) // handle overflow. cannot reallocate reliably
@@ -243,9 +247,10 @@ QArrayData::reallocateUnaligned(QArrayData *data, void *dataPointer,
QArrayData *header = static_cast<QArrayData *>(::realloc(data, size_t(allocSize)));
if (header) {
- header->flags = options;
- header->alloc = uint(capacity);
+ header->alloc = capacity;
dataPointer = reinterpret_cast<char *>(header) + offset;
+ } else {
+ dataPointer = nullptr;
}
return qMakePair(static_cast<QArrayData *>(header), dataPointer);
}
diff --git a/src/corelib/tools/qarraydata.h b/src/corelib/tools/qarraydata.h
index 856a9521ad..c76ff3d9f0 100644
--- a/src/corelib/tools/qarraydata.h
+++ b/src/corelib/tools/qarraydata.h
@@ -49,14 +49,21 @@ QT_BEGIN_NAMESPACE
template <class T> struct QTypedArrayData;
-struct Q_CORE_EXPORT QArrayData
+struct QArrayData
{
- enum ArrayOption {
- /// this option is used by the allocate() function
- DefaultAllocationFlags = 0,
- CapacityReserved = 0x1, //!< the capacity was reserved by the user, try to keep it
- GrowsForward = 0x2, //!< allocate with eyes towards growing through append()
- GrowsBackwards = 0x4 //!< allocate with eyes towards growing through prepend()
+ enum AllocationOption {
+ Grow,
+ KeepSize
+ };
+
+ enum GrowthPosition {
+ GrowsAtEnd,
+ GrowsAtBeginning
+ };
+
+ enum ArrayOption {
+ ArrayOptionDefault = 0,
+ CapacityReserved = 0x1 //!< the capacity was reserved by the user, try to keep it
};
Q_DECLARE_FLAGS(ArrayOptions, ArrayOption)
@@ -64,12 +71,12 @@ struct Q_CORE_EXPORT QArrayData
uint flags;
qsizetype alloc;
- inline qsizetype allocatedCapacity() noexcept
+ qsizetype allocatedCapacity() noexcept
{
return alloc;
}
- inline qsizetype constAllocatedCapacity() const noexcept
+ qsizetype constAllocatedCapacity() const noexcept
{
return alloc;
}
@@ -107,23 +114,15 @@ struct Q_CORE_EXPORT QArrayData
return newSize;
}
- ArrayOptions detachFlags() const noexcept
- {
- ArrayOptions result = DefaultAllocationFlags;
- if (flags & CapacityReserved)
- result |= CapacityReserved;
- return result;
- }
-
- Q_REQUIRED_RESULT
+ [[nodiscard]]
#if defined(Q_CC_GNU)
__attribute__((__malloc__))
#endif
- static void *allocate(QArrayData **pdata, qsizetype objectSize, qsizetype alignment,
- qsizetype capacity, ArrayOptions options = DefaultAllocationFlags) noexcept;
- Q_REQUIRED_RESULT static QPair<QArrayData *, void *> reallocateUnaligned(QArrayData *data, void *dataPointer,
- qsizetype objectSize, qsizetype newCapacity, ArrayOptions newOptions = DefaultAllocationFlags) noexcept;
- static void deallocate(QArrayData *data, qsizetype objectSize,
+ static Q_CORE_EXPORT void *allocate(QArrayData **pdata, qsizetype objectSize, qsizetype alignment,
+ qsizetype capacity, AllocationOption option = QArrayData::KeepSize) noexcept;
+ [[nodiscard]] static Q_CORE_EXPORT QPair<QArrayData *, void *> reallocateUnaligned(QArrayData *data, void *dataPointer,
+ qsizetype objectSize, qsizetype newCapacity, AllocationOption option) noexcept;
+ static Q_CORE_EXPORT void deallocate(QArrayData *data, qsizetype objectSize,
qsizetype alignment) noexcept;
};
@@ -133,87 +132,13 @@ template <class T>
struct QTypedArrayData
: QArrayData
{
- class iterator {
- T *i = nullptr;
- public:
- typedef std::random_access_iterator_tag iterator_category;
- typedef qsizetype difference_type;
- typedef T value_type;
- typedef T *pointer;
- typedef T &reference;
-
- inline constexpr iterator() = default;
- inline iterator(T *n) : i(n) {}
- inline T &operator*() const { return *i; }
- inline T *operator->() const { return i; }
- inline T &operator[](qsizetype j) const { return *(i + j); }
- inline constexpr bool operator==(iterator o) const { return i == o.i; }
- inline constexpr bool operator!=(iterator o) const { return i != o.i; }
- inline constexpr bool operator<(iterator other) const { return i < other.i; }
- inline constexpr bool operator<=(iterator other) const { return i <= other.i; }
- inline constexpr bool operator>(iterator other) const { return i > other.i; }
- inline constexpr bool operator>=(iterator other) const { return i >= other.i; }
- inline constexpr bool operator==(pointer p) const { return i == p; }
- inline constexpr bool operator!=(pointer p) const { return i != p; }
- inline iterator &operator++() { ++i; return *this; }
- inline iterator operator++(int) { T *n = i; ++i; return n; }
- inline iterator &operator--() { i--; return *this; }
- inline iterator operator--(int) { T *n = i; i--; return n; }
- inline iterator &operator+=(qsizetype j) { i+=j; return *this; }
- inline iterator &operator-=(qsizetype j) { i-=j; return *this; }
- inline iterator operator+(qsizetype j) const { return iterator(i+j); }
- inline iterator operator-(qsizetype j) const { return iterator(i-j); }
- friend inline iterator operator+(qsizetype j, iterator k) { return k + j; }
- inline qsizetype operator-(iterator j) const { return i - j.i; }
- inline operator T*() const { return i; }
- };
-
- class const_iterator {
- const T *i = nullptr;
- public:
- typedef std::random_access_iterator_tag iterator_category;
- typedef qsizetype difference_type;
- typedef T value_type;
- typedef const T *pointer;
- typedef const T &reference;
-
- inline constexpr const_iterator() = default;
- inline const_iterator(const T *n) : i(n) {}
- inline constexpr const_iterator(iterator o): i(o) {}
- inline const T &operator*() const { return *i; }
- inline const T *operator->() const { return i; }
- inline const T &operator[](qsizetype j) const { return *(i + j); }
- inline constexpr bool operator==(const_iterator o) const { return i == o.i; }
- inline constexpr bool operator!=(const_iterator o) const { return i != o.i; }
- inline constexpr bool operator<(const_iterator other) const { return i < other.i; }
- inline constexpr bool operator<=(const_iterator other) const { return i <= other.i; }
- inline constexpr bool operator>(const_iterator other) const { return i > other.i; }
- inline constexpr bool operator>=(const_iterator other) const { return i >= other.i; }
- inline constexpr bool operator==(iterator o) const { return i == const_iterator(o).i; }
- inline constexpr bool operator!=(iterator o) const { return i != const_iterator(o).i; }
- inline constexpr bool operator==(pointer p) const { return i == p; }
- inline constexpr bool operator!=(pointer p) const { return i != p; }
- inline const_iterator &operator++() { ++i; return *this; }
- inline const_iterator operator++(int) { const T *n = i; ++i; return n; }
- inline const_iterator &operator--() { i--; return *this; }
- inline const_iterator operator--(int) { const T *n = i; i--; return n; }
- inline const_iterator &operator+=(qsizetype j) { i+=j; return *this; }
- inline const_iterator &operator-=(qsizetype j) { i-=j; return *this; }
- inline const_iterator operator+(qsizetype j) const { return const_iterator(i+j); }
- inline const_iterator operator-(qsizetype j) const { return const_iterator(i-j); }
- friend inline const_iterator operator+(qsizetype j, const_iterator k) { return k + j; }
- inline qsizetype operator-(const_iterator j) const { return i - j.i; }
- inline operator const T*() const { return i; }
- };
-
- class AlignmentDummy { QArrayData header; T data; };
+ struct AlignmentDummy { QArrayData header; T data; };
- Q_REQUIRED_RESULT static QPair<QTypedArrayData *, T *> allocate(qsizetype capacity,
- ArrayOptions options = DefaultAllocationFlags)
+ [[nodiscard]] static QPair<QTypedArrayData *, T *> allocate(qsizetype capacity, AllocationOption option = QArrayData::KeepSize)
{
static_assert(sizeof(QTypedArrayData) == sizeof(QArrayData));
QArrayData *d;
- void *result = QArrayData::allocate(&d, sizeof(T), alignof(AlignmentDummy), capacity, options);
+ void *result = QArrayData::allocate(&d, sizeof(T), alignof(AlignmentDummy), capacity, option);
#if (defined(Q_CC_GNU) && Q_CC_GNU >= 407) || QT_HAS_BUILTIN(__builtin_assume_aligned)
result = __builtin_assume_aligned(result, Q_ALIGNOF(AlignmentDummy));
#endif
@@ -221,12 +146,11 @@ struct QTypedArrayData
}
static QPair<QTypedArrayData *, T *>
- reallocateUnaligned(QTypedArrayData *data, T *dataPointer, qsizetype capacity,
- ArrayOptions options = DefaultAllocationFlags)
+ reallocateUnaligned(QTypedArrayData *data, T *dataPointer, qsizetype capacity, AllocationOption option)
{
static_assert(sizeof(QTypedArrayData) == sizeof(QArrayData));
QPair<QArrayData *, void *> pair =
- QArrayData::reallocateUnaligned(data, dataPointer, sizeof(T), capacity, options);
+ QArrayData::reallocateUnaligned(data, dataPointer, sizeof(T), capacity, option);
return qMakePair(static_cast<QTypedArrayData *>(pair.first), static_cast<T *>(pair.second));
}
diff --git a/src/corelib/tools/qarraydataops.h b/src/corelib/tools/qarraydataops.h
index 1d7e307192..5f43ed3dc0 100644
--- a/src/corelib/tools/qarraydataops.h
+++ b/src/corelib/tools/qarraydataops.h
@@ -58,178 +58,6 @@ template <class T> struct QArrayDataPointer;
namespace QtPrivate {
-/*!
- \internal
-
- This class provides basic building blocks to do reversible operations. This
- in turn allows to reason about exception safety under certain conditions.
-
- This class is not part of the Qt API. It exists for the convenience of other
- Qt classes. This class may change from version to version without notice,
- or even be removed.
-
- We mean it.
- */
-template<typename T>
-struct QArrayExceptionSafetyPrimitives
-{
- using parameter_type = typename QArrayDataPointer<T>::parameter_type;
- using iterator = typename QArrayDataPointer<T>::iterator;
-
- // Constructs a range of elements at the specified position. If an exception
- // is thrown during construction, already constructed elements are
- // destroyed. By design, only one function (create/copy/clone/move) and only
- // once is supposed to be called per class instance.
- struct Constructor
- {
- T *const where;
- size_t n = 0;
-
- template<typename It>
- using iterator_copy_value = decltype(*std::declval<It>());
- template<typename It>
- using iterator_move_value = decltype(std::move(*std::declval<It>()));
-
- Constructor(T *w) noexcept : where(w) {}
- qsizetype create(size_t size) noexcept(std::is_nothrow_default_constructible_v<T>)
- {
- n = 0;
- while (n != size) {
- new (where + n) T;
- ++n;
- }
- return qsizetype(std::exchange(n, 0));
- }
- template<typename ForwardIt>
- qsizetype copy(ForwardIt first, ForwardIt last)
- noexcept(std::is_nothrow_constructible_v<T, iterator_copy_value<ForwardIt>>)
- {
- n = 0;
- for (; first != last; ++first) {
- new (where + n) T(*first);
- ++n;
- }
- return qsizetype(std::exchange(n, 0));
- }
- qsizetype clone(size_t size, parameter_type t)
- noexcept(std::is_nothrow_constructible_v<T, parameter_type>)
- {
- n = 0;
- while (n != size) {
- new (where + n) T(t);
- ++n;
- }
- return qsizetype(std::exchange(n, 0));
- }
- template<typename ForwardIt>
- qsizetype move(ForwardIt first, ForwardIt last)
- noexcept(std::is_nothrow_constructible_v<T, iterator_move_value<ForwardIt>>)
- {
- n = 0;
- for (; first != last; ++first) {
- new (where + n) T(std::move(*first));
- ++n;
- }
- return qsizetype(std::exchange(n, 0));
- }
- ~Constructor() noexcept(std::is_nothrow_destructible_v<T>)
- {
- while (n)
- where[--n].~T();
- }
- };
-
- // Watches passed iterator. Unless commit() is called, all the elements that
- // the watched iterator passes through are deleted at the end of object
- // lifetime.
- //
- // Requirements: when not at starting position, the iterator is expected to
- // point to a valid object (to initialized memory)
- template<typename It = iterator>
- struct Destructor
- {
- It *iter;
- It end;
- It intermediate;
-
- Destructor(It &it) noexcept(std::is_nothrow_copy_constructible_v<It>)
- : iter(std::addressof(it)), end(it)
- { }
- void commit() noexcept
- {
- iter = std::addressof(end);
- }
- void freeze() noexcept(std::is_nothrow_copy_constructible_v<It>)
- {
- intermediate = *iter; iter = std::addressof(intermediate);
- }
- ~Destructor() noexcept(std::is_nothrow_destructible_v<T>)
- {
- // Step is either 1 or -1 and depends on the interposition of *iter
- // and end. Note that *iter is expected to point to a valid object
- // (see the logic below).
- for (const int step = *iter < end ? 1 : -1; *iter != end; std::advance(*iter, step))
- (*iter)->~T();
- }
- };
-
- // Moves the data range in memory by the specified amount. Unless commit()
- // is called, the data is moved back to the original place at the end of
- // object lifetime.
- struct Displacer
- {
- T *const begin;
- T *const end;
- qsizetype displace;
-
- static_assert(QTypeInfo<T>::isRelocatable, "Type must be relocatable");
-
- Displacer(T *start, T *finish, qsizetype diff) noexcept
- : begin(start), end(finish), displace(diff)
- {
- ::memmove(static_cast<void *>(begin + displace), static_cast<void *>(begin),
- (end - begin) * sizeof(T));
- }
- void commit() noexcept { displace = 0; }
- ~Displacer() noexcept
- {
- if (displace)
- ::memmove(static_cast<void *>(begin), static_cast<void *>(begin + displace),
- (end - begin) * sizeof(T));
- }
- };
-
- // Watches passed iterator. Moves the data range (defined as a start
- // iterator and a length) to the new starting position at the end of object
- // lifetime.
- struct Mover
- {
- T *&destination;
- const T *const source;
- size_t n;
- qsizetype &size;
-
- static_assert(QTypeInfo<T>::isRelocatable, "Type must be relocatable");
-
- Mover(T *&start, size_t length, qsizetype &sz) noexcept
- : destination(start), source(start), n(length), size(sz)
- { }
- ~Mover() noexcept
- {
- ::memmove(static_cast<void *>(destination), static_cast<const void *>(source),
- n * sizeof(T));
- size -= source > destination ? source - destination : destination - source;
- }
- };
-};
-
-// Tags for compile-time dispatch based on backwards vs forward growing policy
-struct GrowsForwardTag {};
-struct GrowsBackwardsTag {};
-template<typename> struct InverseTag;
-template<> struct InverseTag<GrowsForwardTag> { using tag = GrowsBackwardsTag; };
-template<> struct InverseTag<GrowsBackwardsTag> { using tag = GrowsForwardTag; };
-
QT_WARNING_PUSH
#if defined(Q_CC_GNU) && Q_CC_GNU >= 700
QT_WARNING_DISABLE_GCC("-Wstringop-overflow")
@@ -239,30 +67,62 @@ template <class T>
struct QPodArrayOps
: public QArrayDataPointer<T>
{
+ static_assert (std::is_nothrow_destructible_v<T>, "Types with throwing destructors are not supported in Qt containers.");
+
protected:
typedef QTypedArrayData<T> Data;
-
- template <typename ...Args>
- void createInPlace(T *where, Args&&... args) { new (where) T(std::forward<Args>(args)...); }
+ using DataPointer = QArrayDataPointer<T>;
public:
typedef typename QArrayDataPointer<T>::parameter_type parameter_type;
- void appendInitialize(size_t newSize)
+ void appendInitialize(qsizetype newSize) noexcept
{
Q_ASSERT(this->isMutable());
Q_ASSERT(!this->isShared());
- Q_ASSERT(newSize > size_t(this->size));
- Q_ASSERT(newSize - this->size <= size_t(this->freeSpaceAtEnd()));
+ Q_ASSERT(newSize > this->size);
+ Q_ASSERT(newSize - this->size <= this->freeSpaceAtEnd());
- ::memset(static_cast<void *>(this->end()), 0, (newSize - this->size) * sizeof(T));
+ T *where = this->end();
this->size = qsizetype(newSize);
+ const T *e = this->end();
+ while (where != e)
+ *where++ = T();
}
- void moveAppend(T *b, T *e)
- { insert(this->end(), b, e); }
+ void copyAppend(const T *b, const T *e) noexcept
+ {
+ Q_ASSERT(this->isMutable() || b == e);
+ Q_ASSERT(!this->isShared() || b == e);
+ Q_ASSERT(b <= e);
+ Q_ASSERT((e - b) <= this->freeSpaceAtEnd());
- void truncate(size_t newSize)
+ if (b == e)
+ return;
+
+ ::memcpy(static_cast<void *>(this->end()), static_cast<const void *>(b), (e - b) * sizeof(T));
+ this->size += (e - b);
+ }
+
+ void copyAppend(qsizetype n, parameter_type t) noexcept
+ {
+ Q_ASSERT(!this->isShared() || n == 0);
+ Q_ASSERT(this->freeSpaceAtEnd() >= n);
+ if (!n)
+ return;
+
+ T *where = this->end();
+ this->size += qsizetype(n);
+ while (n--)
+ *where++ = t;
+ }
+
+ void moveAppend(T *b, T *e) noexcept
+ {
+ copyAppend(b, e);
+ }
+
+ void truncate(size_t newSize) noexcept
{
Q_ASSERT(this->isMutable());
Q_ASSERT(!this->isShared());
@@ -271,7 +131,7 @@ public:
this->size = qsizetype(newSize);
}
- void destroyAll() // Call from destructors, ONLY!
+ void destroyAll() noexcept // Call from destructors, ONLY!
{
Q_ASSERT(this->d);
Q_ASSERT(this->d->ref_.loadRelaxed() == 0);
@@ -280,154 +140,120 @@ public:
// exception safe; size not updated.
}
- void insert(T *where, const T *b, const T *e)
- { insert(GrowsForwardTag{}, where, b, e); }
-
- void insert(GrowsForwardTag, T *where, const T *b, const T *e)
+ T *createHole(QArrayData::GrowthPosition pos, qsizetype where, qsizetype n)
{
- Q_ASSERT(this->isMutable() || (b == e && where == this->end()));
- Q_ASSERT(!this->isShared() || (b == e && where == this->end()));
- Q_ASSERT(where >= this->begin() && where <= this->end());
- Q_ASSERT(b <= e);
- Q_ASSERT(e <= where || b > this->end() || where == this->end()); // No overlap or append
- Q_ASSERT((e - b) <= this->freeSpaceAtEnd());
-
- ::memmove(static_cast<void *>(where + (e - b)), static_cast<void *>(where),
- (static_cast<const T*>(this->end()) - where) * sizeof(T));
- ::memcpy(static_cast<void *>(where), static_cast<const void *>(b), (e - b) * sizeof(T));
- this->size += (e - b);
- }
+ Q_ASSERT((pos == QArrayData::GrowsAtBeginning && n <= this->freeSpaceAtBegin()) ||
+ (pos == QArrayData::GrowsAtEnd && n <= this->freeSpaceAtEnd()));
- void insert(GrowsBackwardsTag, T *where, const T *b, const T *e)
- {
- Q_ASSERT(this->isMutable() || (b == e && where == this->end()));
- Q_ASSERT(!this->isShared() || (b == e && where == this->end()));
- Q_ASSERT(where >= this->begin() && where <= this->end());
- Q_ASSERT(b <= e);
- Q_ASSERT(e <= where || b > this->end() || where == this->end()); // No overlap or append
- Q_ASSERT((e - b) <= this->freeSpaceAtBegin());
-
- auto oldBegin = this->begin();
- this->ptr -= (e - b);
- ::memmove(static_cast<void *>(this->begin()), static_cast<void *>(oldBegin),
- (where - static_cast<const T*>(oldBegin)) * sizeof(T));
- ::memcpy(static_cast<void *>(where - (e - b)), static_cast<const void *>(b),
- (e - b) * sizeof(T));
- this->size += (e - b);
+ T *insertionPoint = this->ptr + where;
+ if (pos == QArrayData::GrowsAtEnd) {
+ if (where < this->size)
+ ::memmove(static_cast<void *>(insertionPoint + n), static_cast<void *>(insertionPoint), (this->size - where) * sizeof(T));
+ } else {
+ if (where > 0)
+ ::memmove(static_cast<void *>(this->ptr - n), static_cast<const void *>(this->ptr), where * sizeof(T));
+ this->ptr -= n;
+ insertionPoint -= n;
+ }
+ this->size += n;
+ return insertionPoint;
}
- void insert(T *where, size_t n, parameter_type t)
- { insert(GrowsForwardTag{}, where, n, t); }
-
- void insert(GrowsForwardTag, T *where, size_t n, parameter_type t)
+ void insert(qsizetype i, const T *data, qsizetype n)
{
- Q_ASSERT(!this->isShared() || (n == 0 && where == this->end()));
- Q_ASSERT(where >= this->begin() && where <= this->end());
- Q_ASSERT(size_t(this->freeSpaceAtEnd()) >= n);
+ typename Data::GrowthPosition pos = Data::GrowsAtEnd;
+ if (this->size != 0 && i <= (this->size >> 1))
+ pos = Data::GrowsAtBeginning;
+ DataPointer oldData;
+ this->detachAndGrow(pos, n, &oldData);
+ Q_ASSERT((pos == Data::GrowsAtBeginning && this->freeSpaceAtBegin() >= n) ||
+ (pos == Data::GrowsAtEnd && this->freeSpaceAtEnd() >= n));
- ::memmove(static_cast<void *>(where + n), static_cast<void *>(where),
- (static_cast<const T*>(this->end()) - where) * sizeof(T));
- this->size += qsizetype(n); // PODs can't throw on copy
- while (n--)
- *where++ = t;
- }
-
- void insert(GrowsBackwardsTag, T *where, size_t n, parameter_type t)
- {
- Q_ASSERT(!this->isShared() || (n == 0 && where == this->end()));
- Q_ASSERT(where >= this->begin() && where <= this->end());
- Q_ASSERT(size_t(this->freeSpaceAtBegin()) >= n);
-
- auto oldBegin = this->begin();
- this->ptr -= n;
- ::memmove(static_cast<void *>(this->begin()), static_cast<void *>(oldBegin),
- (where - static_cast<const T*>(oldBegin)) * sizeof(T));
- this->size += qsizetype(n); // PODs can't throw on copy
- where -= n;
- while (n--)
- *where++ = t;
+ T *where = createHole(pos, i, n);
+ ::memcpy(static_cast<void *>(where), static_cast<const void *>(data), n * sizeof(T));
}
-
- template <typename ...Args>
- void emplace(T *where, Args&&... args)
- { emplace(GrowsForwardTag{}, where, std::forward<Args>(args)...); }
-
- template <typename ...Args>
- void emplace(GrowsForwardTag, T *where, Args&&... args)
+ void insert(qsizetype i, qsizetype n, parameter_type t)
{
- Q_ASSERT(!this->isShared());
- Q_ASSERT(where >= this->begin() && where <= this->end());
- Q_ASSERT(this->freeSpaceAtEnd() >= 1);
+ T copy(t);
- if (where == this->end()) {
- new (this->end()) T(std::forward<Args>(args)...);
- } else {
- // Preserve the value, because it might be a reference to some part of the moved chunk
- T t(std::forward<Args>(args)...);
+ typename Data::GrowthPosition pos = Data::GrowsAtEnd;
+ if (this->size != 0 && i <= (this->size >> 1))
+ pos = Data::GrowsAtBeginning;
+ this->detachAndGrow(pos, n);
+ Q_ASSERT((pos == Data::GrowsAtBeginning && this->freeSpaceAtBegin() >= n) ||
+ (pos == Data::GrowsAtEnd && this->freeSpaceAtEnd() >= n));
- ::memmove(static_cast<void *>(where + 1), static_cast<void *>(where),
- (static_cast<const T*>(this->end()) - where) * sizeof(T));
- *where = t;
- }
-
- ++this->size;
+ T *where = createHole(pos, i, n);
+ while (n--)
+ *where++ = copy;
}
- template <typename ...Args>
- void emplace(GrowsBackwardsTag, T *where, Args&&... args)
+ template<typename... Args>
+ void emplace(qsizetype i, Args &&... args)
{
- Q_ASSERT(!this->isShared());
- Q_ASSERT(where >= this->begin() && where <= this->end());
- Q_ASSERT(this->freeSpaceAtBegin() >= 1);
-
- if (where == this->begin()) {
- new (this->begin() - 1) T(std::forward<Args>(args)...);
- --this->ptr;
- } else {
- // Preserve the value, because it might be a reference to some part of the moved chunk
- T t(std::forward<Args>(args)...);
-
- auto oldBegin = this->begin();
- --this->ptr;
- ::memmove(static_cast<void *>(this->begin()), static_cast<void *>(oldBegin),
- (where - oldBegin) * sizeof(T));
- *(where - 1) = t;
+ bool detach = this->needsDetach();
+ if (!detach) {
+ if (i == this->size && this->freeSpaceAtEnd()) {
+ new (this->end()) T(std::forward<Args>(args)...);
+ ++this->size;
+ return;
+ }
+ if (i == 0 && this->freeSpaceAtBegin()) {
+ new (this->begin() - 1) T(std::forward<Args>(args)...);
+ --this->ptr;
+ ++this->size;
+ return;
+ }
}
+ T tmp(std::forward<Args>(args)...);
+ typename QArrayData::GrowthPosition pos = QArrayData::GrowsAtEnd;
+ if (this->size != 0 && i <= (this->size >> 1))
+ pos = QArrayData::GrowsAtBeginning;
+ if (detach ||
+ (pos == QArrayData::GrowsAtBeginning && !this->freeSpaceAtBegin()) ||
+ (pos == QArrayData::GrowsAtEnd && !this->freeSpaceAtEnd()))
+ this->reallocateAndGrow(pos, 1);
- ++this->size;
+ T *where = createHole(pos, i, 1);
+ new (where) T(std::move(tmp));
}
- void erase(T *b, T *e)
- { erase(GrowsForwardTag{}, b, e); }
-
- void erase(GrowsForwardTag, T *b, T *e)
+ void erase(T *b, qsizetype n)
{
+ T *e = b + n;
Q_ASSERT(this->isMutable());
Q_ASSERT(b < e);
Q_ASSERT(b >= this->begin() && b < this->end());
Q_ASSERT(e > this->begin() && e <= this->end());
- ::memmove(static_cast<void *>(b), static_cast<void *>(e),
- (static_cast<T *>(this->end()) - e) * sizeof(T));
- this->size -= (e - b);
+ // Comply with std::vector::erase(): erased elements and all after them
+ // are invalidated. However, erasing from the beginning effectively
+ // means that all iterators are invalidated. We can use this freedom to
+ // erase by moving towards the end.
+ if (b == this->begin())
+ this->ptr = e;
+ else if (e != this->end())
+ ::memmove(static_cast<void *>(b), static_cast<void *>(e), (static_cast<T *>(this->end()) - e) * sizeof(T));
+ this->size -= n;
}
- void erase(GrowsBackwardsTag, T *b, T *e)
+ void eraseFirst() noexcept
{
Q_ASSERT(this->isMutable());
- Q_ASSERT(b < e);
- Q_ASSERT(b >= this->begin() && b < this->end());
- Q_ASSERT(e > this->begin() && e <= this->end());
+ Q_ASSERT(this->size);
+ ++this->ptr;
+ --this->size;
+ }
- const auto oldBegin = this->begin();
- this->ptr += (e - b);
- ::memmove(static_cast<void *>(this->begin()), static_cast<void *>(oldBegin),
- (b - static_cast<T *>(oldBegin)) * sizeof(T));
- this->size -= (e - b);
+ void eraseLast() noexcept
+ {
+ Q_ASSERT(this->isMutable());
+ Q_ASSERT(this->size);
+ --this->size;
}
- void assign(T *b, T *e, parameter_type t)
+ void assign(T *b, T *e, parameter_type t) noexcept
{
Q_ASSERT(b <= e);
Q_ASSERT(b >= this->begin() && e <= this->end());
@@ -457,21 +283,10 @@ public:
}
}
- void reallocate(qsizetype alloc, typename Data::ArrayOptions options)
+ void reallocate(qsizetype alloc, QArrayData::AllocationOption option)
{
- // when reallocating, take care of the situation when no growth is
- // happening - need to move the data in this case, unfortunately
- const bool grows = options & (Data::GrowsForward | Data::GrowsBackwards);
-
- // ### optimize me: there may be cases when moving is not obligatory
- if (const auto gap = this->freeSpaceAtBegin(); this->d && !grows && gap) {
- auto oldBegin = this->begin();
- this->ptr -= gap;
- ::memmove(static_cast<void *>(this->begin()), static_cast<void *>(oldBegin),
- this->size * sizeof(T));
- }
-
- auto pair = Data::reallocateUnaligned(this->d, this->ptr, alloc, options);
+ auto pair = Data::reallocateUnaligned(this->d, this->ptr, alloc, option);
+ Q_ASSERT(pair.first != nullptr);
this->d = pair.first;
this->ptr = pair.second;
}
@@ -482,42 +297,76 @@ template <class T>
struct QGenericArrayOps
: public QArrayDataPointer<T>
{
+ static_assert (std::is_nothrow_destructible_v<T>, "Types with throwing destructors are not supported in Qt containers.");
+
protected:
typedef QTypedArrayData<T> Data;
-
- template <typename ...Args>
- void createInPlace(T *where, Args&&... args) { new (where) T(std::forward<Args>(args)...); }
+ using DataPointer = QArrayDataPointer<T>;
public:
typedef typename QArrayDataPointer<T>::parameter_type parameter_type;
- void appendInitialize(size_t newSize)
+ void appendInitialize(qsizetype newSize)
{
Q_ASSERT(this->isMutable());
Q_ASSERT(!this->isShared());
- Q_ASSERT(newSize > size_t(this->size));
- Q_ASSERT(newSize - this->size <= size_t(this->freeSpaceAtEnd()));
+ Q_ASSERT(newSize > this->size);
+ Q_ASSERT(newSize - this->size <= this->freeSpaceAtEnd());
T *const b = this->begin();
do {
new (b + this->size) T;
- } while (size_t(++this->size) != newSize);
+ } while (++this->size != newSize);
}
- void moveAppend(T *b, T *e)
+ void copyAppend(const T *b, const T *e)
{
Q_ASSERT(this->isMutable() || b == e);
Q_ASSERT(!this->isShared() || b == e);
Q_ASSERT(b <= e);
Q_ASSERT((e - b) <= this->freeSpaceAtEnd());
- typedef typename QArrayExceptionSafetyPrimitives<T>::Constructor CopyConstructor;
+ if (b == e) // short-cut and handling the case b and e == nullptr
+ return;
+
+ T *data = this->begin();
+ while (b < e) {
+ new (data + this->size) T(*b);
+ ++b;
+ ++this->size;
+ }
+ }
+
+ void copyAppend(qsizetype n, parameter_type t)
+ {
+ Q_ASSERT(!this->isShared() || n == 0);
+ Q_ASSERT(this->freeSpaceAtEnd() >= n);
+ if (!n)
+ return;
+
+ T *data = this->begin();
+ while (n--) {
+ new (data + this->size) T(t);
+ ++this->size;
+ }
+ }
+
+ void moveAppend(T *b, T *e)
+ {
+ Q_ASSERT(this->isMutable() || b == e);
+ Q_ASSERT(!this->isShared() || b == e);
+ Q_ASSERT(b <= e);
+ Q_ASSERT((e - b) <= this->freeSpaceAtEnd());
- // Provides strong exception safety guarantee,
- // provided T::~T() nothrow
+ if (b == e)
+ return;
- CopyConstructor copier(this->end());
- this->size += copier.move(b, e);
+ T *data = this->begin();
+ while (b < e) {
+ new (data + this->size) T(std::move(*b));
+ ++b;
+ ++this->size;
+ }
}
void truncate(size_t newSize)
@@ -526,10 +375,8 @@ public:
Q_ASSERT(!this->isShared());
Q_ASSERT(newSize < size_t(this->size));
- const T *const b = this->begin();
- do {
- (b + --this->size)->~T();
- } while (size_t(this->size) != newSize);
+ std::destroy(this->begin() + newSize, this->end());
+ this->size = newSize;
}
void destroyAll() // Call from destructors, ONLY
@@ -540,304 +387,262 @@ public:
Q_ASSERT(this->d->ref_.loadRelaxed() == 0);
- const T *const b = this->begin();
- const T *i = this->end();
-
- while (i != b)
- (--i)->~T();
+ std::destroy(this->begin(), this->end());
}
- void insert(T *where, const T *b, const T *e)
- { insert(GrowsForwardTag{}, where, b, e); }
-
- void insert(GrowsForwardTag, T *where, const T *b, const T *e)
+ struct Inserter
{
- Q_ASSERT(this->isMutable() || (b == e && where == this->end()));
- Q_ASSERT(!this->isShared() || (b == e && where == this->end()));
- Q_ASSERT(where >= this->begin() && where <= this->end());
- Q_ASSERT(b <= e);
- Q_ASSERT(e <= where || b > this->end() || where == this->end()); // No overlap or append
- Q_ASSERT((e - b) <= this->freeSpaceAtEnd());
-
- typedef typename QArrayExceptionSafetyPrimitives<T>::template Destructor<T *> Destructor;
-
- // Array may be truncated at where in case of exceptions
-
- T *const end = this->end();
- const T *readIter = end;
- T *writeIter = end + (e - b);
+ QArrayDataPointer<T> *data;
+ qsizetype increment = 1;
+ T *begin;
+ qsizetype size;
- const T *const step1End = where + qMax(e - b, end - where);
+ qsizetype sourceCopyConstruct, nSource, move, sourceCopyAssign;
+ T *end, *last, *where;
- Destructor destroyer(writeIter);
-
- // Construct new elements in array
- while (writeIter != step1End) {
- --readIter;
- // If exception happens on construction, we should not call ~T()
- new (writeIter - 1) T(*readIter);
- --writeIter;
- }
-
- while (writeIter != end) {
- --e;
- // If exception happens on construction, we should not call ~T()
- new (writeIter - 1) T(*e);
- --writeIter;
- }
-
- destroyer.commit();
- this->size += destroyer.end - end;
-
- // Copy assign over existing elements
- while (readIter != where) {
- --readIter;
- --writeIter;
- *writeIter = *readIter;
+ Inserter(QArrayDataPointer<T> *d, QArrayData::GrowthPosition pos)
+ : data(d), increment(pos == QArrayData::GrowsAtBeginning ? -1 : 1)
+ {
+ begin = d->ptr;
+ size = d->size;
+ if (increment < 0)
+ begin += size - 1;
}
-
- while (writeIter != where) {
- --e;
- --writeIter;
- *writeIter = *e;
+ ~Inserter() {
+ if (increment < 0)
+ begin -= size - 1;
+ data->ptr = begin;
+ data->size = size;
}
- }
-
- void insert(GrowsBackwardsTag, T *where, const T *b, const T *e)
- {
- Q_ASSERT(this->isMutable() || (b == e && where == this->end()));
- Q_ASSERT(!this->isShared() || (b == e && where == this->end()));
- Q_ASSERT(where >= this->begin() && where <= this->end());
- Q_ASSERT(b <= e);
- Q_ASSERT(e <= where || b > this->end() || where == this->end()); // No overlap or append
- Q_ASSERT((e - b) <= this->freeSpaceAtBegin());
-
- typedef typename QArrayExceptionSafetyPrimitives<T>::template Destructor<T *> Destructor;
-
- T *const begin = this->begin();
- const T *readIter = begin;
- T *writeIter = begin - (e - b);
- const T *const step1End = where - qMax(e - b, where - begin);
-
- Destructor destroyer(writeIter);
+ void setup(qsizetype pos, qsizetype n)
+ {
- // Construct new elements in array
- while (writeIter != step1End) {
- new (writeIter) T(*readIter);
- ++readIter;
- ++writeIter;
+ if (increment > 0) {
+ end = begin + size;
+ last = end - 1;
+ where = begin + pos;
+ qsizetype dist = size - pos;
+ sourceCopyConstruct = 0;
+ nSource = n;
+ move = n - dist; // smaller 0
+ sourceCopyAssign = n;
+ if (n > dist) {
+ sourceCopyConstruct = n - dist;
+ move = 0;
+ sourceCopyAssign -= sourceCopyConstruct;
+ }
+ } else {
+ end = begin - size;
+ last = end + 1;
+ where = end + pos;
+ sourceCopyConstruct = 0;
+ nSource = -n;
+ move = pos - n; // larger 0
+ sourceCopyAssign = -n;
+ if (n > pos) {
+ sourceCopyConstruct = pos - n;
+ move = 0;
+ sourceCopyAssign -= sourceCopyConstruct;
+ }
+ }
}
- while (writeIter != begin) {
- new (writeIter) T(*b);
- ++b;
- ++writeIter;
- }
+ void insert(qsizetype pos, const T *source, qsizetype n)
+ {
+ qsizetype oldSize = size;
+ Q_UNUSED(oldSize);
+
+ setup(pos, n);
+ if (increment < 0)
+ source += n - 1;
+
+ // first create new elements at the end, by copying from elements
+ // to be inserted (if they extend past the current end of the array)
+ for (qsizetype i = 0; i != sourceCopyConstruct; i += increment) {
+ new (end + i) T(source[nSource - sourceCopyConstruct + i]);
+ ++size;
+ }
+ Q_ASSERT(size <= oldSize + n);
- destroyer.commit();
- this->size += begin - destroyer.end;
- this->ptr -= begin - destroyer.end;
+ // now move construct new elements at the end from existing elements inside
+ // the array.
+ for (qsizetype i = sourceCopyConstruct; i != nSource; i += increment) {
+ new (end + i) T(std::move(*(end + i - nSource)));
+ ++size;
+ }
+ // array has the new size now!
+ Q_ASSERT(size == oldSize + n);
- // Copy assign over existing elements
- while (readIter != where) {
- *writeIter = *readIter;
- ++readIter;
- ++writeIter;
- }
+ // now move assign existing elements towards the end
+ for (qsizetype i = 0; i != move; i -= increment)
+ last[i] = std::move(last[i - nSource]);
- while (writeIter != where) {
- *writeIter = *b;
- ++b;
- ++writeIter;
+ // finally copy the remaining elements from source over
+ for (qsizetype i = 0; i != sourceCopyAssign; i += increment)
+ where[i] = source[i];
}
- }
-
- void insert(T *where, size_t n, parameter_type t)
- { insert(GrowsForwardTag{}, where, n, t); }
- void insert(GrowsForwardTag, T *where, size_t n, parameter_type t)
- {
- Q_ASSERT(!this->isShared() || (n == 0 && where == this->end()));
- Q_ASSERT(where >= this->begin() && where <= this->end());
- Q_ASSERT(size_t(this->freeSpaceAtEnd()) >= n);
+ void insert(qsizetype pos, const T &t, qsizetype n)
+ {
+ qsizetype oldSize = size;
+ Q_UNUSED(oldSize);
- typedef typename QArrayExceptionSafetyPrimitives<T>::template Destructor<T *> Destructor;
+ setup(pos, n);
- // Array may be truncated at where in case of exceptions
- T *const end = this->end();
- const T *readIter = end;
- T *writeIter = end + n;
+ // first create new elements at the end, by copying from elements
+ // to be inserted (if they extend past the current end of the array)
+ for (qsizetype i = 0; i != sourceCopyConstruct; i += increment) {
+ new (end + i) T(t);
+ ++size;
+ }
+ Q_ASSERT(size <= oldSize + n);
- const T *const step1End = where + qMax<size_t>(n, end - where);
+ // now move construct new elements at the end from existing elements inside
+ // the array.
+ for (qsizetype i = sourceCopyConstruct; i != nSource; i += increment) {
+ new (end + i) T(std::move(*(end + i - nSource)));
+ ++size;
+ }
+ // array has the new size now!
+ Q_ASSERT(size == oldSize + n);
- Destructor destroyer(writeIter);
+ // now move assign existing elements towards the end
+ for (qsizetype i = 0; i != move; i -= increment)
+ last[i] = std::move(last[i - nSource]);
- // Construct new elements in array
- while (writeIter != step1End) {
- --readIter;
- // If exception happens on construction, we should not call ~T()
- new (writeIter - 1) T(*readIter);
- --writeIter;
+ // finally copy the remaining elements from source over
+ for (qsizetype i = 0; i != sourceCopyAssign; i += increment)
+ where[i] = t;
}
- while (writeIter != end) {
- --n;
- // If exception happens on construction, we should not call ~T()
- new (writeIter - 1) T(t);
- --writeIter;
- }
+ void insertOne(qsizetype pos, T &&t)
+ {
+ setup(pos, 1);
- destroyer.commit();
- this->size += destroyer.end - end;
+ if (sourceCopyConstruct) {
+ Q_ASSERT(sourceCopyConstruct == increment);
+ new (end) T(std::move(t));
+ ++size;
+ } else {
+ // create a new element at the end by move constructing one existing element
+ // inside the array.
+ new (end) T(std::move(*(end - increment)));
+ ++size;
- // Copy assign over existing elements
- while (readIter != where) {
- --readIter;
- --writeIter;
- *writeIter = *readIter;
- }
+ // now move assign existing elements towards the end
+ for (qsizetype i = 0; i != move; i -= increment)
+ last[i] = std::move(last[i - increment]);
- while (writeIter != where) {
- --n;
- --writeIter;
- *writeIter = t;
+ // and move the new item into place
+ *where = std::move(t);
+ }
}
- }
+ };
- void insert(GrowsBackwardsTag, T *where, size_t n, parameter_type t)
+ void insert(qsizetype i, const T *data, qsizetype n)
{
- Q_ASSERT(!this->isShared() || (n == 0 && where == this->end()));
- Q_ASSERT(where >= this->begin() && where <= this->end());
- Q_ASSERT(size_t(this->freeSpaceAtBegin()) >= n);
-
- typedef typename QArrayExceptionSafetyPrimitives<T>::template Destructor<T *> Destructor;
-
- T *const begin = this->begin();
- const T *readIter = begin;
- T *writeIter = begin - n;
-
- const T *const step1End = where - qMax<size_t>(n, where - begin);
+ typename Data::GrowthPosition pos = Data::GrowsAtEnd;
+ if (this->size != 0 && i <= (this->size >> 1))
+ pos = Data::GrowsAtBeginning;
+ DataPointer oldData;
+ this->detachAndGrow(pos, n, &oldData);
+ Q_ASSERT((pos == Data::GrowsAtBeginning && this->freeSpaceAtBegin() >= n) ||
+ (pos == Data::GrowsAtEnd && this->freeSpaceAtEnd() >= n));
- Destructor destroyer(writeIter);
-
- // Construct new elements in array
- while (writeIter != step1End) {
- new (writeIter) T(*readIter);
- ++readIter;
- ++writeIter;
- }
-
- while (writeIter != begin) {
- new (writeIter) T(t);
- ++writeIter;
- }
-
- destroyer.commit();
- this->size += begin - destroyer.end;
- this->ptr -= begin - destroyer.end;
-
- // Copy assign over existing elements
- while (readIter != where) {
- *writeIter = *readIter;
- ++readIter;
- ++writeIter;
- }
-
- while (writeIter != where) {
- *writeIter = t;
- ++writeIter;
- }
+ Inserter(this, pos).insert(i, data, n);
}
-
- template <typename iterator, typename ...Args>
- void emplace(iterator where, Args&&... args)
- { emplace(GrowsForwardTag{}, where, std::forward<Args>(args)...); }
-
- template <typename iterator, typename ...Args>
- void emplace(GrowsForwardTag, iterator where, Args&&... args)
+ void insert(qsizetype i, qsizetype n, parameter_type t)
{
- Q_ASSERT(!this->isShared());
- Q_ASSERT(where >= this->begin() && where <= this->end());
- Q_ASSERT(this->freeSpaceAtEnd() >= 1);
+ T copy(t);
- createInPlace(this->end(), std::forward<Args>(args)...);
- ++this->size;
+ typename Data::GrowthPosition pos = Data::GrowsAtEnd;
+ if (this->size != 0 && i <= (this->size >> 1))
+ pos = Data::GrowsAtBeginning;
+ this->detachAndGrow(pos, n);
+ Q_ASSERT((pos == Data::GrowsAtBeginning && this->freeSpaceAtBegin() >= n) ||
+ (pos == Data::GrowsAtEnd && this->freeSpaceAtEnd() >= n));
- std::rotate(where, this->end() - 1, this->end());
+ Inserter(this, pos).insert(i, copy, n);
}
- template <typename iterator, typename ...Args>
- void emplace(GrowsBackwardsTag, iterator where, Args&&... args)
+ template<typename... Args>
+ void emplace(qsizetype i, Args &&... args)
{
- Q_ASSERT(!this->isShared());
- Q_ASSERT(where >= this->begin() && where <= this->end());
- Q_ASSERT(this->freeSpaceAtBegin() >= 1);
-
- createInPlace(this->begin() - 1, std::forward<Args>(args)...);
- --this->ptr;
- ++this->size;
+ bool detach = this->needsDetach();
+ if (!detach) {
+ if (i == this->size && this->freeSpaceAtEnd()) {
+ new (this->end()) T(std::forward<Args>(args)...);
+ ++this->size;
+ return;
+ }
+ if (i == 0 && this->freeSpaceAtBegin()) {
+ new (this->begin() - 1) T(std::forward<Args>(args)...);
+ --this->ptr;
+ ++this->size;
+ return;
+ }
+ }
+ T tmp(std::forward<Args>(args)...);
+ typename QArrayData::GrowthPosition pos = QArrayData::GrowsAtEnd;
+ if (this->size != 0 && i <= (this->size >> 1))
+ pos = QArrayData::GrowsAtBeginning;
+ if (detach ||
+ (pos == QArrayData::GrowsAtBeginning && !this->freeSpaceAtBegin()) ||
+ (pos == QArrayData::GrowsAtEnd && !this->freeSpaceAtEnd()))
+ this->reallocateAndGrow(pos, 1);
- std::rotate(this->begin(), this->begin() + 1, where);
+ Inserter(this, pos).insertOne(i, std::move(tmp));
}
- void erase(T *b, T *e)
- { erase(GrowsForwardTag{}, b, e); }
-
- void erase(GrowsForwardTag, T *b, T *e)
+ void erase(T *b, qsizetype n)
{
+ T *e = b + n;
Q_ASSERT(this->isMutable());
Q_ASSERT(b < e);
Q_ASSERT(b >= this->begin() && b < this->end());
Q_ASSERT(e > this->begin() && e <= this->end());
- const T *const end = this->end();
-
- // move (by assignment) the elements from e to end
- // onto b to the new end
- while (e != end) {
- *b = *e;
- ++b;
- ++e;
+ // Comply with std::vector::erase(): erased elements and all after them
+ // are invalidated. However, erasing from the beginning effectively
+ // means that all iterators are invalidated. We can use this freedom to
+ // erase by moving towards the end.
+ if (b == this->begin()) {
+ this->ptr = e;
+ } else {
+ const T *const end = this->end();
+
+ // move (by assignment) the elements from e to end
+ // onto b to the new end
+ while (e != end) {
+ *b = std::move(*e);
+ ++b;
+ ++e;
+ }
}
-
- // destroy the final elements at the end
- // here, b points to the new end and e to the actual end
- do {
- // Exceptions or not, dtor called once per instance
- --this->size;
- (--e)->~T();
- } while (e != b);
+ this->size -= n;
+ std::destroy(b, e);
}
- void erase(GrowsBackwardsTag, T *b, T *e)
+ void eraseFirst() noexcept
{
Q_ASSERT(this->isMutable());
- Q_ASSERT(b < e);
- Q_ASSERT(b >= this->begin() && b < this->end());
- Q_ASSERT(e > this->begin() && e <= this->end());
-
- const T *const begin = this->begin();
-
- // move (by assignment) the elements from begin to b
- // onto the new begin to e
- while (b != begin) {
- --b;
- --e;
- *e = *b;
- }
+ Q_ASSERT(this->size);
+ this->begin()->~T();
+ ++this->ptr;
+ --this->size;
+ }
- // destroy the final elements at the begin
- // here, e points to the new begin and b to the actual begin
- do {
- // Exceptions or not, dtor called once per instance
- ++this->ptr;
- --this->size;
- (b++)->~T();
- } while (b != e);
+ void eraseLast() noexcept
+ {
+ Q_ASSERT(this->isMutable());
+ Q_ASSERT(this->size);
+ (this->end() - 1)->~T();
+ --this->size;
}
+
void assign(T *b, T *e, parameter_type t)
{
Q_ASSERT(b <= e);
@@ -866,144 +671,186 @@ template <class T>
struct QMovableArrayOps
: QGenericArrayOps<T>
{
- // using QGenericArrayOps<T>::appendInitialize;
+ static_assert (std::is_nothrow_destructible_v<T>, "Types with throwing destructors are not supported in Qt containers.");
+
+protected:
+ typedef QTypedArrayData<T> Data;
+ using DataPointer = QArrayDataPointer<T>;
+
+public:
// using QGenericArrayOps<T>::copyAppend;
// using QGenericArrayOps<T>::moveAppend;
// using QGenericArrayOps<T>::truncate;
// using QGenericArrayOps<T>::destroyAll;
typedef typename QGenericArrayOps<T>::parameter_type parameter_type;
- void insert(T *where, const T *b, const T *e)
- { insert(GrowsForwardTag{}, where, b, e); }
-
- void insert(GrowsForwardTag, T *where, const T *b, const T *e)
+ struct Inserter
{
- Q_ASSERT(this->isMutable() || (b == e && where == this->end()));
- Q_ASSERT(!this->isShared() || (b == e && where == this->end()));
- Q_ASSERT(where >= this->begin() && where <= this->end());
- Q_ASSERT(b <= e);
- Q_ASSERT(e <= where || b > this->end() || where == this->end()); // No overlap or append
- Q_ASSERT((e - b) <= this->freeSpaceAtEnd());
+ QArrayDataPointer<T> *data;
+ T *displaceFrom;
+ T *displaceTo;
+ qsizetype nInserts = 0;
+ qsizetype bytes;
- typedef typename QArrayExceptionSafetyPrimitives<T>::Displacer ReversibleDisplace;
- typedef typename QArrayExceptionSafetyPrimitives<T>::Constructor CopyConstructor;
+ qsizetype increment = 1;
- // Provides strong exception safety guarantee,
- // provided T::~T() nothrow
+ Inserter(QArrayDataPointer<T> *d, QArrayData::GrowthPosition pos)
+ : data(d), increment(pos == QArrayData::GrowsAtBeginning ? -1 : 1)
+ {
+ }
+ ~Inserter() {
+ if constexpr (!std::is_nothrow_copy_constructible_v<T>) {
+ if (displaceFrom != displaceTo) {
+ ::memmove(static_cast<void *>(displaceFrom), static_cast<void *>(displaceTo), bytes);
+ nInserts -= qAbs(displaceFrom - displaceTo);
+ }
+ }
+ if (increment < 0)
+ data->ptr -= nInserts;
+ data->size += nInserts;
+ }
- ReversibleDisplace displace(where, this->end(), e - b);
- CopyConstructor copier(where);
- const auto copiedSize = copier.copy(b, e);
- displace.commit();
- this->size += copiedSize;
- }
+ T *displace(qsizetype pos, qsizetype n)
+ {
+ nInserts = n;
+ T *insertionPoint = data->ptr + pos;
+ if (increment > 0) {
+ displaceFrom = data->ptr + pos;
+ displaceTo = displaceFrom + n;
+ bytes = data->size - pos;
+ } else {
+ displaceFrom = data->ptr;
+ displaceTo = displaceFrom - n;
+ --insertionPoint;
+ bytes = pos;
+ }
+ bytes *= sizeof(T);
+ ::memmove(static_cast<void *>(displaceTo), static_cast<void *>(displaceFrom), bytes);
+ return insertionPoint;
+ }
- void insert(GrowsBackwardsTag, T *where, const T *b, const T *e)
- {
- Q_ASSERT(this->isMutable() || (b == e && where == this->end()));
- Q_ASSERT(!this->isShared() || (b == e && where == this->end()));
- Q_ASSERT(where >= this->begin() && where <= this->end());
- Q_ASSERT(b <= e);
- Q_ASSERT(e <= where || b > this->end() || where == this->end()); // No overlap or append
- Q_ASSERT((e - b) <= this->freeSpaceAtBegin());
+ void insert(qsizetype pos, const T *source, qsizetype n)
+ {
+ T *where = displace(pos, n);
- typedef typename QArrayExceptionSafetyPrimitives<T>::Constructor CopyConstructor;
- typedef typename QArrayExceptionSafetyPrimitives<T>::Displacer ReversibleDisplace;
+ if (increment < 0)
+ source += n - 1;
- // Provides strong exception safety guarantee,
- // provided T::~T() nothrow
+ while (n--) {
+ new (where) T(*source);
+ where += increment;
+ source += increment;
+ displaceFrom += increment;
+ }
+ }
- ReversibleDisplace displace(this->begin(), where, -(e - b));
- CopyConstructor copier(where - (e - b));
- const auto copiedSize = copier.copy(b, e);
- displace.commit();
- this->ptr -= copiedSize;
- this->size += copiedSize;
- }
+ void insert(qsizetype pos, const T &t, qsizetype n)
+ {
+ T *where = displace(pos, n);
- void insert(T *where, size_t n, parameter_type t)
- { insert(GrowsForwardTag{}, where, n, t); }
+ while (n--) {
+ new (where) T(t);
+ where += increment;
+ displaceFrom += increment;
+ }
+ }
- void insert(GrowsForwardTag, T *where, size_t n, parameter_type t)
- {
- Q_ASSERT(!this->isShared() || (n == 0 && where == this->end()));
- Q_ASSERT(where >= this->begin() && where <= this->end());
- Q_ASSERT(size_t(this->freeSpaceAtEnd()) >= n);
+ void insertOne(qsizetype pos, T &&t)
+ {
+ T *where = displace(pos, 1);
+ new (where) T(std::move(t));
+ displaceFrom += increment;
+ Q_ASSERT(displaceFrom == displaceTo);
+ }
+
+ };
- typedef typename QArrayExceptionSafetyPrimitives<T>::Displacer ReversibleDisplace;
- typedef typename QArrayExceptionSafetyPrimitives<T>::Constructor CopyConstructor;
- // Provides strong exception safety guarantee,
- // provided T::~T() nothrow
+ void insert(qsizetype i, const T *data, qsizetype n)
+ {
+ typename Data::GrowthPosition pos = Data::GrowsAtEnd;
+ if (this->size != 0 && i <= (this->size >> 1))
+ pos = Data::GrowsAtBeginning;
+ DataPointer oldData;
+ this->detachAndGrow(pos, n, &oldData);
+ Q_ASSERT((pos == Data::GrowsAtBeginning && this->freeSpaceAtBegin() >= n) ||
+ (pos == Data::GrowsAtEnd && this->freeSpaceAtEnd() >= n));
- ReversibleDisplace displace(where, this->end(), qsizetype(n));
- CopyConstructor copier(where);
- const auto copiedSize = copier.clone(n, t);
- displace.commit();
- this->size += copiedSize;
+ Inserter(this, pos).insert(i, data, n);
}
- void insert(GrowsBackwardsTag, T *where, size_t n, parameter_type t)
+ void insert(qsizetype i, qsizetype n, parameter_type t)
{
- Q_ASSERT(!this->isShared() || (n == 0 && where == this->end()));
- Q_ASSERT(where >= this->begin() && where <= this->end());
- Q_ASSERT(size_t(this->freeSpaceAtBegin()) >= n);
-
- typedef typename QArrayExceptionSafetyPrimitives<T>::Constructor CopyConstructor;
- typedef typename QArrayExceptionSafetyPrimitives<T>::Displacer ReversibleDisplace;
-
- // Provides strong exception safety guarantee,
- // provided T::~T() nothrow
-
- ReversibleDisplace displace(this->begin(), where, -qsizetype(n));
- CopyConstructor copier(where - n);
- const auto copiedSize = copier.clone(n, t);
- displace.commit();
- this->ptr -= copiedSize;
- this->size += copiedSize;
- }
+ T copy(t);
- // use moving insert
- using QGenericArrayOps<T>::insert;
+ typename Data::GrowthPosition pos = Data::GrowsAtEnd;
+ if (this->size != 0 && i <= (this->size >> 1))
+ pos = Data::GrowsAtBeginning;
+ this->detachAndGrow(pos, n);
+ Q_ASSERT((pos == Data::GrowsAtBeginning && this->freeSpaceAtBegin() >= n) ||
+ (pos == Data::GrowsAtEnd && this->freeSpaceAtEnd() >= n));
- void erase(T *b, T *e)
- { erase(GrowsForwardTag{}, b, e); }
+ Inserter(this, pos).insert(i, copy, n);
+ }
- void erase(GrowsForwardTag, T *b, T *e)
+ template<typename... Args>
+ void emplace(qsizetype i, Args &&... args)
{
- Q_ASSERT(this->isMutable());
- Q_ASSERT(b < e);
- Q_ASSERT(b >= this->begin() && b < this->end());
- Q_ASSERT(e > this->begin() && e <= this->end());
-
- typedef typename QArrayExceptionSafetyPrimitives<T>::Mover Mover;
-
- Mover mover(e, static_cast<const T *>(this->end()) - e, this->size);
+ bool detach = this->needsDetach();
+ if (!detach) {
+ if (i == this->size && this->freeSpaceAtEnd()) {
+ new (this->end()) T(std::forward<Args>(args)...);
+ ++this->size;
+ return;
+ }
+ if (i == 0 && this->freeSpaceAtBegin()) {
+ new (this->begin() - 1) T(std::forward<Args>(args)...);
+ --this->ptr;
+ ++this->size;
+ return;
+ }
+ }
+ T tmp(std::forward<Args>(args)...);
+ typename QArrayData::GrowthPosition pos = QArrayData::GrowsAtEnd;
+ if (this->size != 0 && i <= (this->size >> 1))
+ pos = QArrayData::GrowsAtBeginning;
+ if (detach ||
+ (pos == QArrayData::GrowsAtBeginning && !this->freeSpaceAtBegin()) ||
+ (pos == QArrayData::GrowsAtEnd && !this->freeSpaceAtEnd()))
+ this->reallocateAndGrow(pos, 1);
- // destroy the elements we're erasing
- do {
- // Exceptions or not, dtor called once per instance
- (--e)->~T();
- } while (e != b);
+ Inserter(this, pos).insertOne(i, std::move(tmp));
}
- void erase(GrowsBackwardsTag, T *b, T *e)
+ void erase(T *b, qsizetype n)
{
+ T *e = b + n;
+
Q_ASSERT(this->isMutable());
Q_ASSERT(b < e);
Q_ASSERT(b >= this->begin() && b < this->end());
Q_ASSERT(e > this->begin() && e <= this->end());
- typedef typename QArrayExceptionSafetyPrimitives<T>::Mover Mover;
+ // Comply with std::vector::erase(): erased elements and all after them
+ // are invalidated. However, erasing from the beginning effectively
+ // means that all iterators are invalidated. We can use this freedom to
+ // erase by moving towards the end.
- Mover mover(this->ptr, b - static_cast<const T *>(this->begin()), this->size);
+ std::destroy(b, e);
+ if (b == this->begin()) {
+ this->ptr = e;
+ } else if (e != this->end()) {
+ memmove(static_cast<void *>(b), static_cast<const void *>(e), (static_cast<const T *>(this->end()) - e)*sizeof(T));
+ }
+ this->size -= n;
+ }
- // destroy the elements we're erasing
- do {
- // Exceptions or not, dtor called once per instance
- ++this->ptr;
- (b++)->~T();
- } while (b != e);
+ void reallocate(qsizetype alloc, QArrayData::AllocationOption option)
+ {
+ auto pair = Data::reallocateUnaligned(this->d, this->ptr, alloc, option);
+ Q_ASSERT(pair.first != nullptr);
+ this->d = pair.first;
+ this->ptr = pair.second;
}
};
@@ -1035,354 +882,27 @@ template <class T>
struct QCommonArrayOps : QArrayOpsSelector<T>::Type
{
using Base = typename QArrayOpsSelector<T>::Type;
+ using Data = QTypedArrayData<T>;
+ using DataPointer = QArrayDataPointer<T>;
using parameter_type = typename Base::parameter_type;
- using iterator = typename Base::iterator;
- using const_iterator = typename Base::const_iterator;
protected:
using Self = QCommonArrayOps<T>;
- // Tag dispatched helper functions
- inline void adjustPointer(GrowsBackwardsTag, size_t distance) noexcept
- {
- this->ptr -= distance;
- }
- inline void adjustPointer(GrowsForwardTag, size_t distance) noexcept
- {
- this->ptr += distance;
- }
- qsizetype freeSpace(GrowsBackwardsTag) const noexcept { return this->freeSpaceAtBegin(); }
- qsizetype freeSpace(GrowsForwardTag) const noexcept { return this->freeSpaceAtEnd(); }
-
- struct RelocatableMoveOps
- {
- // The necessary evil. Performs move "to the left" when grows backwards and
- // move "to the right" when grows forward
- template<typename GrowthTag>
- static void moveInGrowthDirection(GrowthTag tag, Self *this_, size_t futureGrowth)
- {
- Q_ASSERT(this_->isMutable());
- Q_ASSERT(!this_->isShared());
- Q_ASSERT(futureGrowth <= size_t(this_->freeSpace(tag)));
-
- const auto oldBegin = this_->begin();
- this_->adjustPointer(tag, futureGrowth);
-
- // Note: move all elements!
- ::memmove(static_cast<void *>(this_->begin()), static_cast<const void *>(oldBegin),
- this_->size * sizeof(T));
- }
- };
-
- struct GenericMoveOps
- {
- template <typename ...Args>
- static void createInPlace(T *where, Args&&... args)
- {
- new (where) T(std::forward<Args>(args)...);
- }
-
- template <typename ...Args>
- static void createInPlace(std::reverse_iterator<iterator> where, Args&&... args)
- {
- // Note: instead of std::addressof(*where)
- createInPlace(where.base() - 1, std::forward<Args>(args)...);
- }
-
- // Moves non-pod data range. Handles overlapping regions. By default, expect
- // this method to perform move to the _right_. When move to the _left_ is
- // needed, use reverse iterators.
- template<typename GrowthTag, typename It>
- static void moveNonPod(GrowthTag, Self *this_, It where, It begin, It end)
- {
- Q_ASSERT(begin <= end);
- Q_ASSERT(where > begin); // move to the right
-
- using Destructor = typename QArrayExceptionSafetyPrimitives<T>::template Destructor<It>;
-
- auto start = where + std::distance(begin, end);
- auto e = end;
-
- Destructor destroyer(start); // Keep track of added items
-
- auto [oldRangeEnd, overlapStart] = std::minmax(where, end);
-
- // step 1. move-initialize elements in uninitialized memory region
- while (start != overlapStart) {
- --e;
- createInPlace(start - 1, std::move_if_noexcept(*e));
- // change tracked iterator only after creation succeeded - avoid
- // destructing partially constructed objects if exception thrown
- --start;
- }
-
- // re-created the range. now there is an initialized memory region
- // somewhere in the allocated area. if something goes wrong, we must
- // clean it up, so "freeze" the position for now (cannot commit yet)
- destroyer.freeze();
-
- // step 2. move assign over existing elements in the overlapping
- // region (if there's an overlap)
- while (e != begin) {
- --start;
- --e;
- *start = std::move_if_noexcept(*e);
- }
-
- // step 3. destroy elements in the old range
- const qsizetype originalSize = this_->size;
- start = begin; // delete elements in reverse order to prevent any gaps
- while (start != oldRangeEnd) {
- // Exceptions or not, dtor called once per instance
- if constexpr (std::is_same_v<std::decay_t<GrowthTag>, GrowsForwardTag>)
- ++this_->ptr;
- --this_->size;
- (start++)->~T();
- }
-
- destroyer.commit();
- // restore old size as we consider data move to be done, the pointer
- // still has to be adjusted!
- this_->size = originalSize;
- }
-
- // Super inefficient function. The necessary evil. Performs move "to
- // the left" when grows backwards and move "to the right" when grows
- // forward
- template<typename GrowthTag>
- static void moveInGrowthDirection(GrowthTag tag, Self *this_, size_t futureGrowth)
- {
- Q_ASSERT(this_->isMutable());
- Q_ASSERT(!this_->isShared());
- Q_ASSERT(futureGrowth <= size_t(this_->freeSpace(tag)));
-
- if (futureGrowth == 0) // avoid doing anything if there's no need
- return;
-
- // Note: move all elements!
- if constexpr (std::is_same_v<std::decay_t<GrowthTag>, GrowsBackwardsTag>) {
- auto where = this_->begin() - futureGrowth;
- // here, magic happens. instead of having move to the right, we'll
- // have move to the left by using reverse iterators
- moveNonPod(tag, this_,
- std::make_reverse_iterator(where + this_->size), // rwhere
- std::make_reverse_iterator(this_->end()), // rbegin
- std::make_reverse_iterator(this_->begin())); // rend
- this_->ptr = where;
- } else {
- auto where = this_->begin() + futureGrowth;
- moveNonPod(tag, this_, where, this_->begin(), this_->end());
- this_->ptr = where;
- }
- }
- };
-
- // Moves all elements in a specific direction by moveSize if available
- // free space at one of the ends is smaller than required. Free space
- // becomes available at the beginning if grows backwards and at the end
- // if grows forward
- template<typename GrowthTag>
- qsizetype prepareFreeSpace(GrowthTag tag, size_t required, size_t moveSize)
- {
- Q_ASSERT(this->isMutable() || required == 0);
- Q_ASSERT(!this->isShared() || required == 0);
- Q_ASSERT(required <= this->constAllocatedCapacity() - this->size);
-
- using MoveOps = std::conditional_t<QTypeInfo<T>::isRelocatable,
- RelocatableMoveOps,
- GenericMoveOps>;
-
- // if free space at the end is not enough, we need to move the data,
- // move is performed in an inverse direction
- if (size_t(freeSpace(tag)) < required) {
- using MoveTag = typename InverseTag<std::decay_t<GrowthTag>>::tag;
- MoveOps::moveInGrowthDirection(MoveTag{}, this, moveSize);
-
- if constexpr (std::is_same_v<MoveTag, GrowsBackwardsTag>) {
- return -qsizetype(moveSize); // moving data to the left
- } else {
- return qsizetype(moveSize); // moving data to the right
- }
- }
- return 0;
- }
-
- // Helper wrapper that adjusts passed iterators along with moving the data
- // around. The adjustment is necessary when iterators point inside the
- // to-be-moved range
- template<typename GrowthTag, typename It>
- void prepareFreeSpace(GrowthTag tag, size_t required, size_t moveSize, It &b, It &e) {
- // Returns whether passed iterators are inside [this->begin(), this->end()]
- const auto iteratorsInRange = [&] (const It &first, const It &last) {
- using DecayedIt = std::decay_t<It>;
- using RemovedConstVolatileIt = std::remove_cv_t<It>;
- constexpr bool selfIterator =
- // if passed type is an iterator type:
- std::is_same_v<DecayedIt, iterator>
- || std::is_same_v<DecayedIt, const_iterator>
- // if passed type is a pointer type:
- || std::is_same_v<RemovedConstVolatileIt, T *>
- || std::is_same_v<RemovedConstVolatileIt, const T *>
- || std::is_same_v<RemovedConstVolatileIt, const volatile T *>;
- if constexpr (selfIterator) {
- return (first >= this->begin() && last <= this->end());
- } else {
- return false;
- }
- };
-
- const bool inRange = iteratorsInRange(b, e);
- const auto diff = prepareFreeSpace(tag, required, moveSize);
- if (inRange) {
- std::advance(b, diff);
- std::advance(e, diff);
- }
- }
-
- size_t moveSizeForAppend(size_t)
- {
- // Qt5 QList in append: make 100% free space at end if not enough space
- // Now:
- return this->freeSpaceAtBegin();
- }
-
- size_t moveSizeForPrepend(size_t required)
- {
- // Qt5 QList in prepend: make 33% of all space at front if not enough space
- // Now:
- qsizetype space = this->allocatedCapacity() / 3;
- space = qMax(space, qsizetype(required)); // in case required > 33% of all space
- return qMin(space, this->freeSpaceAtEnd());
- }
-
- // Helper functions that reduce usage boilerplate
- void prepareSpaceForAppend(size_t required)
- {
- prepareFreeSpace(GrowsForwardTag{}, required, moveSizeForAppend(required));
- }
- void prepareSpaceForPrepend(size_t required)
- {
- prepareFreeSpace(GrowsBackwardsTag{}, required, moveSizeForPrepend(required));
- }
- template<typename It>
- void prepareSpaceForAppend(It &b, It &e, size_t required)
- {
- prepareFreeSpace(GrowsForwardTag{}, required, moveSizeForAppend(required), b, e);
- }
- template<typename It>
- void prepareSpaceForPrepend(It &b, It &e, size_t required)
- {
- prepareFreeSpace(GrowsBackwardsTag{}, required, moveSizeForPrepend(required), b, e);
- }
-
- // Tells how much of the given size to insert at the beginning of the
- // container. This is insert-specific helper function
- qsizetype sizeToInsertAtBegin(const T *const where, qsizetype maxSize)
- {
- Q_ASSERT(size_t(maxSize) <= this->allocatedCapacity() - this->size);
- Q_ASSERT(where >= this->begin() && where <= this->end()); // in range
-
- const auto freeAtBegin = this->freeSpaceAtBegin();
- const auto freeAtEnd = this->freeSpaceAtEnd();
-
- // Idea: * if enough space on both sides, try to affect less elements
- // * if enough space on one of the sides, use only that side
- // * otherwise, split between front and back (worst case)
- if (freeAtBegin >= maxSize && freeAtEnd >= maxSize) {
- if (where - this->begin() < this->end() - where) {
- return maxSize;
- } else {
- return 0;
- }
- } else if (freeAtBegin >= maxSize) {
- return maxSize;
- } else if (freeAtEnd >= maxSize) {
- return 0;
- } else {
- return maxSize - freeAtEnd;
- }
- }
-
public:
- // Returns whether reallocation is desirable before adding more elements
- // into the container. This is a helper function that one can use to
- // theoretically improve average operations performance. Ignoring this
- // function does not affect the correctness of the array operations.
- bool shouldGrowBeforeInsert(const_iterator where, qsizetype n) const noexcept
- {
- if (this->d == nullptr)
- return true;
- if (this->d->flags & QArrayData::CapacityReserved)
- return false;
- if (!(this->d->flags & (QArrayData::GrowsForward | QArrayData::GrowsBackwards)))
- return false;
- Q_ASSERT(where >= this->begin() && where <= this->end()); // in range
-
- const qsizetype freeAtBegin = this->freeSpaceAtBegin();
- const qsizetype freeAtEnd = this->freeSpaceAtEnd();
- const qsizetype capacity = this->constAllocatedCapacity();
-
- if (this->size > 0 && where == this->begin()) { // prepend
- // Qt5 QList in prepend: not enough space at begin && 33% full
- // Now (below):
- return freeAtBegin < n && (this->size >= (capacity / 3));
- }
-
- if (where == this->end()) { // append
- // Qt5 QList in append: not enough space at end && less than 66% free space at front
- // Now (below):
- return freeAtEnd < n && !((freeAtBegin - n) >= (2 * capacity / 3));
- }
-
- // Qt5 QList in insert: no free space
- // Now: no free space OR not enough space on either of the sides (bad perf. case)
- return (freeAtBegin + freeAtEnd) < n || (freeAtBegin < n && freeAtEnd < n);
- }
-
// using Base::truncate;
// using Base::destroyAll;
// using Base::assign;
// using Base::compare;
- void appendInitialize(size_t newSize)
- {
- Q_ASSERT(this->isMutable());
- Q_ASSERT(!this->isShared());
- Q_ASSERT(newSize > size_t(this->size));
- Q_ASSERT(newSize <= this->allocatedCapacity());
-
- // Since this is mostly an initialization function, do not follow append
- // logic of space arrangement. Instead, only prepare as much free space
- // as needed for this specific operation
- const size_t n = newSize - this->size;
- prepareFreeSpace(GrowsForwardTag{}, n,
- qMin(n, size_t(this->freeSpaceAtBegin()))); // ### perf. loss
-
- Base::appendInitialize(newSize);
- }
-
- void copyAppend(const T *b, const T *e)
- {
- Q_ASSERT(this->isMutable() || b == e);
- Q_ASSERT(!this->isShared() || b == e);
- Q_ASSERT(b <= e);
- Q_ASSERT(size_t(e - b) <= this->allocatedCapacity() - this->size);
-
- prepareSpaceForAppend(b, e, e - b); // ### perf. loss
- Base::insert(GrowsForwardTag{}, this->end(), b, e);
- }
-
template<typename It>
- void copyAppend(It b, It e, QtPrivate::IfIsForwardIterator<It> = true,
- QtPrivate::IfIsNotSame<std::decay_t<It>, iterator> = true,
- QtPrivate::IfIsNotSame<std::decay_t<It>, const_iterator> = true)
+ void appendIteratorRange(It b, It e, QtPrivate::IfIsForwardIterator<It> = true)
{
Q_ASSERT(this->isMutable() || b == e);
Q_ASSERT(!this->isShared() || b == e);
const qsizetype distance = std::distance(b, e);
- Q_ASSERT(distance >= 0 && size_t(distance) <= this->allocatedCapacity() - this->size);
-
- prepareSpaceForAppend(b, e, distance); // ### perf. loss
+ Q_ASSERT(distance >= 0 && distance <= this->allocatedCapacity() - this->size);
+ Q_UNUSED(distance);
T *iter = this->end();
for (; b != e; ++iter, ++b) {
@@ -1390,125 +910,6 @@ public:
++this->size;
}
}
-
- void moveAppend(T *b, T *e)
- {
- Q_ASSERT(this->isMutable() || b == e);
- Q_ASSERT(!this->isShared() || b == e);
- Q_ASSERT(b <= e);
- Q_ASSERT(size_t(e - b) <= this->allocatedCapacity() - this->size);
-
- prepareSpaceForAppend(b, e, e - b); // ### perf. loss
- Base::moveAppend(b, e);
- }
-
- void copyAppend(size_t n, parameter_type t)
- {
- Q_ASSERT(!this->isShared() || n == 0);
- Q_ASSERT(this->allocatedCapacity() - size_t(this->size) >= n);
-
- // Preserve the value, because it might be a reference to some part of the moved chunk
- T tmp(t);
- prepareSpaceForAppend(n); // ### perf. loss
- Base::insert(GrowsForwardTag{}, this->end(), n, tmp);
- }
-
- void insert(T *where, const T *b, const T *e)
- {
- Q_ASSERT(this->isMutable() || (b == e && where == this->end()));
- Q_ASSERT(!this->isShared() || (b == e && where == this->end()));
- Q_ASSERT(where >= this->begin() && where <= this->end());
- Q_ASSERT(b <= e);
- Q_ASSERT(e <= where || b > this->end() || where == this->end()); // No overlap or append
- Q_ASSERT(size_t(e - b) <= this->allocatedCapacity() - this->size);
-
- if (this->size > 0 && where == this->begin()) { // prepend case - special space arrangement
- prepareSpaceForPrepend(b, e, e - b); // ### perf. loss
- Base::insert(GrowsBackwardsTag{}, this->begin(), b, e);
- return;
- } else if (where == this->end()) { // append case - special space arrangement
- copyAppend(b, e);
- return;
- }
-
- // Insert elements based on the divided distance. Good case: only 1
- // insert happens (either to the front part or to the back part). Bad
- // case: both inserts happen, meaning that we touch all N elements in
- // the container (this should be handled "outside" by ensuring enough
- // free space by reallocating more frequently)
- const auto k = sizeToInsertAtBegin(where, e - b);
- Base::insert(GrowsBackwardsTag{}, where, b, b + k);
- Base::insert(GrowsForwardTag{}, where, b + k, e);
- }
-
- void insert(T *where, size_t n, parameter_type t)
- {
- Q_ASSERT(!this->isShared() || (n == 0 && where == this->end()));
- Q_ASSERT(where >= this->begin() && where <= this->end());
- Q_ASSERT(this->allocatedCapacity() - size_t(this->size) >= n);
-
- if (this->size > 0 && where == this->begin()) { // prepend case - special space arrangement
- // Preserve the value, because it might be a reference to some part of the moved chunk
- T tmp(t);
- prepareSpaceForPrepend(n); // ### perf. loss
- Base::insert(GrowsBackwardsTag{}, this->begin(), n, tmp);
- return;
- } else if (where == this->end()) { // append case - special space arrangement
- copyAppend(n, t);
- return;
- }
-
- // Insert elements based on the divided distance. Good case: only 1
- // insert happens (either to the front part or to the back part). Bad
- // case: both inserts happen, meaning that we touch all N elements in
- // the container (this should be handled "outside" by ensuring enough
- // free space by reallocating more frequently)
- const auto beginSize = sizeToInsertAtBegin(where, qsizetype(n));
- Base::insert(GrowsBackwardsTag{}, where, beginSize, t);
- Base::insert(GrowsForwardTag{}, where, qsizetype(n) - beginSize, t);
- }
-
- template <typename iterator, typename ...Args>
- void emplace(iterator where, Args&&... args)
- {
- Q_ASSERT(!this->isShared());
- Q_ASSERT(where >= this->begin() && where <= this->end());
- Q_ASSERT(this->allocatedCapacity() - this->size >= 1);
-
- // Qt5 QList in insert(1): try to move less data around
- // Now:
- const bool shouldInsertAtBegin = (where - this->begin()) < (this->end() - where)
- || this->freeSpaceAtEnd() <= 0;
- if (this->freeSpaceAtBegin() > 0 && shouldInsertAtBegin) {
- Base::emplace(GrowsBackwardsTag{}, where, std::forward<Args>(args)...);
- } else {
- Base::emplace(GrowsForwardTag{}, where, std::forward<Args>(args)...);
- }
- }
-
- template <typename ...Args>
- void emplaceBack(Args&&... args)
- {
- this->emplace(this->end(), std::forward<Args>(args)...);
- }
-
- void erase(T *b, T *e)
- {
- Q_ASSERT(this->isMutable());
- Q_ASSERT(b < e);
- Q_ASSERT(b >= this->begin() && b < this->end());
- Q_ASSERT(e > this->begin() && e <= this->end());
-
- // Comply with std::vector::erase(): erased elements and all after them
- // are invalidated. However, erasing from the beginning effectively
- // means that all iterators are invalidated. We can use this freedom to
- // erase by moving towards the end.
- if (b == this->begin()) {
- Base::erase(GrowsBackwardsTag{}, b, e);
- } else {
- Base::erase(GrowsForwardTag{}, b, e);
- }
- }
};
} // namespace QtPrivate
diff --git a/src/corelib/tools/qarraydatapointer.h b/src/corelib/tools/qarraydatapointer.h
index ad5acdb7fd..aa94819b35 100644
--- a/src/corelib/tools/qarraydatapointer.h
+++ b/src/corelib/tools/qarraydatapointer.h
@@ -53,9 +53,10 @@ private:
typedef QArrayDataOps<T> DataOps;
public:
- typedef typename Data::iterator iterator;
- typedef typename Data::const_iterator const_iterator;
- enum { pass_parameter_by_value = std::is_fundamental<T>::value || std::is_pointer<T>::value };
+ enum {
+ pass_parameter_by_value =
+ std::is_arithmetic<T>::value || std::is_pointer<T>::value || std::is_enum<T>::value
+ };
typedef typename std::conditional<pass_parameter_by_value, T, const T &>::type parameter_type;
@@ -101,12 +102,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
{
@@ -144,12 +140,12 @@ public:
T *data() noexcept { return ptr; }
const T *data() const noexcept { return ptr; }
- iterator begin(iterator = iterator()) noexcept { return data(); }
- iterator end(iterator = iterator()) noexcept { return data() + size; }
- const_iterator begin(const_iterator = const_iterator()) const noexcept { return data(); }
- const_iterator end(const_iterator = const_iterator()) const noexcept { return data() + size; }
- const_iterator constBegin(const_iterator = const_iterator()) const noexcept { return data(); }
- const_iterator constEnd(const_iterator = const_iterator()) const noexcept { return data() + size; }
+ T *begin() noexcept { return data(); }
+ T *end() noexcept { return data() + size; }
+ const T *begin() const noexcept { return data(); }
+ const T *end() const noexcept { return data() + size; }
+ const T *constBegin() const noexcept { return data(); }
+ const T *constEnd() const noexcept { return data() + size; }
void swap(QArrayDataPointer &other) noexcept
{
@@ -164,33 +160,70 @@ public:
swap(tmp);
}
- bool detach()
+ void detach(QArrayDataPointer *old = nullptr)
{
- if (needsDetach()) {
- QPair<Data *, T *> copy = clone(detachFlags());
- QArrayDataPointer old(d, ptr, size);
- d = copy.first;
- ptr = copy.second;
- return true;
+ if (needsDetach())
+ reallocateAndGrow(QArrayData::GrowsAtEnd, 0, old);
+ }
+
+ // pass in a pointer to a default constructed QADP, to keep it alive beyond the detach() call
+ void detachAndGrow(QArrayData::GrowthPosition where, qsizetype n, QArrayDataPointer *old = nullptr)
+ {
+ if (!needsDetach()) {
+ if (!n ||
+ (where == QArrayData::GrowsAtBeginning && freeSpaceAtBegin() >= n) ||
+ (where == QArrayData::GrowsAtEnd && freeSpaceAtEnd() >= n))
+ return;
}
+ reallocateAndGrow(where, n, old);
+ }
- return false;
+ Q_NEVER_INLINE void reallocateAndGrow(QArrayData::GrowthPosition where, qsizetype n, QArrayDataPointer *old = nullptr)
+ {
+ if constexpr (QTypeInfo<T>::isRelocatable && alignof(T) <= alignof(std::max_align_t)) {
+ if (where == QArrayData::GrowsAtEnd && !old && !needsDetach() && n > 0) {
+ (*this)->reallocate(constAllocatedCapacity() - freeSpaceAtEnd() + n, QArrayData::Grow); // fast path
+ return;
+ }
+ }
+
+ QArrayDataPointer dp(allocateGrow(*this, n, where));
+ if (where == QArrayData::GrowsAtBeginning) {
+ dp.ptr += n;
+ Q_ASSERT(dp.freeSpaceAtBegin() >= n);
+ } else {
+ Q_ASSERT(dp.freeSpaceAtEnd() >= n);
+ }
+ if (size) {
+ qsizetype toCopy = size;
+ if (n < 0)
+ toCopy += n;
+ if (needsDetach() || old)
+ dp->copyAppend(begin(), begin() + toCopy);
+ else
+ dp->moveAppend(begin(), begin() + toCopy);
+ dp.d->flags = flags();
+ Q_ASSERT(dp.size == toCopy);
+ }
+
+ swap(dp);
+ if (old)
+ old->swap(dp);
}
// forwards from QArrayData
- size_t allocatedCapacity() noexcept { return d ? d->allocatedCapacity() : 0; }
- size_t constAllocatedCapacity() const noexcept { return d ? d->constAllocatedCapacity() : 0; }
+ qsizetype allocatedCapacity() noexcept { return d ? d->allocatedCapacity() : 0; }
+ qsizetype constAllocatedCapacity() const noexcept { return d ? d->constAllocatedCapacity() : 0; }
void ref() noexcept { if (d) d->ref(); }
bool deref() noexcept { return !d || d->deref(); }
bool isMutable() const noexcept { return d; }
bool isShared() const noexcept { return !d || d->isShared(); }
bool isSharedWith(const QArrayDataPointer &other) const noexcept { return d && d == other.d; }
bool needsDetach() const noexcept { return !d || d->needsDetach(); }
- size_t detachCapacity(size_t newSize) const noexcept { return d ? d->detachCapacity(newSize) : newSize; }
- const typename Data::ArrayOptions flags() const noexcept { return d ? typename Data::ArrayOption(d->flags) : Data::DefaultAllocationFlags; }
+ qsizetype detachCapacity(qsizetype newSize) const noexcept { return d ? d->detachCapacity(newSize) : newSize; }
+ const typename Data::ArrayOptions flags() const noexcept { return d ? typename Data::ArrayOption(d->flags) : Data::ArrayOptionDefault; }
void setFlag(typename Data::ArrayOptions f) noexcept { Q_ASSERT(d); d->flags |= f; }
- void clearFlag(typename Data::ArrayOptions f) noexcept { Q_ASSERT(d); d->flags &= ~f; }
- typename Data::ArrayOptions detachFlags() const noexcept { return d ? d->detachFlags() : Data::DefaultAllocationFlags; }
+ void clearFlag(typename Data::ArrayOptions f) noexcept { if (d) d->flags &= ~f; }
Data *d_ptr() noexcept { return d; }
void setBegin(T *begin) noexcept { ptr = begin; }
@@ -209,74 +242,50 @@ public:
return d->constAllocatedCapacity() - freeSpaceAtBegin() - this->size;
}
- static QArrayDataPointer allocateGrow(const QArrayDataPointer &from,
- qsizetype newSize, QArrayData::ArrayOptions options)
- {
- return allocateGrow(from, from.detachCapacity(newSize), newSize, options);
- }
-
- static QArrayDataPointer allocateGrow(const QArrayDataPointer &from, qsizetype capacity,
- qsizetype newSize, QArrayData::ArrayOptions options)
+ // allocate and grow. Ensure that at the minimum requiredSpace is available at the requested end
+ static QArrayDataPointer allocateGrow(const QArrayDataPointer &from, qsizetype n, QArrayData::GrowthPosition position)
{
- auto [header, dataPtr] = Data::allocate(capacity, options);
+ // calculate new capacity. We keep the free capacity at the side that does not have to grow
+ // to avoid quadratic behavior with mixed append/prepend cases
+
+ // use qMax below, because constAllocatedCapacity() can be 0 when using fromRawData()
+ qsizetype minimalCapacity = qMax(from.size, from.constAllocatedCapacity()) + n;
+ // subtract the free space at the side we want to allocate. This ensures that the total size requested is
+ // the existing allocation at the other side + size + n.
+ minimalCapacity -= (position == QArrayData::GrowsAtEnd) ? from.freeSpaceAtEnd() : from.freeSpaceAtBegin();
+ qsizetype capacity = from.detachCapacity(minimalCapacity);
+ const bool grows = capacity > from.constAllocatedCapacity();
+ auto [header, dataPtr] = Data::allocate(capacity, grows ? QArrayData::Grow : QArrayData::KeepSize);
const bool valid = header != nullptr && dataPtr != nullptr;
- const bool grows = (options & (Data::GrowsForward | Data::GrowsBackwards));
- if (!valid || !grows)
+ if (!valid)
return QArrayDataPointer(header, dataPtr);
- // when growing, special rules apply to memory layout
+ // Idea: * when growing backwards, adjust pointer to prepare free space at the beginning
+ // * when growing forward, adjust by the previous data pointer offset
- if (from.needsDetach()) {
- // When detaching: the free space reservation is biased towards
- // append as in Qt5 QList. If we're growing backwards, put the data
- // in the middle instead of at the end - assuming that prepend is
- // uncommon and even initial prepend will eventually be followed by
- // at least some appends.
- if (options & Data::GrowsBackwards)
- dataPtr += (header->alloc - newSize) / 2;
- } else {
- // When not detaching: fake ::realloc() policy - preserve existing
- // free space at beginning.
- dataPtr += from.freeSpaceAtBegin();
- }
+ // TODO: what's with CapacityReserved?
+ dataPtr += (position == QArrayData::GrowsAtBeginning) ? qMax(0, (header->alloc - from.size - n) / 2)
+ : from.freeSpaceAtBegin();
+ header->flags = from.flags();
return QArrayDataPointer(header, dataPtr);
}
-private:
- Q_REQUIRED_RESULT QPair<Data *, T *> clone(QArrayData::ArrayOptions options) const
+ friend bool operator==(const QArrayDataPointer &lhs, const QArrayDataPointer &rhs) noexcept
+ {
+ return lhs.data() == rhs.data() && lhs.size == rhs.size;
+ }
+
+ friend bool operator!=(const QArrayDataPointer &lhs, const QArrayDataPointer &rhs) noexcept
{
- QPair<Data *, T *> pair = Data::allocate(detachCapacity(size), options);
- QArrayDataPointer copy(pair.first, pair.second, 0);
- if (size)
- copy->copyAppend(begin(), end());
-
- pair.first = copy.d;
- copy.d = nullptr;
- copy.ptr = nullptr;
- return pair;
+ return lhs.data() != rhs.data() || lhs.size != rhs.size;
}
-protected:
Data *d;
T *ptr;
-
-public:
qsizetype size;
};
template <class T>
-inline bool operator==(const QArrayDataPointer<T> &lhs, const QArrayDataPointer<T> &rhs) noexcept
-{
- return lhs.data() == rhs.data() && lhs.size == rhs.size;
-}
-
-template <class T>
-inline bool operator!=(const QArrayDataPointer<T> &lhs, const QArrayDataPointer<T> &rhs) noexcept
-{
- return lhs.data() != rhs.data() || lhs.size != rhs.size;
-}
-
-template <class T>
inline void qSwap(QArrayDataPointer<T> &p1, QArrayDataPointer<T> &p2) noexcept
{
p1.swap(p2);
diff --git a/src/corelib/tools/qbitarray.cpp b/src/corelib/tools/qbitarray.cpp
index 9bcd6a9306..18ce7035d9 100644
--- a/src/corelib/tools/qbitarray.cpp
+++ b/src/corelib/tools/qbitarray.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2020 The Qt Company Ltd.
** Copyright (C) 2019 Intel Corporation.
** Contact: https://www.qt.io/licensing/
**
@@ -137,35 +137,35 @@ QT_BEGIN_NAMESPACE
* *d.constData() is the QByteArray's terminating NUL (0) byte.
*
* This allows for fast calculation of the bit array size:
- * inline int size() const { return (d.size() << 3) - *d.constData(); }
+ * inline qsizetype size() const { return (d.size() << 3) - *d.constData(); }
*/
/*!
Constructs a bit array containing \a size bits. The bits are
initialized with \a value, which defaults to false (0).
*/
-QBitArray::QBitArray(int size, bool value)
- : d(size <= 0 ? 0 : 1 + (size + 7)/8, Qt::Uninitialized)
+QBitArray::QBitArray(qsizetype size, bool value)
+ : d(size <= 0 ? 0 : 1 + (size + 7) / 8, Qt::Uninitialized)
{
Q_ASSERT_X(size >= 0, "QBitArray::QBitArray", "Size must be greater than or equal to 0.");
if (size <= 0)
return;
- uchar* c = reinterpret_cast<uchar*>(d.data());
+ uchar *c = reinterpret_cast<uchar *>(d.data());
memset(c + 1, value ? 0xff : 0, d.size() - 1);
- *c = d.size()*8 - size;
+ *c = d.size() * 8 - size;
if (value && size && size & 7)
- *(c+1+size/8) &= (1 << (size & 7)) - 1;
+ *(c + 1 + size / 8) &= (1 << (size & 7)) - 1;
}
-/*! \fn int QBitArray::size() const
+/*! \fn qsizetype QBitArray::size() const
Returns the number of bits stored in the bit array.
\sa resize()
*/
-/*! \fn int QBitArray::count() const
+/*! \fn qsizetype QBitArray::count() const
Same as size().
*/
@@ -175,9 +175,9 @@ QBitArray::QBitArray(int size, bool value)
1-bits stored in the bit array; otherwise the number
of 0-bits is returned.
*/
-int QBitArray::count(bool on) const
+qsizetype QBitArray::count(bool on) const
{
- int numBits = 0;
+ qsizetype numBits = 0;
const quint8 *bits = reinterpret_cast<const quint8 *>(d.data()) + 1;
// the loops below will try to read from *end
@@ -187,20 +187,20 @@ int QBitArray::count(bool on) const
while (bits + 7 <= end) {
quint64 v = qFromUnaligned<quint64>(bits);
bits += 8;
- numBits += int(qPopulationCount(v));
+ numBits += qsizetype(qPopulationCount(v));
}
if (bits + 3 <= end) {
quint32 v = qFromUnaligned<quint32>(bits);
bits += 4;
- numBits += int(qPopulationCount(v));
+ numBits += qsizetype(qPopulationCount(v));
}
if (bits + 1 < end) {
quint16 v = qFromUnaligned<quint16>(bits);
bits += 2;
- numBits += int(qPopulationCount(v));
+ numBits += qsizetype(qPopulationCount(v));
}
if (bits < end)
- numBits += int(qPopulationCount(bits[0]));
+ numBits += qsizetype(qPopulationCount(bits[0]));
return on ? numBits : size() - numBits;
}
@@ -217,19 +217,19 @@ int QBitArray::count(bool on) const
\sa size()
*/
-void QBitArray::resize(int size)
+void QBitArray::resize(qsizetype size)
{
if (!size) {
d.resize(0);
} else {
- int s = d.size();
- d.resize(1 + (size+7)/8);
- uchar* c = reinterpret_cast<uchar*>(d.data());
+ qsizetype s = d.size();
+ d.resize(1 + (size + 7) / 8);
+ uchar *c = reinterpret_cast<uchar *>(d.data());
if (size > (s << 3))
memset(c + s, 0, d.size() - s);
else if (size & 7)
- *(c+1+size/8) &= (1 << (size & 7)) - 1;
- *c = d.size()*8 - size;
+ *(c + 1 + size / 8) &= (1 << (size & 7)) - 1;
+ *c = d.size() * 8 - size;
}
}
@@ -256,7 +256,7 @@ void QBitArray::resize(int size)
\sa isEmpty()
*/
-/*! \fn bool QBitArray::fill(bool value, int size = -1)
+/*! \fn bool QBitArray::fill(bool value, qsizetype size = -1)
Sets every bit in the bit array to \a value, returning true if successful;
otherwise returns \c false. If \a size is different from -1 (the default),
@@ -285,15 +285,15 @@ void QBitArray::resize(int size)
\snippet code/src_corelib_tools_qbitarray.cpp 15
*/
-void QBitArray::fill(bool value, int begin, int end)
+void QBitArray::fill(bool value, qsizetype begin, qsizetype end)
{
while (begin < end && begin & 0x7)
setBit(begin++, value);
- int len = end - begin;
+ qsizetype len = end - begin;
if (len <= 0)
return;
- int s = len & ~0x7;
- uchar *c = reinterpret_cast<uchar*>(d.data());
+ qsizetype s = len & ~qsizetype(0x7);
+ uchar *c = reinterpret_cast<uchar *>(d.data());
memset(c + (begin >> 3) + 1, value ? 0xff : 0, s >> 3);
begin += s;
while (begin < end)
@@ -391,7 +391,7 @@ quint32 QBitArray::toUInt32(QSysInfo::Endian endianness, bool *ok) const noexcep
\sa resize(), isEmpty()
*/
-/*! \fn void QBitArray::truncate(int pos)
+/*! \fn void QBitArray::truncate(qsizetype pos)
Truncates the bit array at index position \a pos.
@@ -400,7 +400,7 @@ quint32 QBitArray::toUInt32(QSysInfo::Endian endianness, bool *ok) const noexcep
\sa resize()
*/
-/*! \fn bool QBitArray::toggleBit(int i)
+/*! \fn bool QBitArray::toggleBit(qsizetype i)
Inverts the value of the bit at index position \a i, returning the
previous value of that bit as either true (if it was set) or false (if
@@ -415,7 +415,7 @@ quint32 QBitArray::toUInt32(QSysInfo::Endian endianness, bool *ok) const noexcep
\sa setBit(), clearBit()
*/
-/*! \fn bool QBitArray::testBit(int i) const
+/*! \fn bool QBitArray::testBit(qsizetype i) const
Returns \c true if the bit at index position \a i is 1; otherwise
returns \c false.
@@ -426,7 +426,7 @@ quint32 QBitArray::toUInt32(QSysInfo::Endian endianness, bool *ok) const noexcep
\sa setBit(), clearBit()
*/
-/*! \fn bool QBitArray::setBit(int i)
+/*! \fn bool QBitArray::setBit(qsizetype i)
Sets the bit at index position \a i to 1.
@@ -436,14 +436,14 @@ quint32 QBitArray::toUInt32(QSysInfo::Endian endianness, bool *ok) const noexcep
\sa clearBit(), toggleBit()
*/
-/*! \fn void QBitArray::setBit(int i, bool value)
+/*! \fn void QBitArray::setBit(qsizetype i, bool value)
\overload
Sets the bit at index position \a i to \a value.
*/
-/*! \fn void QBitArray::clearBit(int i)
+/*! \fn void QBitArray::clearBit(qsizetype i)
Sets the bit at index position \a i to 0.
@@ -453,7 +453,7 @@ quint32 QBitArray::toUInt32(QSysInfo::Endian endianness, bool *ok) const noexcep
\sa setBit(), toggleBit()
*/
-/*! \fn bool QBitArray::at(int i) const
+/*! \fn bool QBitArray::at(qsizetype i) const
Returns the value of the bit at index position \a i.
@@ -463,7 +463,7 @@ quint32 QBitArray::toUInt32(QSysInfo::Endian endianness, bool *ok) const noexcep
\sa operator[]()
*/
-/*! \fn QBitRef QBitArray::operator[](int i)
+/*! \fn QBitRef QBitArray::operator[](qsizetype i)
Returns the bit at index position \a i as a modifiable reference.
@@ -484,17 +484,7 @@ quint32 QBitArray::toUInt32(QSysInfo::Endian endianness, bool *ok) const noexcep
\sa at(), testBit(), setBit(), clearBit()
*/
-/*! \fn bool QBitArray::operator[](int i) const
-
- \overload
-*/
-
-/*! \fn QBitRef QBitArray::operator[](uint i)
-
- \overload
-*/
-
-/*! \fn bool QBitArray::operator[](uint i) const
+/*! \fn bool QBitArray::operator[](qsizetype i) const
\overload
*/
@@ -565,10 +555,10 @@ quint32 QBitArray::toUInt32(QSysInfo::Endian endianness, bool *ok) const noexcep
QBitArray &QBitArray::operator&=(const QBitArray &other)
{
resize(qMax(size(), other.size()));
- uchar *a1 = reinterpret_cast<uchar*>(d.data()) + 1;
- const uchar *a2 = reinterpret_cast<const uchar*>(other.d.constData()) + 1;
- int n = other.d.size() -1 ;
- int p = d.size() - 1 - n;
+ uchar *a1 = reinterpret_cast<uchar *>(d.data()) + 1;
+ const uchar *a2 = reinterpret_cast<const uchar *>(other.d.constData()) + 1;
+ qsizetype n = other.d.size() - 1;
+ qsizetype p = d.size() - 1 - n;
while (n-- > 0)
*a1++ &= *a2++;
while (p-- > 0)
@@ -594,9 +584,9 @@ QBitArray &QBitArray::operator&=(const QBitArray &other)
QBitArray &QBitArray::operator|=(const QBitArray &other)
{
resize(qMax(size(), other.size()));
- uchar *a1 = reinterpret_cast<uchar*>(d.data()) + 1;
+ uchar *a1 = reinterpret_cast<uchar *>(d.data()) + 1;
const uchar *a2 = reinterpret_cast<const uchar *>(other.d.constData()) + 1;
- int n = other.d.size() - 1;
+ qsizetype n = other.d.size() - 1;
while (n-- > 0)
*a1++ |= *a2++;
return *this;
@@ -620,9 +610,9 @@ QBitArray &QBitArray::operator|=(const QBitArray &other)
QBitArray &QBitArray::operator^=(const QBitArray &other)
{
resize(qMax(size(), other.size()));
- uchar *a1 = reinterpret_cast<uchar*>(d.data()) + 1;
+ uchar *a1 = reinterpret_cast<uchar *>(d.data()) + 1;
const uchar *a2 = reinterpret_cast<const uchar *>(other.d.constData()) + 1;
- int n = other.d.size() - 1;
+ qsizetype n = other.d.size() - 1;
while (n-- > 0)
*a1++ ^= *a2++;
return *this;
@@ -640,17 +630,17 @@ QBitArray &QBitArray::operator^=(const QBitArray &other)
QBitArray QBitArray::operator~() const
{
- int sz = size();
+ qsizetype sz = size();
QBitArray a(sz);
const uchar *a1 = reinterpret_cast<const uchar *>(d.constData()) + 1;
- uchar *a2 = reinterpret_cast<uchar*>(a.d.data()) + 1;
- int n = d.size() - 1;
+ uchar *a2 = reinterpret_cast<uchar *>(a.d.data()) + 1;
+ qsizetype n = d.size() - 1;
while (n-- > 0)
*a2++ = ~*a1++;
- if (sz && sz%8)
- *(a2-1) &= (1 << (sz%8)) - 1;
+ if (sz && sz % 8)
+ *(a2 - 1) &= (1 << (sz % 8)) - 1;
return a;
}
@@ -735,7 +725,7 @@ QBitArray operator^(const QBitArray &a1, const QBitArray &a2)
It is not for use in any other context.
*/
-/*! \fn QBitRef::QBitRef (QBitArray& a, int i)
+/*! \fn QBitRef::QBitRef (QBitArray& a, qsizetype i)
Constructs a reference to element \a i in the QBitArray \a a.
This is what QBitArray::operator[] constructs its return value
@@ -764,7 +754,6 @@ QBitArray operator^(const QBitArray &a1, const QBitArray &a2)
Sets the value referenced by the QBitRef to \a v.
*/
-
/*****************************************************************************
QBitArray stream functions
*****************************************************************************/
@@ -780,11 +769,19 @@ QBitArray operator^(const QBitArray &a1, const QBitArray &a2)
QDataStream &operator<<(QDataStream &out, const QBitArray &ba)
{
- quint32 len = ba.size();
- out << len;
- if (len > 0)
- out.writeRawData(ba.d.constData() + 1, ba.d.size() - 1);
- return out;
+ if (out.version() < QDataStream::Qt_6_0) {
+ quint32 len = ba.size();
+ out << len;
+ if (len > 0)
+ out.writeRawData(ba.d.constData() + 1, ba.d.size() - 1);
+ return out;
+ } else {
+ quint64 len = ba.size();
+ out << len;
+ if (len > 0)
+ out.writeRawData(ba.d.constData() + 1, ba.d.size() - 1);
+ return out;
+ }
}
/*!
@@ -798,19 +795,27 @@ QDataStream &operator<<(QDataStream &out, const QBitArray &ba)
QDataStream &operator>>(QDataStream &in, QBitArray &ba)
{
ba.clear();
- quint32 len;
- in >> len;
+ qsizetype len;
+ if (in.version() < QDataStream::Qt_6_0) {
+ quint32 tmp;
+ in >> tmp;
+ len = tmp;
+ } else {
+ quint64 tmp;
+ in >> tmp;
+ len = tmp;
+ }
if (len == 0) {
ba.clear();
return in;
}
- const quint32 Step = 8 * 1024 * 1024;
- quint32 totalBytes = (len + 7) / 8;
- quint32 allocated = 0;
+ const qsizetype Step = 8 * 1024 * 1024;
+ qsizetype totalBytes = (len + 7) / 8;
+ qsizetype allocated = 0;
while (allocated < totalBytes) {
- int blockSize = qMin(Step, totalBytes - allocated);
+ qsizetype blockSize = qMin(Step, totalBytes - allocated);
ba.d.resize(allocated + blockSize + 1);
if (in.readRawData(ba.d.data() + 1 + allocated, blockSize) != blockSize) {
ba.clear();
@@ -820,7 +825,7 @@ QDataStream &operator>>(QDataStream &in, QBitArray &ba)
allocated += blockSize;
}
- int paddingMask = ~((0x1 << (len & 0x7)) - 1);
+ qsizetype paddingMask = ~((0x1 << (len & 0x7)) - 1);
if (paddingMask != ~0x0 && (ba.d.constData()[ba.d.size() - 1] & paddingMask)) {
ba.clear();
in.setStatus(QDataStream::ReadCorruptData);
@@ -837,7 +842,7 @@ QDebug operator<<(QDebug dbg, const QBitArray &array)
{
QDebugStateSaver saver(dbg);
dbg.nospace() << "QBitArray(";
- for (int i = 0; i < array.size();) {
+ for (qsizetype i = 0; i < array.size();) {
if (array.testBit(i))
dbg << '1';
else
diff --git a/src/corelib/tools/qbitarray.h b/src/corelib/tools/qbitarray.h
index 25c95bc2a5..75d680dc84 100644
--- a/src/corelib/tools/qbitarray.h
+++ b/src/corelib/tools/qbitarray.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2020 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.
@@ -44,7 +44,6 @@
QT_BEGIN_NAMESPACE
-
class QBitRef;
class Q_CORE_EXPORT QBitArray
{
@@ -57,52 +56,49 @@ class Q_CORE_EXPORT QBitArray
public:
inline QBitArray() noexcept {}
- explicit QBitArray(int size, bool val = false);
+ explicit QBitArray(qsizetype size, bool val = false);
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); }
- inline int size() const { return (d.size() << 3) - *d.constData(); }
- inline int count() const { return (d.size() << 3) - *d.constData(); }
- int count(bool on) const;
+ inline qsizetype size() const { return (d.size() << 3) - *d.constData(); }
+ inline qsizetype count() const { return (d.size() << 3) - *d.constData(); }
+ qsizetype count(bool on) const;
inline bool isEmpty() const { return d.isEmpty(); }
inline bool isNull() const { return d.isNull(); }
- void resize(int size);
+ void resize(qsizetype size);
inline void detach() { d.detach(); }
inline bool isDetached() const { return d.isDetached(); }
inline void clear() { d.clear(); }
- bool testBit(int i) const;
- void setBit(int i);
- void setBit(int i, bool val);
- void clearBit(int i);
- bool toggleBit(int i);
+ bool testBit(qsizetype i) const;
+ void setBit(qsizetype i);
+ void setBit(qsizetype i, bool val);
+ void clearBit(qsizetype i);
+ bool toggleBit(qsizetype i);
- bool at(int i) const;
- QBitRef operator[](int i);
- bool operator[](int i) const;
- QBitRef operator[](uint i);
- bool operator[](uint i) const;
+ bool at(qsizetype i) const;
+ QBitRef operator[](qsizetype i);
+ bool operator[](qsizetype i) const;
- QBitArray& operator&=(const QBitArray &);
- QBitArray& operator|=(const QBitArray &);
- QBitArray& operator^=(const QBitArray &);
- QBitArray operator~() const;
+ QBitArray &operator&=(const QBitArray &);
+ QBitArray &operator|=(const QBitArray &);
+ QBitArray &operator^=(const QBitArray &);
+ QBitArray operator~() const;
- 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; }
- inline bool fill(bool val, int size = -1);
- void fill(bool val, int first, int last);
+ inline bool fill(bool val, qsizetype size = -1);
+ void fill(bool val, qsizetype first, qsizetype last);
- inline void truncate(int pos) { if (pos < size()) resize(pos); }
+ inline void truncate(qsizetype pos) { if (pos < size()) resize(pos); }
const char *bits() const { return isEmpty() ? nullptr : d.constData() + 1; }
static QBitArray fromBits(const char *data, qsizetype len);
@@ -114,56 +110,53 @@ public:
inline DataPtr &data_ptr() { return d.data_ptr(); }
};
-inline bool QBitArray::fill(bool aval, int asize)
+inline bool QBitArray::fill(bool aval, qsizetype asize)
{ *this = QBitArray((asize < 0 ? this->size() : asize), aval); return true; }
Q_CORE_EXPORT QBitArray operator&(const QBitArray &, const QBitArray &);
Q_CORE_EXPORT QBitArray operator|(const QBitArray &, const QBitArray &);
Q_CORE_EXPORT QBitArray operator^(const QBitArray &, const QBitArray &);
-inline bool QBitArray::testBit(int i) const
-{ Q_ASSERT(uint(i) < uint(size()));
+inline bool QBitArray::testBit(qsizetype i) const
+{ Q_ASSERT(size_t(i) < size_t(size()));
return (*(reinterpret_cast<const uchar*>(d.constData())+1+(i>>3)) & (1 << (i & 7))) != 0; }
-inline void QBitArray::setBit(int i)
-{ Q_ASSERT(uint(i) < uint(size()));
+inline void QBitArray::setBit(qsizetype i)
+{ Q_ASSERT(size_t(i) < size_t(size()));
*(reinterpret_cast<uchar*>(d.data())+1+(i>>3)) |= uchar(1 << (i & 7)); }
-inline void QBitArray::clearBit(int i)
-{ Q_ASSERT(uint(i) < uint(size()));
+inline void QBitArray::clearBit(qsizetype i)
+{ Q_ASSERT(size_t(i) < size_t(size()));
*(reinterpret_cast<uchar*>(d.data())+1+(i>>3)) &= ~uchar(1 << (i & 7)); }
-inline void QBitArray::setBit(int i, bool val)
+inline void QBitArray::setBit(qsizetype i, bool val)
{ if (val) setBit(i); else clearBit(i); }
-inline bool QBitArray::toggleBit(int i)
-{ Q_ASSERT(uint(i) < uint(size()));
+inline bool QBitArray::toggleBit(qsizetype i)
+{ Q_ASSERT(size_t(i) < size_t(size()));
uchar b = uchar(1<<(i&7)); uchar* p = reinterpret_cast<uchar*>(d.data())+1+(i>>3);
uchar c = uchar(*p&b); *p^=b; return c!=0; }
-inline bool QBitArray::operator[](int i) const { return testBit(i); }
-inline bool QBitArray::operator[](uint i) const { return testBit(i); }
-inline bool QBitArray::at(int i) const { return testBit(i); }
+inline bool QBitArray::operator[](qsizetype i) const { return testBit(i); }
+inline bool QBitArray::at(qsizetype i) const { return testBit(i); }
class Q_CORE_EXPORT QBitRef
{
private:
- QBitArray& a;
- int i;
- inline QBitRef(QBitArray& array, int idx) : a(array), i(idx) {}
+ QBitArray &a;
+ qsizetype i;
+ inline QBitRef(QBitArray &array, qsizetype idx) : a(array), i(idx) { }
friend class QBitArray;
+
public:
inline operator bool() const { return a.testBit(i); }
inline bool operator!() const { return !a.testBit(i); }
- QBitRef& operator=(const QBitRef& val) { a.setBit(i, val); return *this; }
- QBitRef& operator=(bool val) { a.setBit(i, val); return *this; }
+ QBitRef &operator=(const QBitRef &val) { a.setBit(i, val); return *this; }
+ QBitRef &operator=(bool val) { a.setBit(i, val); return *this; }
};
-inline QBitRef QBitArray::operator[](int i)
+inline QBitRef QBitArray::operator[](qsizetype i)
{ Q_ASSERT(i >= 0); return QBitRef(*this, i); }
-inline QBitRef QBitArray::operator[](uint i)
-{ return QBitRef(*this, i); }
-
#ifndef QT_NO_DATASTREAM
Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QBitArray &);
diff --git a/src/corelib/tools/qcache.h b/src/corelib/tools/qcache.h
index fbfa2ab997..74784af121 100644
--- a/src/corelib/tools/qcache.h
+++ b/src/corelib/tools/qcache.h
@@ -48,11 +48,12 @@ QT_BEGIN_NAMESPACE
template <class Key, class T>
class QCache
{
- struct Value {
+ struct Value
+ {
T *t = nullptr;
- int cost = 0;
+ qsizetype cost = 0;
Value() noexcept = default;
- Value(T *tt, int c) noexcept
+ Value(T *tt, qsizetype c) noexcept
: t(tt), cost(c)
{}
Value(Value &&other) noexcept
@@ -68,19 +69,20 @@ class QCache
return *this;
}
~Value() { delete t; }
+
private:
Q_DISABLE_COPY(Value)
};
- struct Chain {
- Chain() noexcept
- : prev(this), next(this)
- {}
+ struct Chain
+ {
+ Chain() noexcept : prev(this), next(this) { }
Chain *prev;
Chain *next;
};
- struct Node : public Chain {
+ struct Node : public Chain
+ {
using KeyType = Key;
using ValueType = Value;
@@ -99,11 +101,11 @@ class QCache
value(std::move(t))
{
}
- static void createInPlace(Node *n, const Key &k, T *o, int cost)
+ static void createInPlace(Node *n, const Key &k, T *o, qsizetype cost)
{
new (n) Node{ Key(k), Value(o, cost) };
}
- void emplace(T *o, int cost)
+ void emplace(T *o, qsizetype cost)
{
value = Value(o, cost);
}
@@ -143,8 +145,8 @@ class QCache
mutable Chain chain;
Data d;
- int mx = 0;
- int total = 0;
+ qsizetype mx = 0;
+ qsizetype total = 0;
void unlink(Node *n) noexcept(std::is_nothrow_destructible_v<Node>)
{
@@ -175,7 +177,7 @@ class QCache
return n->value.t;
}
- void trim(int m) noexcept(std::is_nothrow_destructible_v<Node>)
+ void trim(qsizetype m) noexcept(std::is_nothrow_destructible_v<Node>)
{
Chain *n = chain.prev;
while (n != &chain && total > m) {
@@ -189,31 +191,38 @@ class QCache
Q_DISABLE_COPY(QCache)
public:
- inline explicit QCache(int maxCost = 100) noexcept
+ inline explicit QCache(qsizetype maxCost = 100) noexcept
: mx(maxCost)
- {}
- inline ~QCache() { clear(); }
+ {
+ }
+ inline ~QCache()
+ {
+ static_assert(std::is_nothrow_destructible_v<Key>, "Types with throwing destructors are not supported in Qt containers.");
+ static_assert(std::is_nothrow_destructible_v<T>, "Types with throwing destructors are not supported in Qt containers.");
- inline int maxCost() const noexcept { return mx; }
- void setMaxCost(int m) noexcept(std::is_nothrow_destructible_v<Node>)
+ clear();
+ }
+
+ inline qsizetype maxCost() const noexcept { return mx; }
+ void setMaxCost(qsizetype m) noexcept(std::is_nothrow_destructible_v<Node>)
{
mx = m;
trim(mx);
}
- inline int totalCost() const noexcept { return total; }
+ inline qsizetype totalCost() const noexcept { return total; }
- inline qsizetype size() const noexcept { return d.size; }
- inline qsizetype count() const noexcept { return d.size; }
+ inline qsizetype size() const noexcept { return qsizetype(d.size); }
+ inline qsizetype count() const noexcept { return qsizetype(d.size); }
inline bool isEmpty() const noexcept { return !d.size; }
inline QList<Key> keys() const
{
QList<Key> k;
- if (d.size) {
- k.reserve(typename QList<Key>::size_type(d.size));
+ if (size()) {
+ k.reserve(size());
for (auto it = d.begin(); it != d.end(); ++it)
k << it.node()->key;
}
- Q_ASSERT(k.size() == qsizetype(d.size));
+ Q_ASSERT(k.size() == size());
return k;
}
@@ -225,11 +234,10 @@ public:
chain.prev = &chain;
}
- bool insert(const Key &key, T *object, int cost = 1)
+ bool insert(const Key &key, T *object, qsizetype cost = 1)
{
- remove(key);
-
if (cost > mx) {
+ remove(key);
delete object;
return false;
}
diff --git a/src/corelib/tools/qcache.qdoc b/src/corelib/tools/qcache.qdoc
index ffc21318f4..f9b1ffa8f4 100644
--- a/src/corelib/tools/qcache.qdoc
+++ b/src/corelib/tools/qcache.qdoc
@@ -80,7 +80,7 @@
\sa QPixmapCache, QHash, QMap
*/
-/*! \fn template <class Key, class T> QCache<Key, T>::QCache(int maxCost = 100)
+/*! \fn template <class Key, class T> QCache<Key, T>::QCache(qsizetype maxCost = 100)
Constructs a cache whose contents will never have a total cost
greater than \a maxCost.
@@ -91,14 +91,14 @@
Destroys the cache. Deletes all the objects in the cache.
*/
-/*! \fn template <class Key, class T> int QCache<Key, T>::maxCost() const
+/*! \fn template <class Key, class T> qsizetype QCache<Key, T>::maxCost() const
Returns the maximum allowed total cost of the cache.
\sa setMaxCost(), totalCost()
*/
-/*! \fn template <class Key, class T> void QCache<Key, T>::setMaxCost(int cost)
+/*! \fn template <class Key, class T> void QCache<Key, T>::setMaxCost(qsizetype cost)
Sets the maximum allowed total cost of the cache to \a cost. If
the current total cost is greater than \a cost, some objects are
@@ -107,7 +107,7 @@
\sa maxCost(), totalCost()
*/
-/*! \fn template <class Key, class T> int QCache<Key, T>::totalCost() const
+/*! \fn template <class Key, class T> qsizetype QCache<Key, T>::totalCost() const
Returns the total cost of the objects in the cache.
@@ -120,14 +120,14 @@
\sa setMaxCost()
*/
-/*! \fn template <class Key, class T> int QCache<Key, T>::size() const
+/*! \fn template <class Key, class T> qsizetype QCache<Key, T>::size() const
Returns the number of objects in the cache.
\sa isEmpty()
*/
-/*! \fn template <class Key, class T> int QCache<Key, T>::count() const
+/*! \fn template <class Key, class T> qsizetype QCache<Key, T>::count() const
Same as size().
*/
@@ -153,7 +153,7 @@
*/
-/*! \fn template <class Key, class T> bool QCache<Key, T>::insert(const Key &key, T *object, int cost = 1)
+/*! \fn template <class Key, class T> bool QCache<Key, T>::insert(const Key &key, T *object, qsizetype cost = 1)
Inserts \a object into the cache with key \a key and
associated cost \a cost. Any object with the same key already in
diff --git a/src/corelib/tools/qcommandlineoption.h b/src/corelib/tools/qcommandlineoption.h
index 6de9a31aea..2e7d8fd9da 100644
--- a/src/corelib/tools/qcommandlineoption.h
+++ b/src/corelib/tools/qcommandlineoption.h
@@ -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); }
diff --git a/src/corelib/tools/qcommandlineparser.cpp b/src/corelib/tools/qcommandlineparser.cpp
index 1b93fb84cf..99e7484664 100644
--- a/src/corelib/tools/qcommandlineparser.cpp
+++ b/src/corelib/tools/qcommandlineparser.cpp
@@ -1135,7 +1135,7 @@ QString QCommandLineParserPrivate::helpText(bool includeQtOptions) const
usage += QLatin1Char(' ') + arg.syntax;
text += QCommandLineParser::tr("Usage: %1").arg(usage) + nl;
if (!description.isEmpty())
- text += description + nl;
+ text += description + nl;
text += nl;
if (!options.isEmpty())
text += QCommandLineParser::tr("Options:") + nl;
diff --git a/src/corelib/tools/qcontainerfwd.h b/src/corelib/tools/qcontainerfwd.h
index 575cd1def9..96480c4a8a 100644
--- a/src/corelib/tools/qcontainerfwd.h
+++ b/src/corelib/tools/qcontainerfwd.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2020 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.
@@ -37,40 +37,46 @@
**
****************************************************************************/
+#include <QtCore/qglobal.h>
+
#ifndef QCONTAINERFWD_H
#define QCONTAINERFWD_H
-#include <QtCore/qglobal.h>
-
// std headers can unfortunately not be forward declared
#include <tuple>
#include <variant>
QT_BEGIN_NAMESPACE
-template <class Key, class T> class QCache;
-template <class Key, class T> class QHash;
-template <class Key, class T> class QMap;
-template <class Key, class T> class QMultiHash;
-template <class Key, class T> class QMultiMap;
+template <typename Key, typename T> class QCache;
+template <typename Key, typename T> class QHash;
+template <typename Key, typename T> class QMap;
+template <typename Key, typename T> class QMultiHash;
+template <typename Key, typename T> class QMultiMap;
template <typename T1, typename T2>
using QPair = std::pair<T1, T2>;
-template <class T> class QQueue;
-template <class T> class QSet;
-template <class T> class QStack;
-template<class T, qsizetype Prealloc = 256> class QVarLengthArray;
-template <class T> class QList;
-template<typename T> using QVector = QList<T>;
+template <typename T> class QQueue;
+template <typename T> class QSet;
+template <typename T> class QStack;
+template <typename T, qsizetype Prealloc = 256> class QVarLengthArray;
+template <typename T> class QList;
#ifndef Q_CLANG_QDOC
+template<typename T> using QVector = QList<T>;
using QStringList = QList<QString>;
using QByteArrayList = QList<QByteArray>;
#else
+template<typename T> class QVector;
class QStringList;
class QByteArrayList;
#endif
class QMetaType;
class QVariant;
+using QVariantList = QList<QVariant>;
+using QVariantMap = QMap<QString, QVariant>;
+using QVariantHash = QHash<QString, QVariant>;
+using QVariantPair = QPair<QVariant, QVariant>;
+
QT_END_NAMESPACE
#endif // QCONTAINERFWD_H
diff --git a/src/corelib/tools/qcontainertools_impl.h b/src/corelib/tools/qcontainertools_impl.h
index caac5a07e8..f4dfecffce 100644
--- a/src/corelib/tools/qcontainertools_impl.h
+++ b/src/corelib/tools/qcontainertools_impl.h
@@ -106,11 +106,7 @@ void reserveIfForwardIterator(Container *c, ForwardIterator f, ForwardIterator l
c->reserve(static_cast<typename Container::size_type>(std::distance(f, l)));
}
-// for detecting expression validity
-template <typename ... T>
-using void_t = void;
-
-template <typename Iterator, typename = void_t<>>
+template <typename Iterator, typename = std::void_t<>>
struct AssociativeIteratorHasKeyAndValue : std::false_type
{
};
@@ -118,14 +114,14 @@ struct AssociativeIteratorHasKeyAndValue : std::false_type
template <typename Iterator>
struct AssociativeIteratorHasKeyAndValue<
Iterator,
- void_t<decltype(std::declval<Iterator &>().key()),
- decltype(std::declval<Iterator &>().value())>
+ std::void_t<decltype(std::declval<Iterator &>().key()),
+ decltype(std::declval<Iterator &>().value())>
>
: std::true_type
{
};
-template <typename Iterator, typename = void_t<>, typename = void_t<>>
+template <typename Iterator, typename = std::void_t<>, typename = std::void_t<>>
struct AssociativeIteratorHasFirstAndSecond : std::false_type
{
};
@@ -133,8 +129,8 @@ struct AssociativeIteratorHasFirstAndSecond : std::false_type
template <typename Iterator>
struct AssociativeIteratorHasFirstAndSecond<
Iterator,
- void_t<decltype(std::declval<Iterator &>()->first),
- decltype(std::declval<Iterator &>()->second)>
+ std::void_t<decltype(std::declval<Iterator &>()->first),
+ decltype(std::declval<Iterator &>()->second)>
>
: std::true_type
{
@@ -151,6 +147,9 @@ using IfAssociativeIteratorHasFirstAndSecond =
template <typename T, typename U>
using IfIsNotSame =
typename std::enable_if<!std::is_same<T, U>::value, bool>::type;
+
+template<typename T, typename U>
+using IfIsNotConvertible = typename std::enable_if<!std::is_convertible<T, U>::value, bool>::type;
} // namespace QtPrivate
QT_END_NAMESPACE
diff --git a/src/corelib/tools/qcontiguouscache.cpp b/src/corelib/tools/qcontiguouscache.cpp
index cc3510ef88..95537961f9 100644
--- a/src/corelib/tools/qcontiguouscache.cpp
+++ b/src/corelib/tools/qcontiguouscache.cpp
@@ -119,7 +119,7 @@ void QContiguousCacheData::freeData(QContiguousCacheData *data)
See the \l{Contiguous Cache Example}{Contiguous Cache} example.
*/
-/*! \fn template<typename T> QContiguousCache<T>::QContiguousCache(int capacity)
+/*! \fn template<typename T> QContiguousCache<T>::QContiguousCache(qsizetype capacity)
Constructs a cache with the given \a capacity.
@@ -224,7 +224,7 @@ void QContiguousCacheData::freeData(QContiguousCacheData *data)
\sa operator==()
*/
-/*! \fn template<typename T> int QContiguousCache<T>::capacity() const
+/*! \fn template<typename T> qsizetype QContiguousCache<T>::capacity() const
Returns the number of items the cache can store before it is full.
When a cache contains a number of items equal to its capacity, adding new
@@ -233,12 +233,12 @@ void QContiguousCacheData::freeData(QContiguousCacheData *data)
\sa setCapacity(), size()
*/
-/*! \fn template<typename T> int QContiguousCache<T>::count() const
+/*! \fn template<typename T> qsizetype QContiguousCache<T>::count() const
Same as size().
*/
-/*! \fn template<typename T> int QContiguousCache<T>::size() const
+/*! \fn template<typename T> qsizetype QContiguousCache<T>::size() const
Returns the number of items contained within the cache.
@@ -260,7 +260,7 @@ void QContiguousCacheData::freeData(QContiguousCacheData *data)
\sa size(), capacity()
*/
-/*! \fn template<typename T> int QContiguousCache<T>::available() const
+/*! \fn template<typename T> qsizetype QContiguousCache<T>::available() const
Returns the number of items that can be added to the cache before it becomes full.
@@ -272,7 +272,7 @@ void QContiguousCacheData::freeData(QContiguousCacheData *data)
Removes all items from the cache. The capacity is unchanged.
*/
-/*! \fn template<typename T> void QContiguousCache<T>::setCapacity(int size)
+/*! \fn template<typename T> void QContiguousCache<T>::setCapacity(qsizetype size)
Sets the capacity of the cache to the given \a size. A cache can hold a
number of items equal to its capacity. When inserting, appending or prepending
@@ -285,7 +285,7 @@ void QContiguousCacheData::freeData(QContiguousCacheData *data)
\sa capacity(), isFull()
*/
-/*! \fn template<typename T> const T &QContiguousCache<T>::at(int i) const
+/*! \fn template<typename T> const T &QContiguousCache<T>::at(qsizetype i) const
Returns the item at index position \a i in the cache. \a i must
be a valid index position in the cache (i.e, firstIndex() <= \a i <= lastIndex()).
@@ -299,7 +299,7 @@ void QContiguousCacheData::freeData(QContiguousCacheData *data)
\sa firstIndex(), lastIndex(), insert(), operator[]()
*/
-/*! \fn template<typename T> T &QContiguousCache<T>::operator[](int i)
+/*! \fn template<typename T> T &QContiguousCache<T>::operator[](qsizetype i)
Returns the item at index position \a i as a modifiable reference. If
the cache does not contain an item at the given index position \a i
@@ -314,7 +314,7 @@ void QContiguousCacheData::freeData(QContiguousCacheData *data)
\sa insert(), at()
*/
-/*! \fn template<typename T> const T &QContiguousCache<T>::operator[](int i) const
+/*! \fn template<typename T> const T &QContiguousCache<T>::operator[](qsizetype i) const
\overload
@@ -337,7 +337,7 @@ void QContiguousCacheData::freeData(QContiguousCacheData *data)
\sa append(), insert(), isFull()
*/
-/*! \fn template<typename T> void QContiguousCache<T>::insert(int i, const T &value)
+/*! \fn template<typename T> void QContiguousCache<T>::insert(qsizetype i, const T &value)
Inserts the \a value at the index position \a i. If the cache already contains
an item at \a i then that value is replaced. If \a i is either one more than
@@ -357,14 +357,14 @@ void QContiguousCacheData::freeData(QContiguousCacheData *data)
\sa prepend(), append(), isFull(), firstIndex(), lastIndex()
*/
-/*! \fn template<typename T> bool QContiguousCache<T>::containsIndex(int i) const
+/*! \fn template<typename T> bool QContiguousCache<T>::containsIndex(qsizetype i) const
Returns \c true if the cache's index range includes the given index \a i.
\sa firstIndex(), lastIndex()
*/
-/*! \fn template<typename T> int QContiguousCache<T>::firstIndex() const
+/*! \fn template<typename T> qsizetype QContiguousCache<T>::firstIndex() const
Returns the first valid index in the cache. The index will be invalid if the
cache is empty.
@@ -372,7 +372,7 @@ void QContiguousCacheData::freeData(QContiguousCacheData *data)
\sa capacity(), size(), lastIndex()
*/
-/*! \fn template<typename T> int QContiguousCache<T>::lastIndex() const
+/*! \fn template<typename T> qsizetype QContiguousCache<T>::lastIndex() const
Returns the last valid index in the cache. The index will be invalid if the cache is empty.
diff --git a/src/corelib/tools/qcontiguouscache.h b/src/corelib/tools/qcontiguouscache.h
index 79f5e3fdb6..d830c31891 100644
--- a/src/corelib/tools/qcontiguouscache.h
+++ b/src/corelib/tools/qcontiguouscache.h
@@ -73,6 +73,8 @@ struct QContiguousCacheTypedData : public QContiguousCacheData
template<typename T>
class QContiguousCache {
+ static_assert(std::is_nothrow_destructible_v<T>, "Types with throwing destructors are not supported in Qt containers.");
+
typedef QContiguousCacheTypedData<T> Data;
Data *d;
public:
@@ -94,8 +96,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>
@@ -210,13 +211,13 @@ void QContiguousCache<T>::setCapacity(qsizetype asize)
x->alloc = asize;
x->count = qMin(d->count, asize);
x->offset = d->offset + d->count - x->count;
- if(asize)
+ if (asize)
x->start = x->offset % x->alloc;
else
x->start = 0;
qsizetype oldcount = x->count;
- if(oldcount)
+ if (oldcount)
{
T *dest = x->array + (x->start + x->count-1) % x->alloc;
T *src = d->array + (d->start + d->count-1) % d->alloc;
diff --git a/src/corelib/tools/qcryptographichash.cpp b/src/corelib/tools/qcryptographichash.cpp
index d5a6c4e5a0..47b72038eb 100644
--- a/src/corelib/tools/qcryptographichash.cpp
+++ b/src/corelib/tools/qcryptographichash.cpp
@@ -93,39 +93,7 @@ static SHA3Final * const sha3Final = Final;
#endif
-/*
- These #defines replace the typedefs needed by the RFC6234 code. Normally
- the typedefs would come from from stdint.h, but since this header is not
- available on all platforms (MSVC 2008, for example), we #define them to the
- Qt equivalents.
-*/
-
-#ifdef uint64_t
-#undef uint64_t
-#endif
-
-#define uint64_t QT_PREPEND_NAMESPACE(quint64)
-
-#ifdef uint32_t
-#undef uint32_t
-#endif
-
-#define uint32_t QT_PREPEND_NAMESPACE(quint32)
-
-#ifdef uint8_t
-#undef uint8_t
-#endif
-
-#define uint8_t QT_PREPEND_NAMESPACE(quint8)
-
-#ifdef int_least16_t
-#undef int_least16_t
-#endif
-
-#define int_least16_t QT_PREPEND_NAMESPACE(qint16)
-
-// Header from rfc6234 with 1 modification:
-// sha1.h - commented out '#include <stdint.h>' on line 74
+// Header from rfc6234
#include "../../3rdparty/rfc6234/sha.h"
/*
@@ -149,19 +117,14 @@ static int SHA384_512AddLength(SHA512Context *context, unsigned int length);
// sha384-512.c - appended 'M' to the SHA224_256AddLength macro on line 304
#include "../../3rdparty/rfc6234/sha384-512.c"
-#undef uint64_t
-#undef uint32_t
-#undef uint68_t
-#undef int_least16_t
-
static inline int SHA224_256AddLength(SHA256Context *context, unsigned int length)
{
- QT_PREPEND_NAMESPACE(quint32) addTemp;
+ uint32_t addTemp;
return SHA224_256AddLengthM(context, length);
}
static inline int SHA384_512AddLength(SHA512Context *context, unsigned int length)
{
- QT_PREPEND_NAMESPACE(quint64) addTemp;
+ uint64_t addTemp;
return SHA384_512AddLengthM(context, length);
}
@@ -437,19 +400,19 @@ void QCryptographicHash::addData(const char *data, qsizetype length)
break;
case RealSha3_224:
case Keccak_224:
- sha3Update(&d->sha3Context, reinterpret_cast<const BitSequence *>(data), quint64(length) * 8);
+ sha3Update(&d->sha3Context, reinterpret_cast<const BitSequence *>(data), uint64_t(length) * 8);
break;
case RealSha3_256:
case Keccak_256:
- sha3Update(&d->sha3Context, reinterpret_cast<const BitSequence *>(data), quint64(length) * 8);
+ sha3Update(&d->sha3Context, reinterpret_cast<const BitSequence *>(data), uint64_t(length) * 8);
break;
case RealSha3_384:
case Keccak_384:
- sha3Update(&d->sha3Context, reinterpret_cast<const BitSequence *>(data), quint64(length) * 8);
+ sha3Update(&d->sha3Context, reinterpret_cast<const BitSequence *>(data), uint64_t(length) * 8);
break;
case RealSha3_512:
case Keccak_512:
- sha3Update(&d->sha3Context, reinterpret_cast<const BitSequence *>(data), quint64(length) * 8);
+ sha3Update(&d->sha3Context, reinterpret_cast<const BitSequence *>(data), uint64_t(length) * 8);
break;
case Blake2b_160:
case Blake2b_256:
@@ -482,7 +445,7 @@ void QCryptographicHash::addData(const QByteArray &data)
and hashes it. Returns \c true if reading was successful.
\since 5.0
*/
-bool QCryptographicHash::addData(QIODevice* device)
+bool QCryptographicHash::addData(QIODevice *device)
{
if (!device->isReadable())
return false;
@@ -493,8 +456,8 @@ bool QCryptographicHash::addData(QIODevice* device)
char buffer[1024];
int length;
- while ((length = device->read(buffer,sizeof(buffer))) > 0)
- addData(buffer,length);
+ while ((length = device->read(buffer, sizeof(buffer))) > 0)
+ addData(buffer, length);
return device->atEnd();
}
@@ -542,19 +505,19 @@ QByteArray QCryptographicHash::result() const
SHA224Result(&copy, reinterpret_cast<unsigned char *>(d->result.data()));
break;
}
- case Sha256:{
+ case Sha256: {
SHA256Context copy = d->sha256Context;
d->result.resize(SHA256HashSize);
SHA256Result(&copy, reinterpret_cast<unsigned char *>(d->result.data()));
break;
}
- case Sha384:{
+ case Sha384: {
SHA384Context copy = d->sha384Context;
d->result.resize(SHA384HashSize);
SHA384Result(&copy, reinterpret_cast<unsigned char *>(d->result.data()));
break;
}
- case Sha512:{
+ case Sha512: {
SHA512Context copy = d->sha512Context;
d->result.resize(SHA512HashSize);
SHA512Result(&copy, reinterpret_cast<unsigned char *>(d->result.data()));
diff --git a/src/corelib/tools/qcryptographichash.h b/src/corelib/tools/qcryptographichash.h
index bef0c4dbe1..4d76d06e59 100644
--- a/src/corelib/tools/qcryptographichash.h
+++ b/src/corelib/tools/qcryptographichash.h
@@ -105,7 +105,7 @@ public:
void addData(const char *data, qsizetype length);
void addData(const QByteArray &data);
- bool addData(QIODevice* device);
+ bool addData(QIODevice *device);
QByteArray result() const;
diff --git a/src/corelib/tools/qduplicatetracker_p.h b/src/corelib/tools/qduplicatetracker_p.h
index baf21bfd12..e5bb11793a 100644
--- a/src/corelib/tools/qduplicatetracker_p.h
+++ b/src/corelib/tools/qduplicatetracker_p.h
@@ -75,7 +75,7 @@ class QDuplicateTracker {
public:
QDuplicateTracker() = default;
void reserve(int n) { set.reserve(n); }
- Q_REQUIRED_RESULT bool hasSeen(const T &s)
+ [[nodiscard]] bool hasSeen(const T &s)
{
bool inserted;
#ifdef __cpp_lib_memory_resource
@@ -87,7 +87,7 @@ public:
#endif
return !inserted;
}
- Q_REQUIRED_RESULT bool hasSeen(T &&s)
+ [[nodiscard]] bool hasSeen(T &&s)
{
bool inserted;
#ifdef __cpp_lib_memory_resource
diff --git a/src/corelib/tools/qeasingcurve.cpp b/src/corelib/tools/qeasingcurve.cpp
index 389efcb8f9..9eb74d12cc 100644
--- a/src/corelib/tools/qeasingcurve.cpp
+++ b/src/corelib/tools/qeasingcurve.cpp
@@ -320,7 +320,8 @@ static bool isConfigFunction(QEasingCurve::Type type)
type == QEasingCurve::TCBSpline;
}
-struct TCBPoint {
+struct TCBPoint
+{
QPointF _point;
qreal _t;
qreal _c;
@@ -605,8 +606,8 @@ struct BezierEase : public QEasingCurveFunction
const qreal s = 1 - t;
- const qreal s_squared = s*s;
- const qreal t_squared = t*t;
+ const qreal s_squared = s * s;
+ const qreal t_squared = t * t;
const qreal s_cubic = s_squared * s;
const qreal t_cubic = t_squared * t;
@@ -623,8 +624,8 @@ struct BezierEase : public QEasingCurveFunction
const qreal s = 1 - t;
- const qreal s_squared = s*s;
- const qreal t_squared = t*t;
+ const qreal s_squared = s * s;
+ const qreal t_squared = t * t;
const qreal s_cubic = s_squared * s;
const qreal t_cubic = t_squared * t;
@@ -639,7 +640,7 @@ struct BezierEase : public QEasingCurveFunction
const qreal p2 = singleCubicBezier.p2x;
const qreal p3 = singleCubicBezier.p3x;
- const qreal t_squared = t*t;
+ const qreal t_squared = t * t;
return -3*p0 + 3*p1 + 6*p0*t - 12*p1*t + 6*p2*t + 3*p3*t_squared - 3*p0*t_squared + 9*p1*t_squared - 9*p2*t_squared;
}
@@ -739,7 +740,7 @@ struct BezierEase : public QEasingCurveFunction
qreal cos = b * x - a * x_squared;
if (cos < 0)
- return 0.225 * (cos * 1 *-cos - cos) + cos;
+ return 0.225 * (cos * 1 * -cos - cos) + cos;
return 0.225 * (cos * cos - cos) + cos;
}
@@ -794,15 +795,15 @@ struct BezierEase : public QEasingCurveFunction
if (D >= 0) {
const qreal D_sqrt = qSqrt(D);
- qreal u = _cbrt( -q * 0.5 + D_sqrt);
- qreal v = _cbrt( -q * 0.5 - D_sqrt);
+ qreal u = _cbrt(-q * 0.5 + D_sqrt);
+ qreal v = _cbrt(-q * 0.5 - D_sqrt);
qreal z1 = u + v;
qreal t1 = z1 - a_by3;
if (inRange(t1))
return t1;
- qreal z2 = -1 *u;
+ qreal z2 = -1 * u;
qreal t2 = z2 - a_by3;
return t2;
}
@@ -825,7 +826,7 @@ struct BezierEase : public QEasingCurveFunction
cosacos(g, s1, s2, s3);
- qreal z1 = -1* f * s2;
+ qreal z1 = -1 * f * s2;
qreal t1 = z1 - a_by3;
if (inRange(t1))
return t1;
@@ -940,7 +941,7 @@ struct ElasticEase : public QEasingCurveFunction
{
qreal p = (_p < 0) ? qreal(0.3) : _p;
qreal a = (_a < 0) ? qreal(1.0) : _a;
- switch(_t) {
+ switch (_t) {
case QEasingCurve::InElastic:
return easeInElastic(t, a, p);
case QEasingCurve::OutElastic:
@@ -973,7 +974,7 @@ struct BounceEase : public QEasingCurveFunction
qreal value(qreal t) override
{
qreal a = (_a < 0) ? qreal(1.0) : _a;
- switch(_t) {
+ switch (_t) {
case QEasingCurve::InBounce:
return easeInBounce(t, a);
case QEasingCurve::OutBounce:
@@ -1011,7 +1012,7 @@ struct BackEase : public QEasingCurveFunction
if (!(t < 1))
return 1;
qreal o = (_o < 0) ? qreal(1.70158) : _o;
- switch(_t) {
+ switch (_t) {
case QEasingCurve::InBack:
return easeInBack(t, o);
case QEasingCurve::OutBack:
@@ -1028,7 +1029,7 @@ struct BackEase : public QEasingCurveFunction
static QEasingCurve::EasingFunction curveToFunc(QEasingCurve::Type curve)
{
- switch(curve) {
+ switch (curve) {
case QEasingCurve::Linear:
return &easeNone;
case QEasingCurve::InQuad:
@@ -1103,7 +1104,7 @@ static QEasingCurve::EasingFunction curveToFunc(QEasingCurve::Type curve)
static QEasingCurveFunction *curveToFunctionObject(QEasingCurve::Type type)
{
- switch(type) {
+ switch (type) {
case QEasingCurve::InElastic:
case QEasingCurve::OutElastic:
case QEasingCurve::InOutElastic:
@@ -1197,14 +1198,14 @@ bool QEasingCurve::operator==(const QEasingCurve &other) const
&& d_ptr->type == other.d_ptr->type;
if (res) {
if (d_ptr->config && other.d_ptr->config) {
- // catch the config content
+ // catch the config content
res = d_ptr->config->operator==(*(other.d_ptr->config));
} else if (d_ptr->config || other.d_ptr->config) {
- // one one has a config object, which could contain default values
- res = qFuzzyCompare(amplitude(), other.amplitude()) &&
- qFuzzyCompare(period(), other.period()) &&
- qFuzzyCompare(overshoot(), other.overshoot());
+ // one one has a config object, which could contain default values
+ res = qFuzzyCompare(amplitude(), other.amplitude())
+ && qFuzzyCompare(period(), other.period())
+ && qFuzzyCompare(overshoot(), other.overshoot());
}
}
return res;
@@ -1275,7 +1276,7 @@ void QEasingCurve::setPeriod(qreal period)
*/
qreal QEasingCurve::overshoot() const
{
- return d_ptr->config ? d_ptr->config->_o : qreal(1.70158) ;
+ return d_ptr->config ? d_ptr->config->_o : qreal(1.70158);
}
/*!
@@ -1372,7 +1373,7 @@ void QEasingCurve::addTCBSegment(const QPointF &nextPoint, qreal t, qreal c, qre
if (!d_ptr->config)
d_ptr->config = curveToFunctionObject(d_ptr->type);
- d_ptr->config->_tcbPoints.append(TCBPoint(nextPoint, t, c ,b));
+ d_ptr->config->_tcbPoints.append(TCBPoint(nextPoint, t, c, b));
if (nextPoint == QPointF(1.0, 1.0)) {
d_ptr->config->_bezierCurves = tcbToBezier(d_ptr->config->_tcbPoints);
diff --git a/src/corelib/tools/qeasingcurve.h b/src/corelib/tools/qeasingcurve.h
index e6ee7b56d5..7e50743bf1 100644
--- a/src/corelib/tools/qeasingcurve.h
+++ b/src/corelib/tools/qeasingcurve.h
@@ -49,7 +49,6 @@ QT_REQUIRE_CONFIG(easingcurve);
QT_BEGIN_NAMESPACE
-
class QEasingCurvePrivate;
class QPointF;
class Q_CORE_EXPORT QEasingCurve
@@ -80,8 +79,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); }
@@ -98,7 +96,7 @@ public:
qreal overshoot() const;
void setOvershoot(qreal overshoot);
- void addCubicBezierSegment(const QPointF & c1, const QPointF & c2, const QPointF & endPoint);
+ void addCubicBezierSegment(const QPointF &c1, const QPointF &c2, const QPointF &endPoint);
void addTCBSegment(const QPointF &nextPoint, qreal t, qreal c, qreal b);
QList<QPointF> toCubicSpline() const;
@@ -109,13 +107,14 @@ public:
EasingFunction customType() const;
qreal valueForProgress(qreal progress) const;
+
private:
QEasingCurvePrivate *d_ptr;
#ifndef QT_NO_DEBUG_STREAM
friend Q_CORE_EXPORT QDebug operator<<(QDebug debug, const QEasingCurve &item);
#endif
#ifndef QT_NO_DATASTREAM
- friend Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QEasingCurve&);
+ friend Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QEasingCurve &);
friend Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QEasingCurve &);
#endif
};
@@ -126,7 +125,7 @@ Q_CORE_EXPORT QDebug operator<<(QDebug debug, const QEasingCurve &item);
#endif
#ifndef QT_NO_DATASTREAM
-Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QEasingCurve&);
+Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QEasingCurve &);
Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QEasingCurve &);
#endif
diff --git a/src/corelib/tools/qflatmap_p.h b/src/corelib/tools/qflatmap_p.h
index bf0efb2543..1b3eaea01c 100644
--- a/src/corelib/tools/qflatmap_p.h
+++ b/src/corelib/tools/qflatmap_p.h
@@ -109,6 +109,8 @@ template<class Key, class T, class Compare = std::less<Key>, class KeyContainer
class MappedContainer = QList<T>>
class QFlatMap : private QFlatMapValueCompare<Key, T, Compare>
{
+ static_assert(std::is_nothrow_destructible_v<T>, "Types with throwing destructors are not supported in Qt containers.");
+
using full_map_t = QFlatMap<Key, T, Compare, KeyContainer, MappedContainer>;
template <class U>
diff --git a/src/corelib/tools/qfreelist.cpp b/src/corelib/tools/qfreelist.cpp
index dd584413fc..38ad13a1ee 100644
--- a/src/corelib/tools/qfreelist.cpp
+++ b/src/corelib/tools/qfreelist.cpp
@@ -48,9 +48,9 @@ enum {
Offset2 = 0x00080000,
Offset3 = 0x00800000,
- Size0 = Offset1 - Offset0,
- Size1 = Offset2 - Offset1,
- Size2 = Offset3 - Offset2,
+ Size0 = Offset1 - Offset0,
+ Size1 = Offset2 - Offset1,
+ Size2 = Offset3 - Offset2,
Size3 = QFreeListDefaultConstants::MaxIndex - Offset3
};
diff --git a/src/corelib/tools/qfreelist_p.h b/src/corelib/tools/qfreelist_p.h
index c49473802a..f54e5aad65 100644
--- a/src/corelib/tools/qfreelist_p.h
+++ b/src/corelib/tools/qfreelist_p.h
@@ -56,7 +56,6 @@
QT_BEGIN_NAMESPACE
-
/*! \internal
Element in a QFreeList. ConstReferenceType and ReferenceType are used as
@@ -208,9 +207,7 @@ public:
template <typename T, typename ConstantsType>
constexpr inline QFreeList<T, ConstantsType>::QFreeList()
:
-#if defined(Q_COMPILER_CONSTEXPR)
_v{}, // uniform initialization required
-#endif
_next(ConstantsType::InitialNextValue)
{ }
@@ -251,7 +248,7 @@ inline int QFreeList<T, ConstantsType>::next()
v = allocate((id & ConstantsType::IndexMask) - at, ConstantsType::Sizes[block]);
if (!_v[block].testAndSetRelease(nullptr, v)) {
// race with another thread lost
- delete [] v;
+ delete[] v;
v = _v[block].loadAcquire();
Q_ASSERT(v != nullptr);
}
diff --git a/src/corelib/tools/qhash.cpp b/src/corelib/tools/qhash.cpp
index 7c58be0f84..112a492526 100644
--- a/src/corelib/tools/qhash.cpp
+++ b/src/corelib/tools/qhash.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2020 The Qt Company Ltd.
** Copyright (C) 2016 Intel Corporation.
** Copyright (C) 2012 Giuseppe D'Angelo <dangelog@gmail.com>.
** Contact: https://www.qt.io/licensing/
@@ -387,11 +387,23 @@ static uint siphash(const uint8_t *in, uint inlen, const uint seed)
}
#endif
+#if defined(__SANITIZE_ADDRESS__) || defined(__SANITIZE_THREAD__) // GCC
+# define QHASH_AES_SANITIZER_BUILD
+#elif QT_HAS_FEATURE(address_sanitizer) || QT_HAS_FEATURE(thread_sanitizer) // Clang
+# define QHASH_AES_SANITIZER_BUILD
+#endif
+// When built with a sanitizer, aeshash() is rightfully reported to have a
+// heap-buffer-overflow issue. However, we consider it to be safe in this
+// specific case and overcome the problem by correctly discarding the
+// out-of-range bits. To allow building the code with sanitizer,
+// QHASH_AES_SANITIZER_BUILD is used to disable aeshash() usage.
#if QT_COMPILER_SUPPORTS_HERE(AES) && QT_COMPILER_SUPPORTS_HERE(SSE4_2) && \
- !(defined(__SANITIZE_ADDRESS__) || defined(__SANITIZE_THREAD__))
+ !defined(QHASH_AES_SANITIZER_BUILD)
# define AESHASH
+#undef QHASH_AES_SANITIZER_BUILD
+
QT_FUNCTION_TARGET(AES)
static size_t aeshash(const uchar *p, size_t len, size_t seed) noexcept
{
@@ -549,12 +561,12 @@ size_t qHash(QStringView key, size_t seed) noexcept
size_t qHash(const QBitArray &bitArray, size_t seed) noexcept
{
- int m = bitArray.d.size() - 1;
+ qsizetype m = bitArray.d.size() - 1;
size_t result = qHashBits(reinterpret_cast<const uchar *>(bitArray.d.constData()), size_t(qMax(0, m)), seed);
// deal with the last 0 to 7 bits manually, because we can't trust that
// the padding is initialized to 0 in bitArray.d
- int n = bitArray.size();
+ qsizetype n = bitArray.size();
if (n & 0x7)
result = ((result << 4) + bitArray.d.at(m)) & ((1 << n) - 1);
return result;
@@ -702,16 +714,6 @@ uint qt_hash(QStringView key, uint chained) noexcept
}
/*!
- \fn template <typename T1, typename T2> size_t qHash(const QPair<T1, T2> &key, size_t seed = 0)
- \since 5.0
- \relates QHash
-
- Returns the hash value for the \a key, using \a seed to seed the calculation.
-
- Types \c T1 and \c T2 must be supported by qHash().
-*/
-
-/*!
\fn template <typename T1, typename T2> size_t qHash(const std::pair<T1, T2> &key, size_t seed = 0)
\since 5.7
\relates QHash
@@ -719,11 +721,6 @@ uint qt_hash(QStringView key, uint chained) noexcept
Returns the hash value for the \a key, using \a seed to seed the calculation.
Types \c T1 and \c T2 must be supported by qHash().
-
- \note The return type of this function is \e{not} the same as that of
- \snippet code/src_corelib_tools_qhash.cpp 29
- The two functions use different hashing algorithms; due to binary compatibility
- constraints, we cannot change the QPair algorithm to match the std::pair one before Qt 6.
*/
/*!
@@ -1422,7 +1419,7 @@ size_t qHash(long double key, size_t seed) noexcept
*/
-/*! \fn template <class Key, class T> void QHash<Key, T>::reserve(int size)
+/*! \fn template <class Key, class T> void QHash<Key, T>::reserve(qsizetype size)
Ensures that the QHash's internal hash table has space to store at
least \a size items without having to grow the hash table.
@@ -1769,10 +1766,6 @@ size_t qHash(long double key, size_t seed) noexcept
\sa remove(), take(), find()
*/
-/*! \fn template <class Key, class T> QHash<Key, T>::iterator QHash<Key, T>::erase(iterator pos)
- \overload
-*/
-
/*! \fn template <class Key, class T> QHash<Key, T>::iterator QHash<Key, T>::find(const Key &key)
Returns an iterator pointing to the item with the \a key in the
@@ -1818,8 +1811,8 @@ size_t qHash(long double key, size_t seed) noexcept
*/
/*!
- \fn template <typename T> template <typename ...Args> QHash<Key, T>::iterator QHash<Key, T>::emplace(const Key &key, Args&&... args)
- \fn template <typename T> template <typename ...Args> QHash<Key, T>::iterator QHash<Key, T>::emplace(Key &&key, Args&&... args)
+ \fn template <class Key, class T> template <typename ...Args> QHash<Key, T>::iterator QHash<Key, T>::emplace(const Key &key, Args&&... args)
+ \fn template <class Key, class T> template <typename ...Args> QHash<Key, T>::iterator QHash<Key, T>::emplace(Key &&key, Args&&... args)
Inserts a new element into the container. This new element
is constructed in-place using \a args as the arguments for its
@@ -2240,8 +2233,6 @@ size_t qHash(long double key, size_t seed) noexcept
item.
Calling this function on QHash::end() leads to undefined results.
-
- \sa operator--()
*/
/*! \fn template <class Key, class T> QHash<Key, T>::const_iterator QHash<Key, T>::const_iterator::operator++(int)
@@ -2325,7 +2316,6 @@ size_t qHash(long double key, size_t seed) noexcept
Calling this function on QHash::keyEnd() leads to undefined results.
- \sa operator--()
*/
/*! \fn template <class Key, class T> QHash<Key, T>::key_iterator QHash<Key, T>::key_iterator::operator++(int)
@@ -2466,8 +2456,6 @@ size_t qHash(long double key, size_t seed) noexcept
Constructs a copy of \a other (which can be a QHash or a
QMultiHash).
-
- \sa operator=()
*/
/*! \fn template <class Key, class T> template <class InputIterator> QMultiHash<Key, T>::QMultiHash(InputIterator begin, InputIterator end)
@@ -2507,8 +2495,8 @@ size_t qHash(long double key, size_t seed) noexcept
*/
/*!
- \fn template <typename T> template <typename ...Args> QMultiHash<Key, T>::iterator QMultiHash<Key, T>::emplace(const Key &key, Args&&... args)
- \fn template <typename T> template <typename ...Args> QMultiHash<Key, T>::iterator QMultiHash<Key, T>::emplace(Key &&key, Args&&... args)
+ \fn template <class Key, class T> template <typename ...Args> QMultiHash<Key, T>::iterator QMultiHash<Key, T>::emplace(const Key &key, Args&&... args)
+ \fn template <class Key, class T> template <typename ...Args> QMultiHash<Key, T>::iterator QMultiHash<Key, T>::emplace(Key &&key, Args&&... args)
Inserts a new element into the container. This new element
is constructed in-place using \a args as the arguments for its
@@ -2525,8 +2513,8 @@ size_t qHash(long double key, size_t seed) noexcept
*/
/*!
- \fn template <typename T> template <typename ...Args> QMultiHash<Key, T>::iterator QMultiHash<Key, T>::emplaceReplace(const Key &key, Args&&... args)
- \fn template <typename T> template <typename ...Args> QMultiHash<Key, T>::iterator QMultiHash<Key, T>::emplaceReplace(Key &&key, Args&&... args)
+ \fn template <class Key, class T> template <typename ...Args> QMultiHash<Key, T>::iterator QMultiHash<Key, T>::emplaceReplace(const Key &key, Args&&... args)
+ \fn template <class Key, class T> template <typename ...Args> QMultiHash<Key, T>::iterator QMultiHash<Key, T>::emplaceReplace(Key &&key, Args&&... args)
Inserts a new element into the container. This new element
is constructed in-place using \a args as the arguments for its
@@ -2550,6 +2538,16 @@ size_t qHash(long double key, size_t seed) noexcept
\sa insert()
*/
+
+/*! \fn template <class Key, class T> QMultiHash &QMultiHash<Key, T>::unite(const QHash<Key, T> &other)
+ \since 6.0
+
+ Inserts all the items in the \a other hash into this hash
+ and returns a reference to this hash.
+
+ \sa insert()
+*/
+
/*! \fn template <class Key, class T> QList<Key> QMultiHash<Key, T>::uniqueKeys() const
\since 5.13
@@ -3084,7 +3082,7 @@ size_t qHash(long double key, size_t seed) noexcept
while iterators are active on that container. For more information,
read \l{Implicit sharing iterator problem}.
- \sa QMultiHash::iterator, QMultiHashIterator
+ \sa QMultiHash::iterator
*/
/*! \fn template <class Key, class T> QMultiHash<Key, T>::const_iterator::const_iterator()
@@ -3157,8 +3155,6 @@ size_t qHash(long double key, size_t seed) noexcept
item.
Calling this function on QMultiHash::end() leads to undefined results.
-
- \sa operator--()
*/
/*! \fn template <class Key, class T> QMultiHash<Key, T>::const_iterator QMultiHash<Key, T>::const_iterator::operator++(int)
@@ -3241,8 +3237,6 @@ size_t qHash(long double key, size_t seed) noexcept
item.
Calling this function on QMultiHash::keyEnd() leads to undefined results.
-
- \sa operator--()
*/
/*! \fn template <class Key, class T> QMultiHash<Key, T>::key_iterator QMultiHash<Key, T>::key_iterator::operator++(int)
diff --git a/src/corelib/tools/qhash.h b/src/corelib/tools/qhash.h
index 2b1b155efb..5dc88943fc 100644
--- a/src/corelib/tools/qhash.h
+++ b/src/corelib/tools/qhash.h
@@ -59,11 +59,10 @@ struct QHashDummyValue
namespace QHashPrivate {
// QHash uses a power of two growth policy.
-namespace GrowthPolicy
-{
+namespace GrowthPolicy {
inline constexpr size_t maxNumBuckets() noexcept
{
- return size_t(1) << (8*sizeof(size_t) - 1);
+ return size_t(1) << (8 * sizeof(size_t) - 1);
}
inline constexpr size_t bucketsForCapacity(size_t requestedCapacity) noexcept
{
@@ -71,7 +70,7 @@ inline constexpr size_t bucketsForCapacity(size_t requestedCapacity) noexcept
return 16;
if (requestedCapacity >= maxNumBuckets())
return maxNumBuckets();
- return qNextPowerOfTwo(QIntegerForSize<sizeof(size_t)>::Unsigned(2*requestedCapacity - 1));
+ return qNextPowerOfTwo(QIntegerForSize<sizeof(size_t)>::Unsigned(2 * requestedCapacity - 1));
}
inline constexpr size_t bucketForHash(size_t nBuckets, size_t hash) noexcept
{
@@ -185,9 +184,8 @@ struct MultiNode
MultiNode(MultiNode &&other)
: key(other.key),
- value(other.value)
+ value(qExchange(other.value, nullptr))
{
- other.value = nullptr;
}
MultiNode(const MultiNode &other)
@@ -217,16 +215,13 @@ struct MultiNode
void insertMulti(Args &&... args)
{
Chain *e = new Chain{ T(std::forward<Args>(args)...), nullptr };
- e->next = value;
- value = e;
+ e->next = qExchange(value, e);
}
template<typename ...Args>
void emplaceValue(Args &&... args)
{
value->value = T(std::forward<Args>(args)...);
}
-
- // compiler generated move operators are fine
};
template<typename Node>
@@ -286,7 +281,7 @@ struct Span {
entries[o].node().~Node();
}
}
- delete [] entries;
+ delete[] entries;
entries = nullptr;
}
}
@@ -391,14 +386,14 @@ struct Span {
// in here. The likelihood of having below 16 entries is very small,
// so start with that and increment by 16 each time we need to add
// some more space
- const size_t increment = NEntries/8;
+ const size_t increment = NEntries / 8;
size_t alloc = allocated + increment;
Entry *newEntries = new Entry[alloc];
// we only add storage if the previous storage was fully filled, so
// simply copy the old data over
if constexpr (isRelocatable<Node>()) {
if (allocated)
- memcpy(newEntries, entries, allocated*sizeof(Entry));
+ memcpy(newEntries, entries, allocated * sizeof(Entry));
} else {
for (size_t i = 0; i < allocated; ++i) {
new (&newEntries[i].node()) Node(std::move(entries[i].node()));
@@ -408,7 +403,7 @@ struct Span {
for (size_t i = allocated; i < allocated + increment; ++i) {
newEntries[i].nextFree() = uchar(i + 1);
}
- delete [] entries;
+ delete[] entries;
entries = newEntries;
allocated = uchar(alloc);
}
@@ -475,10 +470,9 @@ struct Data
return dd;
}
-
void clear()
{
- delete [] spans;
+ delete[] spans;
spans = nullptr;
size = 0;
numBuckets = 0;
@@ -528,7 +522,7 @@ struct Data
}
span.freeData();
}
- delete [] oldSpans;
+ delete[] oldSpans;
}
size_t nextBucket(size_t bucket) const noexcept
@@ -583,7 +577,8 @@ struct Data
return it.node();
}
- struct InsertionResult {
+ struct InsertionResult
+ {
iterator it;
bool initialized;
};
@@ -696,12 +691,13 @@ struct iterator {
} // namespace QHashPrivate
-template <class Key, class T>
+template <typename Key, typename T>
class QHash
{
using Node = QHashPrivate::Node<Key, T>;
using Data = QHashPrivate::Data<Node>;
friend class QSet<Key>;
+ friend class QMultiHash<Key, T>;
Data *d = nullptr;
@@ -729,6 +725,9 @@ public:
}
~QHash()
{
+ static_assert(std::is_nothrow_destructible_v<Key>, "Types with throwing destructors are not supported in Qt containers.");
+ static_assert(std::is_nothrow_destructible_v<T>, "Types with throwing destructors are not supported in Qt containers.");
+
if (d && !d->ref.deref())
delete d;
}
@@ -750,15 +749,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);
@@ -1149,14 +1140,14 @@ public:
-template <class Key, class T>
+template <typename Key, typename T>
class QMultiHash
{
using Node = QHashPrivate::MultiNode<Key, T>;
using Data = QHashPrivate::Data<Node>;
using Chain = QHashPrivate::MultiNodeChain<T>;
- Data *d = nullptr;
+ Data *d = nullptr;
qsizetype m_size = 0;
public:
@@ -1203,6 +1194,9 @@ public:
}
~QMultiHash()
{
+ static_assert(std::is_nothrow_destructible_v<Key>, "Types with throwing destructors are not supported in Qt containers.");
+ static_assert(std::is_nothrow_destructible_v<T>, "Types with throwing destructors are not supported in Qt containers.");
+
if (d && !d->ref.deref())
delete d;
}
@@ -1220,10 +1214,10 @@ public:
}
return *this;
}
- QMultiHash(QMultiHash &&other) noexcept : d(other.d), m_size(other.m_size)
+ QMultiHash(QMultiHash &&other) noexcept
+ : d(qExchange(other.d, nullptr)),
+ m_size(qExchange(other.m_size, 0))
{
- other.d = nullptr;
- other.m_size = 0;
}
QMultiHash &operator=(QMultiHash &&other) noexcept(std::is_nothrow_destructible<Node>::value)
{
@@ -1232,18 +1226,28 @@ public:
return *this;
}
- QMultiHash(const QHash<Key, T> &other)
+ explicit QMultiHash(const QHash<Key, T> &other)
: QMultiHash(other.begin(), other.end())
{}
+
+ explicit QMultiHash(QHash<Key, T> &&other)
+ {
+ unite(std::move(other));
+ }
void swap(QMultiHash &other) noexcept { qSwap(d, other.d); qSwap(m_size, other.m_size); }
bool operator==(const QMultiHash &other) const noexcept
{
if (d == other.d)
return true;
- if (!d || ! other.d)
+ if (m_size != other.m_size)
return false;
- if (m_size != other.m_size || d->size != other.d->size)
+ if (m_size == 0)
+ return true;
+ // equal size, and both non-zero size => d pointers allocated for both
+ Q_ASSERT(d);
+ Q_ASSERT(other.d);
+ if (d->size != other.d->size)
return false;
for (auto it = other.d->begin(); it != other.d->end(); ++it) {
auto i = d->find(it.node()->key);
@@ -1816,6 +1820,26 @@ public:
return *this;
}
+ QMultiHash &unite(const QHash<Key, T> &other)
+ {
+ for (auto cit = other.cbegin(); cit != other.cend(); ++cit)
+ insert(cit.key(), *cit);
+ return *this;
+ }
+
+ QMultiHash &unite(QHash<Key, T> &&other)
+ {
+ if (!other.isDetached()) {
+ unite(other);
+ return *this;
+ }
+ auto it = other.d->begin();
+ for (const auto end = other.d->end(); it != end; ++it)
+ emplace(std::move(it.node()->key), std::move(it.node()->takeValue()));
+ other.clear();
+ return *this;
+ }
+
QPair<iterator, iterator> equal_range(const Key &key)
{
detach();
@@ -1847,160 +1871,37 @@ private:
}
};
-#if !defined(QT_NO_JAVA_STYLE_ITERATORS)
-template<class Key, class T>
-class QHashIterator
-{
- typedef typename QHash<Key, T>::const_iterator const_iterator;
- typedef const_iterator Item;
- QHash<Key, T> c;
- const_iterator i, n;
- inline bool item_exists() const noexcept { return n != c.constEnd(); }
-
-public:
- inline QHashIterator(const QHash<Key, T> &container) noexcept
- : c(container), i(c.constBegin()), n(c.constEnd())
- { }
- inline QHashIterator &operator=(const QHash<Key, T> &container) noexcept
- {
- c = container;
- i = c.constBegin();
- n = c.constEnd();
- return *this;
- }
- inline void toFront() noexcept
- {
- i = c.constBegin();
- n = c.constEnd();
- }
- inline void toBack() noexcept
- {
- i = c.constEnd();
- n = c.constEnd();
- }
- inline bool hasNext() const noexcept { return i != c.constEnd(); }
- inline Item next() noexcept
- {
- n = i++;
- return n;
- }
- inline Item peekNext() const noexcept { return i; }
- inline const T &value() const noexcept
- {
- Q_ASSERT(item_exists());
- return *n;
- }
- inline const Key &key() const noexcept
- {
- Q_ASSERT(item_exists());
- return n.key();
- }
- inline bool findNext(const T &t) noexcept
- {
- while ((n = i) != c.constEnd())
- if (*i++ == t)
- return true;
- return false;
- }
-};
-
-template<class Key, class T>
-class QMutableHashIterator
-{
- typedef typename QHash<Key, T>::iterator iterator;
- typedef typename QHash<Key, T>::const_iterator const_iterator;
- typedef iterator Item;
- QHash<Key, T> *c;
- iterator i, n;
- inline bool item_exists() const noexcept { return const_iterator(n) != c->constEnd(); }
-
-public:
- inline QMutableHashIterator(QHash<Key, T> &container)
- : c(&container)
- {
- i = c->begin();
- n = c->end();
- }
- inline QMutableHashIterator &operator=(QHash<Key, T> &container)
- {
- c = &container;
- i = c->begin();
- n = c->end();
- return *this;
- }
- inline void toFront()
- {
- i = c->begin();
- n = c->end();
- }
- inline void toBack() noexcept
- {
- i = c->end();
- n = c->end();
- }
- inline bool hasNext() const noexcept { return const_iterator(i) != c->constEnd(); }
- inline Item next() noexcept
- {
- n = i++;
- return n;
- }
- inline Item peekNext() const noexcept { return i; }
- inline void remove()
- {
- if (const_iterator(n) != c->constEnd()) {
- i = c->erase(n);
- n = c->end();
- }
- }
- inline void setValue(const T &t)
- {
- if (const_iterator(n) != c->constEnd())
- *n = t;
- }
- inline T &value() noexcept
- {
- Q_ASSERT(item_exists());
- return *n;
- }
- inline const T &value() const noexcept
- {
- Q_ASSERT(item_exists());
- return *n;
- }
- inline const Key &key() const noexcept
- {
- Q_ASSERT(item_exists());
- return n.key();
- }
- inline bool findNext(const T &t) noexcept
- {
- while (const_iterator(n = i) != c->constEnd())
- if (*i++ == t)
- return true;
- return false;
- }
-};
-#endif // !QT_NO_JAVA_STYLE_ITERATORS
+Q_DECLARE_ASSOCIATIVE_FORWARD_ITERATOR(Hash)
+Q_DECLARE_MUTABLE_ASSOCIATIVE_FORWARD_ITERATOR(Hash)
+Q_DECLARE_ASSOCIATIVE_FORWARD_ITERATOR(MultiHash)
+Q_DECLARE_MUTABLE_ASSOCIATIVE_FORWARD_ITERATOR(MultiHash)
template <class Key, class T>
size_t qHash(const QHash<Key, T> &key, size_t seed = 0)
noexcept(noexcept(qHash(std::declval<Key&>())) && noexcept(qHash(std::declval<T&>())))
{
- QtPrivate::QHashCombineCommutative hash;
+ size_t hash = 0;
for (auto it = key.begin(), end = key.end(); it != end; ++it) {
- const Key &k = it.key();
- const T &v = it.value();
- seed = hash(seed, std::pair<const Key&, const T&>(k, v));
+ QtPrivate::QHashCombine combine;
+ size_t h = combine(seed, it.key());
+ // use + to keep the result independent of the ordering of the keys
+ hash += combine(h, it.value());
}
- return seed;
+ return hash;
}
template <class Key, class T>
inline size_t qHash(const QMultiHash<Key, T> &key, size_t seed = 0)
noexcept(noexcept(qHash(std::declval<Key&>())) && noexcept(qHash(std::declval<T&>())))
{
- const QHash<Key, T> &key2 = key;
- return qHash(key2, seed);
+ size_t hash = 0;
+ for (auto it = key.begin(), end = key.end(); it != end; ++it) {
+ QtPrivate::QHashCombine combine;
+ size_t h = combine(seed, it.key());
+ // use + to keep the result independent of the ordering of the keys
+ hash += combine(h, it.value());
+ }
+ return hash;
}
QT_END_NAMESPACE
diff --git a/src/corelib/tools/qhashfunctions.h b/src/corelib/tools/qhashfunctions.h
index 94c6e13b1c..9cfa852ba2 100644
--- a/src/corelib/tools/qhashfunctions.h
+++ b/src/corelib/tools/qhashfunctions.h
@@ -172,7 +172,8 @@ template<typename T> inline size_t qHash(const T &t, size_t seed)
namespace QtPrivate {
-struct QHashCombine {
+struct QHashCombine
+{
typedef size_t result_type;
template <typename T>
constexpr result_type operator()(size_t seed, const T &t) const noexcept(noexcept(qHash(t)))
@@ -180,7 +181,8 @@ struct QHashCombine {
{ return seed ^ (qHash(t) + 0x9e3779b9 + (seed << 6) + (seed >> 2)) ; }
};
-struct QHashCombineCommutative {
+struct QHashCombineCommutative
+{
// QHashCombine is a good hash combiner, but is not commutative,
// ie. it depends on the order of the input elements. That is
// usually what we want: {0,1,3} should hash differently than
diff --git a/src/corelib/tools/qiterator.h b/src/corelib/tools/qiterator.h
index c315b77c85..8922f34758 100644
--- a/src/corelib/tools/qiterator.h
+++ b/src/corelib/tools/qiterator.h
@@ -181,11 +181,72 @@ public: \
n = c->end(); return false; } \
};
+#define Q_DECLARE_ASSOCIATIVE_FORWARD_ITERATOR(C) \
+\
+template <class Key, class T> \
+class Q##C##Iterator \
+{ \
+ typedef typename Q##C<Key,T>::const_iterator const_iterator; \
+ Q##C<Key,T> c; \
+ const_iterator i, n; \
+ inline bool item_exists() const { return n != c.constEnd(); } \
+public: \
+ typedef const_iterator Item; \
+ inline Q##C##Iterator(const Q##C<Key,T> &container) \
+ : c(container), i(c.constBegin()), n(c.constEnd()) {} \
+ inline Q##C##Iterator &operator=(const Q##C<Key,T> &container) \
+ { c = container; i = c.constBegin(); n = c.constEnd(); return *this; } \
+ inline void toFront() { i = c.constBegin(); n = c.constEnd(); } \
+ inline void toBack() { i = c.constEnd(); n = c.constEnd(); } \
+ inline bool hasNext() const { return i != c.constEnd(); } \
+ inline Item next() { n = i++; return n; } \
+ inline Item peekNext() const { return i; } \
+ inline const T &value() const { Q_ASSERT(item_exists()); return *n; } \
+ inline const Key &key() const { Q_ASSERT(item_exists()); return n.key(); } \
+ inline bool findNext(const T &t) \
+ { while ((n = i) != c.constEnd()) if (*i++ == t) return true; return false; } \
+};
+
+#define Q_DECLARE_MUTABLE_ASSOCIATIVE_FORWARD_ITERATOR(C) \
+\
+template <class Key, class T> \
+class QMutable##C##Iterator \
+{ \
+ typedef typename Q##C<Key,T>::iterator iterator; \
+ typedef typename Q##C<Key,T>::const_iterator const_iterator; \
+ Q##C<Key,T> *c; \
+ iterator i, n; \
+ inline bool item_exists() const { return const_iterator(n) != c->constEnd(); } \
+public: \
+ typedef iterator Item; \
+ inline QMutable##C##Iterator(Q##C<Key,T> &container) \
+ : c(&container) \
+ { i = c->begin(); n = c->end(); } \
+ inline QMutable##C##Iterator &operator=(Q##C<Key,T> &container) \
+ { c = &container; i = c->begin(); n = c->end(); return *this; } \
+ inline void toFront() { i = c->begin(); n = c->end(); } \
+ inline void toBack() { i = c->end(); n = c->end(); } \
+ inline bool hasNext() const { return const_iterator(i) != c->constEnd(); } \
+ inline Item next() { n = i++; return n; } \
+ inline Item peekNext() const { return i; } \
+ inline void remove() \
+ { if (const_iterator(n) != c->constEnd()) { i = c->erase(n); n = c->end(); } } \
+ inline void setValue(const T &t) { if (const_iterator(n) != c->constEnd()) *n = t; } \
+ inline T &value() { Q_ASSERT(item_exists()); return *n; } \
+ inline const T &value() const { Q_ASSERT(item_exists()); return *n; } \
+ inline const Key &key() const { Q_ASSERT(item_exists()); return n.key(); } \
+ inline bool findNext(const T &t) \
+ { while (const_iterator(n = i) != c->constEnd()) if (*i++ == t) return true; return false; } \
+};
+
+
#else // QT_NO_JAVA_STYLE_ITERATORS
#define Q_DECLARE_SEQUENTIAL_ITERATOR(C)
#define Q_DECLARE_MUTABLE_SEQUENTIAL_ITERATOR(C)
#define Q_DECLARE_ASSOCIATIVE_ITERATOR(C)
#define Q_DECLARE_MUTABLE_ASSOCIATIVE_ITERATOR(C)
+#define Q_DECLARE_ASSOCIATIVE_FORWARD_ITERATOR(C)
+#define Q_DECLARE_MUTABLE_ASSOCIATIVE_FORWARD_ITERATOR(C)
#endif // QT_NO_JAVA_STYLE_ITERATORS
template<typename Key, typename T, class Iterator>
@@ -205,20 +266,17 @@ public:
return std::pair<Key, T>(i.key(), i.value());
}
- struct pointer {
- pointer(value_type&& r_)
- : r(std::move(r_))
- {}
+ struct pointer
+ {
+ pointer(value_type &&r_) : r(std::move(r_)) { }
pointer() = default;
pointer(const pointer &other) = default;
pointer(pointer &&other) = default;
- pointer& operator=(const pointer &other) = default;
- pointer& operator=(pointer &&other) = default;
+ pointer &operator=(const pointer &other) = default;
+ pointer &operator=(pointer &&other) = default;
- value_type& operator*() const {
- return r;
- }
+ value_type &operator*() const { return r; }
value_type r;
const value_type *operator->() const {
diff --git a/src/corelib/tools/qiterator.qdoc b/src/corelib/tools/qiterator.qdoc
index 2c07dcf423..1ba5b66318 100644
--- a/src/corelib/tools/qiterator.qdoc
+++ b/src/corelib/tools/qiterator.qdoc
@@ -89,8 +89,7 @@
\sa operator*()
*/
-/*! \fn template<typename Key, typename T, class Iterator> bool operator==(QKeyValueIterator<Key, T, Iterator> lhs, QKeyValueIterator<Key, T, Iterator> rhs)
- \relates QKeyValueIterator
+/*! \fn template<typename Key, typename T, class Iterator> bool QKeyValueIterator<Key, T, Iterator>::operator==(QKeyValueIterator<Key, T, Iterator> lhs, QKeyValueIterator<Key, T, Iterator> rhs)
Returns \c true if \a rhs points to the same item as \a lhs otherwise returns
\c false.
@@ -98,8 +97,7 @@
\sa operator!=()
*/
-/*! \fn template<typename Key, typename T, class Iterator> bool operator!=(QKeyValueIterator<Key, T, Iterator> lhs, QKeyValueIterator<Key, T, Iterator> rhs) const
- \relates QKeyValueIterator
+/*! \fn template<typename Key, typename T, class Iterator> bool QKeyValueIterator<Key, T, Iterator>::operator!=(QKeyValueIterator<Key, T, Iterator> lhs, QKeyValueIterator<Key, T, Iterator> rhs)
Returns \c true if \a rhs points to a different item than \a lhs otherwise
returns \c false.
@@ -163,9 +161,8 @@
\brief The QListIterator class provides a Java-style const iterator for QList and QQueue.
QList has both \l{Java-style iterators} and \l{STL-style
- iterators}. The Java-style iterators are more high-level and
- easier to use than the STL-style iterators; on the other hand,
- they are slightly less efficient.
+ iterators}. STL-style iterators are more efficient and should
+ be preferred.
An alternative to using iterators is to use index positions. Most
QList member functions take an index as their first parameter,
@@ -214,10 +211,9 @@
\inmodule QtCore
\brief The QSetIterator class provides a Java-style const iterator for QSet.
- QSet supports both \l{Java-style iterators} and \l{STL-style
- iterators}. The Java-style iterators are more high-level and
- easier to use than the STL-style iterators; on the other hand,
- they are slightly less efficient.
+ QSet has both \l{Java-style iterators} and \l{STL-style
+ iterators}. STL-style iterators are more efficient and should
+ be preferred.
QSetIterator\<T\> allows you to iterate over a QSet\<T\>. If you
want to modify the set as you iterate over it, use
@@ -263,9 +259,8 @@
\brief The QMutableListIterator class provides a Java-style non-const iterator for QList, QQueue and QStack.
QList has both \l{Java-style iterators} and \l{STL-style
- iterators}. The Java-style iterators are more high-level and
- easier to use than the STL-style iterators; on the other hand,
- they are slightly less efficient.
+ iterators}. STL-style iterators are more efficient and should
+ be preferred.
An alternative to using iterators is to use index positions. Most
QList member functions take an index as their first parameter,
@@ -330,9 +325,8 @@
\brief The QMutableSetIterator class provides a Java-style non-const iterator for QSet.
QSet has both \l{Java-style iterators} and \l{STL-style
- iterators}. The Java-style iterators are more high-level and
- easier to use than the STL-style iterators; on the other hand,
- they are slightly less efficient.
+ iterators}. STL-style iterators are more efficient and should
+ be preferred.
QMutableSetIterator\<T\> allows you to iterate over a QSet\<T\>
and remove items from the set as you iterate. If you don't want
@@ -357,10 +351,6 @@
\image javaiterators1.png
- Here's how to iterate over the elements in reverse order:
-
- \snippet code/doc_src_qiterator.cpp 18
-
If you want to remove items as you iterate over the set, use
remove().
@@ -425,7 +415,6 @@
/*! \fn template <class T> void QListIterator<T>::toBack()
\fn template <class T> void QSetIterator<T>::toBack()
\fn template <class T> void QMutableListIterator<T>::toBack()
- \fn template <class T> void QMutableSetIterator<T>::toBack()
Moves the iterator to the back of the container (after the last
item).
@@ -433,10 +422,17 @@
\sa toFront(), previous()
*/
+/*! \fn template <class T> void QMutableSetIterator<T>::toBack()
+
+ Moves the iterator to the back of the container (after the last
+ item).
+
+ \sa toFront()
+*/
+
/*! \fn template <class T> bool QListIterator<T>::hasNext() const
\fn template <class T> bool QSetIterator<T>::hasNext() const
\fn template <class T> bool QMutableListIterator<T>::hasNext() const
- \fn template <class T> bool QMutableSetIterator<T>::hasNext() const
Returns \c true if there is at least one item ahead of the iterator,
i.e. the iterator is \e not at the back of the container;
@@ -445,9 +441,17 @@
\sa hasPrevious(), next()
*/
+/*! \fn template <class T> bool QMutableSetIterator<T>::hasNext() const
+
+ Returns \c true if there is at least one item ahead of the iterator,
+ i.e. the iterator is \e not at the back of the container;
+ otherwise returns \c false.
+
+ \sa next()
+*/
+
/*! \fn template <class T> const T &QListIterator<T>::next()
\fn template <class T> const T &QSetIterator<T>::next()
- \fn template <class T> const T &QMutableSetIterator<T>::next()
Returns the next item and advances the iterator by one position.
@@ -457,6 +461,25 @@
\sa hasNext(), peekNext(), previous()
*/
+/* \fn template <class T> const T &QMutableSetIterator<T>::next()
+ Returns the next item and advances the iterator by one position.
+
+ Calling this function on an iterator located at the back of the
+ container leads to undefined results.
+
+ \sa hasNext(), peekNext()
+*/
+
+/*! \fn template <class T> const T &QMutableSetIterator<T>::next()
+
+ Returns the next item and advances the iterator by one position.
+
+ Calling this function on an iterator located at the back of the
+ container leads to undefined results.
+
+ \sa hasNext(), peekNext()
+*/
+
/*! \fn template <class T> T &QMutableListIterator<T>::next()
Returns a reference to the next item, and advances the iterator
@@ -470,7 +493,6 @@
/*! \fn template <class T> const T &QListIterator<T>::peekNext() const
\fn template <class T> const T &QSetIterator<T>::peekNext() const
- \fn template <class T> const T &QMutableSetIterator<T>::peekNext() const
Returns the next item without moving the iterator.
@@ -480,25 +502,25 @@
\sa hasNext(), next(), peekPrevious()
*/
-/*! \fn template <class T> T &QMutableListIterator<T>::peekNext() const
+/*!
+ \fn template <class T> const T &QMutableSetIterator<T>::peekNext() const
- Returns a reference to the next item, without moving the iterator.
+ Returns the next item without moving the iterator.
Calling this function on an iterator located at the back of the
container leads to undefined results.
- \sa hasNext(), next(), peekPrevious()
+ \sa hasNext(), next()
*/
-/*!
- \fn template <class T> bool QMutableSetIterator<T>::hasPrevious() const
- \obsolete Deprecated in order to align with std::unordered_set functionality.
+/*! \fn template <class T> T &QMutableListIterator<T>::peekNext() const
- Returns \c true if there is at least one item behind the iterator,
- i.e. the iterator is \e not at the front of the container;
- otherwise returns \c false.
+ Returns a reference to the next item, without moving the iterator.
- \sa hasNext(), previous()
+ Calling this function on an iterator located at the back of the
+ container leads to undefined results.
+
+ \sa hasNext(), next(), peekPrevious()
*/
/*! \fn template <class T> bool QListIterator<T>::hasPrevious() const
@@ -512,19 +534,6 @@
\sa hasNext(), previous()
*/
-/*!
- \fn template <class T> const T &QMutableSetIterator<T>::previous()
- \obsolete Deprecated in order to align with std::unordered_set functionality.
-
- Returns the previous item and moves the iterator back by one
- position.
-
- Calling this function on an iterator located at the front of the
- container leads to undefined results.
-
- \sa hasPrevious(), peekPrevious(), next()
-*/
-
/*! \fn template <class T> const T &QListIterator<T>::previous()
\fn template <class T> const T &QSetIterator<T>::previous()
@@ -548,18 +557,6 @@
\sa hasPrevious(), peekPrevious(), next()
*/
-/*!
- \fn template <class T> const T &QMutableSetIterator<T>::peekPrevious() const
- \obsolete Deprecated in order to align with std::unordered_set functionality.
-
- Returns the previous item without moving the iterator.
-
- Calling this function on an iterator located at the front of the
- container leads to undefined results.
-
- \sa hasPrevious(), previous(), peekNext()
-*/
-
/*! \fn template <class T> const T &QListIterator<T>::peekPrevious() const
\fn template <class T> const T &QSetIterator<T>::peekPrevious() const
@@ -583,7 +580,6 @@
/*!
\fn template <class T> bool QMutableSetIterator<T>::findNext(const T &value)
- \obsolete Deprecated in order to align with std::unordered_set functionality.
Searches for \a value starting from the current iterator position
forward. Returns \c true if \a value is found; otherwise returns \c false.
@@ -591,8 +587,6 @@
After the call, if \a value was found, the iterator is positioned
just after the matching item; otherwise, the iterator is
positioned at the back of the container.
-
- \sa findPrevious()
*/
/*! \fn template <class T> bool QListIterator<T>::findNext(const T &value)
@@ -612,7 +606,6 @@
/*! \fn template <class T> bool QListIterator<T>::findPrevious(const T &value)
\fn template <class T> bool QSetIterator<T>::findPrevious(const T &value)
\fn template <class T> bool QMutableListIterator<T>::findPrevious(const T &value)
- \fn template <class T> bool QMutableSetIterator<T>::findPrevious(const T &value)
Searches for \a value starting from the current iterator position
backward. Returns \c true if \a value is found; otherwise returns
@@ -639,7 +632,7 @@
/*! \fn template <class T> void QMutableSetIterator<T>::remove()
Removes the last item that was jumped over using one of the
- traversal functions (next(), previous(), findNext(), findPrevious()).
+ traversal functions (next(), findNext()).
Example:
\snippet code/doc_src_qiterator.cpp 22
@@ -662,7 +655,6 @@
*/
/*! \fn template <class T> const T &QMutableListIterator<T>::value() const
- \fn template <class T> const T &QMutableSetIterator<T>::value() const
Returns the value of the last item that was jumped over using one
of the traversal functions (next(), previous(), findNext(),
@@ -673,6 +665,12 @@
equivalent to peekNext().
*/
+/*! \fn template <class T> const T &QMutableSetIterator<T>::value() const
+
+ Returns the value of the last item that was jumped over using
+ next() or findNext().
+*/
+
/*!
\fn template <class T> T &QMutableListIterator<T>::value()
\overload
@@ -696,9 +694,8 @@
\brief The QMapIterator class provides a Java-style const iterator for QMap.
QMap has both \l{Java-style iterators} and \l{STL-style
- iterators}. The Java-style iterators are more high-level and
- easier to use than the STL-style iterators; on the other hand,
- they are slightly less efficient.
+ iterators}. STL-style iterators are more efficient and should
+ be preferred.
QMapIterator\<Key, T\> allows you to iterate over a QMap.
If you want to modify the map as you iterate over
@@ -747,9 +744,8 @@
\brief The QMultiMapIterator class provides a Java-style const iterator for QMultiMap.
QMultiMap has both \l{Java-style iterators} and \l{STL-style
- iterators}. The Java-style iterators are more high-level and
- easier to use than the STL-style iterators; on the other hand,
- they are slightly less efficient.
+ iterators}. STL-style iterators are more efficient and should
+ be preferred.
QMultiMapIterator\<Key, T\> allows you to iterate over a QMultiMap.
If you want to modify the map as you iterate over
@@ -789,7 +785,7 @@
continue iterating over the original map, ignoring the modified
copy.
- \sa QMutableMultiMapIterator, QMultiMapIterator::const_iterator
+ \sa QMutableMultiMapIterator
*/
/*!
@@ -799,9 +795,8 @@
\brief The QHashIterator class provides a Java-style const iterator for QHash and QMultiHash.
QHash has both \l{Java-style iterators} and \l{STL-style
- iterators}. The Java-style iterators are more high-level and
- easier to use than the STL-style iterators; on the other hand,
- they are slightly less efficient.
+ iterators}. STL-style iterators are more efficient and should
+ be preferred.
QHashIterator\<Key, T\> allows you to iterate over a QHash (or a
QMultiHash). If you want to modify the hash as you iterate over
@@ -847,9 +842,8 @@
\brief The QMutableMapIterator class provides a Java-style non-const iterator for QMap.
QMap has both \l{Java-style iterators} and \l{STL-style
- iterators}. The Java-style iterators are more high-level and
- easier to use than the STL-style iterators; on the other hand,
- they are slightly less efficient.
+ iterators}. STL-style iterators are more efficient and should
+ be preferred.
QMutableMapIterator\<Key, T\> allows you to iterate over a QMap
and modify the map. If you don't want to modify
@@ -912,9 +906,8 @@
\brief The QMutableMultiMapIterator class provides a Java-style non-const iterator for QMultiMap.
QMultiMap has both \l{Java-style iterators} and \l{STL-style
- iterators}. The Java-style iterators are more high-level and
- easier to use than the STL-style iterators; on the other hand,
- they are slightly less efficient.
+ iterators}. STL-style iterators are more efficient and should
+ be preferred.
QMutableMultiMapIterator\<Key, T\> allows you to iterate over a QMultiMap
and modify the map. If you don't want to modify
@@ -977,9 +970,8 @@
\brief The QMutableHashIterator class provides a Java-style non-const iterator for QHash and QMultiHash.
QHash has both \l{Java-style iterators} and \l{STL-style
- iterators}. The Java-style iterators are more high-level and
- easier to use than the STL-style iterators; on the other hand,
- they are slightly less efficient.
+ iterators}. STL-style iterators are more efficient and should
+ be preferred.
QMutableHashIterator\<Key, T\> allows you to iterate over a QHash
(or a QMultiHash) and modify the hash. If you don't want to modify
@@ -1139,7 +1131,7 @@
Calling this function on an iterator located at the back of the
container leads to undefined results.
- \sa hasNext(), peekNext(), previous()
+ \sa hasNext(), {QMapIterator::}{peekNext()}, previous()
*/
/*! \fn template <class Key, class T> QMutableMapIterator<Key, T>::Item QMutableMapIterator<Key, T>::next()
@@ -1185,7 +1177,7 @@
*/
/*! \fn template <class Key, class T> QMapIterator<Key, T>::Item QMapIterator<Key, T>::peekNext() const
- \fn template <class Key, class T> QMutableMapIterator<Key, T>::Item QMutableMapIterator<Key, T>::peekNext()
+ \fn template <class Key, class T> QMutableMapIterator<Key, T>::Item QMutableMapIterator<Key, T>::peekNext() const
Returns the next item without moving the iterator.
@@ -1199,7 +1191,7 @@
*/
/*! \fn template <class Key, class T> QMutableMapIterator<Key, T>::Item QMutableMapIterator<Key, T>::peekNext() const
- \fn template <class Key, class T> QMutableMultiMapIterator<Key, T>::Item QMutableMultiMapIterator<Key, T>::peekNext()
+ \fn template <class Key, class T> QMutableMultiMapIterator<Key, T>::Item QMutableMultiMapIterator<Key, T>::peekNext() const
Returns a reference to the next item without moving the iterator.
@@ -1252,28 +1244,6 @@
\sa hasNext(), previous()
*/
-/*!
- \fn template <class Key, class T> bool QHashIterator<Key, T>::hasPrevious() const
- \obsolete Deprecated in order to align with std::unordered_set functionality.
-
- Returns \c true if there is at least one item behind the iterator,
- i.e. the iterator is \e not at the front of the container;
- otherwise returns \c false.
-
- \sa hasNext(), previous()
-*/
-
-/*!
- \fn template <class Key, class T> bool QMutableHashIterator<Key, T>::hasPrevious() const
- \obsolete Deprecated in order to align with std::unordered_set functionality.
-
- Returns \c true if there is at least one item behind the iterator,
- i.e. the iterator is \e not at the front of the container;
- otherwise returns \c false.
-
- \sa hasNext(), previous()
-*/
-
/*! \fn template <class Key, class T> QMapIterator<Key, T>::Item QMapIterator<Key, T>::previous()
\fn template <class Key, class T> QMutableMapIterator<Key, T>::Item QMutableMapIterator<Key, T>::previous()
\fn template <class Key, class T> QMultiMapIterator<Key, T>::Item QMultiMapIterator<Key, T>::previous()
@@ -1291,38 +1261,6 @@
\sa hasPrevious(), peekPrevious(), next()
*/
-/*!
- \fn template <class Key, class T> QHashIterator<Key, T>::Item QHashIterator<Key, T>::previous()
- \obsolete Deprecated in order to align with std::unordered_set functionality.
-
- Returns the previous item and moves the iterator back by one
- position.
-
- Call key() on the return value to obtain the item's key, and
- value() to obtain the value.
-
- Calling this function on an iterator located at the front of the
- container leads to undefined results.
-
- \sa hasPrevious(), peekPrevious(), next()
-*/
-
-/*!
- \fn template <class Key, class T> QMutableHashIterator<Key, T>::Item QMutableHashIterator<Key, T>::previous()
- \obsolete Deprecated in order to align with std::unordered_set functionality.
-
- Returns the previous item and moves the iterator back by one
- position.
-
- Call key() on the return value to obtain the item's key, and
- value() to obtain the value.
-
- Calling this function on an iterator located at the front of the
- container leads to undefined results.
-
- \sa hasPrevious(), peekPrevious(), next()
-*/
-
/*! \fn template <class Key, class T> QMapIterator<Key, T>::Item QMapIterator<Key, T>::peekPrevious() const
\fn template <class Key, class T> QMutableMapIterator<Key, T>::Item QMutableMapIterator<Key, T>::peekPrevious() const
\fn template <class Key, class T> QMultiMapIterator<Key, T>::Item QMultiMapIterator<Key, T>::peekPrevious() const
@@ -1336,37 +1274,7 @@
Calling this function on an iterator located at the front of the
container leads to undefined results.
- \sa hasPrevious(), previous(), peekNext()
-*/
-
-/*!
- \fn template <class Key, class T> QHashIterator<Key, T>::Item QHashIterator<Key, T>::peekPrevious() const
- \obsolete Deprecated in order to align with std::unordered_set functionality.
-
- Returns the previous item without moving the iterator.
-
- Call key() on the return value to obtain the item's key, and
- value() to obtain the value.
-
- Calling this function on an iterator located at the front of the
- container leads to undefined results.
-
- \sa hasPrevious(), previous(), peekNext()
-*/
-
-/*!
- \fn template <class Key, class T> QMutableHashIterator<Key, T>::Item QMutableHashIterator<Key, T>::peekPrevious() const
- \obsolete Deprecated in order to align with std::unordered_set functionality.
-
- Returns the previous item without moving the iterator.
-
- Call key() on the return value to obtain the item's key, and
- value() to obtain the value.
-
- Calling this function on an iterator located at the front of the
- container leads to undefined results.
-
- \sa hasPrevious(), previous(), peekNext()
+ \sa hasPrevious(), previous(), {QMapIterator::}{peekNext()}
*/
/*! \fn template <class Key, class T> const T &QMapIterator<Key, T>::value() const
@@ -1495,36 +1403,6 @@
\sa findNext()
*/
-/*!
- \fn template <class Key, class T> bool QHashIterator<Key, T>::findPrevious(const T &value)
- \obsolete Deprecated in order to align with std::unordered_set functionality.
-
- Searches for \a value starting from the current iterator position
- backward. Returns \c true if a (key, value) pair with value \a value
- is found; otherwise returns \c false.
-
- After the call, if \a value was found, the iterator is positioned
- just before the matching item; otherwise, the iterator is
- positioned at the front of the container.
-
- \sa findNext()
-*/
-
-/*!
- \fn template <class Key, class T> bool QMutableHashIterator<Key, T>::findPrevious(const T &value)
- \obsolete Deprecated in order to align with std::unordered_set functionality.
-
- Searches for \a value starting from the current iterator position
- backward. Returns \c true if a (key, value) pair with value \a value
- is found; otherwise returns \c false.
-
- After the call, if \a value was found, the iterator is positioned
- just before the matching item; otherwise, the iterator is
- positioned at the front of the container.
-
- \sa findNext()
-*/
-
/*! \fn template <class Key, class T> void QMutableMapIterator<Key, T>::remove()
\fn template <class Key, class T> void QMutableMultiMapIterator<Key, T>::remove()
diff --git a/src/corelib/tools/qline.cpp b/src/corelib/tools/qline.cpp
index d284883dcc..ebcbba0195 100644
--- a/src/corelib/tools/qline.cpp
+++ b/src/corelib/tools/qline.cpp
@@ -38,8 +38,10 @@
****************************************************************************/
#include "qline.h"
+
#include "qdebug.h"
#include "qdatastream.h"
+#include "qmath.h"
#include <private/qnumeric_p.h>
QT_BEGIN_NAMESPACE
@@ -98,7 +100,7 @@ QT_BEGIN_NAMESPACE
/*!
\fn bool QLine::isNull() const
- Returns \c true if the line is not set up with valid start and end point;
+ Returns \c true if the line does not have distinct start and end points;
otherwise returns \c false.
*/
@@ -427,8 +429,14 @@ QDataStream &operator>>(QDataStream &stream, QLine &line)
/*!
\fn bool QLineF::isNull() const
- Returns \c true if the line is not set up with valid start and end point;
- otherwise returns \c false.
+ Returns \c true if the line does not have distinct start and end points;
+ otherwise returns \c false. The start and end points are considered distinct
+ if qFuzzyCompare() can distinguish them in at least one coordinate.
+
+ \note Due to the use of fuzzy comparison, isNull() may return \c true for
+ lines whose length() is not zero.
+
+ \sa qFuzzyCompare(), length()
*/
/*!
@@ -511,10 +519,10 @@ QDataStream &operator>>(QDataStream &stream, QLine &line)
Sets the length of the line to the given \a length. QLineF will
move the end point - p2() - of the line to give the line its new length.
- If the line is a null line, the length will remain zero regardless
- of the length specified.
+ A null line will not be rescaled. For non-null lines with very short lengths
+ (represented by denormal floating-point values), results may be imprecise.
- \sa length(), isNull()
+ \sa length(), isNull(), unitVector()
*/
/*!
@@ -559,13 +567,12 @@ QDataStream &operator>>(QDataStream &stream, QLine &line)
/*!
Returns the length of the line.
- \sa setLength()
+ \sa setLength(), isNull()
*/
qreal QLineF::length() const
{
- qreal x = pt2.x() - pt1.x();
- qreal y = pt2.y() - pt1.y();
- return qSqrt(x*x + y*y);
+ using std::hypot;
+ return hypot(dx(), dy());
}
/*!
@@ -636,16 +643,18 @@ QLineF QLineF::fromPolar(qreal length, qreal angle)
/*!
Returns the unit vector for this line, i.e a line starting at the
- same point as \e this line with a length of 1.0.
+ same point as \e this line with a length of 1.0, provided the line
+ is non-null.
- \sa normalVector()
+ \sa normalVector(), setLength()
*/
QLineF QLineF::unitVector() const
{
- qreal x = pt2.x() - pt1.x();
- qreal y = pt2.y() - pt1.y();
+ qreal x = dx();
+ qreal y = dy();
+ using std::hypot;
+ qreal len = hypot(x, y);
- qreal len = qSqrt(x*x + y*y);
QLineF f(p1(), QPointF(pt1.x() + x/len, pt1.y() + y/len));
#ifndef QT_NO_DEBUG
diff --git a/src/corelib/tools/qline.h b/src/corelib/tools/qline.h
index c3fb2fd5f5..e35de2af6d 100644
--- a/src/corelib/tools/qline.h
+++ b/src/corelib/tools/qline.h
@@ -40,8 +40,6 @@
#ifndef QLINE_H
#define QLINE_H
-#include <QtCore/qmath.h>
-
#include <QtCore/qpoint.h>
QT_BEGIN_NAMESPACE
@@ -75,18 +73,18 @@ public:
inline void translate(const QPoint &p);
inline void translate(int dx, int dy);
- Q_REQUIRED_RESULT constexpr inline QLine translated(const QPoint &p) const;
- Q_REQUIRED_RESULT constexpr inline QLine translated(int dx, int dy) const;
+ [[nodiscard]] constexpr inline QLine translated(const QPoint &p) const;
+ [[nodiscard]] constexpr inline QLine translated(int dx, int dy) const;
- Q_REQUIRED_RESULT constexpr inline QPoint center() const;
+ [[nodiscard]] constexpr inline QPoint center() const;
inline void setP1(const QPoint &p1);
inline void setP2(const QPoint &p2);
inline void setPoints(const QPoint &p1, const QPoint &p2);
inline void setLine(int x1, int y1, int x2, int y2);
- constexpr inline bool operator==(const QLine &d) const;
- constexpr inline bool operator!=(const QLine &d) const { return !(*this == d); }
+ constexpr inline bool operator==(const QLine &d) const noexcept;
+ constexpr inline bool operator!=(const QLine &d) const noexcept { return !(*this == d); }
private:
QPoint pt1, pt2;
@@ -196,7 +194,7 @@ inline void QLine::setLine(int aX1, int aY1, int aX2, int aY2)
pt2 = QPoint(aX2, aY2);
}
-constexpr inline bool QLine::operator==(const QLine &d) const
+constexpr inline bool QLine::operator==(const QLine &d) const noexcept
{
return pt1 == d.pt1 && pt2 == d.pt2;
}
@@ -225,7 +223,7 @@ public:
constexpr inline QLineF(qreal x1, qreal y1, qreal x2, qreal y2);
constexpr inline QLineF(const QLine &line) : pt1(line.p1()), pt2(line.p2()) { }
- Q_REQUIRED_RESULT static QLineF fromPolar(qreal length, qreal angle);
+ [[nodiscard]] static QLineF fromPolar(qreal length, qreal angle);
constexpr bool isNull() const;
@@ -249,8 +247,8 @@ public:
qreal angleTo(const QLineF &l) const;
- Q_REQUIRED_RESULT QLineF unitVector() const;
- Q_REQUIRED_RESULT constexpr inline QLineF normalVector() const;
+ [[nodiscard]] QLineF unitVector() const;
+ [[nodiscard]] constexpr inline QLineF normalVector() const;
IntersectionType intersects(const QLineF &l, QPointF *intersectionPoint = nullptr) const;
@@ -258,10 +256,10 @@ public:
inline void translate(const QPointF &p);
inline void translate(qreal dx, qreal dy);
- Q_REQUIRED_RESULT constexpr inline QLineF translated(const QPointF &p) const;
- Q_REQUIRED_RESULT constexpr inline QLineF translated(qreal dx, qreal dy) const;
+ [[nodiscard]] constexpr inline QLineF translated(const QPointF &p) const;
+ [[nodiscard]] constexpr inline QLineF translated(qreal dx, qreal dy) const;
- Q_REQUIRED_RESULT constexpr inline QPointF center() const;
+ [[nodiscard]] constexpr inline QPointF center() const;
inline void setP1(const QPointF &p1);
inline void setP2(const QPointF &p2);
@@ -372,15 +370,14 @@ constexpr inline QPointF QLineF::center() const
return QPointF(0.5 * pt1.x() + 0.5 * pt2.x(), 0.5 * pt1.y() + 0.5 * pt2.y());
}
-QT_WARNING_DISABLE_FLOAT_COMPARE
-
inline void QLineF::setLength(qreal len)
{
- const qreal oldlength = qSqrt(dx() * dx() + dy() * dy());
- if (!oldlength)
+ if (isNull())
return;
- const qreal factor = len / oldlength;
- pt2 = QPointF(pt1.x() + dx() * factor, pt1.y() + dy() * factor);
+ Q_ASSERT(length() > 0);
+ const QLineF v = unitVector();
+ len /= v.length(); // In case it's not quite exactly 1.
+ pt2 = QPointF(pt1.x() + len * v.dx(), pt1.y() + len * v.dy());
}
constexpr inline QPointF QLineF::pointAt(qreal t) const
diff --git a/src/corelib/tools/qlist.h b/src/corelib/tools/qlist.h
index 3f621e71fb..517ba10326 100644
--- a/src/corelib/tools/qlist.h
+++ b/src/corelib/tools/qlist.h
@@ -58,31 +58,52 @@ namespace QtPrivate {
template <typename V, typename U> qsizetype lastIndexOf(const QList<V> &list, const U &u, qsizetype from) noexcept;
}
-template <typename T> struct QListSpecialMethods
+template <typename T> struct QListSpecialMethodsBase
{
protected:
- ~QListSpecialMethods() = default;
+ ~QListSpecialMethodsBase() = default;
+
+ using Self = QList<T>;
+ Self *self() { return static_cast<Self *>(this); }
+ const Self *self() const { return static_cast<const Self *>(this); }
+
public:
- qsizetype indexOf(const T &t, qsizetype from = 0) const noexcept;
- qsizetype lastIndexOf(const T &t, qsizetype from = -1) const noexcept;
+ template <typename AT = T>
+ qsizetype indexOf(const AT &t, qsizetype from = 0) const noexcept;
+ template <typename AT = T>
+ qsizetype lastIndexOf(const AT &t, qsizetype from = -1) const noexcept;
- bool contains(const T &t) const noexcept
+ template <typename AT = T>
+ bool contains(const AT &t) const noexcept
{
- return indexOf(t) != -1;
+ return self()->indexOf(t) != -1;
}
};
+template <typename T> struct QListSpecialMethods : QListSpecialMethodsBase<T>
+{
+protected:
+ ~QListSpecialMethods() = default;
+public:
+ using QListSpecialMethodsBase<T>::indexOf;
+ using QListSpecialMethodsBase<T>::lastIndexOf;
+ using QListSpecialMethodsBase<T>::contains;
+};
template <> struct QListSpecialMethods<QByteArray>;
template <> struct QListSpecialMethods<QString>;
+#ifdef Q_QDOC // define QVector for QDoc
+template<typename T> class QVector : public QList<T> {};
+#endif
+
template <typename T>
class QList
#ifndef Q_QDOC
: public QListSpecialMethods<T>
#endif
{
- typedef QTypedArrayData<T> Data;
- typedef QArrayDataOps<T> DataOps;
- typedef QArrayDataPointer<T> DataPointer;
+ using Data = QTypedArrayData<T>;
+ using DataOps = QArrayDataOps<T>;
+ using DataPointer = QArrayDataPointer<T>;
class DisableRValueRefs {};
DataPointer d;
@@ -91,25 +112,101 @@ class QList
template <typename V, typename U> friend qsizetype QtPrivate::lastIndexOf(const QList<V> &list, const U &u, qsizetype from) noexcept;
public:
- typedef T Type;
- typedef T value_type;
- typedef value_type *pointer;
- typedef const value_type *const_pointer;
- typedef value_type &reference;
- typedef const value_type &const_reference;
- typedef qsizetype size_type;
- typedef qptrdiff difference_type;
- typedef typename Data::iterator iterator;
- typedef typename Data::const_iterator const_iterator;
- typedef iterator Iterator;
- typedef const_iterator ConstIterator;
- typedef std::reverse_iterator<iterator> reverse_iterator;
- typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
- typedef typename DataPointer::parameter_type parameter_type;
+ using Type = T;
+ using value_type = T;
+ using pointer = T *;
+ using const_pointer = const T *;
+ using reference = T &;
+ using const_reference = const T &;
+ using size_type = qsizetype;
+ using difference_type = qptrdiff;
+#ifndef Q_QDOC
+ using parameter_type = typename DataPointer::parameter_type;
using rvalue_ref = typename std::conditional<DataPointer::pass_parameter_by_value, DisableRValueRefs, T &&>::type;
+#else // simplified aliases for QDoc
+ using parameter_type = const T &;
+ using rvalue_ref = T &&;
+#endif
+
+ class iterator {
+ T *i = nullptr;
+ public:
+ typedef std::random_access_iterator_tag iterator_category;
+ typedef qsizetype difference_type;
+ typedef T value_type;
+ typedef T *pointer;
+ typedef T &reference;
+
+ inline constexpr iterator() = default;
+ inline iterator(T *n) : i(n) {}
+ inline T &operator*() const { return *i; }
+ inline T *operator->() const { return i; }
+ inline T &operator[](qsizetype j) const { return *(i + j); }
+ inline constexpr bool operator==(iterator o) const { return i == o.i; }
+ inline constexpr bool operator!=(iterator o) const { return i != o.i; }
+ inline constexpr bool operator<(iterator other) const { return i < other.i; }
+ inline constexpr bool operator<=(iterator other) const { return i <= other.i; }
+ inline constexpr bool operator>(iterator other) const { return i > other.i; }
+ inline constexpr bool operator>=(iterator other) const { return i >= other.i; }
+ inline constexpr bool operator==(pointer p) const { return i == p; }
+ inline constexpr bool operator!=(pointer p) const { return i != p; }
+ inline iterator &operator++() { ++i; return *this; }
+ inline iterator operator++(int) { T *n = i; ++i; return n; }
+ inline iterator &operator--() { i--; return *this; }
+ inline iterator operator--(int) { T *n = i; i--; return n; }
+ inline iterator &operator+=(qsizetype j) { i+=j; return *this; }
+ inline iterator &operator-=(qsizetype j) { i-=j; return *this; }
+ inline iterator operator+(qsizetype j) const { return iterator(i+j); }
+ inline iterator operator-(qsizetype j) const { return iterator(i-j); }
+ friend inline iterator operator+(qsizetype j, iterator k) { return k + j; }
+ inline qsizetype operator-(iterator j) const { return i - j.i; }
+ inline operator T*() const { return i; }
+ };
+
+ class const_iterator {
+ const T *i = nullptr;
+ public:
+ typedef std::random_access_iterator_tag iterator_category;
+ typedef qsizetype difference_type;
+ typedef T value_type;
+ typedef const T *pointer;
+ typedef const T &reference;
+
+ inline constexpr const_iterator() = default;
+ inline const_iterator(const T *n) : i(n) {}
+ inline constexpr const_iterator(iterator o): i(o) {}
+ inline const T &operator*() const { return *i; }
+ inline const T *operator->() const { return i; }
+ inline const T &operator[](qsizetype j) const { return *(i + j); }
+ inline constexpr bool operator==(const_iterator o) const { return i == o.i; }
+ inline constexpr bool operator!=(const_iterator o) const { return i != o.i; }
+ inline constexpr bool operator<(const_iterator other) const { return i < other.i; }
+ inline constexpr bool operator<=(const_iterator other) const { return i <= other.i; }
+ inline constexpr bool operator>(const_iterator other) const { return i > other.i; }
+ inline constexpr bool operator>=(const_iterator other) const { return i >= other.i; }
+ inline constexpr bool operator==(iterator o) const { return i == const_iterator(o).i; }
+ inline constexpr bool operator!=(iterator o) const { return i != const_iterator(o).i; }
+ inline constexpr bool operator==(pointer p) const { return i == p; }
+ inline constexpr bool operator!=(pointer p) const { return i != p; }
+ inline const_iterator &operator++() { ++i; return *this; }
+ inline const_iterator operator++(int) { const T *n = i; ++i; return n; }
+ inline const_iterator &operator--() { i--; return *this; }
+ inline const_iterator operator--(int) { const T *n = i; i--; return n; }
+ inline const_iterator &operator+=(qsizetype j) { i+=j; return *this; }
+ inline const_iterator &operator-=(qsizetype j) { i-=j; return *this; }
+ inline const_iterator operator+(qsizetype j) const { return const_iterator(i+j); }
+ inline const_iterator operator-(qsizetype j) const { return const_iterator(i-j); }
+ friend inline const_iterator operator+(qsizetype j, const_iterator k) { return k + j; }
+ inline qsizetype operator-(const_iterator j) const { return i - j.i; }
+ inline operator const T*() const { return i; }
+ };
+ using Iterator = iterator;
+ using ConstIterator = const_iterator;
+ using reverse_iterator = std::reverse_iterator<iterator>;
+ using const_reverse_iterator = std::reverse_iterator<const_iterator>;
private:
- void resize_internal(qsizetype i, Qt::Initialization);
+ void resize_internal(qsizetype i);
bool isValidIterator(const_iterator i) const
{
const std::less<const T*> less = {};
@@ -129,7 +226,7 @@ public:
if (size)
d->appendInitialize(size);
}
- QList(qsizetype size, const T &t)
+ QList(qsizetype size, parameter_type t)
: d(Data::allocate(size))
{
if (size)
@@ -150,22 +247,25 @@ public:
d->copyAppend(args.begin(), args.end());
return *this;
}
- template <typename InputIterator, QtPrivate::IfIsForwardIterator<InputIterator> = true>
+ template <typename InputIterator, QtPrivate::IfIsInputIterator<InputIterator> = true>
QList(InputIterator i1, InputIterator i2)
{
- const auto distance = std::distance(i1, i2);
- if (distance) {
- d = DataPointer(Data::allocate(distance));
- d->copyAppend(i1, i2);
+ if constexpr (!std::is_convertible_v<typename std::iterator_traits<Iterator>::iterator_category, std::forward_iterator_tag>) {
+ std::copy(i1, i2, std::back_inserter(*this));
+ } else {
+ const auto distance = std::distance(i1, i2);
+ if (distance) {
+ d = DataPointer(Data::allocate(distance));
+ if constexpr (std::is_same_v<std::decay_t<InputIterator>, iterator> ||
+ std::is_same_v<std::decay_t<InputIterator>, const_iterator>) {
+ d->copyAppend(i1, i2);
+ } else {
+ d->appendIteratorRange(i1, i2);
+ }
+ }
}
}
- template <typename InputIterator, QtPrivate::IfIsNotForwardIterator<InputIterator> = true>
- QList(InputIterator i1, InputIterator i2)
- {
- std::copy(i1, i2, std::back_inserter(*this));
- }
-
// This constructor is here for compatibility with QStringList in Qt 5, that has a QStringList(const QString &) constructor
template<typename String, typename = std::enable_if_t<std::is_same_v<T, QString> && std::is_convertible_v<String, QString>>>
inline explicit QList(const String &str)
@@ -175,10 +275,54 @@ public:
void swap(QList<T> &other) noexcept { qSwap(d, other.d); }
- template <typename U>
- friend QTypeTraits::compare_eq_result<U> operator==(const QList<U> &l, const QList<U> &r);
- template <typename U>
- friend QTypeTraits::compare_eq_result<U> operator!=(const QList<U> &l, const QList<U> &r);
+ template <typename U = T>
+ QTypeTraits::compare_eq_result<U> operator==(const QList &other) const
+ {
+ if (size() != other.size())
+ return false;
+ if (begin() == other.begin())
+ return true;
+
+ // do element-by-element comparison
+ return d->compare(begin(), other.begin(), size());
+ }
+ template <typename U = T>
+ QTypeTraits::compare_eq_result<U> operator!=(const QList &other) const
+ {
+ return !(*this == other);
+ }
+
+ template <typename U = T>
+ QTypeTraits::compare_lt_result<U> operator<(const QList &other) const
+ noexcept(noexcept(std::lexicographical_compare<typename QList<U>::const_iterator,
+ typename QList::const_iterator>(
+ std::declval<QList<U>>().begin(), std::declval<QList<U>>().end(),
+ other.begin(), other.end())))
+ {
+ return std::lexicographical_compare(begin(), end(),
+ other.begin(), other.end());
+ }
+
+ template <typename U = T>
+ QTypeTraits::compare_lt_result<U> operator>(const QList &other) const
+ noexcept(noexcept(other < std::declval<QList<U>>()))
+ {
+ return other < *this;
+ }
+
+ template <typename U = T>
+ QTypeTraits::compare_lt_result<U> operator<=(const QList &other) const
+ noexcept(noexcept(other < std::declval<QList<U>>()))
+ {
+ return !(other < *this);
+ }
+
+ template <typename U = T>
+ QTypeTraits::compare_lt_result<U> operator>=(const QList &other) const
+ noexcept(noexcept(std::declval<QList<U>>() < other))
+ {
+ return !(*this < other);
+ }
qsizetype size() const noexcept { return d->size; }
qsizetype count() const noexcept { return size(); }
@@ -188,13 +332,13 @@ public:
void resize(qsizetype size)
{
- resize_internal(size, Qt::Uninitialized);
+ resize_internal(size);
if (size > this->size())
d->appendInitialize(size);
}
void resize(qsizetype size, parameter_type c)
{
- resize_internal(size, Qt::Uninitialized);
+ resize_internal(size);
if (size > this->size())
d->copyAppend(size - this->size(), c);
}
@@ -216,7 +360,7 @@ public:
return;
if (d->needsDetach()) {
// must allocate memory
- DataPointer detached(Data::allocate(d.allocatedCapacity(), d->detachFlags()));
+ DataPointer detached(Data::allocate(d.allocatedCapacity()));
d.swap(detached);
} else {
d->truncate(0);
@@ -235,20 +379,38 @@ public:
return data()[i];
}
const_reference operator[](qsizetype i) const noexcept { return at(i); }
- void append(const_reference t)
- { append(const_iterator(std::addressof(t)), const_iterator(std::addressof(t)) + 1); }
+ void append(parameter_type t) { emplaceBack(t); }
void append(const_iterator i1, const_iterator i2);
- void append(rvalue_ref t) { emplaceBack(std::move(t)); }
- void append(const QList<T> &l) { append(l.constBegin(), l.constEnd()); }
+ void append(rvalue_ref t)
+ {
+ if constexpr (DataPointer::pass_parameter_by_value) {
+ Q_UNUSED(t);
+ } else {
+ emplaceBack(std::move(t));
+ }
+ }
+ void append(const QList<T> &l)
+ {
+ append(l.constBegin(), l.constEnd());
+ }
void append(QList<T> &&l);
- void prepend(rvalue_ref t);
- void prepend(const T &t);
+ void prepend(rvalue_ref t) {
+ if constexpr (DataPointer::pass_parameter_by_value) {
+ Q_UNUSED(t);
+ } else {
+ emplaceFront(std::move(t));
+ }
+ }
+ void prepend(parameter_type t) { emplaceFront(t); }
+
+ template<typename... Args>
+ inline reference emplaceBack(Args &&... args);
template <typename ...Args>
- reference emplaceBack(Args&&... args) { return *emplace(count(), std::forward<Args>(args)...); }
+ inline reference emplaceFront(Args&&... args);
iterator insert(qsizetype i, parameter_type t)
- { return insert(i, 1, t); }
+ { return emplace(i, t); }
iterator insert(qsizetype i, qsizetype n, parameter_type t);
iterator insert(const_iterator before, parameter_type t)
{
@@ -265,7 +427,15 @@ public:
Q_ASSERT_X(isValidIterator(before), "QList::insert", "The specified iterator argument 'before' is invalid");
return insert(std::distance(constBegin(), before), std::move(t));
}
- iterator insert(qsizetype i, rvalue_ref t) { return emplace(i, std::move(t)); }
+ iterator insert(qsizetype i, rvalue_ref t) {
+ if constexpr (DataPointer::pass_parameter_by_value) {
+ Q_UNUSED(i);
+ Q_UNUSED(t);
+ return end();
+ } else {
+ return emplace(i, std::move(t));
+ }
+ }
template <typename ...Args>
iterator emplace(const_iterator before, Args&&... args)
@@ -281,24 +451,31 @@ public:
iterator insert( const_iterator pos, InputIt first, InputIt last );
iterator insert( const_iterator pos, std::initializer_list<T> ilist );
#endif
- void replace(qsizetype i, const T &t)
+ void replace(qsizetype i, parameter_type t)
{
Q_ASSERT_X(i >= 0 && i < d->size, "QList<T>::replace", "index out of range");
- const T copy(t);
- data()[i] = copy;
+ DataPointer oldData;
+ d.detach(&oldData);
+ d.data()[i] = t;
}
void replace(qsizetype i, rvalue_ref t)
{
- Q_ASSERT_X(i >= 0 && i < d->size, "QList<T>::replace", "index out of range");
- const T copy(std::move(t));
- data()[i] = std::move(copy);
+ if constexpr (DataPointer::pass_parameter_by_value) {
+ Q_UNUSED(i);
+ Q_UNUSED(t);
+ } else {
+ Q_ASSERT_X(i >= 0 && i < d->size, "QList<T>::replace", "index out of range");
+ DataPointer oldData;
+ d.detach(&oldData);
+ d.data()[i] = std::move(t);
+ }
}
void remove(qsizetype i, qsizetype n = 1);
- void removeFirst() { Q_ASSERT(!isEmpty()); remove(0); }
- void removeLast() { Q_ASSERT(!isEmpty()); remove(size() - 1); }
- value_type takeFirst() { Q_ASSERT(!isEmpty()); value_type v = std::move(first()); remove(0); return v; }
- value_type takeLast() { Q_ASSERT(!isEmpty()); value_type v = std::move(last()); remove(size() - 1); return v; }
+ void removeFirst() noexcept;
+ void removeLast() noexcept;
+ value_type takeFirst() { Q_ASSERT(!isEmpty()); value_type v = std::move(first()); d->eraseFirst(); return v; }
+ value_type takeLast() { Q_ASSERT(!isEmpty()); value_type v = std::move(last()); d->eraseLast(); return v; }
QList<T> &fill(parameter_type t, qsizetype size = -1);
@@ -307,32 +484,44 @@ public:
using QListSpecialMethods<T>::indexOf;
using QListSpecialMethods<T>::lastIndexOf;
#else
- qsizetype indexOf(const T &t, qsizetype from = 0) const noexcept;
- qsizetype lastIndexOf(const T &t, qsizetype from = -1) const noexcept;
- bool contains(const T &t) const noexcept;
+ template <typename AT>
+ qsizetype indexOf(const AT &t, qsizetype from = 0) const noexcept;
+ template <typename AT>
+ qsizetype lastIndexOf(const AT &t, qsizetype from = -1) const noexcept;
+ template <typename AT>
+ bool contains(const AT &t) const noexcept;
#endif
- qsizetype count(const T &t) const noexcept
+ template <typename AT = T>
+ qsizetype count(const AT &t) const noexcept
{
return qsizetype(std::count(&*cbegin(), &*cend(), t));
}
- // QList compatibility
void removeAt(qsizetype i) { remove(i); }
- qsizetype removeAll(const T &t)
+ template <typename AT = T>
+ qsizetype removeAll(const AT &t)
{
const const_iterator ce = this->cend(), cit = std::find(this->cbegin(), ce, t);
if (cit == ce)
return 0;
qsizetype index = cit - this->cbegin();
- // next operation detaches, so ce, cit, t may become invalidated:
- const T tCopy = t;
+
+ // Next operation detaches, so ce, cit may become invalidated.
+ // Moreover -- unlike std::erase -- we do support the case where t
+ // belongs to this list, so we have to save it from invalidation
+ // by taking a copy. This is made slightly more complex by the fact
+ // that t might not be copiable (in which case it certainly does not
+ // belong to this list), in which case we just use the original.
+ using CopyProxy = std::conditional_t<std::is_copy_constructible_v<AT>, AT, const AT &>;
+ const AT &tCopy = CopyProxy(t);
const iterator e = end(), it = std::remove(begin() + index, e, tCopy);
const qsizetype result = std::distance(it, e);
- erase(it, e);
+ d->truncate(d->size - result);
return result;
}
- bool removeOne(const T &t)
+ template <typename AT = T>
+ bool removeOne(const AT &t)
{
const qsizetype i = indexOf(t);
if (i < 0)
@@ -377,13 +566,13 @@ public:
// more Qt
inline T& first() { Q_ASSERT(!isEmpty()); return *begin(); }
- inline const T &first() const { Q_ASSERT(!isEmpty()); return *begin(); }
- inline const T &constFirst() const { Q_ASSERT(!isEmpty()); return *begin(); }
+ inline const T &first() const noexcept { Q_ASSERT(!isEmpty()); return *begin(); }
+ inline const T &constFirst() const noexcept { Q_ASSERT(!isEmpty()); return *begin(); }
inline T& last() { Q_ASSERT(!isEmpty()); return *(end()-1); }
- inline const T &last() const { Q_ASSERT(!isEmpty()); return *(end()-1); }
- inline const T &constLast() const { Q_ASSERT(!isEmpty()); return *(end()-1); }
- inline bool startsWith(const T &t) const { return !isEmpty() && first() == t; }
- inline bool endsWith(const T &t) const { return !isEmpty() && last() == t; }
+ inline const T &last() const noexcept { Q_ASSERT(!isEmpty()); return *(end()-1); }
+ inline const T &constLast() const noexcept { Q_ASSERT(!isEmpty()); return *(end()-1); }
+ inline bool startsWith(parameter_type t) const { return !isEmpty() && first() == t; }
+ inline bool endsWith(parameter_type t) const { return !isEmpty() && last() == t; }
QList<T> mid(qsizetype pos, qsizetype len = -1) const;
QList<T> first(qsizetype n) const
@@ -410,7 +599,7 @@ public:
}
T value(qsizetype i) const { return value(i, T()); }
- T value(qsizetype i, const T &defaultValue) const;
+ T value(qsizetype i, parameter_type defaultValue) const;
void swapItemsAt(qsizetype i, qsizetype j) {
Q_ASSERT_X(i >= 0 && i < size() && j >= 0 && j < size(),
@@ -420,34 +609,34 @@ public:
}
// STL compatibility
- inline void push_back(const T &t) { append(t); }
+ inline void push_back(parameter_type t) { append(t); }
void push_back(rvalue_ref t) { append(std::move(t)); }
void push_front(rvalue_ref t) { prepend(std::move(t)); }
- inline void push_front(const T &t) { prepend(t); }
- void pop_back() { removeLast(); }
- void pop_front() { removeFirst(); }
+ inline void push_front(parameter_type t) { prepend(t); }
+ void pop_back() noexcept { removeLast(); }
+ void pop_front() noexcept { removeFirst(); }
template <typename ...Args>
reference emplace_back(Args&&... args) { return emplaceBack(std::forward<Args>(args)...); }
- inline bool empty() const
+ inline bool empty() const noexcept
{ return d->size == 0; }
inline reference front() { return first(); }
- inline const_reference front() const { return first(); }
+ inline const_reference front() const noexcept { return first(); }
inline reference back() { return last(); }
- inline const_reference back() const { return last(); }
+ inline const_reference back() const noexcept { return last(); }
void shrink_to_fit() { squeeze(); }
// comfort
- QList<T> &operator+=(const QList<T> &l) { append(l.cbegin(), l.cend()); return *this; }
+ QList<T> &operator+=(const QList<T> &l) { append(l); return *this; }
QList<T> &operator+=(QList<T> &&l) { append(std::move(l)); return *this; }
inline QList<T> operator+(const QList<T> &l) const
{ QList n = *this; n += l; return n; }
inline QList<T> operator+(QList<T> &&l) const
{ QList n = *this; n += std::move(l); return n; }
- inline QList<T> &operator+=(const T &t)
+ inline QList<T> &operator+=(parameter_type t)
{ append(t); return *this; }
- inline QList<T> &operator<< (const T &t)
+ inline QList<T> &operator<< (parameter_type t)
{ append(t); return *this; }
inline QList<T> &operator<<(const QList<T> &l)
{ *this += l; return *this; }
@@ -459,14 +648,14 @@ public:
{ append(std::move(t)); return *this; }
// Consider deprecating in 6.4 or later
- static QList<T> fromList(const QList<T> &list) { return list; }
- QList<T> toList() const { return *this; }
+ static QList<T> fromList(const QList<T> &list) noexcept { return list; }
+ QList<T> toList() const noexcept { return *this; }
- static inline QList<T> fromVector(const QList<T> &vector) { return vector; }
- inline QList<T> toVector() const { return *this; }
+ static inline QList<T> fromVector(const QList<T> &vector) noexcept { return vector; }
+ inline QList<T> toVector() const noexcept { return *this; }
template<qsizetype N>
- static QList<T> fromReadOnlyData(const T (&t)[N])
+ static QList<T> fromReadOnlyData(const T (&t)[N]) noexcept
{
return QList<T>({ nullptr, const_cast<T *>(t), N });
}
@@ -480,21 +669,13 @@ QList(InputIterator, InputIterator) -> QList<ValueType>;
#endif
template <typename T>
-inline void QList<T>::resize_internal(qsizetype newSize, Qt::Initialization)
+inline void QList<T>::resize_internal(qsizetype newSize)
{
Q_ASSERT(newSize >= 0);
if (d->needsDetach() || newSize > capacity() - d.freeSpaceAtBegin()) {
- // must allocate memory
- DataPointer detached(Data::allocate(d->detachCapacity(newSize),
- d->detachFlags()));
- if (size() && newSize) {
- detached->copyAppend(constBegin(), constBegin() + qMin(newSize, size()));
- }
- d.swap(detached);
- }
-
- if (newSize < size())
+ d.reallocateAndGrow(QArrayData::GrowsAtEnd, newSize - d.size);
+ } else if (newSize < size())
d->truncate(newSize);
}
@@ -512,23 +693,31 @@ void QList<T>::reserve(qsizetype asize)
}
}
- DataPointer detached(Data::allocate(qMax(asize, size()),
- d->detachFlags() | Data::CapacityReserved));
+ DataPointer detached(Data::allocate(qMax(asize, size())));
detached->copyAppend(constBegin(), constEnd());
+ if (detached.d_ptr())
+ detached->setFlag(Data::CapacityReserved);
d.swap(detached);
}
template <typename T>
inline void QList<T>::squeeze()
{
- if (d->needsDetach() || size() != capacity()) {
+ if (!d.isMutable())
+ return;
+ if (d->needsDetach() || size() < capacity()) {
// must allocate memory
- DataPointer detached(Data::allocate(size(), d->detachFlags() & ~Data::CapacityReserved));
+ DataPointer detached(Data::allocate(size()));
if (size()) {
- detached->copyAppend(constBegin(), constEnd());
+ if (d.needsDetach())
+ detached->copyAppend(constBegin(), constEnd());
+ else
+ detached->moveAppend(d.data(), d.data() + d.size);
}
d.swap(detached);
}
+ // We're detached so this is fine
+ d->clearFlag(Data::CapacityReserved);
}
template <typename T>
@@ -540,33 +729,29 @@ inline void QList<T>::remove(qsizetype i, qsizetype n)
if (n == 0)
return;
- const size_t newSize = size() - n;
- if (d->needsDetach() ||
- ((d->flags() & Data::CapacityReserved) == 0
- && newSize < d->allocatedCapacity()/2)) {
- // allocate memory
- DataPointer detached(Data::allocate(d->detachCapacity(newSize), d->detachFlags()));
- const_iterator where = constBegin() + i;
- if (newSize) {
- detached->copyAppend(constBegin(), where);
- detached->copyAppend(where + n, constEnd());
- }
- d.swap(detached);
- } else {
- // we're detached and we can just move data around
- d->erase(d->begin() + i, d->begin() + i + n);
- }
+ d.detach();
+ d->erase(d->begin() + i, n);
}
template <typename T>
-inline void QList<T>::prepend(const T &t)
-{ insert(0, 1, t); }
+inline void QList<T>::removeFirst() noexcept
+{
+ Q_ASSERT(!isEmpty());
+ d.detach();
+ d->eraseFirst();
+}
+
template <typename T>
-void QList<T>::prepend(rvalue_ref t)
-{ insert(0, std::move(t)); }
+inline void QList<T>::removeLast() noexcept
+{
+ Q_ASSERT(!isEmpty());
+ d.detach();
+ d->eraseLast();
+}
+
template<typename T>
-inline T QList<T>::value(qsizetype i, const T &defaultValue) const
+inline T QList<T>::value(qsizetype i, parameter_type defaultValue) const
{
return size_t(i) < size_t(d->size) ? at(i) : defaultValue;
}
@@ -576,46 +761,31 @@ inline void QList<T>::append(const_iterator i1, const_iterator i2)
{
if (i1 == i2)
return;
- const size_t distance = std::distance(i1, i2);
- const size_t newSize = size() + distance;
- const bool shouldGrow = d->shouldGrowBeforeInsert(d.end(), qsizetype(distance));
- if (d->needsDetach() || newSize > d->allocatedCapacity() || shouldGrow) {
- DataPointer detached(DataPointer::allocateGrow(d, newSize,
- d->detachFlags() | Data::GrowsForward));
- detached->copyAppend(constBegin(), constEnd());
- detached->copyAppend(i1, i2);
- d.swap(detached);
- } else {
- // we're detached and we can just move data around
- d->copyAppend(i1, i2);
- }
+ const auto distance = std::distance(i1, i2);
+ DataPointer oldData;
+ d.detachAndGrow(QArrayData::GrowsAtEnd, distance, &oldData);
+ d->copyAppend(i1, i2);
}
template <typename T>
inline void QList<T>::append(QList<T> &&other)
{
+ Q_ASSERT(&other != this);
if (other.isEmpty())
return;
if (other.d->needsDetach() || !std::is_nothrow_move_constructible_v<T>)
return append(other);
- const size_t newSize = size() + other.size();
- const bool shouldGrow = d->shouldGrowBeforeInsert(d.end(), other.size());
- if (d->needsDetach() || newSize > d->allocatedCapacity() || shouldGrow) {
- DataPointer detached(DataPointer::allocateGrow(d, newSize,
- d->detachFlags() | Data::GrowsForward));
-
- if (!d->needsDetach())
- detached->moveAppend(begin(), end());
- else
- detached->copyAppend(cbegin(), cend());
- detached->moveAppend(other.begin(), other.end());
+ d.detachAndGrow(QArrayData::GrowsAtEnd, other.size());
+ d->moveAppend(other.begin(), other.end());
+}
- d.swap(detached);
- } else {
- // we're detached and we can just move data around
- d->moveAppend(other.begin(), other.end());
- }
+template<typename T>
+template<typename... Args>
+inline typename QList<T>::reference QList<T>::emplaceFront(Args &&... args)
+{
+ d->emplace(0, std::forward<Args>(args)...);
+ return *d.begin();
}
@@ -625,31 +795,7 @@ QList<T>::insert(qsizetype i, qsizetype n, parameter_type t)
{
Q_ASSERT_X(size_t(i) <= size_t(d->size), "QList<T>::insert", "index out of range");
- // we don't have a quick exit for n == 0
- // it's not worth wasting CPU cycles for that
-
- const size_t newSize = size() + n;
- const bool shouldGrow = d->shouldGrowBeforeInsert(d.begin() + i, n);
- if (d->needsDetach() || newSize > d->allocatedCapacity() || shouldGrow) {
- typename Data::ArrayOptions flags = d->detachFlags() | Data::GrowsForward;
- if (d.size != 0 && i <= d.size / 4)
- flags |= Data::GrowsBackwards;
-
- DataPointer detached(DataPointer::allocateGrow(d, newSize, flags));
- const_iterator where = constBegin() + i;
- detached->copyAppend(constBegin(), where);
- detached->copyAppend(n, t);
- detached->copyAppend(where, constEnd());
- d.swap(detached);
- } else {
- // we're detached and we can just move data around
- if (i == size()) {
- d->copyAppend(n, t);
- } else {
- T copy(t);
- d->insert(d.begin() + i, n, copy);
- }
- }
+ d->insert(i, n, t);
return d.begin() + i;
}
@@ -658,33 +804,19 @@ template <typename ...Args>
typename QList<T>::iterator
QList<T>::emplace(qsizetype i, Args&&... args)
{
- Q_ASSERT_X(i >= 0 && i <= d->size, "QList<T>::insert", "index out of range");
-
- const bool shouldGrow = d->shouldGrowBeforeInsert(d.begin() + i, 1);
- const size_t newSize = size() + 1;
- if (d->needsDetach() || newSize > d->allocatedCapacity() || shouldGrow) {
- typename Data::ArrayOptions flags = d->detachFlags() | Data::GrowsForward;
- if (d.size != 0 && i <= d.size / 4)
- flags |= Data::GrowsBackwards;
-
- DataPointer detached(DataPointer::allocateGrow(d, newSize, flags));
- const_iterator where = constBegin() + i;
- // Create an element here to handle cases when a user moves the element
- // from a container to the same container. This is a critical step for
- // COW types (e.g. Qt types) since copyAppend() done before emplace()
- // would shallow-copy the passed element and ruin the move
- T tmp(std::forward<Args>(args)...);
-
- detached->copyAppend(constBegin(), where);
- detached->emplace(detached.end(), std::move(tmp));
- detached->copyAppend(where, constEnd());
- d.swap(detached);
- } else {
- d->emplace(d.begin() + i, std::forward<Args>(args)...);
- }
+ Q_ASSERT_X(i >= 0 && i <= d->size, "QList<T>::insert", "index out of range");
+ d->emplace(i, std::forward<Args>(args)...);
return d.begin() + i;
}
+template<typename T>
+template<typename... Args>
+inline typename QList<T>::reference QList<T>::emplaceBack(Args &&... args)
+{
+ d->emplace(d->size, std::forward<Args>(args)...);
+ return *(d.end() - 1);
+}
+
template <typename T>
typename QList<T>::iterator QList<T>::erase(const_iterator abegin, const_iterator aend)
{
@@ -692,7 +824,7 @@ typename QList<T>::iterator QList<T>::erase(const_iterator abegin, const_iterato
Q_ASSERT_X(isValidIterator(aend), "QList::erase", "The specified iterator argument 'aend' is invalid");
Q_ASSERT(aend >= abegin);
- qsizetype i = std::distance(d.constBegin(), abegin);
+ qsizetype i = std::distance(constBegin(), abegin);
qsizetype n = std::distance(abegin, aend);
remove(i, n);
@@ -706,8 +838,7 @@ inline QList<T> &QList<T>::fill(parameter_type t, qsizetype newSize)
newSize = size();
if (d->needsDetach() || newSize > capacity()) {
// must allocate memory
- DataPointer detached(Data::allocate(d->detachCapacity(newSize),
- d->detachFlags()));
+ DataPointer detached(Data::allocate(d->detachCapacity(newSize)));
detached->copyAppend(newSize, t);
d.swap(detached);
} else {
@@ -756,15 +887,17 @@ qsizetype lastIndexOf(const QList<T> &vector, const U &u, qsizetype from) noexce
}
template <typename T>
-qsizetype QListSpecialMethods<T>::indexOf(const T &t, qsizetype from) const noexcept
+template <typename AT>
+qsizetype QListSpecialMethodsBase<T>::indexOf(const AT &t, qsizetype from) const noexcept
{
- return QtPrivate::indexOf(*static_cast<const QList<T> *>(this), t, from);
+ return QtPrivate::indexOf(*self(), t, from);
}
template <typename T>
-qsizetype QListSpecialMethods<T>::lastIndexOf(const T &t, qsizetype from) const noexcept
+template <typename AT>
+qsizetype QListSpecialMethodsBase<T>::lastIndexOf(const AT &t, qsizetype from) const noexcept
{
- return QtPrivate::lastIndexOf(*static_cast<const QList<T> *>(this), t, from);
+ return QtPrivate::lastIndexOf(*self(), t, from);
}
template <typename T>
@@ -799,58 +932,6 @@ size_t qHash(const QList<T> &key, size_t seed = 0)
return qHashRange(key.cbegin(), key.cend(), seed);
}
-template <typename U>
-QTypeTraits::compare_eq_result<U> operator==(const QList<U> &l, const QList<U> &r)
-{
- if (l.size() != r.size())
- return false;
- if (l.begin() == r.begin())
- return true;
-
- // do element-by-element comparison
- return l.d->compare(l.begin(), r.begin(), l.size());
-}
-
-template <typename U>
-QTypeTraits::compare_eq_result<U> operator!=(const QList<U> &l, const QList<U> &r)
-{
- return !(l == r);
-}
-
-template <typename T>
-auto operator<(const QList<T> &lhs, const QList<T> &rhs)
- noexcept(noexcept(std::lexicographical_compare(lhs.begin(), lhs.end(),
- rhs.begin(), rhs.end())))
- -> decltype(std::declval<T>() < std::declval<T>())
-{
- return std::lexicographical_compare(lhs.begin(), lhs.end(),
- rhs.begin(), rhs.end());
-}
-
-template <typename T>
-auto operator>(const QList<T> &lhs, const QList<T> &rhs)
- noexcept(noexcept(lhs < rhs))
- -> decltype(lhs < rhs)
-{
- return rhs < lhs;
-}
-
-template <typename T>
-auto operator<=(const QList<T> &lhs, const QList<T> &rhs)
- noexcept(noexcept(lhs < rhs))
- -> decltype(lhs < rhs)
-{
- return !(lhs > rhs);
-}
-
-template <typename T>
-auto operator>=(const QList<T> &lhs, const QList<T> &rhs)
- noexcept(noexcept(lhs < rhs))
- -> decltype(lhs < rhs)
-{
- return !(lhs < rhs);
-}
-
QList<uint> QStringView::toUcs4() const { return QtPrivate::convertToUcs4(*this); }
QT_END_NAMESPACE
diff --git a/src/corelib/tools/qlist.qdoc b/src/corelib/tools/qlist.qdoc
index c25a7fe4cb..33046f8a2f 100644
--- a/src/corelib/tools/qlist.qdoc
+++ b/src/corelib/tools/qlist.qdoc
@@ -153,20 +153,24 @@
support \c operator==(). These requirements are documented on a
per-function basis.
- Like the other container classes, QList provides \l{Java-style
- iterators} (QListIterator and QMutableListIterator) and
- \l{STL-style iterators} (QList::const_iterator and
- QList::iterator). In practice, these are rarely used, because
- you can use indexes into the QList.
+ Like the other container classes, QList provides \l{Java-style iterators}
+ (QListIterator and QMutableListIterator) and \l{STL-style iterators}
+ (QList::const_iterator and QList::iterator). In practice, iterators are
+ handy when working with generic algorithms provided by \l{generic
+ algorithms}{Qt} and the C++ standard library. \l{Java-style iterators} are
+ provided for backwards compatibility, prefer \l{STL-style iterators} when
+ writing C++ code.
+
+ \note Iterators and references to individual QList elements are subject to
+ stability issues. They are often invalidated when QList-modifying operation
+ (e.g. insert() or remove()) is called. When stability and iterator-like
+ functionality is required, you should use indexes instead of iterators as
+ they are not tied to QList internal state and thus do not get invalidated.
In addition to QList, Qt also provides QVarLengthArray, a very
low-level class with little functionality that is optimized for
speed.
- QList does \e not support inserting, prepending, appending or replacing
- with references to its own values. Doing so will cause your application to
- abort with an error message.
-
\section2 More Information on Using Qt Containers
For a detailed discussion comparing Qt containers with each other and
@@ -279,7 +283,7 @@
\sa resize()
*/
-/*! \fn template <typename T> QList<T>::QList(qsizetype size, const T &value)
+/*! \fn template <typename T> QList<T>::QList(qsizetype size, parameter_type value)
Constructs a list with an initial size of \a size elements.
Each element is initialized with \a value.
@@ -304,9 +308,6 @@
\since 4.8
Constructs a list from the std::initializer_list given by \a args.
-
- This constructor is only enabled if the compiler supports C++11 initializer
- lists.
*/
/*! \fn template <typename T> template<typename InputIterator> QList<T>::QList(InputIterator first, InputIterator last)
@@ -338,13 +339,9 @@
/*!
\fn template <typename T> QList<T> &QList<T>::operator=(std::initializer_list<T> args)
+ \since 5.14
Assigns the collection of values in \a args to this QList instance.
-
- This operator is only enabled if the compiler supports C++11 initializer
- lists.
-
- \since 5.14
*/
/*! \fn template <typename T> void QList<T>::swap(QList<T> &other)
@@ -391,49 +388,45 @@
\sa operator==()
*/
-/*! \fn template <typename T> bool operator<(const QList<T> &lhs, const QList<T> &rhs)
+/*! \fn template <typename T> bool QList<T>::operator<(const QList<T> &other) const
\since 5.6
- \relates QList
- Returns \c true if list \a lhs is
+ Returns \c true if this list is
\l{http://en.cppreference.com/w/cpp/algorithm/lexicographical_compare}
- {lexicographically less than} \a rhs; otherwise returns \c false.
+ {lexicographically less than} \a other; otherwise returns \c false.
This function requires the value type to have an implementation
of \c operator<().
*/
-/*! \fn template <typename T> bool operator<=(const QList<T> &lhs, const QList<T> &rhs)
+/*! \fn template <typename T> bool QList<T>::operator<=(const QList<T> &other) const
\since 5.6
- \relates QList
- Returns \c true if list \a lhs is
+ Returns \c true if this list is
\l{http://en.cppreference.com/w/cpp/algorithm/lexicographical_compare}
- {lexicographically less than or equal to} \a rhs; otherwise returns \c false.
+ {lexicographically less than or equal to} \a other; otherwise returns \c false.
This function requires the value type to have an implementation
of \c operator<().
*/
-/*! \fn template <typename T> bool operator>(const QList<T> &lhs, const QList<T> &rhs)
+/*! \fn template <typename T> bool QList<T>::operator>(const QList<T> &other) const
\since 5.6
- \relates QList
- Returns \c true if list \a lhs is
+ Returns \c true if this list is
\l{http://en.cppreference.com/w/cpp/algorithm/lexicographical_compare}
- {lexicographically greater than} \a rhs; otherwise returns \c false.
+ {lexicographically greater than} \a other; otherwise returns \c false.
This function requires the value type to have an implementation
of \c operator<().
*/
-/*! \fn template <typename T> bool operator>=(const QList<T> &lhs, const QList<T> &rhs)
+/*! \fn template <typename T> bool QList<T>::operator>=(const QList<T> &other) const
\since 5.6
- \relates QList
- Returns \c true if list \a lhs is
+ Returns \c true if this list is
\l{http://en.cppreference.com/w/cpp/algorithm/lexicographical_compare}
- {lexicographically greater than or equal to} \a rhs; otherwise returns \c false.
+ {lexicographically greater than or equal to} \a other; otherwise returns \c false.
This function requires the value type to have an implementation
of \c operator<().
@@ -508,16 +501,8 @@
may have used more memory than the normal QList growth strategy
would have allocated—or you may have used less.
- An alternative to reserve() is calling resize(). Whether or not that is
- faster than reserve() depends on the element type, because resize()
- default-constructs all elements, and requires assignment to existing
- entries rather than calling append(), which copy- or move-constructs.
- For simple types, like \c int or \c double, resize() is typically faster,
- but for anything more complex, you should prefer reserve().
-
- \warning If the size passed to resize() was underestimated, you run out
- of allocated space and into undefined behavior. This problem does not
- exist with reserve(), because it treats the size as just a hint.
+ \warning reserve() reserves memory but does not change the size of the list.
+ Accessing data beyond the end of the list is undefined behavior.
\sa squeeze(), capacity()
*/
@@ -637,7 +622,7 @@
*/
/*!
- \fn template <typename T> void QList<T>::append(const T &value)
+ \fn template <typename T> void QList<T>::append(parameter_type value)
Inserts \a value at the end of the list.
@@ -655,7 +640,7 @@
*/
/*!
- \fn template <typename T> void QList<T>::append(T &&value)
+ \fn template <typename T> void QList<T>::append(rvalue_ref value)
\since 5.6
\overload
@@ -686,8 +671,8 @@
*/
/*!
- \fn template <typename T> void QList<T>::prepend(const T &value)
- \fn template <typename T> void QList<T>::prepend(T &&value)
+ \fn template <typename T> void QList<T>::prepend(parameter_type value)
+ \fn template <typename T> void QList<T>::prepend(rvalue_ref value)
Inserts \a value at the beginning of the list.
@@ -727,8 +712,8 @@
\sa emplace
*/
-/*! \fn template <typename T> void QList<T>::insert(qsizetype i, const T &value)
- \fn template <typename T> void QList<T>::insert(qsizetype i, T &&value)
+/*! \fn template <typename T> void QList<T>::insert(qsizetype i, parameter_type value)
+ \fn template <typename T> void QList<T>::insert(qsizetype i, rvalue_ref value)
Inserts \a value at index position \a i in the list. If \a i is
0, the value is prepended to the list. If \a i is size(), the
@@ -746,7 +731,7 @@
\sa append(), prepend(), remove()
*/
-/*! \fn template <typename T> void QList<T>::insert(qsizetype i, qsizetype count, const T &value)
+/*! \fn template <typename T> void QList<T>::insert(qsizetype i, qsizetype count, parameter_type value)
\overload
@@ -757,9 +742,8 @@
\snippet code/src_corelib_tools_qlist.cpp 10
*/
-/*!
- \fn template <typename T> QList<T>::iterator QList<T>::insert(iterator before, const T &value)
- \fn template <typename T> QList<T>::iterator QList<T>::insert(iterator before, T &&value)
+/*! \fn template <typename T> QList<T>::iterator QList<T>::insert(const_iterator before, parameter_type value)
+ \fn template <typename T> QList<T>::iterator QList<T>::insert(const_iterator before, rvalue_ref value)
\overload
@@ -767,7 +751,7 @@
\a before. Returns an iterator pointing at the inserted item.
*/
-/*! \fn template <typename T> QList<T>::iterator QList<T>::insert(iterator before, qsizetype count, const T &value)
+/*! \fn template <typename T> QList<T>::iterator QList<T>::insert(const_iterator before, qsizetype count, parameter_type value)
Inserts \a count copies of \a value in front of the item pointed to
by the iterator \a before. Returns an iterator pointing at the
@@ -794,7 +778,8 @@
*/
-/*! \fn template <typename T> void QList<T>::replace(qsizetype i, const T &value)
+/*! \fn template <typename T> void QList<T>::replace(qsizetype i, parameter_type value)
+ \fn template <typename T> void QList<T>::replace(qsizetype i, rvalue_ref value)
Replaces the item at index position \a i with \a value.
@@ -808,15 +793,15 @@
Removes \a n elements from the list, starting at index position \a i.
- If too many elements are removed from the list, the list may shrink the
- capacity to reduce the allocated memory size. To make sure this does not
- happen, use reserve() to give a hint to the list that the capacity should be
- preserved.
+//! [shrinking-erase]
+ Element removal will preserve the list's capacity and not reduce the amount of
+ allocated memory. To shed extra capacity and free as much memory as possible,
+ call squeeze().
+//! [shrinking-erase]
//! [iterator-invalidation-erase]
- \note When QList is not \l{implicitly shared} and the capacity is reserved
- with a call to reserve(), this function only invalidates iterators at or
- after the specified position.
+ \note When QList is not \l{implicitly shared}, this function only
+ invalidates iterators at or after the specified position.
//! [iterator-invalidation-erase]
\sa insert(), replace(), fill()
@@ -831,31 +816,32 @@
remove(i);
\endcode
+ \include qlist.qdoc shrinking-erase
\include qlist.qdoc iterator-invalidation-erase
- \sa remove(), QList::removeAt()
+ \sa remove()
*/
-/*! \fn template <typename T> qsizetype QList<T>::removeAll(const T &t)
+/*! \fn template <typename T> template <typename AT = T> qsizetype QList<T>::removeAll(const AT &t)
\since 5.4
Removes all elements that compare equal to \a t from the
list. Returns the number of elements removed, if any.
- Provided for compatibility with QList.
+ \include qlist.qdoc shrinking-erase
- \sa removeOne(), QList::removeAll()
+ \sa removeOne()
*/
-/*! \fn template <typename T> bool QList<T>::removeOne(const T &t)
+/*! \fn template <typename T> template <typename AT = T> bool QList<T>::removeOne(const AT &t)
\since 5.4
Removes the first element that compares equal to \a t from the
list. Returns whether an element was, in fact, removed.
- Provided for compatibility with QList.
+ \include qlist.qdoc shrinking-erase
- \sa removeAll(), QList::removeOne()
+ \sa removeAll()
*/
/*! \fn template <typename T> qsizetype QList<T>::length() const
@@ -863,9 +849,7 @@
Same as size() and count().
- Provided for compatibility with QList.
-
- \sa size(), count(), QList::length()
+ \sa size(), count()
*/
/*! \fn template <typename T> T QList<T>::takeAt(qsizetype i)
@@ -880,19 +864,15 @@
return t;
\endcode
- Provided for compatibility with QList.
+ \include qlist.qdoc iterator-invalidation-erase
- \sa takeFirst(), takeLast(), QList::takeAt()
+ \sa takeFirst(), takeLast()
*/
/*! \fn template <typename T> void QList<T>::move(qsizetype from, qsizetype to)
\since 5.6
Moves the item at index position \a from to index position \a to.
-
- Provided for compatibility with QList.
-
- \sa QList::move()
*/
/*! \fn template <typename T> void QList<T>::removeFirst()
@@ -902,6 +882,8 @@
the list can be empty, call isEmpty() before calling this
function.
+ \include qlist.qdoc shrinking-erase
+
\sa remove(), takeFirst(), isEmpty()
*/
@@ -912,6 +894,8 @@
empty. If the list can be empty, call isEmpty() before calling
this function.
+ \include qlist.qdoc shrinking-erase
+
\sa remove(), takeLast(), removeFirst(), isEmpty()
*/
@@ -939,7 +923,7 @@
*/
/*!
- \fn template <typename T> template <typename ...Args> QList<T>::iterator QList<T>::emplace(QList<T>::iterator before, Args&&... args)
+ \fn template <typename T> template <typename ...Args> QList<T>::iterator QList<T>::emplace(const_iterator before, Args&&... args)
\overload
@@ -950,11 +934,10 @@
Returns an iterator to the new element.
*/
-/*! \fn template <typename T> QList<T> &QList<T>::fill(const T &value, qsizetype size = -1)
+/*! \fn template <typename T> QList<T> &QList<T>::fill(parameter_type value, qsizetype size = -1)
Assigns \a value to all items in the list. If \a size is
- different from -1 (the default), the list is resized to size \a
- size beforehand.
+ different from -1 (the default), the list is resized to \a size beforehand.
Example:
\snippet code/src_corelib_tools_qlist.cpp 11
@@ -962,7 +945,7 @@
\sa resize()
*/
-/*! \fn template <typename T> qsizetype QList<T>::indexOf(const T &value, qsizetype from = 0) const
+/*! \fn template <typename T> template <typename AT = T> qsizetype QList<T>::indexOf(const AT &value, qsizetype from = 0) const
Returns the index position of the first occurrence of \a value in
the list, searching forward from index position \a from.
@@ -977,7 +960,7 @@
\sa lastIndexOf(), contains()
*/
-/*! \fn template <typename T> qsizetype QList<T>::lastIndexOf(const T &value, qsizetype from = -1) const
+/*! \fn template <typename T> template <typename AT = T> qsizetype QList<T>::lastIndexOf(const AT &value, qsizetype from = -1) const
Returns the index position of the last occurrence of the value \a
value in the list, searching backward from index position \a
@@ -993,7 +976,7 @@
\sa indexOf()
*/
-/*! \fn template <typename T> bool QList<T>::contains(const T &value) const
+/*! \fn template <typename T> template <typename AT = T> bool QList<T>::contains(const AT &value) const
Returns \c true if the list contains an occurrence of \a value;
otherwise returns \c false.
@@ -1004,7 +987,7 @@
\sa indexOf(), count()
*/
-/*! \fn template <typename T> bool QList<T>::startsWith(const T &value) const
+/*! \fn template <typename T> bool QList<T>::startsWith(parameter_type value) const
\since 4.5
Returns \c true if this list is not empty and its first
@@ -1013,7 +996,7 @@
\sa isEmpty(), first()
*/
-/*! \fn template <typename T> bool QList<T>::endsWith(const T &value) const
+/*! \fn template <typename T> bool QList<T>::endsWith(parameter_type value) const
\since 4.5
Returns \c true if this list is not empty and its last
@@ -1023,7 +1006,7 @@
*/
-/*! \fn template <typename T> qsizetype QList<T>::count(const T &value) const
+/*! \fn template <typename T> template <typename AT = T> qsizetype QList<T>::count(const AT &value) const
Returns the number of occurrences of \a value in the list.
@@ -1061,8 +1044,8 @@
/*! \fn template <typename T> QList<T>::const_iterator QList<T>::cbegin() const
\since 5.0
- Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the first item
- in the list.
+ Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the
+ first item in the list.
\include qlist.qdoc iterator-invalidation-func-desc
@@ -1071,8 +1054,8 @@
/*! \fn template <typename T> QList<T>::const_iterator QList<T>::constBegin() const
- Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the first item
- in the list.
+ Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the
+ first item in the list.
\include qlist.qdoc iterator-invalidation-func-desc
@@ -1081,8 +1064,8 @@
/*! \fn template <typename T> QList<T>::iterator QList<T>::end()
- Returns an \l{STL-style iterators}{STL-style iterator} pointing to the imaginary item
- after the last item in the list.
+ Returns an \l{STL-style iterators}{STL-style iterator} pointing to the
+ imaginary item after the last item in the list.
\include qlist.qdoc iterator-invalidation-func-desc
@@ -1097,8 +1080,8 @@
/*! \fn template <typename T> QList<T>::const_iterator QList<T>::cend() const
\since 5.0
- Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the imaginary
- item after the last item in the list.
+ Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the
+ imaginary item after the last item in the list.
\include qlist.qdoc iterator-invalidation-func-desc
@@ -1107,8 +1090,8 @@
/*! \fn template <typename T> QList<T>::const_iterator QList<T>::constEnd() const
- Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the imaginary
- item after the last item in the list.
+ Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the
+ imaginary item after the last item in the list.
\include qlist.qdoc iterator-invalidation-func-desc
@@ -1118,8 +1101,8 @@
/*! \fn template <typename T> QList<T>::reverse_iterator QList<T>::rbegin()
\since 5.6
- Returns a \l{STL-style iterators}{STL-style} reverse iterator pointing to the first
- item in the list, in reverse order.
+ Returns a \l{STL-style iterators}{STL-style} reverse iterator pointing to
+ the first item in the list, in reverse order.
\include qlist.qdoc iterator-invalidation-func-desc
@@ -1134,8 +1117,8 @@
/*! \fn template <typename T> QList<T>::const_reverse_iterator QList<T>::crbegin() const
\since 5.6
- Returns a const \l{STL-style iterators}{STL-style} reverse iterator pointing to the first
- item in the list, in reverse order.
+ Returns a const \l{STL-style iterators}{STL-style} reverse iterator pointing
+ to the first item in the list, in reverse order.
\include qlist.qdoc iterator-invalidation-func-desc
@@ -1145,8 +1128,8 @@
/*! \fn template <typename T> QList<T>::reverse_iterator QList<T>::rend()
\since 5.6
- Returns a \l{STL-style iterators}{STL-style} reverse iterator pointing to one past
- the last item in the list, in reverse order.
+ Returns a \l{STL-style iterators}{STL-style} reverse iterator pointing to
+ one past the last item in the list, in reverse order.
\include qlist.qdoc iterator-invalidation-func-desc
@@ -1161,8 +1144,8 @@
/*! \fn template <typename T> QList<T>::const_reverse_iterator QList<T>::crend() const
\since 5.6
- Returns a const \l{STL-style iterators}{STL-style} reverse iterator pointing to one
- past the last item in the list, in reverse order.
+ Returns a const \l{STL-style iterators}{STL-style} reverse iterator pointing
+ to one past the last item in the list, in reverse order.
\include qlist.qdoc iterator-invalidation-func-desc
@@ -1175,6 +1158,7 @@
list, and returns an iterator to the next item in the list
(which may be end()).
+ \include qlist.qdoc shrinking-erase
\include qlist.qdoc iterator-invalidation-erase
\sa insert(), remove()
@@ -1188,6 +1172,7 @@
end. Returns an iterator to the same item that \a end referred to
before the call.
+ \include qlist.qdoc shrinking-erase
\include qlist.qdoc iterator-invalidation-erase
*/
@@ -1246,27 +1231,27 @@
\sa at(), operator[]()
*/
-/*! \fn template <typename T> T QList<T>::value(qsizetype i, const T &defaultValue) const
+/*! \fn template <typename T> T QList<T>::value(qsizetype i, parameter_type defaultValue) const
\overload
If the index \a i is out of bounds, the function returns \a defaultValue.
*/
-/*! \fn template <typename T> void QList<T>::push_back(const T &value)
+/*! \fn template <typename T> void QList<T>::push_back(parameter_type value)
This function is provided for STL compatibility. It is equivalent
to append(\a value).
*/
-/*! \fn template <typename T> void QList<T>::push_back(T &&value)
+/*! \fn template <typename T> void QList<T>::push_back(rvalue_ref value)
\since 5.6
\overload
*/
/*!
- \fn template <typename T> void QList<T>::push_front(const T &value)
- \fn template <typename T> void QList<T>::push_front(T &&value)
+ \fn template <typename T> void QList<T>::push_front(parameter_type value)
+ \fn template <typename T> void QList<T>::push_front(rvalue_ref value)
This function is provided for STL compatibility. It is equivalent
to prepend(\a value).
@@ -1336,7 +1321,7 @@
\sa operator+(), append()
*/
-/*! \fn template <typename T> void QList<T>::operator+=(const T &value)
+/*! \fn template <typename T> void QList<T>::operator+=(parameter_type value)
\overload
@@ -1345,7 +1330,7 @@
\sa append(), operator<<()
*/
-/*! \fn template <typename T> void QList<T>::operator+=(T &&value)
+/*! \fn template <typename T> void QList<T>::operator+=(rvalue_ref value)
\since 5.11
\overload
@@ -1369,14 +1354,14 @@
\sa operator+=()
*/
-/*! \fn template <typename T> QList<T> &QList<T>::operator<<(const T &value)
+/*! \fn template <typename T> QList<T> &QList<T>::operator<<(parameter_type value)
Appends \a value to the list and returns a reference to this list.
\sa append(), operator+=()
*/
-/*! \fn template <typename T> QList<T> &QList<T>::operator<<(T &&value)
+/*! \fn template <typename T> QList<T> &QList<T>::operator<<(rvalue_ref value)
\since 5.11
\overload
@@ -1402,8 +1387,7 @@
iterator for QList and QStack.
QList provides both \l{STL-style iterators} and \l{Java-style
- iterators}. The STL-style non-const iterator is simply a typedef
- for "T *" (pointer to T).
+ iterators}.
//! [iterator-invalidation-class-desc]
\warning Iterators on implicitly shared containers do not work
@@ -1425,8 +1409,7 @@
iterator for QList and QStack.
QList provides both \l{STL-style iterators} and \l{Java-style
- iterators}. The STL-style const iterator is simply a typedef for
- "const T *" (pointer to const T).
+ iterators}.
\include qlist.qdoc iterator-invalidation-class-desc
@@ -1439,8 +1422,6 @@
The QList::reverse_iterator typedef provides an STL-style non-const
reverse iterator for QList.
- It is simply a typedef for \c{std::reverse_iterator<T*>}.
-
\include qlist.qdoc iterator-invalidation-class-desc
\sa QList::rbegin(), QList::rend(), QList::const_reverse_iterator, QList::iterator
@@ -1452,8 +1433,6 @@
The QList::const_reverse_iterator typedef provides an STL-style const
reverse iterator for QList.
- It is simply a typedef for \c{std::reverse_iterator<const T*>}.
-
\include qlist.qdoc iterator-invalidation-class-desc
\sa QList::rbegin(), QList::rend(), QList::reverse_iterator, QList::const_iterator
@@ -1471,37 +1450,45 @@
/*! \typedef QList::const_pointer
- Typedef for const T *. Provided for STL compatibility.
+ Provided for STL compatibility.
*/
/*! \typedef QList::const_reference
- Typedef for T &. Provided for STL compatibility.
+ Provided for STL compatibility.
*/
/*! \typedef QList::difference_type
- Typedef for ptrdiff_t. Provided for STL compatibility.
+ Provided for STL compatibility.
*/
/*! \typedef QList::pointer
- Typedef for T *. Provided for STL compatibility.
+ Provided for STL compatibility.
*/
/*! \typedef QList::reference
- Typedef for T &. Provided for STL compatibility.
+ Provided for STL compatibility.
*/
/*! \typedef QList::size_type
- Typedef for int. Provided for STL compatibility.
+ Provided for STL compatibility.
*/
/*! \typedef QList::value_type
- Typedef for T. Provided for STL compatibility.
+ Provided for STL compatibility.
+*/
+
+/*! \typedef QList::parameter_type
+
+*/
+
+/*! \typedef QList::rvalue_ref
+
*/
/*! \fn template <typename T> QList<T> QList<T>::toList() const
@@ -1524,32 +1511,6 @@
Returns this list.
*/
-/*! \fn template <typename T> QList<T> QList<T>::fromStdVector(const std::vector<T> &vector)
-
- Returns a QList object with the data contained in \a vector. The
- order of the elements in the QList is the same as in \a vector.
-
- Example:
-
- \snippet code/src_corelib_tools_qlist.cpp 16
-
- \include containers-range-constructor.qdocinc
-
- \sa toStdVector(), QList::fromStdList()
-*/
-
-/*! \fn template <typename T> std::vector<T> QList<T>::toStdVector() const
-
- Returns a std::vector object with the data contained in this QList.
- Example:
-
- \snippet code/src_corelib_tools_qlist.cpp 17
-
- \include containers-range-constructor.qdocinc
-
- \sa fromStdVector(), QList::toStdList()
-*/
-
/*! \fn template <typename T> QDataStream &operator<<(QDataStream &out, const QList<T> &list)
\relates QList
diff --git a/src/corelib/tools/qmakearray_p.h b/src/corelib/tools/qmakearray_p.h
index 71441c2c27..4ed8c16234 100644
--- a/src/corelib/tools/qmakearray_p.h
+++ b/src/corelib/tools/qmakearray_p.h
@@ -61,17 +61,17 @@ QT_BEGIN_NAMESPACE
namespace QtPrivate {
template<typename T>
-constexpr T&& Forward(typename std::remove_reference<T>::type& t) noexcept
+constexpr T &&Forward(typename std::remove_reference<T>::type &t) noexcept
{
- return static_cast<T&&>(t);
+ return static_cast<T &&>(t);
}
template<typename T>
-constexpr T&& Forward(typename std::remove_reference<T>::type&& t) noexcept
+constexpr T &&Forward(typename std::remove_reference<T>::type &&t) noexcept
{
static_assert(!std::is_lvalue_reference<T>::value,
"template argument substituting T is an lvalue reference type");
- return static_cast<T&&>(t);
+ return static_cast<T &&>(t);
}
template <typename ManualType, typename ...>
diff --git a/src/corelib/tools/qmap.h b/src/corelib/tools/qmap.h
index d09fa361a0..e63eb85bca 100644
--- a/src/corelib/tools/qmap.h
+++ b/src/corelib/tools/qmap.h
@@ -68,6 +68,9 @@ public:
using iterator = typename Map::iterator;
using const_iterator = typename Map::const_iterator;
+ static_assert(std::is_nothrow_destructible_v<Key>, "Types with throwing destructors are not supported in Qt containers.");
+ static_assert(std::is_nothrow_destructible_v<T>, "Types with throwing destructors are not supported in Qt containers.");
+
Map m;
QMapData() = default;
@@ -217,7 +220,8 @@ public:
template <class Key, class T>
class QMap
{
- using MapData = QMapData<std::map<Key, T>>;
+ using Map = std::map<Key, T>;
+ using MapData = QMapData<Map>;
QtPrivate::QExplicitlySharedDataPointerV2<MapData> d;
friend class QMultiMap<Key, T>;
@@ -272,12 +276,22 @@ public:
return {};
}
- // CHANGE: non-member equality comparison
- template <typename AKey, typename AT>
- friend QTypeTraits::compare_eq_result<AKey, AT> operator==(const QMap<AKey, AT> &lhs, const QMap<AKey, AT> &rhs);
- template <typename AKey, typename AT>
- friend QTypeTraits::compare_eq_result<AKey, AT> operator!=(const QMap<AKey, AT> &lhs, const QMap<AKey, AT> &rhs);
+ template <typename AKey = Key, typename AT = T> friend
+ QTypeTraits::compare_eq_result<AKey, AT> operator==(const QMap &lhs, const QMap &rhs)
+ {
+ if (lhs.d == rhs.d)
+ return true;
+ if (!lhs.d)
+ return rhs == lhs;
+ Q_ASSERT(lhs.d);
+ return rhs.d ? (lhs.d->m == rhs.d->m) : lhs.d->m.empty();
+ }
+ template <typename AKey = Key, typename AT = T> friend
+ QTypeTraits::compare_eq_result<AKey, AT> operator!=(const QMap &lhs, const QMap &rhs)
+ {
+ return !(lhs == rhs);
+ }
// TODO: add the other comparison operators; std::map has them.
size_type size() const { return d ? size_type(d->m.size()) : size_type(0); }
@@ -436,8 +450,8 @@ public:
friend class QMap<Key, T>;
friend class const_iterator;
- typename MapData::Map::iterator i;
- explicit iterator(typename MapData::Map::iterator it) : i(it) {}
+ typename Map::iterator i;
+ explicit iterator(typename Map::iterator it) : i(it) {}
public:
typedef std::bidirectional_iterator_tag iterator_category;
typedef qptrdiff difference_type;
@@ -481,8 +495,8 @@ public:
class const_iterator
{
friend class QMap<Key, T>;
- typename MapData::Map::const_iterator i;
- explicit const_iterator(typename MapData::Map::const_iterator it) : i(it) {}
+ typename Map::const_iterator i;
+ explicit const_iterator(typename Map::const_iterator it) : i(it) {}
public:
typedef std::bidirectional_iterator_tag iterator_category;
@@ -492,7 +506,7 @@ public:
typedef const T &reference;
const_iterator() = default;
- /* implicit */ const_iterator(const iterator &o) { i = o.i; }
+ Q_IMPLICIT const_iterator(const iterator &o) { i = o.i; }
const Key &key() const { return i->first; }
const T &value() const { return i->second; }
@@ -728,24 +742,6 @@ public:
Q_DECLARE_ASSOCIATIVE_ITERATOR(Map)
Q_DECLARE_MUTABLE_ASSOCIATIVE_ITERATOR(Map)
-template <typename AKey, typename AT>
-QTypeTraits::compare_eq_result<AKey, AT> operator==(const QMap<AKey, AT> &lhs, const QMap<AKey, AT> &rhs)
-{
- if (lhs.d == rhs.d)
- return true;
- if (!lhs.d)
- return rhs == lhs;
- Q_ASSERT(lhs.d);
- return rhs.d ? (lhs.d->m == rhs.d->m) : lhs.d->m.empty();
-}
-
-template <typename AKey, typename AT>
-QTypeTraits::compare_eq_result<AKey, AT> operator!=(const QMap<AKey, AT> &lhs, const QMap<AKey, AT> &rhs)
-{
- return !(lhs == rhs);
-}
-
-
//
// QMultiMap
//
@@ -753,7 +749,8 @@ QTypeTraits::compare_eq_result<AKey, AT> operator!=(const QMap<AKey, AT> &lhs, c
template <class Key, class T>
class QMultiMap
{
- using MapData = QMapData<std::multimap<Key, T>>;
+ using Map = std::multimap<Key, T>;
+ using MapData = QMapData<Map>;
QtPrivate::QExplicitlySharedDataPointerV2<MapData> d;
public:
@@ -842,12 +839,22 @@ public:
return {};
}
- // CHANGE: non-member equality comparison
- template <typename AKey, typename AT>
- friend QTypeTraits::compare_eq_result<AKey, AT> operator==(const QMultiMap<AKey, AT> &lhs, const QMultiMap<AKey, AT> &rhs);
- template <typename AKey, typename AT>
- friend QTypeTraits::compare_eq_result<AKey, AT> operator!=(const QMultiMap<AKey, AT> &lhs, const QMultiMap<AKey, AT> &rhs);
+ template <typename AKey = Key, typename AT = T> friend
+ QTypeTraits::compare_eq_result<AKey, AT> operator==(const QMultiMap &lhs, const QMultiMap &rhs)
+ {
+ if (lhs.d == rhs.d)
+ return true;
+ if (!lhs.d)
+ return rhs == lhs;
+ Q_ASSERT(lhs.d);
+ return rhs.d ? (lhs.d->m == rhs.d->m) : lhs.d->m.empty();
+ }
+ template <typename AKey = Key, typename AT = T> friend
+ QTypeTraits::compare_eq_result<AKey, AT> operator!=(const QMultiMap &lhs, const QMultiMap &rhs)
+ {
+ return !(lhs == rhs);
+ }
// TODO: add the other comparison operators; std::multimap has them.
size_type size() const { return d ? size_type(d->m.size()) : size_type(0); }
@@ -1060,8 +1067,8 @@ public:
friend class QMultiMap<Key, T>;
friend class const_iterator;
- typename MapData::Map::iterator i;
- explicit iterator(typename MapData::Map::iterator it) : i(it) {}
+ typename Map::iterator i;
+ explicit iterator(typename Map::iterator it) : i(it) {}
public:
typedef std::bidirectional_iterator_tag iterator_category;
typedef qptrdiff difference_type;
@@ -1105,8 +1112,8 @@ public:
class const_iterator
{
friend class QMultiMap<Key, T>;
- typename MapData::Map::const_iterator i;
- explicit const_iterator(typename MapData::Map::const_iterator it) : i(it) {}
+ typename Map::const_iterator i;
+ explicit const_iterator(typename Map::const_iterator it) : i(it) {}
public:
typedef std::bidirectional_iterator_tag iterator_category;
@@ -1116,7 +1123,7 @@ public:
typedef const T &reference;
const_iterator() = default;
- /* implicit */ const_iterator(const iterator &o) { i = o.i; }
+ Q_IMPLICIT const_iterator(const iterator &o) { i = o.i; }
const Key &key() const { return i->first; }
const T &value() const { return i->second; }
@@ -1316,55 +1323,30 @@ public:
return iterator(d->m.insert(detachedPos, {key, value}));
}
- // CHANGE: provide insertMulti for compatibility
+#if QT_DEPRECATED_SINCE(6, 0)
+ QT_DEPRECATED_VERSION_X_6_0("Use insert() instead")
iterator insertMulti(const Key &key, const T &value)
{
return insert(key, value);
}
-
+ QT_DEPRECATED_VERSION_X_6_0("Use insert() instead")
iterator insertMulti(const_iterator pos, const Key &key, const T &value)
{
return insert(pos, key, value);
}
+ QT_DEPRECATED_VERSION_X_6_0("Use unite() instead")
void insert(const QMultiMap<Key, T> &map)
{
- if (map.isEmpty())
- return;
-
- detach();
-
- auto copy = map.d->m;
-#ifdef __cpp_lib_node_extract
- copy.merge(std::move(d->m));
-#else
- copy.insert(std::make_move_iterator(d->m.begin()),
- std::make_move_iterator(d->m.end()));
-#endif
- d->m = std::move(copy);
+ unite(map);
}
+ QT_DEPRECATED_VERSION_X_6_0("Use unite() instead")
void insert(QMultiMap<Key, T> &&map)
{
- if (!map.d || map.d->m.empty())
- return;
-
- if (map.d.isShared()) {
- // fall back to a regular copy
- insert(map);
- return;
- }
-
- detach();
-
-#ifdef __cpp_lib_node_extract
- map.d->m.merge(std::move(d->m));
-#else
- map.d->m.insert(std::make_move_iterator(d->m.begin()),
- std::make_move_iterator(d->m.end()));
-#endif
- *this = std::move(map);
+ unite(std::move(map));
}
+#endif
iterator replace(const Key &key, const T &value)
{
@@ -1402,7 +1384,42 @@ public:
QMultiMap &unite(const QMultiMap &other)
{
- insert(other);
+ if (other.isEmpty())
+ return *this;
+
+ detach();
+
+ auto copy = other.d->m;
+#ifdef __cpp_lib_node_extract
+ copy.merge(std::move(d->m));
+#else
+ copy.insert(std::make_move_iterator(d->m.begin()),
+ std::make_move_iterator(d->m.end()));
+#endif
+ d->m = std::move(copy);
+ return *this;
+ }
+
+ QMultiMap &unite(QMultiMap<Key, T> &&other)
+ {
+ if (!other.d || other.d->m.empty())
+ return *this;
+
+ if (other.d.isShared()) {
+ // fall back to a regular copy
+ unite(other);
+ return *this;
+ }
+
+ detach();
+
+#ifdef __cpp_lib_node_extract
+ other.d->m.merge(std::move(d->m));
+#else
+ other.d->m.insert(std::make_move_iterator(d->m.begin()),
+ std::make_move_iterator(d->m.end()));
+#endif
+ *this = std::move(other);
return *this;
}
};
@@ -1410,23 +1427,6 @@ public:
Q_DECLARE_ASSOCIATIVE_ITERATOR(MultiMap)
Q_DECLARE_MUTABLE_ASSOCIATIVE_ITERATOR(MultiMap)
-template <typename AKey, typename AT>
-QTypeTraits::compare_eq_result<AKey, AT> operator==(const QMultiMap<AKey, AT> &lhs, const QMultiMap<AKey, AT> &rhs)
-{
- if (lhs.d == rhs.d)
- return true;
- if (!lhs.d)
- return rhs == lhs;
- Q_ASSERT(lhs.d);
- return rhs.d ? (lhs.d->m == rhs.d->m) : lhs.d->m.empty();
-}
-
-template <typename AKey, typename AT>
-QTypeTraits::compare_eq_result<AKey, AT> operator!=(const QMultiMap<AKey, AT> &lhs, const QMultiMap<AKey, AT> &rhs)
-{
- return !(lhs == rhs);
-}
-
template <typename Key, typename T>
QMultiMap<Key, T> operator+(const QMultiMap<Key, T> &lhs, const QMultiMap<Key, T> &rhs)
{
diff --git a/src/corelib/tools/qmap.qdoc b/src/corelib/tools/qmap.qdoc
index 1857a05a13..ace09e7391 100644
--- a/src/corelib/tools/qmap.qdoc
+++ b/src/corelib/tools/qmap.qdoc
@@ -249,8 +249,7 @@
Returns an STL map equivalent to this QMap.
*/
-/*! \fn template <class Key, class T> bool operator==(const QMap<Key, T> &lhs, const QMap<Key, T> &rhs) const
- \relates QMap
+/*! \fn template <class Key, class T> bool QMap<Key, T>::operator==(const QMap<Key, T> &lhs, const QMap<Key, T> &rhs)
Returns \c true if \a lhs is equal to \a rhs; otherwise returns
false.
@@ -264,8 +263,7 @@
\sa operator!=()
*/
-/*! \fn template <class Key, class T> bool operator!=(const QMap<Key, T> &lhs, const QMap<Key, T> &rhs) const
- \relates QMap
+/*! \fn template <class Key, class T> bool QMap<Key, T>::operator!=(const QMap<Key, T> &lhs, const QMap<Key, T> &rhs)
Returns \c true if \a lhs is not equal to \a rhs; otherwise returns
false.
@@ -781,6 +779,17 @@
\sa QMultiMap::insert()
*/
+/*! \fn template <class Key, class T> void QMap<Key, T>::insert(QMap<Key, T> &&map)
+ \since 5.15
+
+ Moves all the items from \a map into this map.
+
+ If a key is common to both maps, its value will be replaced with
+ the value stored in \a map.
+
+ If \a map is shared, then the items will be copied instead.
+*/
+
/*! \typedef QMap::Iterator
Qt-style synonym for QMap<Key, T>::iterator.
@@ -943,7 +952,7 @@
There is no direct way of changing an item's key through an
iterator, although it can be done by calling QMap::erase()
- followed by QMap::insert() or QMap::insertMulti().
+ followed by QMap::insert().
\sa value()
*/
@@ -977,21 +986,21 @@
*/
/*!
- \fn template <class Key, class T> bool QMap<Key, T>::iterator::operator==(const iterator &other) const
- \fn template <class Key, class T> bool QMap<Key, T>::iterator::operator==(const const_iterator &other) const
+ \fn template <class Key, class T> bool QMap<Key, T>::iterator::operator==(const iterator &lhs, const iterator &rhs)
+ \fn template <class Key, class T> bool QMap<Key, T>::const_iterator::operator==(const const_iterator &lhs, const const_iterator &rhs)
- Returns \c true if \a other points to the same item as this
- iterator; otherwise returns \c false.
+ Returns \c true if \a lhs points to the same item as the \a rhs iterator;
+ otherwise returns \c false.
\sa operator!=()
*/
/*!
- \fn template <class Key, class T> bool QMap<Key, T>::iterator::operator!=(const iterator &other) const
- \fn template <class Key, class T> bool QMap<Key, T>::iterator::operator!=(const const_iterator &other) const
+ \fn template <class Key, class T> bool QMap<Key, T>::iterator::operator!=(const iterator &lhs, const iterator &rhs)
+ \fn template <class Key, class T> bool QMap<Key, T>::const_iterator::operator!=(const const_iterator &lhs, const const_iterator &rhs)
- Returns \c true if \a other points to a different item than this
- iterator; otherwise returns \c false.
+ Returns \c true if \a lhs points to a different item than the \a rhs iterator;
+ otherwise returns \c false.
\sa operator==()
*/
@@ -1150,22 +1159,6 @@
\sa value()
*/
-/*! \fn template <class Key, class T> bool QMap<Key, T>::const_iterator::operator==(const const_iterator &other) const
-
- Returns \c true if \a other points to the same item as this
- iterator; otherwise returns \c false.
-
- \sa operator!=()
-*/
-
-/*! \fn template <class Key, class T> bool QMap<Key, T>::const_iterator::operator!=(const const_iterator &other) const
-
- Returns \c true if \a other points to a different item than this
- iterator; otherwise returns \c false.
-
- \sa operator==()
-*/
-
/*! \fn template <class Key, class T> QMap<Key, T>::const_iterator &QMap<Key, T>::const_iterator::operator++()
The prefix ++ operator (\c{++i}) advances the iterator to the
diff --git a/src/corelib/tools/qmargins.cpp b/src/corelib/tools/qmargins.cpp
index a238032f65..5b3c04d11e 100644
--- a/src/corelib/tools/qmargins.cpp
+++ b/src/corelib/tools/qmargins.cpp
@@ -143,15 +143,13 @@ QT_BEGIN_NAMESPACE
*/
/*!
- \fn bool operator==(const QMargins &m1, const QMargins &m2)
- \relates QMargins
+ \fn bool QMargins::operator==(const QMargins &m1, const QMargins &m2)
Returns \c true if \a m1 and \a m2 are equal; otherwise returns \c false.
*/
/*!
- \fn bool operator!=(const QMargins &m1, const QMargins &m2)
- \relates QMargins
+ \fn bool QMargins::operator!=(const QMargins &m1, const QMargins &m2)
Returns \c true if \a m1 and \a m2 are different; otherwise returns \c false.
*/
@@ -472,7 +470,7 @@ QDebug operator<<(QDebug dbg, const QMargins &m)
QMarginsF defines a set of four margins; left, top, right and bottom,
that describe the size of the borders surrounding a rectangle.
- The isNull() function returns \c true only if all margins are set to zero.
+ The isNull() function returns \c true only if all margins are very close to zero.
QMarginsF objects can be streamed as well as compared.
*/
@@ -507,8 +505,10 @@ QDebug operator<<(QDebug dbg, const QMargins &m)
/*!
\fn bool QMarginsF::isNull() const
- Returns \c true if all margins are 0; otherwise returns
+ Returns \c true if all margins are very close to 0; otherwise returns
false.
+
+ \sa qFuzzyIsNull
*/
@@ -566,17 +566,27 @@ QDebug operator<<(QDebug dbg, const QMargins &m)
*/
/*!
- \fn bool operator==(const QMarginsF &lhs, const QMarginsF &rhs)
- \relates QMarginsF
+ \fn bool QMarginsF::operator==(const QMarginsF &lhs, const QMarginsF &rhs)
- Returns \c true if \a lhs and \a rhs are equal; otherwise returns \c false.
+ Returns \c true if \a lhs and \a rhs are approximately equal; otherwise
+ returns false.
+
+ \warning This function does not check for strict equality; instead,
+ it uses a fuzzy comparison to compare the margins.
+
+ \sa qFuzzyCompare
*/
/*!
- \fn bool operator!=(const QMarginsF &lhs, const QMarginsF &rhs)
- \relates QMarginsF
+ \fn bool QMarginsF::operator!=(const QMarginsF &lhs, const QMarginsF &rhs)
+
+ Returns \c true if \a lhs and \a rhs are sufficiently different; otherwise
+ returns \c false.
+
+ \warning This function does not check for strict inequality; instead,
+ it uses a fuzzy comparison to compare the margins.
- Returns \c true if \a lhs and \a rhs are different; otherwise returns \c false.
+ \sa qFuzzyCompare
*/
/*!
diff --git a/src/corelib/tools/qmargins.h b/src/corelib/tools/qmargins.h
index de7a96e458..b0f61eeb66 100644
--- a/src/corelib/tools/qmargins.h
+++ b/src/corelib/tools/qmargins.h
@@ -81,8 +81,35 @@ private:
int m_right;
int m_bottom;
- friend constexpr inline bool operator==(const QMargins &, const QMargins &) noexcept;
- friend constexpr inline bool operator!=(const QMargins &, const QMargins &) noexcept;
+ friend constexpr inline bool operator==(const QMargins &m1, const QMargins &m2) noexcept
+ {
+ return
+ m1.m_left == m2.m_left &&
+ m1.m_top == m2.m_top &&
+ m1.m_right == m2.m_right &&
+ m1.m_bottom == m2.m_bottom;
+ }
+
+ friend constexpr inline bool operator!=(const QMargins &m1, const QMargins &m2) noexcept
+ {
+ return !(m1 == m2);
+ }
+
+ template <std::size_t I,
+ typename M,
+ std::enable_if_t<(I < 4), bool> = true,
+ std::enable_if_t<std::is_same_v<std::decay_t<M>, QMargins>, bool> = true>
+ friend constexpr decltype(auto) get(M &&m) noexcept
+ {
+ if constexpr (I == 0)
+ return (std::forward<M>(m).m_left);
+ else if constexpr (I == 1)
+ return (std::forward<M>(m).m_top);
+ else if constexpr (I == 2)
+ return (std::forward<M>(m).m_right);
+ else if constexpr (I == 3)
+ return (std::forward<M>(m).m_bottom);
+ }
};
Q_DECLARE_TYPEINFO(QMargins, Q_MOVABLE_TYPE);
@@ -132,24 +159,6 @@ constexpr inline void QMargins::setRight(int aright) noexcept
constexpr inline void QMargins::setBottom(int abottom) noexcept
{ m_bottom = abottom; }
-constexpr inline bool operator==(const QMargins &m1, const QMargins &m2) noexcept
-{
- return
- m1.m_left == m2.m_left &&
- m1.m_top == m2.m_top &&
- m1.m_right == m2.m_right &&
- m1.m_bottom == m2.m_bottom;
-}
-
-constexpr inline bool operator!=(const QMargins &m1, const QMargins &m2) noexcept
-{
- return
- m1.m_left != m2.m_left ||
- m1.m_top != m2.m_top ||
- m1.m_right != m2.m_right ||
- m1.m_bottom != m2.m_bottom;
-}
-
constexpr inline QMargins operator+(const QMargins &m1, const QMargins &m2) noexcept
{
return QMargins(m1.left() + m2.left(), m1.top() + m2.top(),
@@ -321,6 +330,35 @@ private:
qreal m_top;
qreal m_right;
qreal m_bottom;
+
+ friend constexpr inline bool operator==(const QMarginsF &lhs, const QMarginsF &rhs) noexcept
+ {
+ return qFuzzyCompare(lhs.left(), rhs.left())
+ && qFuzzyCompare(lhs.top(), rhs.top())
+ && qFuzzyCompare(lhs.right(), rhs.right())
+ && qFuzzyCompare(lhs.bottom(), rhs.bottom());
+ }
+
+ friend constexpr inline bool operator!=(const QMarginsF &lhs, const QMarginsF &rhs) noexcept
+ {
+ return !(lhs == rhs);
+ }
+
+ template <std::size_t I,
+ typename M,
+ std::enable_if_t<(I < 4), bool> = true,
+ std::enable_if_t<std::is_same_v<std::decay_t<M>, QMarginsF>, bool> = true>
+ friend constexpr decltype(auto) get(M &&m) noexcept
+ {
+ if constexpr (I == 0)
+ return (std::forward<M>(m).m_left);
+ else if constexpr (I == 1)
+ return (std::forward<M>(m).m_top);
+ else if constexpr (I == 2)
+ return (std::forward<M>(m).m_right);
+ else if constexpr (I == 3)
+ return (std::forward<M>(m).m_bottom);
+ }
};
Q_DECLARE_TYPEINFO(QMarginsF, Q_MOVABLE_TYPE);
@@ -375,19 +413,6 @@ constexpr inline void QMarginsF::setRight(qreal aright) noexcept
constexpr inline void QMarginsF::setBottom(qreal abottom) noexcept
{ m_bottom = abottom; }
-constexpr inline bool operator==(const QMarginsF &lhs, const QMarginsF &rhs) noexcept
-{
- return qFuzzyCompare(lhs.left(), rhs.left())
- && qFuzzyCompare(lhs.top(), rhs.top())
- && qFuzzyCompare(lhs.right(), rhs.right())
- && qFuzzyCompare(lhs.bottom(), rhs.bottom());
-}
-
-constexpr inline bool operator!=(const QMarginsF &lhs, const QMarginsF &rhs) noexcept
-{
- return !operator==(lhs, rhs);
-}
-
constexpr inline QMarginsF operator+(const QMarginsF &lhs, const QMarginsF &rhs) noexcept
{
return QMarginsF(lhs.left() + rhs.left(), lhs.top() + rhs.top(),
@@ -501,4 +526,32 @@ Q_CORE_EXPORT QDebug operator<<(QDebug, const QMarginsF &);
QT_END_NAMESPACE
+/*****************************************************************************
+ QMargins/QMarginsF tuple protocol
+ *****************************************************************************/
+
+namespace std {
+ template <>
+ class tuple_size<QT_PREPEND_NAMESPACE(QMargins)> : public integral_constant<size_t, 4> {};
+ template <>
+ class tuple_element<0, QT_PREPEND_NAMESPACE(QMargins)> { public: using type = int; };
+ template <>
+ class tuple_element<1, QT_PREPEND_NAMESPACE(QMargins)> { public: using type = int; };
+ template <>
+ class tuple_element<2, QT_PREPEND_NAMESPACE(QMargins)> { public: using type = int; };
+ template <>
+ class tuple_element<3, QT_PREPEND_NAMESPACE(QMargins)> { public: using type = int; };
+
+ template <>
+ class tuple_size<QT_PREPEND_NAMESPACE(QMarginsF)> : public integral_constant<size_t, 4> {};
+ template <>
+ class tuple_element<0, QT_PREPEND_NAMESPACE(QMarginsF)> { public: using type = QT_PREPEND_NAMESPACE(qreal); };
+ template <>
+ class tuple_element<1, QT_PREPEND_NAMESPACE(QMarginsF)> { public: using type = QT_PREPEND_NAMESPACE(qreal); };
+ template <>
+ class tuple_element<2, QT_PREPEND_NAMESPACE(QMarginsF)> { public: using type = QT_PREPEND_NAMESPACE(qreal); };
+ template <>
+ class tuple_element<3, QT_PREPEND_NAMESPACE(QMarginsF)> { public: using type = QT_PREPEND_NAMESPACE(qreal); };
+}
+
#endif // QMARGINS_H
diff --git a/src/corelib/tools/qmessageauthenticationcode.cpp b/src/corelib/tools/qmessageauthenticationcode.cpp
index ada502ecb8..5f86afc537 100644
--- a/src/corelib/tools/qmessageauthenticationcode.cpp
+++ b/src/corelib/tools/qmessageauthenticationcode.cpp
@@ -42,39 +42,7 @@
#include "qtcore-config_p.h"
-/*
- These #defines replace the typedefs needed by the RFC6234 code. Normally
- the typedefs would come from from stdint.h, but since this header is not
- available on all platforms (MSVC 2008, for example), we #define them to the
- Qt equivalents.
-*/
-
-#ifdef uint64_t
-#undef uint64_t
-#endif
-
-#define uint64_t QT_PREPEND_NAMESPACE(quint64)
-
-#ifdef uint32_t
-#undef uint32_t
-#endif
-
-#define uint32_t QT_PREPEND_NAMESPACE(quint32)
-
-#ifdef uint8_t
-#undef uint8_t
-#endif
-
-#define uint8_t QT_PREPEND_NAMESPACE(quint8)
-
-#ifdef int_least16_t
-#undef int_least16_t
-#endif
-
-#define int_least16_t QT_PREPEND_NAMESPACE(qint16)
-
-// Header from rfc6234 with 1 modification:
-// sha1.h - commented out '#include <stdint.h>' on line 74
+// Header from rfc6234
#include "../../3rdparty/rfc6234/sha.h"
#if QT_CONFIG(system_libb2)
@@ -83,11 +51,6 @@
#include "../../3rdparty/blake2/src/blake2.h"
#endif
-#undef uint64_t
-#undef uint32_t
-#undef uint68_t
-#undef int_least16_t
-
QT_BEGIN_NAMESPACE
static int qt_hash_block_size(QCryptographicHash::Algorithm method)
@@ -250,7 +213,7 @@ void QMessageAuthenticationCode::setKey(const QByteArray &key)
/*!
Adds the first \a length chars of \a data to the message.
*/
-void QMessageAuthenticationCode::addData(const char *data, int length)
+void QMessageAuthenticationCode::addData(const char *data, qsizetype length)
{
d->initMessageHash();
d->messageHash.addData(data, length);
diff --git a/src/corelib/tools/qmessageauthenticationcode.h b/src/corelib/tools/qmessageauthenticationcode.h
index a13a3d2acf..343bf9d617 100644
--- a/src/corelib/tools/qmessageauthenticationcode.h
+++ b/src/corelib/tools/qmessageauthenticationcode.h
@@ -59,7 +59,7 @@ public:
void setKey(const QByteArray &key);
- void addData(const char *data, int length);
+ void addData(const char *data, qsizetype length);
void addData(const QByteArray &data);
bool addData(QIODevice *device);
diff --git a/src/corelib/tools/qmultimap.qdoc b/src/corelib/tools/qmultimap.qdoc
index 01b2f17c73..487480a927 100644
--- a/src/corelib/tools/qmultimap.qdoc
+++ b/src/corelib/tools/qmultimap.qdoc
@@ -259,9 +259,9 @@
fast and never fails.
*/
-/*! \fn template <class Key, class T> bool QMultiMap<Key, T>::operator==(const QMultiMap<Key, T> &other) const
+/*! \fn template<class Key, class T> bool QMultiMap<Key, T>::operator==(const QMultiMap<Key, T> &lhs, const QMultiMap<Key, T> &rhs)
- Returns \c true if \a other is equal to this multi map; otherwise returns
+ Returns \c true if \a lhs is equal to \a rhs; otherwise returns
false.
Two multi maps are considered equal if they contain the same (key,
@@ -273,9 +273,9 @@
\sa operator!=()
*/
-/*! \fn template <class Key, class T> bool QMultiMap<Key, T>::operator!=(const QMultiMap<Key, T> &other) const
+/*! \fn template<class Key, class T> bool QMultiMap<Key, T>::operator!=(const QMultiMap<Key, T> &lhs, const QMultiMap<Key, T> &rhs)
- Returns \c true if \a other is not equal to this multi map; otherwise
+ Returns \c true if \a lhs is not equal to \a rhs; otherwise
returns \c false.
Two multi maps are considered equal if they contain the same (key,
@@ -411,7 +411,7 @@
items for \a key in the multi map, the value of the most recently
inserted one is returned.
- \sa key(), values(), contains(), operator[]()
+ \sa key(), values(), contains()
*/
/*! \fn template <class Key, class T> QList<Key> QMultiMap<Key, T>::keys() const
@@ -819,7 +819,7 @@
\sa replace()
*/
-/*! \fn [qmultimap-insert-pos] template <class Key, class T> QMultiMap<Key, T>::iterator QMultiMap<Key, T>::insert(const_iterator pos, const Key &key, const T &value)
+/*! \fn template <class Key, class T> QMultiMap<Key, T>::iterator QMultiMap<Key, T>::insert(const_iterator pos, const Key &key, const T &value)
\overload
\since 5.1
Inserts a new item with the key \a key and value \a value and with hint \a pos
@@ -842,23 +842,39 @@
crash but there is also a risk that it will silently corrupt both the multi map and the \a pos multi map.
*/
+#if QT_DEPRECATED_SINCE(6, 0)
/*! \fn template <class Key, class T> QMultiMap<Key, T>::iterator QMultiMap<Key, T>::insertMulti(const Key &key, const T &value)
+ \obsolete Use insert() instead.
- Same as insert().
+ Inserts a new item with the key \a key and a value of \a value, and returns an iterator pointing to the new item.
*/
/*! \fn template <class Key, class T> QMultiMap<Key, T>::iterator QMultiMap<Key, T>::insertMulti(const_iterator pos, const Key &key, const T &value)
+ \obsolete Use insert() instead.
\overload
- Same as insert().
+ Inserts a new item with the key \a key and value \a value and with hint \a pos
+ suggesting where to do the insert.
*/
/*! \fn template <class Key, class T> void QMultiMap<Key, T>::insert(const QMultiMap<Key, T> &map)
\since 5.15
+ \obsolete Use unite() instead.
- Same as unite().
+ Inserts all the items in \a map into this map.
*/
+/*! \fn template <class Key, class T> void QMultiMap<Key, T>::insert(QMultiMap<Key, T> &&map)
+ \since 5.15
+ \obsolete Use unite() instead.
+ \overload
+
+ Moves all the items from \a map into this map.
+
+ If \a map is shared, then the items will be copied instead.
+*/
+#endif
+
/*! \fn template <class Key, class T> QMultiMap<Key, T>::iterator QMultiMap<Key, T>::replace(const Key &key, const T &value)
Inserts a new item with the key \a key and a value of \a value.
@@ -924,25 +940,35 @@
*/
/*!
- \fn [qmultimap-unite] template <class Key, class T> QMultiMap<Key, T> &QMultiMap<Key, T>::unite(const QMultiMap<Key, T> &other)
+ \fn template <class Key, class T> QMultiMap<Key, T> &QMultiMap<Key, T>::unite(const QMultiMap<Key, T> &other)
Inserts all the items in the \a other map into this map. If a
key is common to both maps, the resulting map will contain the
key multiple times.
*/
-/*! \fn template <class Key, class T> QMultiMap &QMultiMap<Key, T>::operator+=(const QMultiMap &other)
+/*!
+ \fn template <class Key, class T> QMultiMap<Key, T> &QMultiMap<Key, T>::unite(QMultiMap<Key, T> &&other)
+
+ Moves all the items from the \a other map into this map. If a
+ key is common to both maps, the resulting map will contain the
+ key multiple times.
+
+ If \a other is shared, then the items will be copied instead.
+*/
+
+/*! \fn template <class Key, class T> QMultiMap<Key, T> operator+=(QMultiMap<Key, T> &lhs, const QMultiMap<Key, T> &rhs)
- Inserts all the items in the \a other map into this map and
- returns a reference to this map.
+ Inserts all the items in the \a rhs map into the \a lhs map and
+ returns the resulting map.
\sa insert(), operator+()
*/
-/*! \fn template <class Key, class T> QMultiMap QMultiMap<Key, T>::operator+(const QMultiMap &other) const
+/*! \fn template <class Key, class T> QMultiMap<Key, T> operator+(const QMultiMap<Key, T> &lhs, const QMultiMap<Key, T> &rhs)
- Returns a map that contains all the items in this map in
- addition to all the items in \a other. If a key is common to both
+ Returns a map that contains all the items in the \a lhs map in
+ addition to all the items in \a rhs. If a key is common to both
maps, the resulting map will contain the key multiple times.
\sa operator+=()
@@ -1094,21 +1120,21 @@
*/
/*!
- \fn template <class Key, class T> bool QMultiMap<Key, T>::iterator::operator==(const iterator &other) const
- \fn template <class Key, class T> bool QMultiMap<Key, T>::iterator::operator==(const const_iterator &other) const
+ \fn template<class Key, class T> bool QMultiMap<Key, T>::iterator::operator==(const iterator &lhs, const iterator &rhs)
+ \fn template<class Key, class T> bool QMultiMap<Key, T>::const_iterator::operator==(const const_iterator &lhs, const const_iterator &rhs)
- Returns \c true if \a other points to the same item as this
- iterator; otherwise returns \c false.
+ Returns \c true if \a lhs points to the same item as the \a rhs iterator;
+ otherwise returns \c false.
\sa operator!=()
*/
/*!
- \fn template <class Key, class T> bool QMultiMap<Key, T>::iterator::operator!=(const iterator &other) const
- \fn template <class Key, class T> bool QMultiMap<Key, T>::iterator::operator!=(const const_iterator &other) const
+ \fn template<class Key, class T> bool QMultiMap<Key, T>::iterator::operator!=(const iterator &lhs, const iterator &rhs)
+ \fn template<class Key, class T> bool QMultiMap<Key, T>::const_iterator::operator!=(const const_iterator &lhs, const const_iterator &rhs)
- Returns \c true if \a other points to a different item than this
- iterator; otherwise returns \c false.
+ Returns \c true if \a lhs points to a different item than the \a rhs iterator;
+ otherwise returns \c false.
\sa operator==()
*/
@@ -1269,22 +1295,6 @@
\sa value()
*/
-/*! \fn template <class Key, class T> bool QMultiMap<Key, T>::const_iterator::operator==(const const_iterator &other) const
-
- Returns \c true if \a other points to the same item as this
- iterator; otherwise returns \c false.
-
- \sa operator!=()
-*/
-
-/*! \fn template <class Key, class T> bool QMultiMap<Key, T>::const_iterator::operator!=(const const_iterator &other) const
-
- Returns \c true if \a other points to a different item than this
- iterator; otherwise returns \c false.
-
- \sa operator==()
-*/
-
/*! \fn template <class Key, class T> QMultiMap<Key, T>::const_iterator &QMultiMap<Key, T>::const_iterator::operator++()
The prefix ++ operator (\c{++i}) advances the iterator to the
diff --git a/src/corelib/tools/qoffsetstringarray_p.h b/src/corelib/tools/qoffsetstringarray_p.h
index 678e410250..f99e6b800b 100644
--- a/src/corelib/tools/qoffsetstringarray_p.h
+++ b/src/corelib/tools/qoffsetstringarray_p.h
@@ -65,9 +65,11 @@ struct OffsetSequenceHelper : OffsetSequenceHelper<N - 1, O + I, Idx..., O> { };
template<int Last, int I, int S, int ... Idx>
struct OffsetSequenceHelper<1, Last, I, S, Idx...> : IndexesList<Last + I, Idx..., Last>
{
+ // the unary + before std::numeric_limits below is required. Otherwise we get on g++-10.2:
+ // error: comparison is always false due to limited range of data type [-Werror=type-limits]
static const constexpr auto Length = Last + I;
using Type = typename std::conditional<
- Last <= std::numeric_limits<quint8>::max(),
+ Last <= +std::numeric_limits<quint8>::max(),
quint8,
typename std::conditional<
Last <= std::numeric_limits<quint16>::max(),
@@ -133,6 +135,10 @@ constexpr StaticString<Sum> staticString(const char (&s)[I], const char (&...sx)
QT_WARNING_POP
} // namespace QtPrivate
+QT_WARNING_PUSH
+#if defined(Q_CC_GNU) && __GNUC__ == 9
+QT_WARNING_DISABLE_GCC("-Wstringop-overflow")
+#endif
template<typename T, int SizeString, int SizeOffsets>
class QOffsetStringArray
{
@@ -167,6 +173,7 @@ private:
QtPrivate::StaticString<SizeString> m_string;
const T m_offsets[SizeOffsets];
};
+QT_WARNING_POP
template<typename T, int N, int ... Ox>
constexpr QOffsetStringArray<T, N, sizeof ... (Ox)> qOffsetStringArray(
diff --git a/src/corelib/tools/qpair.qdoc b/src/corelib/tools/qpair.qdoc
index 0e17b6c3b9..d1c49fc520 100644
--- a/src/corelib/tools/qpair.qdoc
+++ b/src/corelib/tools/qpair.qdoc
@@ -26,18 +26,10 @@
****************************************************************************/
/*!
- \class QPair
- \inmodule QtCore
- \obsolete
- \brief QPair is an alias for std::pair.
-
- \ingroup tools
-
- QPair\<T1, T2\> is a typedef for std::pair\<T1, T2\>.
- It is provided for backwards compatibility. Use std::pair directly
- instead.
-
- \sa {Container Classes}
+ \typealias QPair
+ \relates QPair
+ \since 6.0
+ Typedef for std::pair\<T1, T2\>.
*/
/*!
diff --git a/src/corelib/tools/qpoint.cpp b/src/corelib/tools/qpoint.cpp
index eca1b5a0ac..942ae995d5 100644
--- a/src/corelib/tools/qpoint.cpp
+++ b/src/corelib/tools/qpoint.cpp
@@ -244,23 +244,20 @@ QT_BEGIN_NAMESPACE
*/
/*!
- \fn bool operator==(const QPoint &p1, const QPoint &p2)
- \relates QPoint
+ \fn bool QPoint::operator==(const QPoint &p1, const QPoint &p2)
Returns \c true if \a p1 and \a p2 are equal; otherwise returns
false.
*/
/*!
- \fn bool operator!=(const QPoint &p1, const QPoint &p2)
- \relates QPoint
+ \fn bool QPoint::operator!=(const QPoint &p1, const QPoint &p2)
Returns \c true if \a p1 and \a p2 are not equal; otherwise returns \c false.
*/
/*!
- \fn const QPoint operator+(const QPoint &p1, const QPoint &p2)
- \relates QPoint
+ \fn QPoint QPoint::operator+(const QPoint &p1, const QPoint &p2)
Returns a QPoint object that is the sum of the given points, \a p1
and \a p2; each component is added separately.
@@ -269,8 +266,7 @@ QT_BEGIN_NAMESPACE
*/
/*!
- \fn const QPoint operator-(const QPoint &p1, const QPoint &p2)
- \relates QPoint
+ \fn Point QPoint::operator-(const QPoint &p1, const QPoint &p2)
Returns a QPoint object that is formed by subtracting \a p2 from
\a p1; each component is subtracted separately.
@@ -279,8 +275,7 @@ QT_BEGIN_NAMESPACE
*/
/*!
- \fn const QPoint operator*(const QPoint &point, float factor)
- \relates QPoint
+ \fn QPoint QPoint::operator*(const QPoint &point, float factor)
Returns a copy of the given \a point multiplied by the given \a factor.
@@ -291,8 +286,7 @@ QT_BEGIN_NAMESPACE
*/
/*!
- \fn const QPoint operator*(const QPoint &point, double factor)
- \relates QPoint
+ \fn QPoint QPoint::operator*(const QPoint &point, double factor)
Returns a copy of the given \a point multiplied by the given \a factor.
@@ -303,8 +297,7 @@ QT_BEGIN_NAMESPACE
*/
/*!
- \fn const QPoint operator*(const QPoint &point, int factor)
- \relates QPoint
+ \fn QPoint QPoint::operator*(const QPoint &point, int factor)
Returns a copy of the given \a point multiplied by the given \a factor.
@@ -312,9 +305,8 @@ QT_BEGIN_NAMESPACE
*/
/*!
- \fn const QPoint operator*(float factor, const QPoint &point)
+ \fn QPoint QPoint::operator*(float factor, const QPoint &point)
\overload
- \relates QPoint
Returns a copy of the given \a point multiplied by the given \a factor.
@@ -325,9 +317,8 @@ QT_BEGIN_NAMESPACE
*/
/*!
- \fn const QPoint operator*(double factor, const QPoint &point)
+ \fn QPoint QPoint::operator*(double factor, const QPoint &point)
\overload
- \relates QPoint
Returns a copy of the given \a point multiplied by the given \a factor.
@@ -338,9 +329,8 @@ QT_BEGIN_NAMESPACE
*/
/*!
- \fn const QPoint operator*(int factor, const QPoint &point)
+ \fn QPoint QPoint::operator*(int factor, const QPoint &point)
\overload
- \relates QPoint
Returns a copy of the given \a point multiplied by the given \a factor.
@@ -348,17 +338,15 @@ QT_BEGIN_NAMESPACE
*/
/*!
- \fn const QPoint operator+(const QPoint &point)
- \relates QPoint
+ \fn QPoint QPoint::operator+(const QPoint &point)
\since 5.0
Returns \a point unmodified.
*/
/*!
- \fn const QPoint operator-(const QPoint &point)
+ \fn QPoint QPoint::operator-(const QPoint &point)
\overload
- \relates QPoint
Returns a QPoint object that is formed by changing the sign of
both components of the given \a point.
@@ -382,8 +370,7 @@ QT_BEGIN_NAMESPACE
*/
/*!
- \fn const QPoint operator/(const QPoint &point, qreal divisor)
- \relates QPoint
+ \fn const QPoint QPoint::operator/(const QPoint &point, qreal divisor)
Returns the QPoint formed by dividing both components of the given \a point
by the given \a divisor.
@@ -688,8 +675,7 @@ size_t qHash(QPoint key, size_t seed) noexcept
*/
/*!
- \fn const QPointF operator+(const QPointF &p1, const QPointF &p2)
- \relates QPointF
+ \fn QPointF QPointF::operator+(const QPointF &p1, const QPointF &p2)
Returns a QPointF object that is the sum of the given points, \a p1
and \a p2; each component is added separately.
@@ -698,8 +684,7 @@ size_t qHash(QPoint key, size_t seed) noexcept
*/
/*!
- \fn const QPointF operator-(const QPointF &p1, const QPointF &p2)
- \relates QPointF
+ \fn QPointF QPointF::operator-(const QPointF &p1, const QPointF &p2)
Returns a QPointF object that is formed by subtracting \a p2 from \a p1;
each component is subtracted separately.
@@ -708,8 +693,7 @@ size_t qHash(QPoint key, size_t seed) noexcept
*/
/*!
- \fn const QPointF operator*(const QPointF &point, qreal factor)
- \relates QPointF
+ \fn QPointF QPointF::operator*(const QPointF &point, qreal factor)
Returns a copy of the given \a point, multiplied by the given \a factor.
@@ -717,8 +701,7 @@ size_t qHash(QPoint key, size_t seed) noexcept
*/
/*!
- \fn const QPointF operator*(qreal factor, const QPointF &point)
- \relates QPointF
+ \fn QPointF QPointF::operator*(qreal factor, const QPointF &point)
\overload
@@ -726,16 +709,14 @@ size_t qHash(QPoint key, size_t seed) noexcept
*/
/*!
- \fn const QPointF operator+(const QPointF &point)
- \relates QPointF
+ \fn QPointF QPointF::operator+(const QPointF &point)
\since 5.0
Returns \a point unmodified.
*/
/*!
- \fn const QPointF operator-(const QPointF &point)
- \relates QPointF
+ \fn QPointF QPointF::operator-(const QPointF &point)
\overload
Returns a QPointF object that is formed by changing the sign of
@@ -745,8 +726,7 @@ size_t qHash(QPoint key, size_t seed) noexcept
*/
/*!
- \fn const QPointF operator/(const QPointF &point, qreal divisor)
- \relates QPointF
+ \fn QPointF QPointF::operator/(const QPointF &point, qreal divisor)
Returns the QPointF object formed by dividing both components of
the given \a point by the given \a divisor.
@@ -773,17 +753,27 @@ size_t qHash(QPoint key, size_t seed) noexcept
*/
/*!
- \fn bool operator==(const QPointF &p1, const QPointF &p2)
- \relates QPointF
+ \fn bool QPointF::operator==(const QPointF &p1, const QPointF &p2)
- Returns \c true if \a p1 is equal to \a p2; otherwise returns \c false.
+ Returns \c true if \a p1 is approximately equal to \a p2; otherwise
+ returns \c false.
+
+ \warning This function does not check for strict equality; instead,
+ it uses a fuzzy comparison to compare the points' coordinates.
+
+ \sa qFuzzyCompare
*/
/*!
- \fn bool operator!=(const QPointF &p1, const QPointF &p2);
- \relates QPointF
+ \fn bool QPointF::operator!=(const QPointF &p1, const QPointF &p2);
+
+ Returns \c true if \a p1 is sufficiently different from \a p2;
+ otherwise returns \c false.
+
+ \warning This function does not check for strict inequality; instead,
+ it uses a fuzzy comparison to compare the points' coordinates.
- Returns \c true if \a p1 is not equal to \a p2; otherwise returns \c false.
+ \sa qFuzzyCompare
*/
#ifndef QT_NO_DATASTREAM
diff --git a/src/corelib/tools/qpoint.h b/src/corelib/tools/qpoint.h
index e854e77198..f2acb9f3ad 100644
--- a/src/corelib/tools/qpoint.h
+++ b/src/corelib/tools/qpoint.h
@@ -48,7 +48,6 @@ struct CGPoint;
QT_BEGIN_NAMESPACE
-
class QPoint
{
public:
@@ -67,7 +66,7 @@ public:
constexpr QPoint transposed() const noexcept { return {yp, xp}; }
constexpr inline int &rx() noexcept;
- constexpr inline int &ry()noexcept;
+ constexpr inline int &ry() noexcept;
constexpr inline QPoint &operator+=(const QPoint &p);
constexpr inline QPoint &operator-=(const QPoint &p);
@@ -81,28 +80,53 @@ public:
constexpr static inline int dotProduct(const QPoint &p1, const QPoint &p2)
{ return p1.xp * p2.xp + p1.yp * p2.yp; }
- friend constexpr inline bool operator==(const QPoint &, const QPoint &) noexcept;
- friend constexpr inline bool operator!=(const QPoint &, const QPoint &) noexcept;
- friend constexpr inline const QPoint operator+(const QPoint &, const QPoint &);
- friend constexpr inline const QPoint operator-(const QPoint &, const QPoint &);
- friend constexpr inline const QPoint operator*(const QPoint &, float);
- friend constexpr inline const QPoint operator*(float, const QPoint &);
- friend constexpr inline const QPoint operator*(const QPoint &, double);
- friend constexpr inline const QPoint operator*(double, const QPoint &);
- friend constexpr inline const QPoint operator*(const QPoint &, int);
- friend constexpr inline const QPoint operator*(int, const QPoint &);
- friend constexpr inline const QPoint operator+(const QPoint &);
- friend constexpr inline const QPoint operator-(const QPoint &);
- friend constexpr inline const QPoint operator/(const QPoint &, qreal);
+ friend constexpr inline bool operator==(const QPoint &p1, const QPoint &p2) noexcept
+ { return p1.xp == p2.xp && p1.yp == p2.yp; }
+ friend constexpr inline bool operator!=(const QPoint &p1, const QPoint &p2) noexcept
+ { return p1.xp != p2.xp || p1.yp != p2.yp; }
+ friend constexpr inline QPoint operator+(const QPoint &p1, const QPoint &p2) noexcept
+ { return QPoint(p1.xp + p2.xp, p1.yp + p2.yp); }
+ friend constexpr inline QPoint operator-(const QPoint &p1, const QPoint &p2) noexcept
+ { return QPoint(p1.xp - p2.xp, p1.yp - p2.yp); }
+ friend constexpr inline QPoint operator*(const QPoint &p, float factor)
+ { return QPoint(qRound(p.xp * factor), qRound(p.yp * factor)); }
+ friend constexpr inline QPoint operator*(const QPoint &p, double factor)
+ { return QPoint(qRound(p.xp * factor), qRound(p.yp * factor)); }
+ friend constexpr inline QPoint operator*(const QPoint &p, int factor) noexcept
+ { return QPoint(p.xp * factor, p.yp * factor); }
+ friend constexpr inline QPoint operator*(float factor, const QPoint &p)
+ { return QPoint(qRound(p.xp * factor), qRound(p.yp * factor)); }
+ friend constexpr inline QPoint operator*(double factor, const QPoint &p)
+ { return QPoint(qRound(p.xp * factor), qRound(p.yp * factor)); }
+ friend constexpr inline QPoint operator*(int factor, const QPoint &p) noexcept
+ { return QPoint(p.xp * factor, p.yp * factor); }
+ friend constexpr inline QPoint operator+(const QPoint &p) noexcept
+ { return p; }
+ friend constexpr inline QPoint operator-(const QPoint &p) noexcept
+ { return QPoint(-p.xp, -p.yp); }
+ friend constexpr inline QPoint operator/(const QPoint &p, qreal c)
+ { return QPoint(qRound(p.xp / c), qRound(p.yp / c)); }
#if defined(Q_OS_DARWIN) || defined(Q_QDOC)
- Q_REQUIRED_RESULT Q_CORE_EXPORT CGPoint toCGPoint() const noexcept;
+ [[nodiscard]] Q_CORE_EXPORT CGPoint toCGPoint() const noexcept;
#endif
private:
friend class QTransform;
int xp;
int yp;
+
+ template <std::size_t I,
+ typename P,
+ std::enable_if_t<(I < 2), bool> = true,
+ std::enable_if_t<std::is_same_v<std::decay_t<P>, QPoint>, bool> = true>
+ friend constexpr decltype(auto) get(P &&p) noexcept
+ {
+ if constexpr (I == 0)
+ return (std::forward<P>(p).xp);
+ else if constexpr (I == 1)
+ return (std::forward<P>(p).yp);
+ }
};
Q_DECLARE_TYPEINFO(QPoint, Q_MOVABLE_TYPE);
@@ -124,90 +148,85 @@ constexpr inline QPoint::QPoint() noexcept : xp(0), yp(0) {}
constexpr inline QPoint::QPoint(int xpos, int ypos) noexcept : xp(xpos), yp(ypos) {}
constexpr inline bool QPoint::isNull() const noexcept
-{ return xp == 0 && yp == 0; }
+{
+ return xp == 0 && yp == 0;
+}
constexpr inline int QPoint::x() const noexcept
-{ return xp; }
+{
+ return xp;
+}
constexpr inline int QPoint::y() const noexcept
-{ return yp; }
+{
+ return yp;
+}
constexpr inline void QPoint::setX(int xpos) noexcept
-{ xp = xpos; }
+{
+ xp = xpos;
+}
constexpr inline void QPoint::setY(int ypos) noexcept
-{ yp = ypos; }
+{
+ yp = ypos;
+}
inline int constexpr QPoint::manhattanLength() const
-{ return qAbs(x())+qAbs(y()); }
+{
+ return qAbs(x()) + qAbs(y());
+}
constexpr inline int &QPoint::rx() noexcept
-{ return xp; }
+{
+ return xp;
+}
constexpr inline int &QPoint::ry() noexcept
-{ return yp; }
+{
+ return yp;
+}
constexpr inline QPoint &QPoint::operator+=(const QPoint &p)
-{ xp+=p.xp; yp+=p.yp; return *this; }
+{
+ xp += p.xp;
+ yp += p.yp;
+ return *this;
+}
constexpr inline QPoint &QPoint::operator-=(const QPoint &p)
-{ xp-=p.xp; yp-=p.yp; return *this; }
+{
+ xp -= p.xp;
+ yp -= p.yp;
+ return *this;
+}
constexpr inline QPoint &QPoint::operator*=(float factor)
-{ xp = qRound(xp*factor); yp = qRound(yp*factor); return *this; }
+{
+ xp = qRound(xp * factor);
+ yp = qRound(yp * factor);
+ return *this;
+}
constexpr inline QPoint &QPoint::operator*=(double factor)
-{ xp = qRound(xp*factor); yp = qRound(yp*factor); return *this; }
+{
+ xp = qRound(xp * factor);
+ yp = qRound(yp * factor);
+ return *this;
+}
constexpr inline QPoint &QPoint::operator*=(int factor)
-{ xp = xp*factor; yp = yp*factor; return *this; }
-
-constexpr inline bool operator==(const QPoint &p1, const QPoint &p2) noexcept
-{ return p1.xp == p2.xp && p1.yp == p2.yp; }
-
-constexpr inline bool operator!=(const QPoint &p1, const QPoint &p2) noexcept
-{ return p1.xp != p2.xp || p1.yp != p2.yp; }
-
-constexpr inline const QPoint operator+(const QPoint &p1, const QPoint &p2)
-{ return QPoint(p1.xp+p2.xp, p1.yp+p2.yp); }
-
-constexpr inline const QPoint operator-(const QPoint &p1, const QPoint &p2)
-{ return QPoint(p1.xp-p2.xp, p1.yp-p2.yp); }
-
-constexpr inline const QPoint operator*(const QPoint &p, float factor)
-{ return QPoint(qRound(p.xp*factor), qRound(p.yp*factor)); }
-
-constexpr inline const QPoint operator*(const QPoint &p, double factor)
-{ return QPoint(qRound(p.xp*factor), qRound(p.yp*factor)); }
-
-constexpr inline const QPoint operator*(const QPoint &p, int factor)
-{ return QPoint(p.xp*factor, p.yp*factor); }
-
-constexpr inline const QPoint operator*(float factor, const QPoint &p)
-{ return QPoint(qRound(p.xp*factor), qRound(p.yp*factor)); }
-
-constexpr inline const QPoint operator*(double factor, const QPoint &p)
-{ return QPoint(qRound(p.xp*factor), qRound(p.yp*factor)); }
-
-constexpr inline const QPoint operator*(int factor, const QPoint &p)
-{ return QPoint(p.xp*factor, p.yp*factor); }
-
-constexpr inline const QPoint operator+(const QPoint &p)
-{ return p; }
-
-constexpr inline const QPoint operator-(const QPoint &p)
-{ return QPoint(-p.xp, -p.yp); }
-
-constexpr inline QPoint &QPoint::operator/=(qreal c)
{
- xp = qRound(xp/c);
- yp = qRound(yp/c);
+ xp = xp * factor;
+ yp = yp * factor;
return *this;
}
-constexpr inline const QPoint operator/(const QPoint &p, qreal c)
+constexpr inline QPoint &QPoint::operator/=(qreal c)
{
- return QPoint(qRound(p.xp/c), qRound(p.yp/c));
+ xp = qRound(xp / c);
+ yp = qRound(yp / c);
+ return *this;
}
#ifndef QT_NO_DEBUG_STREAM
@@ -246,23 +265,43 @@ public:
constexpr inline QPointF &operator/=(qreal c);
constexpr static inline qreal dotProduct(const QPointF &p1, const QPointF &p2)
- { return p1.xp * p2.xp + p1.yp * p2.yp; }
-
- friend constexpr inline bool operator==(const QPointF &, const QPointF &);
- friend constexpr inline bool operator!=(const QPointF &, const QPointF &);
- friend constexpr inline const QPointF operator+(const QPointF &, const QPointF &);
- friend constexpr inline const QPointF operator-(const QPointF &, const QPointF &);
- friend constexpr inline const QPointF operator*(qreal, const QPointF &);
- friend constexpr inline const QPointF operator*(const QPointF &, qreal);
- friend constexpr inline const QPointF operator+(const QPointF &);
- friend constexpr inline const QPointF operator-(const QPointF &);
- friend constexpr inline const QPointF operator/(const QPointF &, qreal);
+ {
+ return p1.xp * p2.xp + p1.yp * p2.yp;
+ }
+
+ QT_WARNING_PUSH
+ QT_WARNING_DISABLE_FLOAT_COMPARE
+ friend constexpr inline bool operator==(const QPointF &p1, const QPointF &p2)
+ {
+ return ((!p1.xp || !p2.xp) ? qFuzzyIsNull(p1.xp - p2.xp) : qFuzzyCompare(p1.xp, p2.xp))
+ && ((!p1.yp || !p2.yp) ? qFuzzyIsNull(p1.yp - p2.yp) : qFuzzyCompare(p1.yp, p2.yp));
+ }
+ friend constexpr inline bool operator!=(const QPointF &p1, const QPointF &p2)
+ {
+ return !(p1 == p2);
+ }
+ QT_WARNING_POP
+
+ friend constexpr inline QPointF operator+(const QPointF &p1, const QPointF &p2)
+ { return QPointF(p1.xp + p2.xp, p1.yp + p2.yp); }
+ friend constexpr inline QPointF operator-(const QPointF &p1, const QPointF &p2)
+ { return QPointF(p1.xp - p2.xp, p1.yp - p2.yp); }
+ friend constexpr inline QPointF operator*(const QPointF &p, qreal c)
+ { return QPointF(p.xp * c, p.yp * c); }
+ friend constexpr inline QPointF operator*(qreal c, const QPointF &p)
+ { return QPointF(p.xp * c, p.yp * c); }
+ friend constexpr inline QPointF operator+(const QPointF &p)
+ { return p; }
+ friend constexpr inline QPointF operator-(const QPointF &p)
+ { return QPointF(-p.xp, -p.yp); }
+ friend constexpr inline QPointF operator/(const QPointF &p, qreal divisor)
+ { return QPointF(p.xp / divisor, p.yp / divisor); }
constexpr QPoint toPoint() const;
#if defined(Q_OS_DARWIN) || defined(Q_QDOC)
- Q_REQUIRED_RESULT Q_CORE_EXPORT static QPointF fromCGPoint(CGPoint point) noexcept;
- Q_REQUIRED_RESULT Q_CORE_EXPORT CGPoint toCGPoint() const noexcept;
+ [[nodiscard]] Q_CORE_EXPORT static QPointF fromCGPoint(CGPoint point) noexcept;
+ [[nodiscard]] Q_CORE_EXPORT CGPoint toCGPoint() const noexcept;
#endif
private:
@@ -270,6 +309,18 @@ private:
qreal xp;
qreal yp;
+
+ template <std::size_t I,
+ typename P,
+ std::enable_if_t<(I < 2), bool> = true,
+ std::enable_if_t<std::is_same_v<std::decay_t<P>, QPointF>, bool> = true>
+ friend constexpr decltype(auto) get(P &&p) noexcept
+ {
+ if constexpr (I == 0)
+ return (std::forward<P>(p).xp);
+ else if constexpr (I == 1)
+ return (std::forward<P>(p).yp);
+ }
};
Q_DECLARE_TYPEINFO(QPointF, Q_MOVABLE_TYPE);
@@ -294,7 +345,7 @@ constexpr inline QPointF::QPointF(const QPoint &p) noexcept : xp(p.x()), yp(p.y(
constexpr inline qreal QPointF::manhattanLength() const
{
- return qAbs(x())+qAbs(y());
+ return qAbs(x()) + qAbs(y());
}
inline bool QPointF::isNull() const noexcept
@@ -334,79 +385,32 @@ constexpr inline qreal &QPointF::ry() noexcept
constexpr inline QPointF &QPointF::operator+=(const QPointF &p)
{
- xp+=p.xp;
- yp+=p.yp;
+ xp += p.xp;
+ yp += p.yp;
return *this;
}
constexpr inline QPointF &QPointF::operator-=(const QPointF &p)
{
- xp-=p.xp; yp-=p.yp; return *this;
+ xp -= p.xp;
+ yp -= p.yp;
+ return *this;
}
constexpr inline QPointF &QPointF::operator*=(qreal c)
{
- xp*=c; yp*=c; return *this;
-}
-
-QT_WARNING_PUSH
-QT_WARNING_DISABLE_FLOAT_COMPARE
-
-constexpr inline bool operator==(const QPointF &p1, const QPointF &p2)
-{
- return ((!p1.xp || !p2.xp) ? qFuzzyIsNull(p1.xp - p2.xp) : qFuzzyCompare(p1.xp, p2.xp))
- && ((!p1.yp || !p2.yp) ? qFuzzyIsNull(p1.yp - p2.yp) : qFuzzyCompare(p1.yp, p2.yp));
-}
-
-constexpr inline bool operator!=(const QPointF &p1, const QPointF &p2)
-{
- return !(p1 == p2);
-}
-
-QT_WARNING_POP
-
-constexpr inline const QPointF operator+(const QPointF &p1, const QPointF &p2)
-{
- return QPointF(p1.xp+p2.xp, p1.yp+p2.yp);
-}
-
-constexpr inline const QPointF operator-(const QPointF &p1, const QPointF &p2)
-{
- return QPointF(p1.xp-p2.xp, p1.yp-p2.yp);
-}
-
-constexpr inline const QPointF operator*(const QPointF &p, qreal c)
-{
- return QPointF(p.xp*c, p.yp*c);
-}
-
-constexpr inline const QPointF operator*(qreal c, const QPointF &p)
-{
- return QPointF(p.xp*c, p.yp*c);
-}
-
-constexpr inline const QPointF operator+(const QPointF &p)
-{
- return p;
-}
-
-constexpr inline const QPointF operator-(const QPointF &p)
-{
- return QPointF(-p.xp, -p.yp);
+ xp *= c;
+ yp *= c;
+ return *this;
}
constexpr inline QPointF &QPointF::operator/=(qreal divisor)
{
- xp/=divisor;
- yp/=divisor;
+ xp /= divisor;
+ yp /= divisor;
return *this;
}
-constexpr inline const QPointF operator/(const QPointF &p, qreal divisor)
-{
- return QPointF(p.xp/divisor, p.yp/divisor);
-}
-
constexpr inline QPoint QPointF::toPoint() const
{
return QPoint(qRound(xp), qRound(yp));
@@ -418,4 +422,24 @@ Q_CORE_EXPORT QDebug operator<<(QDebug d, const QPointF &p);
QT_END_NAMESPACE
+/*****************************************************************************
+ QPoint/QPointF tuple protocol
+ *****************************************************************************/
+
+namespace std {
+ template <>
+ class tuple_size<QT_PREPEND_NAMESPACE(QPoint)> : public integral_constant<size_t, 2> {};
+ template <>
+ class tuple_element<0, QT_PREPEND_NAMESPACE(QPoint)> { public: using type = int; };
+ template <>
+ class tuple_element<1, QT_PREPEND_NAMESPACE(QPoint)> { public: using type = int; };
+
+ template <>
+ class tuple_size<QT_PREPEND_NAMESPACE(QPointF)> : public integral_constant<size_t, 2> {};
+ template <>
+ class tuple_element<0, QT_PREPEND_NAMESPACE(QPointF)> { public: using type = QT_PREPEND_NAMESPACE(qreal); };
+ template <>
+ class tuple_element<1, QT_PREPEND_NAMESPACE(QPointF)> { public: using type = QT_PREPEND_NAMESPACE(qreal); };
+}
+
#endif // QPOINT_H
diff --git a/src/corelib/tools/qrect.cpp b/src/corelib/tools/qrect.cpp
index 79d00a6fde..d38e532efe 100644
--- a/src/corelib/tools/qrect.cpp
+++ b/src/corelib/tools/qrect.cpp
@@ -1141,8 +1141,7 @@ bool QRect::intersects(const QRect &r) const noexcept
}
/*!
- \fn bool operator==(const QRect &r1, const QRect &r2)
- \relates QRect
+ \fn bool QRect::operator==(const QRect &r1, const QRect &r2)
Returns \c true if the rectangles \a r1 and \a r2 are equal,
otherwise returns \c false.
@@ -1150,8 +1149,7 @@ bool QRect::intersects(const QRect &r) const noexcept
/*!
- \fn bool operator!=(const QRect &r1, const QRect &r2)
- \relates QRect
+ \fn bool QRect::operator!=(const QRect &r1, const QRect &r2)
Returns \c true if the rectangles \a r1 and \a r2 are different, otherwise
returns \c false.
@@ -2130,7 +2128,7 @@ bool QRectF::contains(const QRectF &r) const noexcept
Intersects this rectangle with the given \a rectangle.
- \sa intersected(), operator|=()
+ \sa intersected(), operator&()
*/
@@ -2368,20 +2366,26 @@ QRect QRectF::toAlignedRect() const noexcept
*/
/*!
- \fn bool operator==(const QRectF &r1, const QRectF &r2)
- \relates QRectF
+ \fn bool QRectF::operator==(const QRectF &r1, const QRectF &r2)
- Returns \c true if the rectangles \a r1 and \a r2 are equal,
+ Returns \c true if the rectangles \a r1 and \a r2 are \b approximately equal,
otherwise returns \c false.
+
+ \warning This function does not check for strict equality; instead,
+ it uses a fuzzy comparison to compare the rectangles' coordinates.
+
+ \sa qFuzzyCompare
*/
/*!
- \fn bool operator!=(const QRectF &r1, const QRectF &r2)
- \relates QRectF
+ \fn bool QRectF::operator!=(const QRectF &r1, const QRectF &r2)
- Returns \c true if the rectangles \a r1 and \a r2 are different, otherwise
- returns \c false.
+ Returns \c true if the rectangles \a r1 and \a r2 are sufficiently
+ different, otherwise returns \c false.
+
+ \warning This function does not check for strict inequality; instead,
+ it uses a fuzzy comparison to compare the rectangles' coordinates.
*/
/*!
diff --git a/src/corelib/tools/qrect.h b/src/corelib/tools/qrect.h
index 5deb220b2d..14cab1137e 100644
--- a/src/corelib/tools/qrect.h
+++ b/src/corelib/tools/qrect.h
@@ -71,7 +71,7 @@ public:
constexpr inline int top() const noexcept;
constexpr inline int right() const noexcept;
constexpr inline int bottom() const noexcept;
- Q_REQUIRED_RESULT QRect normalized() const noexcept;
+ [[nodiscard]] QRect normalized() const noexcept;
constexpr inline int x() const noexcept;
constexpr inline int y() const noexcept;
@@ -105,9 +105,9 @@ public:
constexpr inline void translate(int dx, int dy) noexcept;
constexpr inline void translate(const QPoint &p) noexcept;
- Q_REQUIRED_RESULT constexpr inline QRect translated(int dx, int dy) const noexcept;
- Q_REQUIRED_RESULT constexpr inline QRect translated(const QPoint &p) const noexcept;
- Q_REQUIRED_RESULT constexpr inline QRect transposed() const noexcept;
+ [[nodiscard]] constexpr inline QRect translated(int dx, int dy) const noexcept;
+ [[nodiscard]] constexpr inline QRect translated(const QPoint &p) const noexcept;
+ [[nodiscard]] constexpr inline QRect transposed() const noexcept;
constexpr inline void moveTo(int x, int t) noexcept;
constexpr inline void moveTo(const QPoint &p) noexcept;
@@ -119,7 +119,7 @@ public:
constexpr inline void getCoords(int *x1, int *y1, int *x2, int *y2) const;
constexpr inline void adjust(int x1, int y1, int x2, int y2) noexcept;
- Q_REQUIRED_RESULT constexpr inline QRect adjusted(int x1, int y1, int x2, int y2) const noexcept;
+ [[nodiscard]] constexpr inline QRect adjusted(int x1, int y1, int x2, int y2) const noexcept;
constexpr inline QSize size() const noexcept;
constexpr inline int width() const noexcept;
@@ -130,15 +130,15 @@ public:
QRect operator|(const QRect &r) const noexcept;
QRect operator&(const QRect &r) const noexcept;
- inline QRect& operator|=(const QRect &r) noexcept;
- inline QRect& operator&=(const QRect &r) noexcept;
+ inline QRect &operator|=(const QRect &r) noexcept;
+ inline QRect &operator&=(const QRect &r) noexcept;
bool contains(const QRect &r, bool proper = false) const noexcept;
- bool contains(const QPoint &p, bool proper=false) const noexcept;
+ bool contains(const QPoint &p, bool proper = false) const noexcept;
inline bool contains(int x, int y) const noexcept;
inline bool contains(int x, int y, bool proper) const noexcept;
- Q_REQUIRED_RESULT inline QRect united(const QRect &other) const noexcept;
- Q_REQUIRED_RESULT inline QRect intersected(const QRect &other) const noexcept;
+ [[nodiscard]] inline QRect united(const QRect &other) const noexcept;
+ [[nodiscard]] inline QRect intersected(const QRect &other) const noexcept;
bool intersects(const QRect &r) const noexcept;
constexpr inline QRect marginsAdded(const QMargins &margins) const noexcept;
@@ -146,14 +146,16 @@ public:
constexpr inline QRect &operator+=(const QMargins &margins) noexcept;
constexpr inline QRect &operator-=(const QMargins &margins) noexcept;
- Q_REQUIRED_RESULT static constexpr inline QRect span(const QPoint &p1, const QPoint &p2) noexcept;
+ [[nodiscard]] static constexpr inline QRect span(const QPoint &p1, const QPoint &p2) noexcept;
- friend constexpr inline bool operator==(const QRect &, const QRect &) noexcept;
- friend constexpr inline bool operator!=(const QRect &, const QRect &) noexcept;
+ friend constexpr inline bool operator==(const QRect &r1, const QRect &r2) noexcept
+ { return r1.x1==r2.x1 && r1.x2==r2.x2 && r1.y1==r2.y1 && r1.y2==r2.y2; }
+ friend constexpr inline bool operator!=(const QRect &r1, const QRect &r2) noexcept
+ { return r1.x1!=r2.x1 || r1.x2!=r2.x2 || r1.y1!=r2.y1 || r1.y2!=r2.y2; }
friend constexpr inline size_t qHash(const QRect &, size_t) noexcept;
#if defined(Q_OS_DARWIN) || defined(Q_QDOC)
- Q_REQUIRED_RESULT CGRect toCGRect() const noexcept;
+ [[nodiscard]] CGRect toCGRect() const noexcept;
#endif
private:
@@ -164,9 +166,6 @@ private:
};
Q_DECLARE_TYPEINFO(QRect, Q_MOVABLE_TYPE);
-constexpr inline bool operator==(const QRect &, const QRect &) noexcept;
-constexpr inline bool operator!=(const QRect &, const QRect &) noexcept;
-
/*****************************************************************************
QRect stream functions
@@ -428,13 +427,13 @@ inline bool QRect::contains(int ax, int ay) const noexcept
return contains(QPoint(ax, ay), false);
}
-inline QRect& QRect::operator|=(const QRect &r) noexcept
+inline QRect &QRect::operator|=(const QRect &r) noexcept
{
*this = *this | r;
return *this;
}
-inline QRect& QRect::operator&=(const QRect &r) noexcept
+inline QRect &QRect::operator&=(const QRect &r) noexcept
{
*this = *this & r;
return *this;
@@ -450,16 +449,6 @@ inline QRect QRect::united(const QRect &r) const noexcept
return *this | r;
}
-constexpr inline bool operator==(const QRect &r1, const QRect &r2) noexcept
-{
- return r1.x1==r2.x1 && r1.x2==r2.x2 && r1.y1==r2.y1 && r1.y2==r2.y2;
-}
-
-constexpr inline bool operator!=(const QRect &r1, const QRect &r2) noexcept
-{
- return r1.x1!=r2.x1 || r1.x2!=r2.x2 || r1.y1!=r2.y1 || r1.y2!=r2.y2;
-}
-
constexpr inline size_t qHash(const QRect &r, size_t seed = 0) noexcept
{
return qHashMulti(seed, r.x1, r.x2, r.y1, r.y2);
@@ -530,7 +519,7 @@ public:
constexpr inline bool isNull() const noexcept;
constexpr inline bool isEmpty() const noexcept;
constexpr inline bool isValid() const noexcept;
- Q_REQUIRED_RESULT QRectF normalized() const noexcept;
+ [[nodiscard]] QRectF normalized() const noexcept;
constexpr inline qreal left() const noexcept { return xp; }
constexpr inline qreal top() const noexcept { return yp; }
@@ -570,10 +559,10 @@ public:
constexpr inline void translate(qreal dx, qreal dy) noexcept;
constexpr inline void translate(const QPointF &p) noexcept;
- Q_REQUIRED_RESULT constexpr inline QRectF translated(qreal dx, qreal dy) const noexcept;
- Q_REQUIRED_RESULT constexpr inline QRectF translated(const QPointF &p) const noexcept;
+ [[nodiscard]] constexpr inline QRectF translated(qreal dx, qreal dy) const noexcept;
+ [[nodiscard]] constexpr inline QRectF translated(const QPointF &p) const noexcept;
- Q_REQUIRED_RESULT constexpr inline QRectF transposed() const noexcept;
+ [[nodiscard]] constexpr inline QRectF transposed() const noexcept;
constexpr inline void moveTo(qreal x, qreal y) noexcept;
constexpr inline void moveTo(const QPointF &p) noexcept;
@@ -585,7 +574,7 @@ public:
constexpr inline void getCoords(qreal *x1, qreal *y1, qreal *x2, qreal *y2) const;
constexpr inline void adjust(qreal x1, qreal y1, qreal x2, qreal y2) noexcept;
- Q_REQUIRED_RESULT constexpr inline QRectF adjusted(qreal x1, qreal y1, qreal x2, qreal y2) const noexcept;
+ [[nodiscard]] constexpr inline QRectF adjusted(qreal x1, qreal y1, qreal x2, qreal y2) const noexcept;
constexpr inline QSizeF size() const noexcept;
constexpr inline qreal width() const noexcept;
@@ -596,14 +585,14 @@ public:
QRectF operator|(const QRectF &r) const noexcept;
QRectF operator&(const QRectF &r) const noexcept;
- inline QRectF& operator|=(const QRectF &r) noexcept;
- inline QRectF& operator&=(const QRectF &r) noexcept;
+ inline QRectF &operator|=(const QRectF &r) noexcept;
+ inline QRectF &operator&=(const QRectF &r) noexcept;
bool contains(const QRectF &r) const noexcept;
bool contains(const QPointF &p) const noexcept;
inline bool contains(qreal x, qreal y) const noexcept;
- Q_REQUIRED_RESULT inline QRectF united(const QRectF &other) const noexcept;
- Q_REQUIRED_RESULT inline QRectF intersected(const QRectF &other) const noexcept;
+ [[nodiscard]] inline QRectF united(const QRectF &other) const noexcept;
+ [[nodiscard]] inline QRectF intersected(const QRectF &other) const noexcept;
bool intersects(const QRectF &r) const noexcept;
constexpr inline QRectF marginsAdded(const QMarginsF &margins) const noexcept;
@@ -611,15 +600,23 @@ public:
constexpr inline QRectF &operator+=(const QMarginsF &margins) noexcept;
constexpr inline QRectF &operator-=(const QMarginsF &margins) noexcept;
- friend constexpr inline bool operator==(const QRectF &, const QRectF &) noexcept;
- friend constexpr inline bool operator!=(const QRectF &, const QRectF &) noexcept;
+ friend constexpr inline bool operator==(const QRectF &r1, const QRectF &r2) noexcept
+ {
+ return r1.topLeft() == r2.topLeft()
+ && r1.size() == r2.size();
+ }
+ friend constexpr inline bool operator!=(const QRectF &r1, const QRectF &r2) noexcept
+ {
+ return r1.topLeft() != r2.topLeft()
+ || r1.size() != r2.size();
+ }
- Q_REQUIRED_RESULT constexpr inline QRect toRect() const noexcept;
- Q_REQUIRED_RESULT QRect toAlignedRect() const noexcept;
+ [[nodiscard]] constexpr inline QRect toRect() const noexcept;
+ [[nodiscard]] QRect toAlignedRect() const noexcept;
#if defined(Q_OS_DARWIN) || defined(Q_QDOC)
- Q_REQUIRED_RESULT static QRectF fromCGRect(CGRect rect) noexcept;
- Q_REQUIRED_RESULT CGRect toCGRect() const noexcept;
+ [[nodiscard]] static QRectF fromCGRect(CGRect rect) noexcept;
+ [[nodiscard]] CGRect toCGRect() const noexcept;
#endif
private:
@@ -630,9 +627,6 @@ private:
};
Q_DECLARE_TYPEINFO(QRectF, Q_MOVABLE_TYPE);
-constexpr inline bool operator==(const QRectF &, const QRectF &) noexcept;
-constexpr inline bool operator!=(const QRectF &, const QRectF &) noexcept;
-
/*****************************************************************************
QRectF stream functions
@@ -838,13 +832,13 @@ inline bool QRectF::contains(qreal ax, qreal ay) const noexcept
return contains(QPointF(ax, ay));
}
-inline QRectF& QRectF::operator|=(const QRectF &r) noexcept
+inline QRectF &QRectF::operator|=(const QRectF &r) noexcept
{
*this = *this | r;
return *this;
}
-inline QRectF& QRectF::operator&=(const QRectF &r) noexcept
+inline QRectF &QRectF::operator&=(const QRectF &r) noexcept
{
*this = *this & r;
return *this;
@@ -860,21 +854,16 @@ inline QRectF QRectF::united(const QRectF &r) const noexcept
return *this | r;
}
-constexpr inline bool operator==(const QRectF &r1, const QRectF &r2) noexcept
-{
- return qFuzzyCompare(r1.xp, r2.xp) && qFuzzyCompare(r1.yp, r2.yp)
- && qFuzzyCompare(r1.w, r2.w) && qFuzzyCompare(r1.h, r2.h);
-}
-
-constexpr inline bool operator!=(const QRectF &r1, const QRectF &r2) noexcept
-{
- return !qFuzzyCompare(r1.xp, r2.xp) || !qFuzzyCompare(r1.yp, r2.yp)
- || !qFuzzyCompare(r1.w, r2.w) || !qFuzzyCompare(r1.h, r2.h);
-}
-
constexpr inline QRect QRectF::toRect() const noexcept
{
- return QRect(QPoint(qRound(xp), qRound(yp)), QPoint(qRound(xp + w) - 1, qRound(yp + h) - 1));
+ // This rounding is designed to minimize the maximum possible difference
+ // in topLeft(), bottomRight(), and size() after rounding.
+ // All dimensions are at most off by 0.75, and topLeft by at most 0.5.
+ const int nxp = qRound(xp);
+ const int nyp = qRound(yp);
+ const int nw = qRound(w + (xp - nxp) / 2);
+ const int nh = qRound(h + (yp - nyp) / 2);
+ return QRect(nxp, nyp, nw, nh);
}
constexpr inline QRectF operator+(const QRectF &lhs, const QMarginsF &rhs) noexcept
diff --git a/src/corelib/tools/qringbuffer_p.h b/src/corelib/tools/qringbuffer_p.h
index 85a3882a3c..2cd6dd0756 100644
--- a/src/corelib/tools/qringbuffer_p.h
+++ b/src/corelib/tools/qringbuffer_p.h
@@ -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
{
diff --git a/src/corelib/tools/qscopedpointer.cpp b/src/corelib/tools/qscopedpointer.cpp
index eb08bdba62..1dd77a22dc 100644
--- a/src/corelib/tools/qscopedpointer.cpp
+++ b/src/corelib/tools/qscopedpointer.cpp
@@ -126,7 +126,7 @@ QT_BEGIN_NAMESPACE
*/
/*!
- \fn template <typename T, typename Cleanup> QScopedPointer<T, Cleanup>::QScopedPointer(T *p = 0)
+ \fn template <typename T, typename Cleanup> QScopedPointer<T, Cleanup>::QScopedPointer(T *p = nullptr)
Constructs this QScopedPointer instance and sets its pointer to \a p.
*/
@@ -183,21 +183,20 @@ QT_BEGIN_NAMESPACE
*/
/*!
- \fn template <typename T, typename Cleanup> bool operator==(const QScopedPointer<T, Cleanup> &lhs, const QScopedPointer<T, Cleanup> &rhs)
+ \fn template <typename T, typename Cleanup> bool QScopedPointer<T, Cleanup>::operator==(const QScopedPointer<T, Cleanup> &lhs, const QScopedPointer<T, Cleanup> &rhs)
- Returns \c true if \a ptr1 and \a ptr2 refer to the same pointer.
+ Returns \c true if \a lhs and \a rhs refer to the same pointer.
*/
/*!
- \fn template <typename T, typename Cleanup> bool operator!=(const QScopedPointer<T, Cleanup> &lhs, const QScopedPointer<T, Cleanup> &rhs)
+ \fn template <typename T, typename Cleanup> bool QScopedPointer<T, Cleanup>::operator!=(const QScopedPointer<T, Cleanup> &lhs, const QScopedPointer<T, Cleanup> &rhs)
Returns \c true if \a lhs and \a rhs refer to distinct pointers.
*/
/*!
- \fn template <typename T, typename Cleanup> bool operator==(const QScopedPointer<T, Cleanup> &lhs, std::nullptr_t)
- \relates QScopedPointer
+ \fn template <typename T, typename Cleanup> bool QScopedPointer<T, Cleanup>::operator==(const QScopedPointer<T, Cleanup> &lhs, std::nullptr_t)
\since 5.8
Returns \c true if \a lhs refers to \nullptr.
@@ -206,8 +205,7 @@ QT_BEGIN_NAMESPACE
*/
/*!
- \fn template <typename T, typename Cleanup> bool operator==(std::nullptr_t, const QScopedPointer<T, Cleanup> &rhs)
- \relates QScopedPointer
+ \fn template <typename T, typename Cleanup> bool QScopedPointer<T, Cleanup>::operator==(std::nullptr_t, const QScopedPointer<T, Cleanup> &rhs)
\since 5.8
Returns \c true if \a rhs refers to \nullptr.
@@ -216,8 +214,7 @@ QT_BEGIN_NAMESPACE
*/
/*!
- \fn template <typename T, typename Cleanup> bool operator!=(const QScopedPointer<T, Cleanup> &lhs, std::nullptr_t)
- \relates QScopedPointer
+ \fn template <typename T, typename Cleanup> bool QScopedPointer<T, Cleanup>::operator!=(const QScopedPointer<T, Cleanup> &lhs, std::nullptr_t)
\since 5.8
Returns \c true if \a lhs refers to a valid (i.e. non-null) pointer.
@@ -226,8 +223,7 @@ QT_BEGIN_NAMESPACE
*/
/*!
- \fn template <typename T, typename Cleanup> bool operator!=(std::nullptr_t, const QScopedPointer<T, Cleanup> &rhs)
- \relates QScopedPointer
+ \fn template <typename T, typename Cleanup> bool QScopedPointer<T, Cleanup>::operator!=(std::nullptr_t, const QScopedPointer<T, Cleanup> &rhs)
\since 5.8
Returns \c true if \a rhs refers to a valid (i.e. non-null) pointer.
@@ -242,7 +238,7 @@ QT_BEGIN_NAMESPACE
*/
/*!
- \fn template <typename T, typename Cleanup> void QScopedPointer<T, Cleanup>::reset(T *other = 0)
+ \fn template <typename T, typename Cleanup> void QScopedPointer<T, Cleanup>::reset(T *other = nullptr)
Deletes the existing object it is pointing to (if any), and sets its pointer to
\a other. QScopedPointer now owns \a other and will delete it in its
@@ -255,6 +251,8 @@ QT_BEGIN_NAMESPACE
/*!
\fn template <typename T, typename Cleanup> T *QScopedPointer<T, Cleanup>::take()
+ \obsolete Use std::unique_ptr and release() instead.
+
Returns the value of the pointer referenced by this object. The pointer of this
QScopedPointer object will be reset to \nullptr.
@@ -268,8 +266,8 @@ QT_BEGIN_NAMESPACE
\sa isNull()
*/
-/*! \fn template <typename T, typename Cleanup> void QScopedPointer<T, Cleanup>::swap(QScopedPointer<T, Cleanup> &other)
- Swap this pointer with \a other.
+/*! \fn template <typename T, typename Cleanup> void QScopedPointer<T, Cleanup>::swap(QScopedPointer<T, Cleanup> &lhs, QScopedPointer<T, Cleanup> &rhs)
+ Swaps \a lhs with \a rhs.
*/
/*!
diff --git a/src/corelib/tools/qscopedpointer.h b/src/corelib/tools/qscopedpointer.h
index 4acec9c1f6..a4c57aab8a 100644
--- a/src/corelib/tools/qscopedpointer.h
+++ b/src/corelib/tools/qscopedpointer.h
@@ -49,7 +49,7 @@ QT_BEGIN_NAMESPACE
template <typename T>
struct QScopedPointerDeleter
{
- static inline void cleanup(T *pointer)
+ static inline void cleanup(T *pointer) noexcept
{
// Enforce a complete type.
// If you get a compile error here, read the section on forward declared
@@ -59,12 +59,16 @@ struct QScopedPointerDeleter
delete pointer;
}
+ void operator()(T *pointer) const noexcept
+ {
+ cleanup(pointer);
+ }
};
template <typename T>
struct QScopedPointerArrayDeleter
{
- static inline void cleanup(T *pointer)
+ static inline void cleanup(T *pointer) noexcept
{
// Enforce a complete type.
// If you get a compile error here, read the section on forward declared
@@ -72,13 +76,18 @@ struct QScopedPointerArrayDeleter
typedef char IsIncompleteType[ sizeof(T) ? 1 : -1 ];
(void) sizeof(IsIncompleteType);
- delete [] pointer;
+ delete[] pointer;
+ }
+ void operator()(T *pointer) const noexcept
+ {
+ cleanup(pointer);
}
};
struct QScopedPointerPodDeleter
{
- static inline void cleanup(void *pointer) { if (pointer) free(pointer); }
+ static inline void cleanup(void *pointer) noexcept { free(pointer); }
+ void operator()(void *pointer) const noexcept { cleanup(pointer); }
};
#ifndef QT_NO_QOBJECT
@@ -86,6 +95,7 @@ template <typename T>
struct QScopedPointerObjectDeleteLater
{
static inline void cleanup(T *pointer) { if (pointer) pointer->deleteLater(); }
+ void operator()(T *pointer) const { cleanup(pointer); }
};
class QObject;
@@ -146,17 +156,18 @@ public:
{
if (d == other)
return;
- T *oldD = d;
- d = other;
+ T *oldD = qExchange(d, other);
Cleanup::cleanup(oldD);
}
+#if QT_DEPRECATED_SINCE(6, 1)
+ QT_DEPRECATED_VERSION_X_6_1("Use std::unique_ptr instead, and call release().")
T *take() noexcept
{
- T *oldD = d;
- d = nullptr;
+ T *oldD = qExchange(d, nullptr);
return oldD;
}
+#endif
void swap(QScopedPointer<T, Cleanup> &other) noexcept
{
@@ -165,52 +176,45 @@ public:
typedef T *pointer;
-protected:
- T *d;
+ friend bool operator==(const QScopedPointer<T, Cleanup> &lhs, const QScopedPointer<T, Cleanup> &rhs) noexcept
+ {
+ return lhs.data() == rhs.data();
+ }
-private:
- Q_DISABLE_COPY(QScopedPointer)
-};
+ friend bool operator!=(const QScopedPointer<T, Cleanup> &lhs, const QScopedPointer<T, Cleanup> &rhs) noexcept
+ {
+ return lhs.data() != rhs.data();
+ }
-template <class T, class Cleanup>
-inline bool operator==(const QScopedPointer<T, Cleanup> &lhs, const QScopedPointer<T, Cleanup> &rhs) noexcept
-{
- return lhs.data() == rhs.data();
-}
+ friend bool operator==(const QScopedPointer<T, Cleanup> &lhs, std::nullptr_t) noexcept
+ {
+ return lhs.isNull();
+ }
-template <class T, class Cleanup>
-inline bool operator!=(const QScopedPointer<T, Cleanup> &lhs, const QScopedPointer<T, Cleanup> &rhs) noexcept
-{
- return lhs.data() != rhs.data();
-}
+ friend bool operator==(std::nullptr_t, const QScopedPointer<T, Cleanup> &rhs) noexcept
+ {
+ return rhs.isNull();
+ }
-template <class T, class Cleanup>
-inline bool operator==(const QScopedPointer<T, Cleanup> &lhs, std::nullptr_t) noexcept
-{
- return lhs.isNull();
-}
+ friend bool operator!=(const QScopedPointer<T, Cleanup> &lhs, std::nullptr_t) noexcept
+ {
+ return !lhs.isNull();
+ }
-template <class T, class Cleanup>
-inline bool operator==(std::nullptr_t, const QScopedPointer<T, Cleanup> &rhs) noexcept
-{
- return rhs.isNull();
-}
+ friend bool operator!=(std::nullptr_t, const QScopedPointer<T, Cleanup> &rhs) noexcept
+ {
+ return !rhs.isNull();
+ }
-template <class T, class Cleanup>
-inline bool operator!=(const QScopedPointer<T, Cleanup> &lhs, std::nullptr_t) noexcept
-{
- return !lhs.isNull();
-}
+ friend void swap(QScopedPointer<T, Cleanup> &p1, QScopedPointer<T, Cleanup> &p2) noexcept
+ { p1.swap(p2); }
-template <class T, class Cleanup>
-inline bool operator!=(std::nullptr_t, const QScopedPointer<T, Cleanup> &rhs) noexcept
-{
- return !rhs.isNull();
-}
+protected:
+ T *d;
-template <class T, class Cleanup>
-inline void swap(QScopedPointer<T, Cleanup> &p1, QScopedPointer<T, Cleanup> &p2) noexcept
-{ p1.swap(p2); }
+private:
+ Q_DISABLE_COPY(QScopedPointer)
+};
template <typename T, typename Cleanup = QScopedPointerArrayDeleter<T> >
class QScopedArrayPointer : public QScopedPointer<T, Cleanup>
@@ -240,7 +244,8 @@ public:
{ QScopedPointer<T, Cleanup>::swap(other); }
private:
- explicit inline QScopedArrayPointer(void *) {
+ explicit inline QScopedArrayPointer(void *)
+ {
// Enforce the same type.
// If you get a compile error here, make sure you declare
diff --git a/src/corelib/tools/qscopedpointer_p.h b/src/corelib/tools/qscopedpointer_p.h
deleted file mode 100644
index c1c44e7695..0000000000
--- a/src/corelib/tools/qscopedpointer_p.h
+++ /dev/null
@@ -1,148 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists for the convenience
-// of internal files. This header file may change from version to version
-// without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include <QtCore/private/qglobal_p.h>
-
-#ifndef QSCOPEDPOINTER_P_H
-#define QSCOPEDPOINTER_P_H
-
-#include "QtCore/qscopedpointer.h"
-
-QT_BEGIN_NAMESPACE
-
-
-/* Internal helper class - exposes the data through data_ptr (legacy from QShared).
- Required for some internal Qt classes, do not use otherwise. */
-template <typename T, typename Cleanup = QScopedPointerDeleter<T> >
-class QCustomScopedPointer : public QScopedPointer<T, Cleanup>
-{
-public:
- explicit inline QCustomScopedPointer(T *p = 0)
- : QScopedPointer<T, Cleanup>(p)
- {
- }
-
- inline T *&data_ptr()
- {
- return this->d;
- }
-
- inline bool operator==(const QCustomScopedPointer<T, Cleanup> &other) const
- {
- return this->d == other.d;
- }
-
- inline bool operator!=(const QCustomScopedPointer<T, Cleanup> &other) const
- {
- return this->d != other.d;
- }
-
-private:
- Q_DISABLE_COPY(QCustomScopedPointer)
-};
-
-/* Internal helper class - a handler for QShared* classes, to be used in QCustomScopedPointer */
-template <typename T>
-class QScopedPointerSharedDeleter
-{
-public:
- static inline void cleanup(T *d)
- {
- if (d && !d->ref.deref())
- delete d;
- }
-};
-
-/* Internal.
- This class is basically a scoped pointer pointing to a ref-counted object
- */
-template <typename T>
-class QScopedSharedPointer : public QCustomScopedPointer<T, QScopedPointerSharedDeleter<T> >
-{
-public:
- explicit inline QScopedSharedPointer(T *p = 0)
- : QCustomScopedPointer<T, QScopedPointerSharedDeleter<T> >(p)
- {
- }
-
- inline void detach()
- {
- qAtomicDetach(this->d);
- }
-
- inline void assign(T *other)
- {
- if (this->d == other)
- return;
- if (other)
- other->ref.ref();
- T *oldD = this->d;
- this->d = other;
- QScopedPointerSharedDeleter<T>::cleanup(oldD);
- }
-
- inline bool operator==(const QScopedSharedPointer<T> &other) const
- {
- return this->d == other.d;
- }
-
- inline bool operator!=(const QScopedSharedPointer<T> &other) const
- {
- return this->d != other.d;
- }
-
-private:
- Q_DISABLE_COPY(QScopedSharedPointer)
-};
-
-
-QT_END_NAMESPACE
-
-#endif
diff --git a/src/corelib/tools/qscopedvaluerollback.h b/src/corelib/tools/qscopedvaluerollback.h
index b8ceff6665..9b14308ec2 100644
--- a/src/corelib/tools/qscopedvaluerollback.h
+++ b/src/corelib/tools/qscopedvaluerollback.h
@@ -45,30 +45,28 @@
QT_BEGIN_NAMESPACE
template <typename T>
-class
-#if QT_HAS_CPP_ATTRIBUTE(nodiscard) && __cplusplus >= 201703L
-[[nodiscard]]
-#endif
-QScopedValueRollback
+class [[nodiscard]] QScopedValueRollback
{
public:
- explicit QScopedValueRollback(T &var)
+ explicit constexpr QScopedValueRollback(T &var)
: varRef(var), oldValue(var)
{
}
- explicit QScopedValueRollback(T &var, T value)
- : varRef(var), oldValue(std::move(var))
+ explicit constexpr QScopedValueRollback(T &var, T value)
+ : varRef(var), oldValue(qExchange(var, std::move(value)))
{
- varRef = std::move(value);
}
+#if __cpp_constexpr >= 201907L
+ constexpr
+#endif
~QScopedValueRollback()
{
varRef = std::move(oldValue);
}
- void commit()
+ constexpr void commit()
{
oldValue = varRef;
}
diff --git a/src/corelib/tools/qscopeguard.h b/src/corelib/tools/qscopeguard.h
index d288fd63fc..8270f41a2e 100644
--- a/src/corelib/tools/qscopeguard.h
+++ b/src/corelib/tools/qscopeguard.h
@@ -49,13 +49,7 @@
QT_BEGIN_NAMESPACE
template <typename F>
-class
-#if __has_cpp_attribute(nodiscard)
-// Q_REQUIRED_RESULT can be defined as __warn_unused_result__ or as [[nodiscard]]
-// but the 1st one has some limitations for example can be placed only on functions.
-Q_REQUIRED_RESULT
-#endif
-QScopeGuard
+class [[nodiscard]] QScopeGuard
{
public:
explicit QScopeGuard(F &&f) noexcept
@@ -98,10 +92,7 @@ template <typename F> QScopeGuard(F(&)()) -> QScopeGuard<F(*)()>;
//! [qScopeGuard]
template <typename F>
-#if __has_cpp_attribute(nodiscard)
-Q_REQUIRED_RESULT
-#endif
-QScopeGuard<typename std::decay<F>::type> qScopeGuard(F &&f)
+[[nodiscard]] QScopeGuard<typename std::decay<F>::type> qScopeGuard(F &&f)
{
return QScopeGuard<typename std::decay<F>::type>(std::forward<F>(f));
}
diff --git a/src/corelib/tools/qset.h b/src/corelib/tools/qset.h
index 5f1500e747..a3e541ea5e 100644
--- a/src/corelib/tools/qset.h
+++ b/src/corelib/tools/qset.h
@@ -198,6 +198,9 @@ public:
typedef qsizetype size_type;
inline bool empty() const { return isEmpty(); }
+
+ iterator insert(const_iterator, const T &value) { return insert(value); }
+
// comfort
inline QSet<T> &operator<<(const T &value) { insert(value); return *this; }
inline QSet<T> &operator|=(const QSet<T> &other) { unite(other); return *this; }
diff --git a/src/corelib/tools/qset.qdoc b/src/corelib/tools/qset.qdoc
index b6aae2c7ca..4f26d1678c 100644
--- a/src/corelib/tools/qset.qdoc
+++ b/src/corelib/tools/qset.qdoc
@@ -185,7 +185,7 @@
\sa reserve(), squeeze()
*/
-/*! \fn template <class T> void QSet<T>::reserve(int size)
+/*! \fn template <class T> void QSet<T>::reserve(qsizetype size)
Ensures that the set's internal hash table consists of at
least \a size buckets.
@@ -278,12 +278,6 @@
\sa remove(), find()
*/
-/*!
- \fn template <class T> QSet<T>::iterator QSet<T>::erase(iterator pos)
- \since 4.2
- \overload
-*/
-
/*! \fn template <class T> QSet<T>::const_iterator QSet<T>::find(const T &value) const
\since 4.2
@@ -398,58 +392,6 @@
\sa constBegin(), end()
*/
-/*! \fn template <class T> QSet<T>::reverse_iterator QSet<T>::rbegin()
- \obsolete Deprecated in order to align with std::unordered_set functionality.
- \since 5.6
-
- Returns a \l{STL-style iterators}{STL-style} reverse iterator pointing to the first
- item in the set, in reverse order.
-
- \sa begin(), crbegin(), rend()
-*/
-
-/*! \fn template <class T> QSet<T>::const_reverse_iterator QSet<T>::rbegin() const
- \obsolete Deprecated in order to align with std::unordered_set functionality.
- \since 5.6
- \overload
-*/
-
-/*! \fn template <class T> QSet<T>::const_reverse_iterator QSet<T>::crbegin() const
- \obsolete Deprecated in order to align with std::unordered_set functionality.
- \since 5.6
-
- Returns a const \l{STL-style iterators}{STL-style} reverse iterator pointing to the first
- item in the set, in reverse order.
-
- \sa begin(), rbegin(), rend()
-*/
-
-/*! \fn template <class T> QSet<T>::reverse_iterator QSet<T>::rend()
- \obsolete Deprecated in order to align with std::unordered_set functionality.
- \since 5.6
-
- Returns a \l{STL-style iterators}{STL-style} reverse iterator pointing to one past
- the last item in the set, in reverse order.
-
- \sa end(), crend(), rbegin()
-*/
-
-/*! \fn template <class T> QSet<T>::const_reverse_iterator QSet<T>::rend() const
- \obsolete Deprecated in order to align with std::unordered_set functionality.
- \since 5.6
- \overload
-*/
-
-/*! \fn template <class T> QSet<T>::const_reverse_iterator QSet<T>::crend() const
- \obsolete Deprecated in order to align with std::unordered_set functionality.
- \since 5.6
-
- Returns a const \l{STL-style iterators}{STL-style} reverse iterator pointing to one
- past the last item in the set, in reverse order.
-
- \sa end(), rend(), rbegin()
-*/
-
/*!
\typedef QSet::Iterator
\since 4.2
@@ -511,40 +453,6 @@
Typedef for T. Provided for STL compatibility.
*/
-/*! \typedef QSet::reverse_iterator
- \since 5.6
- \obsolete Deprecated in order to align with std::unordered_set functionality.
-
- The QSet::reverse_iterator typedef provides an STL-style non-const
- reverse iterator for QSet.
-
- It is simply a typedef for \c{std::reverse_iterator<QSet::iterator>}.
-
- \warning Iterators on implicitly shared containers do not work
- exactly like STL-iterators. You should avoid copying a container
- while iterators are active on that container. For more information,
- read \l{Implicit sharing iterator problem}.
-
- \sa QSet::rbegin(), QSet::rend(), QSet::const_reverse_iterator, QSet::iterator
-*/
-
-/*! \typedef QSet::const_reverse_iterator
- \since 5.6
- \obsolete Deprecated in order to align with std::unordered_set functionality.
-
- The QSet::const_reverse_iterator typedef provides an STL-style const
- reverse iterator for QSet.
-
- It is simply a typedef for \c{std::reverse_iterator<QSet::const_iterator>}.
-
- \warning Iterators on implicitly shared containers do not work
- exactly like STL-iterators. You should avoid copying a container
- while iterators are active on that container. For more information,
- read \l{Implicit sharing iterator problem}.
-
- \sa QSet::rbegin(), QSet::rend(), QSet::reverse_iterator, QSet::const_iterator
-*/
-
/*!
\fn template <class T> QSet<T>::insert(const T &value)
@@ -600,6 +508,22 @@
*/
/*!
+ \fn QSet::insert(const_iterator it, const T &value)
+ \overload
+ \since 6.1
+
+ Inserts item \a value into the set, if \a value isn't already
+ in the set, and returns an iterator pointing at the inserted
+ item.
+
+ The iterator \a it is ignored.
+
+ This function is provided for compatibility with the STL.
+
+ \sa operator<<(), remove(), contains()
+*/
+
+/*!
\fn template <class T> bool QSet<T>::count() const
Same as size().
@@ -927,196 +851,19 @@
current item.
*/
-/*!
- \fn template <class T> QSet<T>::iterator &QSet<T>::iterator::operator--()
- \obsolete This operator is deprecated in order to align with std::unordered_set functionality.
-
- The prefix -- operator (\c{--it}) makes the preceding item
- current and returns an iterator to the new current item.
-
- Calling this function on QSet::begin() leads to undefined
- results.
-
- \sa operator++()
-*/
-
-/*!
- \fn template <class T> QSet<T>::const_iterator &QSet<T>::const_iterator::operator--()
- \obsolete This operator is deprecated in order to align with std::unordered_set functionality.
-
- The prefix -- operator (\c{--it}) makes the preceding item
- current and returns an iterator to the new current item.
-
- Calling this function on QSet::begin() leads to undefined
- results.
-
- \sa operator++()
-*/
-
-/*!
- \fn template <class T> QSet<T>::iterator QSet<T>::iterator::operator--(int)
- \obsolete This operator is deprecated in order to align with std::unordered_set functionality.
-
- \overload
-
- The postfix -- operator (\c{it--}) makes the preceding item
- current and returns an iterator to the previously current item.
-*/
-
-/*!
- \fn template <class T> QSet<T>::const_iterator QSet<T>::const_iterator::operator--(int)
- \obsolete This operator is deprecated in order to align with std::unordered_set functionality.
-
- \overload
-
- The postfix -- operator (\c{it--}) makes the preceding item
- current and returns an iterator to the previously current item.
-*/
-
-/*!
- \fn template <class T> QSet<T>::iterator QSet<T>::iterator::operator+(int j) const
- \obsolete This operator is deprecated in order to align with std::unordered_set functionality.
-
- Returns an iterator to the item at \a j positions forward from
- this iterator. (If \a j is negative, the iterator goes backward.)
-
- This operation can be slow for large \a j values.
-
- \sa operator-()
-*/
-
-/*!
- \fn template <class T> QSet<T>::const_iterator QSet<T>::const_iterator::operator+(int j) const
- \obsolete This operator is deprecated in order to align with std::unordered_set functionality.
-
- Returns an iterator to the item at \a j positions forward from
- this iterator. (If \a j is negative, the iterator goes backward.)
-
- This operation can be slow for large \a j values.
-
- \sa operator-()
-*/
-
-/*!
- \fn template <class T> QSet<T>::iterator QSet<T>::iterator::operator-(int j) const
- \obsolete This operator is deprecated in order to align with std::unordered_set functionality.
-
- Returns an iterator to the item at \a j positions backward from
- this iterator. (If \a j is negative, the iterator goes forward.)
-
- This operation can be slow for large \a j values.
-
- \sa operator+()
-*/
-
-/*!
- \fn template <class T> QSet<T>::const_iterator QSet<T>::const_iterator::operator-(int j) const
- \obsolete This operator is deprecated in order to align with std::unordered_set functionality.
-
- Returns an iterator to the item at \a j positions backward from
- this iterator. (If \a j is negative, the iterator goes forward.)
-
- This operation can be slow for large \a j values.
-
- \sa operator+()
-*/
-
-/*!
- \fn template <class T> QSet<T>::iterator &QSet<T>::iterator::operator+=(int j)
- \obsolete This operator is deprecated in order to align with std::unordered_set functionality.
-
- Advances the iterator by \a j items. (If \a j is negative, the
- iterator goes backward.)
-
- This operation can be slow for large \a j values.
-
- \sa operator-=(), operator+()
-
-*/
-
-/*!
- \fn template <class T> QSet<T>::const_iterator &QSet<T>::const_iterator::operator+=(int j)
- \obsolete This operator is deprecated in order to align with std::unordered_set functionality.
-
- Advances the iterator by \a j items. (If \a j is negative, the
- iterator goes backward.)
-
- This operation can be slow for large \a j values.
-
- \sa operator-=(), operator+()
-*/
-
-/*!
- \fn template <class T> QSet<T>::iterator &QSet<T>::iterator::operator-=(int j)
- \obsolete This operator is deprecated in order to align with std::unordered_set functionality.
-
- Makes the iterator go back by \a j items. (If \a j is negative,
- the iterator goes forward.)
-
- This operation can be slow for large \a j values.
-
- \sa operator+=(), operator-()
-*/
-
-/*!
- \fn template <class T> QSet<T>::const_iterator &QSet<T>::const_iterator::operator-=(int j)
- \obsolete This operator is deprecated in order to align with std::unordered_set functionality.
-
- Makes the iterator go back by \a j items. (If \a j is negative,
- the iterator goes forward.)
-
- This operation can be slow for large \a j values.
-
- \sa operator+=(), operator-()
-*/
-
-/*! \fn template <class T> QList<T> QSet<T>::toList() const
-
- Returns a new QList containing the elements in the set. The
- order of the elements in the QList is undefined.
-
- Example:
-
- \snippet code/doc_src_qset.cpp 13
-
- \include containers-range-constructor.qdocinc
-
- \sa fromList(), QList::fromSet()
-*/
-
/*! \fn template <class T> QList<T> QSet<T>::values() const
Returns a new QList containing the elements in the set. The
order of the elements in the QList is undefined.
- This is the same as toList().
-
\include containers-range-constructor.qdocinc
This function creates a new list, in \l {linear time}. The time and memory
use that entails can be avoided by iterating from \l constBegin() to
\l constEnd().
-
- \sa fromList(), QList::fromSet()
*/
-/*! \fn template <class T> QSet<T> QSet<T>::fromList(const QList<T> &list)
-
- Returns a new QSet object containing the data contained in \a
- list. Since QSet doesn't allow duplicates, the resulting QSet
- might be smaller than the \a list, because QList can contain
- duplicates.
-
- Example:
-
- \snippet code/doc_src_qset.cpp 14
-
- \include containers-range-constructor.qdocinc
-
- \sa toList(), QList::toSet()
-*/
-
/*!
\fn template <class T> QDataStream &operator<<(QDataStream &out, const QSet<T> &set)
\relates QSet
diff --git a/src/corelib/tools/qshareddata.cpp b/src/corelib/tools/qshareddata.cpp
index 187bfa7a5d..16c10a58ac 100644
--- a/src/corelib/tools/qshareddata.cpp
+++ b/src/corelib/tools/qshareddata.cpp
@@ -65,6 +65,20 @@ QT_BEGIN_NAMESPACE
*/
/*!
+ \class QAdoptSharedDataTag
+ \inmodule QtCore
+ \threadsafe
+ \brief The QAdoptSharedDataTag is a helper tag class.
+ \since 6.0
+
+ QAdoptSharedDataTag objects are used in QSharedDataPointer
+ and QExplicitlySharedDataPointer to adopt a pointer to
+ shared data.
+
+ See QSharedDataPointer and QExplicitlySharedDataPointer for details.
+*/
+
+/*!
\class QSharedDataPointer
\inmodule QtCore
\brief The QSharedDataPointer class represents a pointer to an implicitly shared object.
@@ -302,6 +316,18 @@ QT_BEGIN_NAMESPACE
Same as data(). This function is provided for STL compatibility.
*/
+/*! \fn template <class T> const T* QSharedDataPointer<T>::take()
+ \since 6.0
+
+ Returns a pointer to the shared object, and resets \e this to be \nullptr.
+ (That is, this function sets the \e{d pointer} of \e this to \nullptr.)
+
+ \note The reference count of the returned object will \b{not} be
+ decremented. This function can be used together with the
+ constructor that takes a QAdoptSharedDataTag tag object to transfer
+ the shared data object without intervening atomic operations.
+*/
+
/*! \fn template <class T> const T* QSharedDataPointer<T>::constData() const
Returns a const pointer to the shared data object.
This function does \e not call detach().
@@ -309,6 +335,15 @@ QT_BEGIN_NAMESPACE
\sa data()
*/
+/*! \fn template <class T> void QSharedDataPointer<T>::reset(T *ptr = nullptr)
+ \since 6.0
+
+ Sets the \e{d pointer} of \e this to \a ptr and increments \a{ptr}'s reference
+ count if \a ptr is not \nullptr.
+ The reference count of the old shared data object is decremented,
+ and the object deleted if the reference count reaches 0.
+ */
+
/*! \fn template <class T> void QSharedDataPointer<T>::swap(QSharedDataPointer &other)
Swap this instance's shared data pointer with the shared
data pointer in \a other.
@@ -322,13 +357,23 @@ QT_BEGIN_NAMESPACE
\since 5.2
*/
-/*! \fn template <class T> bool QSharedDataPointer<T>::operator==(const QSharedDataPointer<T>& other) const
- Returns \c true if \a other and \e this have the same \e{d pointer}.
+/*! \fn template <class T> bool QSharedDataPointer<T>::operator==(const QSharedDataPointer<T>& lhs, const QSharedDataPointer<T>& rhs)
+ Returns \c true if \a lhs and \a rhs have the same \e{d pointer}.
+ This function does \e not call detach().
+*/
+
+/*! \fn template <class T> bool QSharedDataPointer<T>::operator!=(const QSharedDataPointer<T>& lhs, const QSharedDataPointer<T>& rhs)
+ Returns \c true if \a lhs and \a rhs do \e not have the same
+ \e{d pointer}. This function does \e not call detach().
+*/
+
+/*! \fn template <class T> bool QSharedDataPointer<T>::operator==(const T *ptr, const QSharedDataPointer<T>& rhs)
+ Returns \c true if the \e{d pointer} of \a rhs is \a ptr.
This function does \e not call detach().
*/
-/*! \fn template <class T> bool QSharedDataPointer<T>::operator!=(const QSharedDataPointer<T>& other) const
- Returns \c true if \a other and \e this do \e not have the same
+/*! \fn template <class T> bool QSharedDataPointer<T>::operator!=(const T *ptr, const QSharedDataPointer<T>& rhs)
+ Returns \c true if the \e{d pointer} of \a rhs is \e not \a ptr.
\e{d pointer}. This function does \e not call detach().
*/
@@ -356,6 +401,15 @@ QT_BEGIN_NAMESPACE
\a data and increments \a{data}'s reference count.
*/
+/*! \fn template <class T> QSharedDataPointer<T>::QSharedDataPointer(T* data, QAdoptSharedDataTag)
+ \since 6.0
+ Constructs a QSharedDataPointer with \e{d pointer} set to
+ \a data. \a data's reference counter is \b{not} incremented;
+ this can be used to adopt pointers obtained from take().
+
+ \sa take()
+*/
+
/*! \fn template <class T> QSharedDataPointer<T>::QSharedDataPointer(const QSharedDataPointer<T>& o)
Sets the \e{d pointer} of \e this to the \e{d pointer} in
\a o and increments the reference count of the shared
@@ -486,8 +540,8 @@ QT_BEGIN_NAMESPACE
the explicitly shared data pointer in \a other.
*/
-/*! \fn template <class T> bool QExplicitlySharedDataPointer<T>::operator==(const QExplicitlySharedDataPointer<T>& other) const
- Returns \c true if \a other and \e this have the same \e{d pointer}.
+/*! \fn template <class T> bool QExplicitlySharedDataPointer<T>::operator==(const QExplicitlySharedDataPointer<T>& lhs, const QExplicitlySharedDataPointer<T>& rhs)
+ Returns \c true if \a lhs and \a rhs have the same \e{d pointer}.
*/
/*!
@@ -498,17 +552,17 @@ QT_BEGIN_NAMESPACE
\since 5.2
*/
-/*! \fn template <class T> bool QExplicitlySharedDataPointer<T>::operator==(const T* ptr) const
- Returns \c true if the \e{d pointer} of \e this is \a ptr.
+/*! \fn template <class T> bool QExplicitlySharedDataPointer<T>::operator==(const T* ptr, const QExplicitlySharedDataPointer<T>& rhs)
+ Returns \c true if the \e{d pointer} of \a rhs is \a ptr.
*/
-/*! \fn template <class T> bool QExplicitlySharedDataPointer<T>::operator!=(const QExplicitlySharedDataPointer<T>& other) const
- Returns \c true if \a other and \e this do \e not have the same
+/*! \fn template <class T> bool QExplicitlySharedDataPointer<T>::operator!=(const QExplicitlySharedDataPointer<T>& lhs, const QExplicitlySharedDataPointer<T>& rhs)
+ Returns \c true if \a lhs and \a rhs do \e not have the same
\e{d pointer}.
*/
-/*! \fn template <class T> bool QExplicitlySharedDataPointer<T>::operator!=(const T* ptr) const
- Returns \c true if the \e{d pointer} of \e this is \e not \a ptr.
+/*! \fn template <class T> bool QExplicitlySharedDataPointer<T>::operator!=(const T* ptr, const QExplicitlySharedDataPointer<T>& rhs)
+ Returns \c true if the \e{d pointer} of \a rhs is \e not \a ptr.
*/
/*! \fn template <class T> QExplicitlySharedDataPointer<T>::QExplicitlySharedDataPointer()
@@ -590,18 +644,25 @@ QT_BEGIN_NAMESPACE
0, the old shared data object is deleted.
*/
-/*! \fn template <class T> void QExplicitlySharedDataPointer<T>::reset()
- Resets \e this to be null - i.e., this function sets the
- \e{d pointer} of \e this to \nullptr, but first it decrements
- the reference count of the shared data object and deletes
- the shared data object if the reference count became 0.
+/*! \fn template <class T> void QExplicitlySharedDataPointer<T>::reset(T *ptr = nullptr)
+ \since 6.0
+
+ Sets the \e{d pointer} of \e this to \a ptr and increments \a{ptr}'s reference
+ count if \a ptr is not \nullptr.
+ The reference count of the old shared data object is decremented,
+ and the object deleted if the reference count reaches 0.
*/
/*! \fn template <class T> T *QExplicitlySharedDataPointer<T>::take()
\since 5.12
Returns a pointer to the shared object, and resets \e this to be \nullptr.
- That is, this function sets the \e{d pointer} of \e this to \nullptr.
+ (That is, this function sets the \e{d pointer} of \e this to \nullptr.)
+
+ \note The reference count of the returned object will \b{not} be
+ decremented. This function can be used together with the
+ constructor that takes a QAdoptSharedDataTag tag object to transfer
+ the shared data object without intervening atomic operations.
*/
/*! \fn template <class T> QExplicitlySharedDataPointer<T>::operator bool () const
diff --git a/src/corelib/tools/qshareddata.h b/src/corelib/tools/qshareddata.h
index 85078670e9..bda117739c 100644
--- a/src/corelib/tools/qshareddata.h
+++ b/src/corelib/tools/qshareddata.h
@@ -44,6 +44,8 @@
#include <QtCore/qatomic.h>
#include <QtCore/qhashfunctions.h>
+#include <functional>
+
QT_BEGIN_NAMESPACE
@@ -54,76 +56,97 @@ class QSharedData
public:
mutable QAtomicInt ref;
- inline QSharedData() noexcept : ref(0) { }
- inline QSharedData(const QSharedData &) noexcept : ref(0) { }
+ QSharedData() noexcept : ref(0) { }
+ QSharedData(const QSharedData &) noexcept : ref(0) { }
// using the assignment operator would lead to corruption in the ref-counting
QSharedData &operator=(const QSharedData &) = delete;
~QSharedData() = default;
};
-template <class T> class QSharedDataPointer
+struct QAdoptSharedDataTag { explicit constexpr QAdoptSharedDataTag() = default; };
+
+template <typename T>
+class QSharedDataPointer
{
public:
typedef T Type;
typedef T *pointer;
- inline void detach() { if (d && d->ref.loadRelaxed() != 1) detach_helper(); }
- inline T &operator*() { detach(); return *d; }
- inline const T &operator*() const { return *d; }
- inline T *operator->() { detach(); return d; }
- inline const T *operator->() const { return d; }
- inline operator T *() { detach(); return d; }
- inline operator const T *() const { return d; }
- inline T *data() { detach(); return d; }
- inline T *get() { detach(); return d; }
- inline const T *data() const { return d; }
- inline const T *get() const { return d; }
- inline const T *constData() const { return d; }
-
- inline bool operator==(const QSharedDataPointer<T> &other) const { return d == other.d; }
- inline bool operator!=(const QSharedDataPointer<T> &other) const { return d != other.d; }
-
- inline QSharedDataPointer() { d = nullptr; }
- inline ~QSharedDataPointer() { if (d && !d->ref.deref()) delete d; }
-
- explicit QSharedDataPointer(T *data) noexcept;
- inline QSharedDataPointer(const QSharedDataPointer<T> &o) : d(o.d) { if (d) d->ref.ref(); }
- inline QSharedDataPointer<T> & operator=(const QSharedDataPointer<T> &o) {
- if (o.d != d) {
- if (o.d)
- o.d->ref.ref();
- T *old = d;
- d = o.d;
+ void detach() { if (d && d->ref.loadRelaxed() != 1) detach_helper(); }
+ T &operator*() { detach(); return *d; }
+ const T &operator*() const { return *d; }
+ T *operator->() { detach(); return d; }
+ const T *operator->() const noexcept { return d; }
+ operator T *() { detach(); return d; }
+ operator const T *() const noexcept { return d; }
+ T *data() { detach(); return d; }
+ T *get() { detach(); return d; }
+ const T *data() const noexcept { return d; }
+ const T *get() const noexcept { return d; }
+ const T *constData() const noexcept { return d; }
+ T *take() noexcept { return qExchange(d, nullptr); }
+
+ QSharedDataPointer() noexcept : d(nullptr) { }
+ ~QSharedDataPointer() { if (d && !d->ref.deref()) delete d; }
+
+ explicit QSharedDataPointer(T *data) noexcept : d(data)
+ { if (d) d->ref.ref(); }
+ QSharedDataPointer(T *data, QAdoptSharedDataTag) noexcept : d(data)
+ {}
+ QSharedDataPointer(const QSharedDataPointer &o) noexcept : d(o.d)
+ { if (d) d->ref.ref(); }
+
+ void reset(T *ptr = nullptr) noexcept
+ {
+ if (ptr != d) {
+ if (ptr)
+ ptr->ref.ref();
+ T *old = qExchange(d, ptr);
if (old && !old->ref.deref())
delete old;
}
- return *this;
}
- inline QSharedDataPointer &operator=(T *o) {
- if (o != d) {
- if (o)
- o->ref.ref();
- T *old = d;
- d = o;
- if (old && !old->ref.deref())
- delete old;
- }
+
+ QSharedDataPointer &operator=(const QSharedDataPointer &o) noexcept
+ {
+ reset(o.d);
return *this;
}
- QSharedDataPointer(QSharedDataPointer &&o) noexcept : d(o.d) { o.d = nullptr; }
- inline QSharedDataPointer<T> &operator=(QSharedDataPointer<T> &&other) noexcept
+ inline QSharedDataPointer &operator=(T *o) noexcept
{
- QSharedDataPointer moved(std::move(other));
- swap(moved);
+ reset(o);
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; }
+ operator bool () const noexcept { return d != nullptr; }
+ bool operator!() const noexcept { return d == nullptr; }
- inline void swap(QSharedDataPointer &other) noexcept
+ void swap(QSharedDataPointer &other) noexcept
{ qSwap(d, other.d); }
+#define DECLARE_COMPARE_SET(T1, A1, T2, A2) \
+ friend bool operator<(T1, T2) noexcept \
+ { return std::less<T*>{}(A1, A2); } \
+ friend bool operator<=(T1, T2) noexcept \
+ { return !std::less<T*>{}(A2, A1); } \
+ friend bool operator>(T1, T2) noexcept \
+ { return std::less<T*>{}(A2, A1); } \
+ friend bool operator>=(T1, T2) noexcept \
+ { return !std::less<T*>{}(A1, A2); } \
+ friend bool operator==(T1, T2) noexcept \
+ { return A1 == A2; } \
+ friend bool operator!=(T1, T2) noexcept \
+ { return A1 != A2; } \
+
+ DECLARE_COMPARE_SET(const QSharedDataPointer &p1, p1.d, const QSharedDataPointer &p2, p2.d)
+ DECLARE_COMPARE_SET(const QSharedDataPointer &p1, p1.d, const T *ptr, ptr)
+ DECLARE_COMPARE_SET(const T *ptr, ptr, const QSharedDataPointer &p2, p2.d)
+ DECLARE_COMPARE_SET(const QSharedDataPointer &p1, p1.d, std::nullptr_t, nullptr)
+ DECLARE_COMPARE_SET(std::nullptr_t, nullptr, const QSharedDataPointer &p2, p2.d)
+
protected:
T *clone();
@@ -133,102 +156,82 @@ private:
T *d;
};
-template <class T> inline bool operator==(std::nullptr_t p1, const QSharedDataPointer<T> &p2)
-{
- Q_UNUSED(p1);
- return !p2;
-}
-
-template <class T> inline bool operator==(const QSharedDataPointer<T> &p1, std::nullptr_t p2)
-{
- Q_UNUSED(p2);
- return !p1;
-}
-
-template <class T> class QExplicitlySharedDataPointer
+template <typename T>
+class QExplicitlySharedDataPointer
{
public:
typedef T Type;
typedef T *pointer;
- inline T &operator*() const { return *d; }
- inline T *operator->() { return d; }
- inline T *operator->() const { return d; }
- inline T *data() const { return d; }
- inline T *get() const { return d; }
- inline const T *constData() const { return d; }
- inline T *take() { T *x = d; d = nullptr; return x; }
-
- inline void detach() { if (d && d->ref.loadRelaxed() != 1) detach_helper(); }
-
- inline void reset()
- {
- if(d && !d->ref.deref())
- delete d;
-
- d = nullptr;
- }
-
- inline operator bool () const { return d != nullptr; }
-
- inline bool operator==(const QExplicitlySharedDataPointer<T> &other) const { return d == other.d; }
- inline bool operator!=(const QExplicitlySharedDataPointer<T> &other) const { return d != other.d; }
- inline bool operator==(const T *ptr) const { return d == ptr; }
- inline bool operator!=(const T *ptr) const { return d != ptr; }
-
- inline QExplicitlySharedDataPointer() { d = nullptr; }
- inline ~QExplicitlySharedDataPointer() { if (d && !d->ref.deref()) delete d; }
-
- explicit QExplicitlySharedDataPointer(T *data) noexcept;
- inline QExplicitlySharedDataPointer(const QExplicitlySharedDataPointer<T> &o) : d(o.d) { if (d) d->ref.ref(); }
-
- template<class X>
- inline QExplicitlySharedDataPointer(const QExplicitlySharedDataPointer<X> &o)
+ T &operator*() const { return *d; }
+ T *operator->() noexcept { return d; }
+ T *operator->() const noexcept { return d; }
+ explicit operator T *() { return d; }
+ explicit operator const T *() const noexcept { return d; }
+ T *data() const noexcept { return d; }
+ T *get() const noexcept { return d; }
+ const T *constData() const noexcept { return d; }
+ T *take() noexcept { return qExchange(d, nullptr); }
+
+ void detach() { if (d && d->ref.loadRelaxed() != 1) detach_helper(); }
+
+ QExplicitlySharedDataPointer() noexcept : d(nullptr) { }
+ ~QExplicitlySharedDataPointer() { if (d && !d->ref.deref()) delete d; }
+
+ explicit QExplicitlySharedDataPointer(T *data) noexcept : d(data)
+ { if (d) d->ref.ref(); }
+ QExplicitlySharedDataPointer(T *data, QAdoptSharedDataTag) noexcept : d(data)
+ {}
+ QExplicitlySharedDataPointer(const QExplicitlySharedDataPointer &o) noexcept : d(o.d)
+ { if (d) d->ref.ref(); }
+
+ template<typename X>
+ QExplicitlySharedDataPointer(const QExplicitlySharedDataPointer<X> &o) noexcept
#ifdef QT_ENABLE_QEXPLICITLYSHAREDDATAPOINTER_STATICCAST
: d(static_cast<T *>(o.data()))
#else
: d(o.data())
#endif
- {
- if(d)
- d->ref.ref();
- }
+ { if (d) d->ref.ref(); }
- inline QExplicitlySharedDataPointer<T> & operator=(const QExplicitlySharedDataPointer<T> &o) {
- if (o.d != d) {
- if (o.d)
- o.d->ref.ref();
- T *old = d;
- d = o.d;
+ void reset(T *ptr = nullptr) noexcept
+ {
+ if (ptr != d) {
+ if (ptr)
+ ptr->ref.ref();
+ T *old = qExchange(d, ptr);
if (old && !old->ref.deref())
delete old;
}
- return *this;
}
- inline QExplicitlySharedDataPointer &operator=(T *o) {
- if (o != d) {
- if (o)
- o->ref.ref();
- T *old = d;
- d = o;
- if (old && !old->ref.deref())
- delete old;
- }
+
+ QExplicitlySharedDataPointer &operator=(const QExplicitlySharedDataPointer &o) noexcept
+ {
+ reset(o.d);
return *this;
}
- inline QExplicitlySharedDataPointer(QExplicitlySharedDataPointer &&o) noexcept : d(o.d) { o.d = nullptr; }
- inline QExplicitlySharedDataPointer<T> &operator=(QExplicitlySharedDataPointer<T> &&other) noexcept
+ QExplicitlySharedDataPointer &operator=(T *o) noexcept
{
- QExplicitlySharedDataPointer moved(std::move(other));
- swap(moved);
+ reset(o);
return *this;
}
+ 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; }
+ operator bool () const noexcept { return d != nullptr; }
+ bool operator!() const noexcept { return d == nullptr; }
- inline void swap(QExplicitlySharedDataPointer &other) noexcept
+ void swap(QExplicitlySharedDataPointer &other) noexcept
{ qSwap(d, other.d); }
+ DECLARE_COMPARE_SET(const QExplicitlySharedDataPointer &p1, p1.d, const QExplicitlySharedDataPointer &p2, p2.d)
+ DECLARE_COMPARE_SET(const QExplicitlySharedDataPointer &p1, p1.d, const T *ptr, ptr)
+ DECLARE_COMPARE_SET(const T *ptr, ptr, const QExplicitlySharedDataPointer &p2, p2.d)
+ DECLARE_COMPARE_SET(const QExplicitlySharedDataPointer &p1, p1.d, std::nullptr_t, nullptr)
+ DECLARE_COMPARE_SET(std::nullptr_t, nullptr, const QExplicitlySharedDataPointer &p2, p2.d)
+
+#undef DECLARE_COMPARE_SET
+
protected:
T *clone();
@@ -238,18 +241,14 @@ private:
T *d;
};
-template <class T>
-Q_INLINE_TEMPLATE QSharedDataPointer<T>::QSharedDataPointer(T *adata) noexcept
- : d(adata)
-{ if (d) d->ref.ref(); }
-
-template <class T>
+// Declared here and as Q_OUTOFLINE_TEMPLATE to work-around MSVC bug causing missing symbols at link time.
+template <typename T>
Q_INLINE_TEMPLATE T *QSharedDataPointer<T>::clone()
{
return new T(*d);
}
-template <class T>
+template <typename T>
Q_OUTOFLINE_TEMPLATE void QSharedDataPointer<T>::detach_helper()
{
T *x = clone();
@@ -259,13 +258,13 @@ Q_OUTOFLINE_TEMPLATE void QSharedDataPointer<T>::detach_helper()
d = x;
}
-template <class T>
+template <typename T>
Q_INLINE_TEMPLATE T *QExplicitlySharedDataPointer<T>::clone()
{
return new T(*d);
}
-template <class T>
+template <typename T>
Q_OUTOFLINE_TEMPLATE void QExplicitlySharedDataPointer<T>::detach_helper()
{
T *x = clone();
@@ -275,38 +274,21 @@ Q_OUTOFLINE_TEMPLATE void QExplicitlySharedDataPointer<T>::detach_helper()
d = x;
}
-template <class T>
-Q_INLINE_TEMPLATE QExplicitlySharedDataPointer<T>::QExplicitlySharedDataPointer(T *adata) noexcept
- : d(adata)
-{ if (d) d->ref.ref(); }
-
-template <class T> inline bool operator==(std::nullptr_t p1, const QExplicitlySharedDataPointer<T> &p2)
-{
- Q_UNUSED(p1);
- return !p2;
-}
-
-template <class T> inline bool operator==(const QExplicitlySharedDataPointer<T> &p1, std::nullptr_t p2)
-{
- Q_UNUSED(p2);
- return !p1;
-}
-
-template <class T>
-Q_INLINE_TEMPLATE void swap(QSharedDataPointer<T> &p1, QSharedDataPointer<T> &p2)
+template <typename T>
+void swap(QSharedDataPointer<T> &p1, QSharedDataPointer<T> &p2) noexcept
{ p1.swap(p2); }
-template <class T>
-Q_INLINE_TEMPLATE void swap(QExplicitlySharedDataPointer<T> &p1, QExplicitlySharedDataPointer<T> &p2)
+template <typename T>
+void swap(QExplicitlySharedDataPointer<T> &p1, QExplicitlySharedDataPointer<T> &p2) noexcept
{ p1.swap(p2); }
-template <class T>
-Q_INLINE_TEMPLATE size_t qHash(const QSharedDataPointer<T> &ptr, size_t seed = 0) noexcept
+template <typename T>
+size_t qHash(const QSharedDataPointer<T> &ptr, size_t seed = 0) noexcept
{
return qHash(ptr.data(), seed);
}
-template <class T>
-Q_INLINE_TEMPLATE size_t qHash(const QExplicitlySharedDataPointer<T> &ptr, size_t seed = 0) noexcept
+template <typename T>
+size_t qHash(const QExplicitlySharedDataPointer<T> &ptr, size_t seed = 0) noexcept
{
return qHash(ptr.data(), seed);
}
@@ -314,6 +296,32 @@ Q_INLINE_TEMPLATE size_t qHash(const QExplicitlySharedDataPointer<T> &ptr, size_
template<typename T> Q_DECLARE_TYPEINFO_BODY(QSharedDataPointer<T>, Q_MOVABLE_TYPE);
template<typename T> Q_DECLARE_TYPEINFO_BODY(QExplicitlySharedDataPointer<T>, Q_MOVABLE_TYPE);
+#define QT_DECLARE_QSDP_SPECIALIZATION_DTOR(Class) \
+ template<> QSharedDataPointer<Class>::~QSharedDataPointer();
+
+#define QT_DECLARE_QSDP_SPECIALIZATION_DTOR_WITH_EXPORT(Class, ExportMacro) \
+ template<> ExportMacro QSharedDataPointer<Class>::~QSharedDataPointer();
+
+#define QT_DEFINE_QSDP_SPECIALIZATION_DTOR(Class) \
+ template<> QSharedDataPointer<Class>::~QSharedDataPointer() \
+ { \
+ if (d && !d->ref.deref()) \
+ delete d; \
+ }
+
+#define QT_DECLARE_QESDP_SPECIALIZATION_DTOR(Class) \
+ template<> QExplicitlySharedDataPointer<Class>::~QExplicitlySharedDataPointer();
+
+#define QT_DECLARE_QESDP_SPECIALIZATION_DTOR_WITH_EXPORT(Class, ExportMacro) \
+ template<> ExportMacro QExplicitlySharedDataPointer<Class>::~QExplicitlySharedDataPointer();
+
+#define QT_DEFINE_QESDP_SPECIALIZATION_DTOR(Class) \
+ template<> QExplicitlySharedDataPointer<Class>::~QExplicitlySharedDataPointer() \
+ { \
+ if (d && !d->ref.deref()) \
+ delete d; \
+ }
+
QT_END_NAMESPACE
#endif // QSHAREDDATA_H
diff --git a/src/corelib/tools/qshareddata_impl.h b/src/corelib/tools/qshareddata_impl.h
index 0a218b0b4b..cf1c534cdf 100644
--- a/src/corelib/tools/qshareddata_impl.h
+++ b/src/corelib/tools/qshareddata_impl.h
@@ -46,6 +46,7 @@
#define QSHAREDDATA_IMPL_H
#include <QtCore/qglobal.h>
+#include <QtCore/qshareddata.h>
QT_BEGIN_NAMESPACE
@@ -66,6 +67,11 @@ public:
d->ref.ref();
}
+ QExplicitlySharedDataPointerV2(T *t, QAdoptSharedDataTag) noexcept
+ : d(t)
+ {
+ }
+
QExplicitlySharedDataPointerV2(const QExplicitlySharedDataPointerV2 &other) noexcept
: d(other.d)
{
@@ -120,6 +126,11 @@ public:
d->ref.ref();
}
+ constexpr T *take() noexcept
+ {
+ return qExchange(d, nullptr);
+ }
+
bool isShared() const noexcept
{
return d && d->ref.loadRelaxed() != 1;
diff --git a/src/corelib/tools/qsharedpointer.h b/src/corelib/tools/qsharedpointer.h
index 5d47369687..82eb80beff 100644
--- a/src/corelib/tools/qsharedpointer.h
+++ b/src/corelib/tools/qsharedpointer.h
@@ -66,7 +66,7 @@ public:
operator bool() const;
bool operator!() const;
T &operator*() const;
- T *operator ->() const;
+ T *operator->() const;
// constructors
QSharedPointer();
diff --git a/src/corelib/tools/qsharedpointer_impl.h b/src/corelib/tools/qsharedpointer_impl.h
index 30bccb66a4..53d9a34acb 100644
--- a/src/corelib/tools/qsharedpointer_impl.h
+++ b/src/corelib/tools/qsharedpointer_impl.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2019 The Qt Company Ltd.
+** Copyright (C) 2020 The Qt Company Ltd.
** Copyright (C) 2020 Intel Corporation.
** Copyright (C) 2019 Klarälvdalens Datakonsult AB.
** Contact: https://www.qt.io/licensing/
@@ -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
@@ -442,6 +437,27 @@ public:
return result;
}
+#define DECLARE_COMPARE_SET(T1, A1, T2, A2) \
+ friend bool operator==(T1, T2) noexcept \
+ { return A1 == A2; } \
+ friend bool operator!=(T1, T2) noexcept \
+ { return A1 != A2; }
+
+#define DECLARE_TEMPLATE_COMPARE_SET(T1, A1, T2, A2) \
+ template <typename X> \
+ friend bool operator==(T1, T2) noexcept \
+ { return A1 == A2; } \
+ template <typename X> \
+ friend bool operator!=(T1, T2) noexcept \
+ { return A1 != A2; }
+
+ DECLARE_TEMPLATE_COMPARE_SET(const QSharedPointer &p1, p1.data(), const QSharedPointer<X> &p2, p2.data())
+ DECLARE_TEMPLATE_COMPARE_SET(const QSharedPointer &p1, p1.data(), X *ptr, ptr)
+ DECLARE_TEMPLATE_COMPARE_SET(X *ptr, ptr, const QSharedPointer &p2, p2.data())
+ DECLARE_COMPARE_SET(const QSharedPointer &p1, p1.data(), std::nullptr_t, nullptr)
+ DECLARE_COMPARE_SET(std::nullptr_t, nullptr, const QSharedPointer &p2, p2.data())
+#undef DECLARE_TEMPLATE_COMPARE_SET
+
private:
explicit QSharedPointer(Qt::Initialization) {}
@@ -563,8 +579,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);
@@ -599,14 +614,6 @@ public:
return *this;
}
- template <class X>
- bool operator==(const QWeakPointer<X> &o) const noexcept
- { return d == o.d && value == static_cast<const T *>(o.value); }
-
- template <class X>
- bool operator!=(const QWeakPointer<X> &o) const noexcept
- { return !(*this == o); }
-
template <class X, IfCompatible<X> = true>
inline QWeakPointer(const QSharedPointer<X> &o) : d(nullptr), value(nullptr)
{ *this = o; }
@@ -618,14 +625,6 @@ public:
return *this;
}
- template <class X>
- bool operator==(const QSharedPointer<X> &o) const noexcept
- { return d == o.d; }
-
- template <class X>
- bool operator!=(const QSharedPointer<X> &o) const noexcept
- { return !(*this == o); }
-
inline void clear() { *this = QWeakPointer(); }
inline QSharedPointer<T> toStrongRef() const { return QSharedPointer<T>(*this); }
@@ -636,6 +635,33 @@ public:
inline T *operator->() const { return data(); }
#endif
+ template <class X>
+ bool operator==(const QWeakPointer<X> &o) const noexcept
+ { return d == o.d && value == static_cast<const T *>(o.value); }
+
+ template <class X>
+ bool operator!=(const QWeakPointer<X> &o) const noexcept
+ { return !(*this == o); }
+
+ template <class X>
+ bool operator==(const QSharedPointer<X> &o) const noexcept
+ { return d == o.d; }
+
+ template <class X>
+ bool operator!=(const QSharedPointer<X> &o) const noexcept
+ { return !(*this == o); }
+
+ template <typename X>
+ friend bool operator==(const QSharedPointer<X> &p1, const QWeakPointer &p2) noexcept
+ { return p2 == p1; }
+ template <typename X>
+ friend bool operator!=(const QSharedPointer<X> &p1, const QWeakPointer &p2) noexcept
+ { return p2 != p1; }
+
+ DECLARE_COMPARE_SET(const QWeakPointer &p1, p1.d, std::nullptr_t, nullptr)
+ DECLARE_COMPARE_SET(std::nullptr_t, nullptr, const QWeakPointer &p2, p2.data())
+#undef DECLARE_COMPARE_SET
+
private:
friend struct QtPrivate::EnableInternalData;
#if defined(Q_NO_TEMPLATE_FRIENDS)
@@ -666,8 +692,8 @@ public:
value = actual;
}
- // ### Qt 6: remove users of this API; no one should ever access
- // a weak pointer's data but the weak pointer itself
+ // ### TODO - QTBUG-88102: remove all users of this API; no one should ever
+ // access a weak pointer's data but the weak pointer itself
inline T *internalData() const noexcept
{
return d == nullptr || d->strongref.loadRelaxed() == 0 ? nullptr : value;
@@ -716,100 +742,6 @@ public:
};
//
-// operator== and operator!=
-//
-template <class T, class X>
-bool operator==(const QSharedPointer<T> &ptr1, const QSharedPointer<X> &ptr2) noexcept
-{
- return ptr1.data() == ptr2.data();
-}
-template <class T, class X>
-bool operator!=(const QSharedPointer<T> &ptr1, const QSharedPointer<X> &ptr2) noexcept
-{
- return ptr1.data() != ptr2.data();
-}
-
-template <class T, class X>
-bool operator==(const QSharedPointer<T> &ptr1, const X *ptr2) noexcept
-{
- return ptr1.data() == ptr2;
-}
-template <class T, class X>
-bool operator==(const T *ptr1, const QSharedPointer<X> &ptr2) noexcept
-{
- return ptr1 == ptr2.data();
-}
-template <class T, class X>
-bool operator!=(const QSharedPointer<T> &ptr1, const X *ptr2) noexcept
-{
- return !(ptr1 == ptr2);
-}
-template <class T, class X>
-bool operator!=(const T *ptr1, const QSharedPointer<X> &ptr2) noexcept
-{
- return !(ptr2 == ptr1);
-}
-
-template <class T, class X>
-bool operator==(const QSharedPointer<T> &ptr1, const QWeakPointer<X> &ptr2) noexcept
-{
- return ptr2 == ptr1;
-}
-template <class T, class X>
-bool operator!=(const QSharedPointer<T> &ptr1, const QWeakPointer<X> &ptr2) noexcept
-{
- return ptr2 != ptr1;
-}
-
-template<class T>
-inline bool operator==(const QSharedPointer<T> &lhs, std::nullptr_t) noexcept
-{
- return lhs.isNull();
-}
-
-template<class T>
-inline bool operator!=(const QSharedPointer<T> &lhs, std::nullptr_t) noexcept
-{
- return !lhs.isNull();
-}
-
-template<class T>
-inline bool operator==(std::nullptr_t, const QSharedPointer<T> &rhs) noexcept
-{
- return rhs.isNull();
-}
-
-template<class T>
-inline bool operator!=(std::nullptr_t, const QSharedPointer<T> &rhs) noexcept
-{
- return !rhs.isNull();
-}
-
-template<class T>
-inline bool operator==(const QWeakPointer<T> &lhs, std::nullptr_t) noexcept
-{
- return lhs.isNull();
-}
-
-template<class T>
-inline bool operator!=(const QWeakPointer<T> &lhs, std::nullptr_t) noexcept
-{
- return !lhs.isNull();
-}
-
-template<class T>
-inline bool operator==(std::nullptr_t, const QWeakPointer<T> &rhs) noexcept
-{
- return rhs.isNull();
-}
-
-template<class T>
-inline bool operator!=(std::nullptr_t, const QWeakPointer<T> &rhs) noexcept
-{
- return !rhs.isNull();
-}
-
-//
// operator-
//
template <class T, class X>
@@ -957,8 +889,8 @@ qobject_cast(const QWeakPointer<T> &src)
return qSharedPointerObjectCast<typename QtSharedPointer::RemovePointer<X>::Type, T>(src);
}
-/// ### Qt 6: make this use toStrongRef() (once support for storing
-/// non-managed QObjects in QWeakPointer is removed)
+/// ### TODO - QTBUG-88102: make this use toStrongRef() (once support for
+/// storing non-managed QObjects in QWeakPointer is removed)
template<typename T>
QWeakPointer<typename std::enable_if<QtPrivate::IsPointerToTypeDerivedFromQObject<T*>::Value, T>::type>
qWeakPointerFromVariant(const QVariant &variant)
diff --git a/src/corelib/tools/qsize.cpp b/src/corelib/tools/qsize.cpp
index 2cbaae117d..788356002c 100644
--- a/src/corelib/tools/qsize.cpp
+++ b/src/corelib/tools/qsize.cpp
@@ -302,37 +302,32 @@ QSize QSize::scaled(const QSize &s, Qt::AspectRatioMode mode) const noexcept
*/
/*!
- \fn bool operator==(const QSize &s1, const QSize &s2)
- \relates QSize
+ \fn bool QSize::operator==(const QSize &s1, const QSize &s2)
Returns \c true if \a s1 and \a s2 are equal; otherwise returns \c false.
*/
/*!
- \fn bool operator!=(const QSize &s1, const QSize &s2)
- \relates QSize
+ \fn bool QSize::operator!=(const QSize &s1, const QSize &s2)
Returns \c true if \a s1 and \a s2 are different; otherwise returns \c false.
*/
/*!
- \fn const QSize operator+(const QSize &s1, const QSize &s2)
- \relates QSize
+ \fn QSize QSize::operator+(const QSize &s1, const QSize &s2)
Returns the sum of \a s1 and \a s2; each component is added separately.
*/
/*!
- \fn const QSize operator-(const QSize &s1, const QSize &s2)
- \relates QSize
+ \fn QSize QSize::operator-(const QSize &s1, const QSize &s2)
Returns \a s2 subtracted from \a s1; each component is subtracted
separately.
*/
/*!
- \fn const QSize operator*(const QSize &size, qreal factor)
- \relates QSize
+ \fn QSize QSize::operator*(const QSize &size, qreal factor)
Multiplies the given \a size by the given \a factor, and returns
the result rounded to the nearest integer.
@@ -341,9 +336,8 @@ QSize QSize::scaled(const QSize &s, Qt::AspectRatioMode mode) const noexcept
*/
/*!
- \fn const QSize operator*(qreal factor, const QSize &size)
+ \fn QSize QSize::operator*(qreal factor, const QSize &size)
\overload
- \relates QSize
Multiplies the given \a size by the given \a factor, and returns
the result rounded to the nearest integer.
@@ -362,8 +356,7 @@ QSize QSize::scaled(const QSize &s, Qt::AspectRatioMode mode) const noexcept
*/
/*!
- \fn const QSize operator/(const QSize &size, qreal divisor)
- \relates QSize
+ \fn QSize QSize::operator/(const QSize &size, qreal divisor)
\overload
Divides the given \a size by the given \a divisor, and returns the
@@ -748,40 +741,44 @@ QSizeF QSizeF::scaled(const QSizeF &s, Qt::AspectRatioMode mode) const noexcept
*/
/*!
- \fn bool operator==(const QSizeF &s1, const QSizeF &s2)
- \relates QSizeF
+ \fn bool QSizeF::operator==(const QSizeF &s1, const QSizeF &s2)
- Returns \c true if \a s1 and \a s2 are equal; otherwise returns
- false.
+ Returns \c true if \a s1 and \a s2 are approximately equal; otherwise
+ returns false.
+
+ \warning This function does not check for strict equality; instead,
+ it uses a fuzzy comparison to compare the sizes' extents.
+
+ \sa qFuzzyCompare
*/
/*!
- \fn bool operator!=(const QSizeF &s1, const QSizeF &s2)
- \relates QSizeF
+ \fn bool QSizeF::operator!=(const QSizeF &s1, const QSizeF &s2)
- Returns \c true if \a s1 and \a s2 are different; otherwise returns \c false.
+ Returns \c true if \a s1 and \a s2 are sufficiently different; otherwise
+ returns \c false.
+
+ \warning This function does not check for strict inequality; instead,
+ it uses a fuzzy comparison to compare the sizes' extents.
*/
/*!
- \fn const QSizeF operator+(const QSizeF &s1, const QSizeF &s2)
- \relates QSizeF
+ \fn QSizeF QSizeF::operator+(const QSizeF &s1, const QSizeF &s2)
Returns the sum of \a s1 and \a s2; each component is added separately.
*/
/*!
- \fn const QSizeF operator-(const QSizeF &s1, const QSizeF &s2)
- \relates QSizeF
+ \fn QSizeF QSizeF::operator-(const QSizeF &s1, const QSizeF &s2)
Returns \a s2 subtracted from \a s1; each component is subtracted
separately.
*/
/*!
- \fn const QSizeF operator*(const QSizeF &size, qreal factor)
+ \fn QSizeF QSizeF::operator*(const QSizeF &size, qreal factor)
\overload
- \relates QSizeF
Multiplies the given \a size by the given \a factor and returns
the result.
@@ -790,10 +787,9 @@ QSizeF QSizeF::scaled(const QSizeF &s, Qt::AspectRatioMode mode) const noexcept
*/
/*!
- \fn const QSizeF operator*(qreal factor, const QSizeF &size)
+ \fn QSizeF QSizeF::operator*(qreal factor, const QSizeF &size)
\overload
- \relates QSizeF
Multiplies the given \a size by the given \a factor and returns
the result.
@@ -811,9 +807,8 @@ QSizeF QSizeF::scaled(const QSizeF &s, Qt::AspectRatioMode mode) const noexcept
*/
/*!
- \fn const QSizeF operator/(const QSizeF &size, qreal divisor)
+ \fn QSizeF QSizeF::operator/(const QSizeF &size, qreal divisor)
- \relates QSizeF
\overload
Divides the given \a size by the given \a divisor and returns the
diff --git a/src/corelib/tools/qsize.h b/src/corelib/tools/qsize.h
index d2598afbea..b2409a4f89 100644
--- a/src/corelib/tools/qsize.h
+++ b/src/corelib/tools/qsize.h
@@ -66,19 +66,19 @@ public:
constexpr inline void setWidth(int w) noexcept;
constexpr inline void setHeight(int h) noexcept;
void transpose() noexcept;
- Q_REQUIRED_RESULT constexpr inline QSize transposed() const noexcept;
+ [[nodiscard]] constexpr inline QSize transposed() const noexcept;
inline void scale(int w, int h, Qt::AspectRatioMode mode) noexcept;
inline void scale(const QSize &s, Qt::AspectRatioMode mode) noexcept;
- Q_REQUIRED_RESULT QSize scaled(int w, int h, Qt::AspectRatioMode mode) const noexcept;
- Q_REQUIRED_RESULT QSize scaled(const QSize &s, Qt::AspectRatioMode mode) const noexcept;
+ [[nodiscard]] QSize scaled(int w, int h, Qt::AspectRatioMode mode) const noexcept;
+ [[nodiscard]] QSize scaled(const QSize &s, Qt::AspectRatioMode mode) const noexcept;
- Q_REQUIRED_RESULT constexpr inline QSize expandedTo(const QSize &) const noexcept;
- Q_REQUIRED_RESULT constexpr inline QSize boundedTo(const QSize &) const noexcept;
+ [[nodiscard]] constexpr inline QSize expandedTo(const QSize &) const noexcept;
+ [[nodiscard]] constexpr inline QSize boundedTo(const QSize &) const noexcept;
- Q_REQUIRED_RESULT constexpr QSize grownBy(QMargins m) const noexcept
+ [[nodiscard]] constexpr QSize grownBy(QMargins m) const noexcept
{ return {width() + m.left() + m.right(), height() + m.top() + m.bottom()}; }
- Q_REQUIRED_RESULT constexpr QSize shrunkBy(QMargins m) const noexcept
+ [[nodiscard]] constexpr QSize shrunkBy(QMargins m) const noexcept
{ return {width() - m.left() - m.right(), height() - m.top() - m.bottom()}; }
constexpr inline int &rwidth() noexcept;
@@ -89,17 +89,24 @@ public:
constexpr inline QSize &operator*=(qreal c) noexcept;
inline QSize &operator/=(qreal c);
- friend inline constexpr bool operator==(const QSize &, const QSize &) noexcept;
- friend inline constexpr bool operator!=(const QSize &, const QSize &) noexcept;
+ friend inline constexpr bool operator==(const QSize &s1, const QSize &s2) noexcept
+ { return s1.wd == s2.wd && s1.ht == s2.ht; }
+ friend inline constexpr bool operator!=(const QSize &s1, const QSize &s2) noexcept
+ { return s1.wd != s2.wd || s1.ht != s2.ht; }
+ friend inline constexpr QSize operator+(const QSize &s1, const QSize &s2) noexcept
+ { return QSize(s1.wd + s2.wd, s1.ht + s2.ht); }
+ friend inline constexpr QSize operator-(const QSize &s1, const QSize &s2) noexcept
+ { return QSize(s1.wd - s2.wd, s1.ht - s2.ht); }
+ friend inline constexpr QSize operator*(const QSize &s, qreal c) noexcept
+ { return QSize(qRound(s.wd * c), qRound(s.ht * c)); }
+ friend inline constexpr QSize operator*(qreal c, const QSize &s) noexcept
+ { return s * c; }
+ friend inline QSize operator/(const QSize &s, qreal c)
+ { Q_ASSERT(!qFuzzyIsNull(c)); return QSize(qRound(s.wd / c), qRound(s.ht / c)); }
friend inline constexpr size_t qHash(const QSize &, size_t) noexcept;
- friend inline constexpr const QSize operator+(const QSize &, const QSize &) noexcept;
- friend inline constexpr const QSize operator-(const QSize &, const QSize &) noexcept;
- friend inline constexpr const QSize operator*(const QSize &, qreal) noexcept;
- friend inline constexpr const QSize operator*(qreal, const QSize &) noexcept;
- friend inline const QSize operator/(const QSize &, qreal);
#if defined(Q_OS_DARWIN) || defined(Q_QDOC)
- Q_REQUIRED_RESULT CGSize toCGSize() const noexcept;
+ [[nodiscard]] CGSize toCGSize() const noexcept;
#endif
private:
@@ -127,13 +134,13 @@ constexpr inline QSize::QSize() noexcept : wd(-1), ht(-1) {}
constexpr inline QSize::QSize(int w, int h) noexcept : wd(w), ht(h) {}
constexpr inline bool QSize::isNull() const noexcept
-{ return wd==0 && ht==0; }
+{ return wd == 0 && ht == 0; }
constexpr inline bool QSize::isEmpty() const noexcept
-{ return wd<1 || ht<1; }
+{ return wd < 1 || ht < 1; }
constexpr inline bool QSize::isValid() const noexcept
-{ return wd>=0 && ht>=0; }
+{ return wd >= 0 && ht >= 0; }
constexpr inline int QSize::width() const noexcept
{ return wd; }
@@ -166,48 +173,37 @@ constexpr inline int &QSize::rheight() noexcept
{ return ht; }
constexpr inline QSize &QSize::operator+=(const QSize &s) noexcept
-{ wd+=s.wd; ht+=s.ht; return *this; }
+{
+ wd += s.wd;
+ ht += s.ht;
+ return *this;
+}
constexpr inline QSize &QSize::operator-=(const QSize &s) noexcept
-{ wd-=s.wd; ht-=s.ht; return *this; }
+{
+ wd -= s.wd;
+ ht -= s.ht;
+ return *this;
+}
constexpr inline QSize &QSize::operator*=(qreal c) noexcept
-{ wd = qRound(wd*c); ht = qRound(ht*c); return *this; }
-
-constexpr inline bool operator==(const QSize &s1, const QSize &s2) noexcept
-{ return s1.wd == s2.wd && s1.ht == s2.ht; }
-
-constexpr inline bool operator!=(const QSize &s1, const QSize &s2) noexcept
-{ return s1.wd != s2.wd || s1.ht != s2.ht; }
+{
+ wd = qRound(wd * c);
+ ht = qRound(ht * c);
+ return *this;
+}
constexpr inline size_t qHash(const QSize &s, size_t seed = 0) noexcept
{ return qHashMulti(seed, s.wd, s.ht); }
-constexpr inline const QSize operator+(const QSize & s1, const QSize & s2) noexcept
-{ return QSize(s1.wd+s2.wd, s1.ht+s2.ht); }
-
-constexpr inline const QSize operator-(const QSize &s1, const QSize &s2) noexcept
-{ return QSize(s1.wd-s2.wd, s1.ht-s2.ht); }
-
-constexpr inline const QSize operator*(const QSize &s, qreal c) noexcept
-{ return QSize(qRound(s.wd*c), qRound(s.ht*c)); }
-
-constexpr inline const QSize operator*(qreal c, const QSize &s) noexcept
-{ return QSize(qRound(s.wd*c), qRound(s.ht*c)); }
-
inline QSize &QSize::operator/=(qreal c)
{
Q_ASSERT(!qFuzzyIsNull(c));
- wd = qRound(wd/c); ht = qRound(ht/c);
+ wd = qRound(wd / c);
+ ht = qRound(ht / c);
return *this;
}
-inline const QSize operator/(const QSize &s, qreal c)
-{
- Q_ASSERT(!qFuzzyIsNull(c));
- return QSize(qRound(s.wd/c), qRound(s.ht/c));
-}
-
constexpr inline QSize QSize::expandedTo(const QSize & otherSize) const noexcept
{
return QSize(qMax(wd,otherSize.wd), qMax(ht,otherSize.ht));
@@ -239,19 +235,19 @@ public:
constexpr inline void setWidth(qreal w) noexcept;
constexpr inline void setHeight(qreal h) noexcept;
void transpose() noexcept;
- Q_REQUIRED_RESULT constexpr inline QSizeF transposed() const noexcept;
+ [[nodiscard]] constexpr inline QSizeF transposed() const noexcept;
inline void scale(qreal w, qreal h, Qt::AspectRatioMode mode) noexcept;
inline void scale(const QSizeF &s, Qt::AspectRatioMode mode) noexcept;
- Q_REQUIRED_RESULT QSizeF scaled(qreal w, qreal h, Qt::AspectRatioMode mode) const noexcept;
- Q_REQUIRED_RESULT QSizeF scaled(const QSizeF &s, Qt::AspectRatioMode mode) const noexcept;
+ [[nodiscard]] QSizeF scaled(qreal w, qreal h, Qt::AspectRatioMode mode) const noexcept;
+ [[nodiscard]] QSizeF scaled(const QSizeF &s, Qt::AspectRatioMode mode) const noexcept;
- Q_REQUIRED_RESULT constexpr inline QSizeF expandedTo(const QSizeF &) const noexcept;
- Q_REQUIRED_RESULT constexpr inline QSizeF boundedTo(const QSizeF &) const noexcept;
+ [[nodiscard]] constexpr inline QSizeF expandedTo(const QSizeF &) const noexcept;
+ [[nodiscard]] constexpr inline QSizeF boundedTo(const QSizeF &) const noexcept;
- Q_REQUIRED_RESULT constexpr QSizeF grownBy(QMarginsF m) const noexcept
+ [[nodiscard]] constexpr QSizeF grownBy(QMarginsF m) const noexcept
{ return {width() + m.left() + m.right(), height() + m.top() + m.bottom()}; }
- Q_REQUIRED_RESULT constexpr QSizeF shrunkBy(QMarginsF m) const noexcept
+ [[nodiscard]] constexpr QSizeF shrunkBy(QMarginsF m) const noexcept
{ return {width() - m.left() - m.right(), height() - m.top() - m.bottom()}; }
constexpr inline qreal &rwidth() noexcept;
@@ -262,19 +258,32 @@ public:
constexpr inline QSizeF &operator*=(qreal c) noexcept;
inline QSizeF &operator/=(qreal c);
- friend constexpr inline bool operator==(const QSizeF &, const QSizeF &) noexcept;
- friend constexpr inline bool operator!=(const QSizeF &, const QSizeF &) noexcept;
- friend constexpr inline const QSizeF operator+(const QSizeF &, const QSizeF &) noexcept;
- friend constexpr inline const QSizeF operator-(const QSizeF &, const QSizeF &) noexcept;
- friend constexpr inline const QSizeF operator*(const QSizeF &, qreal) noexcept;
- friend constexpr inline const QSizeF operator*(qreal, const QSizeF &) noexcept;
- friend inline const QSizeF operator/(const QSizeF &, qreal);
+ QT_WARNING_PUSH
+ QT_WARNING_DISABLE_FLOAT_COMPARE
+ friend constexpr inline bool operator==(const QSizeF &s1, const QSizeF &s2)
+ {
+ return ((!s1.wd || !s2.wd) ? qFuzzyIsNull(s1.wd - s2.wd) : qFuzzyCompare(s1.wd, s2.wd))
+ && ((!s1.ht || !s2.ht) ? qFuzzyIsNull(s1.ht - s2.ht) : qFuzzyCompare(s1.ht, s2.ht));
+ }
+ QT_WARNING_POP
+ friend constexpr inline bool operator!=(const QSizeF &s1, const QSizeF &s2)
+ { return !(s1 == s2); }
+ friend constexpr inline QSizeF operator+(const QSizeF &s1, const QSizeF &s2) noexcept
+ { return QSizeF(s1.wd + s2.wd, s1.ht + s2.ht); }
+ friend constexpr inline QSizeF operator-(const QSizeF &s1, const QSizeF &s2) noexcept
+ { return QSizeF(s1.wd - s2.wd, s1.ht - s2.ht); }
+ friend constexpr inline QSizeF operator*(const QSizeF &s, qreal c) noexcept
+ { return QSizeF(s.wd * c, s.ht * c); }
+ friend constexpr inline QSizeF operator*(qreal c, const QSizeF &s) noexcept
+ { return s * c; }
+ friend inline QSizeF operator/(const QSizeF &s, qreal c)
+ { Q_ASSERT(!qFuzzyIsNull(c)); return QSizeF(s.wd / c, s.ht / c); }
constexpr inline QSize toSize() const noexcept;
#if defined(Q_OS_DARWIN) || defined(Q_QDOC)
- Q_REQUIRED_RESULT static QSizeF fromCGSize(CGSize size) noexcept;
- Q_REQUIRED_RESULT CGSize toCGSize() const noexcept;
+ [[nodiscard]] static QSizeF fromCGSize(CGSize size) noexcept;
+ [[nodiscard]] CGSize toCGSize() const noexcept;
#endif
private:
@@ -344,53 +353,42 @@ constexpr inline qreal &QSizeF::rheight() noexcept
{ return ht; }
constexpr inline QSizeF &QSizeF::operator+=(const QSizeF &s) noexcept
-{ wd += s.wd; ht += s.ht; return *this; }
+{
+ wd += s.wd;
+ ht += s.ht;
+ return *this;
+}
constexpr inline QSizeF &QSizeF::operator-=(const QSizeF &s) noexcept
-{ wd -= s.wd; ht -= s.ht; return *this; }
+{
+ wd -= s.wd;
+ ht -= s.ht;
+ return *this;
+}
constexpr inline QSizeF &QSizeF::operator*=(qreal c) noexcept
-{ wd *= c; ht *= c; return *this; }
-
-constexpr inline bool operator==(const QSizeF &s1, const QSizeF &s2) noexcept
-{ return qFuzzyCompare(s1.wd, s2.wd) && qFuzzyCompare(s1.ht, s2.ht); }
-
-constexpr inline bool operator!=(const QSizeF &s1, const QSizeF &s2) noexcept
-{ return !qFuzzyCompare(s1.wd, s2.wd) || !qFuzzyCompare(s1.ht, s2.ht); }
-
-constexpr inline const QSizeF operator+(const QSizeF & s1, const QSizeF & s2) noexcept
-{ return QSizeF(s1.wd+s2.wd, s1.ht+s2.ht); }
-
-constexpr inline const QSizeF operator-(const QSizeF &s1, const QSizeF &s2) noexcept
-{ return QSizeF(s1.wd-s2.wd, s1.ht-s2.ht); }
-
-constexpr inline const QSizeF operator*(const QSizeF &s, qreal c) noexcept
-{ return QSizeF(s.wd*c, s.ht*c); }
-
-constexpr inline const QSizeF operator*(qreal c, const QSizeF &s) noexcept
-{ return QSizeF(s.wd*c, s.ht*c); }
-
-inline QSizeF &QSizeF::operator/=(qreal c)
{
- Q_ASSERT(!qFuzzyIsNull(c));
- wd = wd/c; ht = ht/c;
+ wd *= c;
+ ht *= c;
return *this;
}
-inline const QSizeF operator/(const QSizeF &s, qreal c)
+inline QSizeF &QSizeF::operator/=(qreal c)
{
Q_ASSERT(!qFuzzyIsNull(c));
- return QSizeF(s.wd/c, s.ht/c);
+ wd = wd / c;
+ ht = ht / c;
+ return *this;
}
-constexpr inline QSizeF QSizeF::expandedTo(const QSizeF & otherSize) const noexcept
+constexpr inline QSizeF QSizeF::expandedTo(const QSizeF &otherSize) const noexcept
{
- return QSizeF(qMax(wd,otherSize.wd), qMax(ht,otherSize.ht));
+ return QSizeF(qMax(wd, otherSize.wd), qMax(ht, otherSize.ht));
}
-constexpr inline QSizeF QSizeF::boundedTo(const QSizeF & otherSize) const noexcept
+constexpr inline QSizeF QSizeF::boundedTo(const QSizeF &otherSize) const noexcept
{
- return QSizeF(qMin(wd,otherSize.wd), qMin(ht,otherSize.ht));
+ return QSizeF(qMin(wd, otherSize.wd), qMin(ht, otherSize.ht));
}
constexpr inline QSize QSizeF::toSize() const noexcept
diff --git a/src/corelib/tools/qtaggedpointer.qdoc b/src/corelib/tools/qtaggedpointer.qdoc
index 303b89232c..36e20ecff0 100644
--- a/src/corelib/tools/qtaggedpointer.qdoc
+++ b/src/corelib/tools/qtaggedpointer.qdoc
@@ -123,9 +123,9 @@
*/
/*!
- \fn template <typename T, typename Tag> bool QTaggedPointer<T, Tag>::operator!() const noexcept
+ \fn template <typename T, typename Tag> bool QTaggedPointer<T, Tag>::operator!(QTaggedPointer<T, Tag> pointer) noexcept
- Returns \c true if the pointer is \nullptr.
+ Returns \c true if \a pointer is \nullptr.
*/
/*!
@@ -153,7 +153,7 @@
*/
/*!
- \fn template <typename T, typename Tag> Tag QTaggedPointer<T, Tag>::pointer() const noexcept
+ \fn template <typename T, typename Tag> T *QTaggedPointer<T, Tag>::data() const noexcept
Returns the pointer stored in the tagged pointer.
*/
@@ -171,8 +171,7 @@
*/
/*!
- \fn template <typename T, typename Tag> inline bool operator==(QTaggedPointer lhs, QTaggedPointer rhs) noexcept
- \relates QTaggedPointer
+ \fn template <typename T, typename Tag> bool QTaggedPointer<T, Tag>::operator==(QTaggedPointer<T, Tag> lhs, QTaggedPointer<T, Tag> rhs) noexcept
Returns \c true if \a lhs is equal to \a rhs; otherwise returns \c false.
@@ -180,8 +179,7 @@
*/
/*!
- \fn template <typename T, typename Tag> inline bool operator!=(QTaggedPointer lhs, QTaggedPointer rhs) noexcept
- \relates QTaggedPointer
+ \fn template <typename T, typename Tag> bool QTaggedPointer<T, Tag>::operator!=(QTaggedPointer<T, Tag> lhs, QTaggedPointer<T, Tag> rhs) noexcept
Returns \c true if \a lhs is not equal to \a rhs; otherwise returns \c false.
@@ -189,29 +187,25 @@
*/
/*!
- \fn template <typename T, typename Tag> inline bool operator==(QTaggedPointer lhs, std::nullptr_t) noexcept
- \relates QTaggedPointer
+ \fn template <typename T, typename Tag> bool QTaggedPointer<T, Tag>::operator==(QTaggedPointer<T, Tag> lhs, std::nullptr_t) noexcept
Returns \c true if \a lhs refers to \c nullptr.
*/
/*!
- \fn template <typename T, typename Tag> inline bool operator==(std::nullptr_t, QTaggedPointer rhs) noexcept
- \relates QTaggedPointer
+ \fn template <typename T, typename Tag> bool QTaggedPointer<T, Tag>::operator==(std::nullptr_t, QTaggedPointer<T, Tag> rhs) noexcept
Returns \c true if \a rhs refers to \c nullptr.
*/
/*!
- \fn template <typename T, typename Tag> inline bool operator!=(QTaggedPointerlhs, std::nullptr_t) noexcept
- \relates QTaggedPointer
+ \fn template <typename T, typename Tag> bool QTaggedPointer<T, Tag>::operator!=(QTaggedPointer<T, Tag> lhs, std::nullptr_t) noexcept
Returns \c true if \a lhs refers to a valid (i.e. non-null) pointer.
*/
/*!
- \fn template <typename T, typename Tag> inline bool operator!=(std::nullptr_t, QTaggedPointer rhs) noexcept
- \relates QTaggedPointer
+ \fn template <typename T, typename Tag> bool QTaggedPointer<T, Tag>::operator!=(std::nullptr_t, QTaggedPointer<T, Tag> rhs) noexcept
Returns \c true if \a rhs refers to a valid (i.e. non-null) pointer.
*/
diff --git a/src/corelib/tools/qtimeline.cpp b/src/corelib/tools/qtimeline.cpp
index f8e78170c4..4609b258fc 100644
--- a/src/corelib/tools/qtimeline.cpp
+++ b/src/corelib/tools/qtimeline.cpp
@@ -96,7 +96,7 @@ void QTimeLinePrivate::setCurrentTime(int msecs)
int lastFrame = q->currentFrame();
// Determine if we are looping.
- int elapsed = (direction == QTimeLine::Backward) ? (-msecs + duration) : msecs;
+ int elapsed = (direction == QTimeLine::Backward) ? (-msecs + duration) : msecs;
int loopCount = elapsed / duration;
bool looping = (loopCount != currentLoopCount);
@@ -490,7 +490,7 @@ QEasingCurve QTimeLine::easingCurve() const
return d->easingCurve;
}
-void QTimeLine::setEasingCurve(const QEasingCurve& curve)
+void QTimeLine::setEasingCurve(const QEasingCurve &curve)
{
Q_D(QTimeLine);
d->easingCurve = curve;
diff --git a/src/corelib/tools/qtools_p.h b/src/corelib/tools/qtools_p.h
index 5b6be12820..8854ae8c48 100644
--- a/src/corelib/tools/qtools_p.h
+++ b/src/corelib/tools/qtools_p.h
@@ -89,7 +89,8 @@ constexpr inline int fromOct(uint c) noexcept
// We typically need an extra bit for qNextPowerOfTwo when determining the next allocation size.
constexpr qsizetype MaxAllocSize = (std::numeric_limits<qsizetype>::max)();
-struct CalculateGrowingBlockSizeResult {
+struct CalculateGrowingBlockSizeResult
+{
qsizetype size;
qsizetype elementCount;
};
diff --git a/src/corelib/tools/qvarlengtharray.h b/src/corelib/tools/qvarlengtharray.h
index b240f8d450..06a4b66125 100644
--- a/src/corelib/tools/qvarlengtharray.h
+++ b/src/corelib/tools/qvarlengtharray.h
@@ -60,6 +60,8 @@ QT_BEGIN_NAMESPACE
template<class T, qsizetype Prealloc>
class QVarLengthArray
{
+ static_assert(std::is_nothrow_destructible_v<T>, "Types with throwing destructors are not supported in Qt containers.");
+
public:
QVarLengthArray() : QVarLengthArray(0) {}
@@ -104,12 +106,10 @@ public:
std::copy(first, last, std::back_inserter(*this));
}
- inline ~QVarLengthArray() {
- if (QTypeInfo<T>::isComplex) {
- T *i = ptr + s;
- while (i-- != ptr)
- i->~T();
- }
+ inline ~QVarLengthArray()
+ {
+ if constexpr (QTypeInfo<T>::isComplex)
+ std::destroy_n(ptr, s);
if (ptr != reinterpret_cast<T *>(array))
free(ptr);
}
@@ -130,7 +130,7 @@ public:
// the moved-from state is the empty state, so we're good with the clear() here:
clear();
Q_ASSERT(capacity() >= Prealloc);
- const auto otherInlineStorage = reinterpret_cast<T*>(other.array);
+ const auto otherInlineStorage = reinterpret_cast<T *>(other.array);
if (other.ptr != otherInlineStorage) {
// heap storage: steal the external buffer, reset other to otherInlineStorage
a = std::exchange(other.a, Prealloc);
@@ -151,19 +151,36 @@ public:
return *this;
}
- inline void removeLast() {
+ inline void removeLast()
+ {
Q_ASSERT(s > 0);
- if (QTypeInfo<T>::isComplex)
+ if constexpr (QTypeInfo<T>::isComplex)
ptr[s - 1].~T();
--s;
}
inline qsizetype size() const { return s; }
inline qsizetype count() const { return s; }
inline qsizetype length() const { return s; }
- inline T& first() { Q_ASSERT(!isEmpty()); return *begin(); }
- inline const T& first() const { Q_ASSERT(!isEmpty()); return *begin(); }
- T& last() { Q_ASSERT(!isEmpty()); return *(end() - 1); }
- const T& last() const { Q_ASSERT(!isEmpty()); return *(end() - 1); }
+ inline T &first()
+ {
+ Q_ASSERT(!isEmpty());
+ return *begin();
+ }
+ inline const T &first() const
+ {
+ Q_ASSERT(!isEmpty());
+ return *begin();
+ }
+ T &last()
+ {
+ Q_ASSERT(!isEmpty());
+ return *(end() - 1);
+ }
+ const T &last() const
+ {
+ Q_ASSERT(!isEmpty());
+ return *(end() - 1);
+ }
inline bool isEmpty() const { return (s == 0); }
inline void resize(qsizetype size);
inline void clear() { resize(0); }
@@ -172,15 +189,20 @@ public:
inline qsizetype capacity() const { return a; }
inline void reserve(qsizetype size);
- inline qsizetype indexOf(const T &t, qsizetype from = 0) const;
- inline qsizetype lastIndexOf(const T &t, qsizetype from = -1) const;
- inline bool contains(const T &t) const;
+ template <typename AT = T>
+ inline qsizetype indexOf(const AT &t, qsizetype from = 0) const;
+ template <typename AT = T>
+ inline qsizetype lastIndexOf(const AT &t, qsizetype from = -1) const;
+ template <typename AT = T>
+ inline bool contains(const AT &t) const;
- inline T &operator[](qsizetype idx) {
+ inline T &operator[](qsizetype idx)
+ {
Q_ASSERT(idx >= 0 && idx < s);
return ptr[idx];
}
- inline const T &operator[](qsizetype idx) const {
+ inline const T &operator[](qsizetype idx) const
+ {
Q_ASSERT(idx >= 0 && idx < s);
return ptr[idx];
}
@@ -189,34 +211,25 @@ public:
T value(qsizetype i) const;
T value(qsizetype i, const T &defaultValue) const;
- inline void append(const T &t) {
- if (s == a) { // i.e. s != 0
+ inline void append(const T &t)
+ {
+ if (s == a) { // i.e. s != 0
T copy(t);
reallocate(s, s << 1);
const qsizetype idx = s++;
- if (QTypeInfo<T>::isComplex) {
- new (ptr + idx) T(std::move(copy));
- } else {
- ptr[idx] = std::move(copy);
- }
+ new (ptr + idx) T(std::move(copy));
} else {
const qsizetype idx = s++;
- if (QTypeInfo<T>::isComplex) {
- new (ptr + idx) T(t);
- } else {
- ptr[idx] = t;
- }
+ new (ptr + idx) T(t);
}
}
- void append(T &&t) {
+ void append(T &&t)
+ {
if (s == a)
reallocate(s, s << 1);
const qsizetype idx = s++;
- if (QTypeInfo<T>::isComplex)
- new (ptr + idx) T(std::move(t));
- else
- ptr[idx] = std::move(t);
+ new (ptr + idx) T(std::move(t));
}
void append(const T *buf, qsizetype size);
@@ -238,10 +251,9 @@ public:
void remove(qsizetype i);
void remove(qsizetype i, qsizetype n);
-
inline T *data() { return ptr; }
inline const T *data() const { return ptr; }
- inline const T * constData() const { return ptr; }
+ inline const T *constData() const { return ptr; }
typedef qsizetype size_type;
typedef T value_type;
typedef value_type *pointer;
@@ -250,9 +262,8 @@ public:
typedef const value_type &const_reference;
typedef qptrdiff difference_type;
-
- typedef T* iterator;
- typedef const T* const_iterator;
+ typedef T *iterator;
+ typedef const T *const_iterator;
typedef std::reverse_iterator<iterator> reverse_iterator;
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
@@ -274,7 +285,7 @@ public:
iterator insert(const_iterator before, T &&x);
inline iterator insert(const_iterator before, const T &x) { return insert(before, 1, x); }
iterator erase(const_iterator begin, const_iterator end);
- inline iterator erase(const_iterator pos) { return erase(pos, pos+1); }
+ inline iterator erase(const_iterator pos) { return erase(pos, pos + 1); }
// STL compatibility:
inline bool empty() const { return isEmpty(); }
@@ -287,6 +298,68 @@ public:
inline const T &back() const { return last(); }
void shrink_to_fit() { squeeze(); }
+#ifdef Q_QDOC
+ template <typename T, qsizetype Prealloc1, qsizetype Prealloc2>
+ friend inline bool operator==(const QVarLengthArray<T, Prealloc1> &l, const QVarLengthArray<T, Prealloc2> &r);
+ template <typename T, qsizetype Prealloc1, qsizetype Prealloc2>
+ friend inline bool operator!=(const QVarLengthArray<T, Prealloc1> &l, const QVarLengthArray<T, Prealloc2> &r);
+ template <typename T, qsizetype Prealloc1, qsizetype Prealloc2>
+ friend inline bool operator< (const QVarLengthArray<T, Prealloc1> &l, const QVarLengthArray<T, Prealloc2> &r);
+ template <typename T, qsizetype Prealloc1, qsizetype Prealloc2>
+ friend inline bool operator> (const QVarLengthArray<T, Prealloc1> &l, const QVarLengthArray<T, Prealloc2> &r);
+ template <typename T, qsizetype Prealloc1, qsizetype Prealloc2>
+ friend inline bool operator<=(const QVarLengthArray<T, Prealloc1> &l, const QVarLengthArray<T, Prealloc2> &r);
+ template <typename T, qsizetype Prealloc1, qsizetype Prealloc2>
+ friend inline bool operator>=(const QVarLengthArray<T, Prealloc1> &l, const QVarLengthArray<T, Prealloc2> &r);
+#else
+ template <typename U = T, qsizetype Prealloc2 = Prealloc> friend
+ QTypeTraits::compare_eq_result<U> operator==(const QVarLengthArray<T, Prealloc> &l, const QVarLengthArray<T, Prealloc2> &r)
+ {
+ if (l.size() != r.size())
+ return false;
+ const T *rb = r.begin();
+ const T *b = l.begin();
+ const T *e = l.end();
+ return std::equal(b, e, QT_MAKE_CHECKED_ARRAY_ITERATOR(rb, r.size()));
+ }
+
+ template <typename U = T, qsizetype Prealloc2 = Prealloc> friend
+ QTypeTraits::compare_eq_result<U> operator!=(const QVarLengthArray<T, Prealloc> &l, const QVarLengthArray<T, Prealloc2> &r)
+ {
+ return !(l == r);
+ }
+
+ template <typename U = T, qsizetype Prealloc2 = Prealloc> friend
+ QTypeTraits::compare_lt_result<U> operator<(const QVarLengthArray<T, Prealloc> &lhs, const QVarLengthArray<T, Prealloc2> &rhs)
+ noexcept(noexcept(std::lexicographical_compare(lhs.begin(), lhs.end(),
+ rhs.begin(), rhs.end())))
+ {
+ return std::lexicographical_compare(lhs.begin(), lhs.end(),
+ rhs.begin(), rhs.end());
+ }
+
+ template <typename U = T, qsizetype Prealloc2 = Prealloc> friend
+ QTypeTraits::compare_lt_result<U> operator>(const QVarLengthArray<T, Prealloc> &lhs, const QVarLengthArray<T, Prealloc2> &rhs)
+ noexcept(noexcept(lhs < rhs))
+ {
+ return rhs < lhs;
+ }
+
+ template <typename U = T, qsizetype Prealloc2 = Prealloc> friend
+ QTypeTraits::compare_lt_result<U> operator<=(const QVarLengthArray<T, Prealloc> &lhs, const QVarLengthArray<T, Prealloc2> &rhs)
+ noexcept(noexcept(lhs < rhs))
+ {
+ return !(lhs > rhs);
+ }
+
+ template <typename U = T, qsizetype Prealloc2 = Prealloc> friend
+ QTypeTraits::compare_lt_result<U> operator>=(const QVarLengthArray<T, Prealloc> &lhs, const QVarLengthArray<T, Prealloc2> &rhs)
+ noexcept(noexcept(lhs < rhs))
+ {
+ return !(lhs < rhs);
+ }
+#endif
+
private:
void reallocate(qsizetype size, qsizetype alloc);
@@ -297,7 +370,7 @@ private:
bool isValidIterator(const const_iterator &i) const
{
- const std::less<const T*> less = {};
+ const std::less<const T *> less = {};
return !less(cend(), i) && !less(i, cbegin());
}
};
@@ -338,7 +411,8 @@ Q_INLINE_TEMPLATE void QVarLengthArray<T, Prealloc>::reserve(qsizetype asize)
{ if (asize > a) reallocate(s, asize); }
template <class T, qsizetype Prealloc>
-Q_INLINE_TEMPLATE qsizetype QVarLengthArray<T, Prealloc>::indexOf(const T &t, qsizetype from) const
+template <typename AT>
+Q_INLINE_TEMPLATE qsizetype QVarLengthArray<T, Prealloc>::indexOf(const AT &t, qsizetype from) const
{
if (from < 0)
from = qMax(from + s, qsizetype(0));
@@ -353,7 +427,8 @@ Q_INLINE_TEMPLATE qsizetype QVarLengthArray<T, Prealloc>::indexOf(const T &t, qs
}
template <class T, qsizetype Prealloc>
-Q_INLINE_TEMPLATE qsizetype QVarLengthArray<T, Prealloc>::lastIndexOf(const T &t, qsizetype from) const
+template <typename AT>
+Q_INLINE_TEMPLATE qsizetype QVarLengthArray<T, Prealloc>::lastIndexOf(const AT &t, qsizetype from) const
{
if (from < 0)
from += s;
@@ -371,7 +446,8 @@ Q_INLINE_TEMPLATE qsizetype QVarLengthArray<T, Prealloc>::lastIndexOf(const T &t
}
template <class T, qsizetype Prealloc>
-Q_INLINE_TEMPLATE bool QVarLengthArray<T, Prealloc>::contains(const T &t) const
+template <typename AT>
+Q_INLINE_TEMPLATE bool QVarLengthArray<T, Prealloc>::contains(const AT &t) const
{
T *b = ptr;
T *i = ptr + s;
@@ -394,14 +470,12 @@ Q_OUTOFLINE_TEMPLATE void QVarLengthArray<T, Prealloc>::append(const T *abuf, qs
if (asize >= a)
reallocate(s, qMax(s * 2, asize));
- if (QTypeInfo<T>::isComplex) {
- // call constructor for new objects (which can throw)
- while (s < asize)
- new (ptr+(s++)) T(*abuf++);
- } else {
+ if constexpr (QTypeInfo<T>::isComplex)
+ std::uninitialized_copy_n(abuf, increment, ptr + s);
+ else
memcpy(static_cast<void *>(&ptr[s]), static_cast<const void *>(abuf), increment * sizeof(T));
- s = asize;
- }
+
+ s = asize;
}
template <class T, qsizetype Prealloc>
@@ -419,7 +493,7 @@ Q_OUTOFLINE_TEMPLATE void QVarLengthArray<T, Prealloc>::reallocate(qsizetype asi
Q_ASSUME(copySize >= 0);
if (aalloc != a) {
if (aalloc > Prealloc) {
- T* newPtr = reinterpret_cast<T *>(malloc(aalloc * sizeof(T)));
+ T *newPtr = reinterpret_cast<T *>(malloc(aalloc * sizeof(T)));
Q_CHECK_PTR(newPtr); // could throw
// by design: in case of QT_NO_EXCEPTIONS malloc must not fail or it crashes here
ptr = newPtr;
@@ -452,10 +526,10 @@ Q_OUTOFLINE_TEMPLATE void QVarLengthArray<T, Prealloc>::reallocate(qsizetype asi
}
s = copySize;
- if (QTypeInfo<T>::isComplex) {
- // destroy remaining old objects
- while (osize > asize)
- (oldPtr+(--osize))->~T();
+ // destroy remaining old objects
+ if constexpr (QTypeInfo<T>::isComplex) {
+ if (osize > asize)
+ std::destroy(oldPtr + asize, oldPtr + osize);
}
if (oldPtr != reinterpret_cast<T *>(array) && oldPtr != ptr)
@@ -585,14 +659,10 @@ Q_OUTOFLINE_TEMPLATE typename QVarLengthArray<T, Prealloc>::iterator QVarLengthA
qsizetype f = qsizetype(abegin - ptr);
qsizetype l = qsizetype(aend - ptr);
qsizetype n = l - f;
- if (QTypeInfo<T>::isComplex) {
- std::copy(ptr + l, ptr + s, QT_MAKE_CHECKED_ARRAY_ITERATOR(ptr + f, s - f));
- T *i = ptr + s;
- T *b = ptr + s - n;
- while (i != b) {
- --i;
- i->~T();
- }
+
+ if constexpr (QTypeInfo<T>::isComplex) {
+ std::move(ptr + l, ptr + s, QT_MAKE_CHECKED_ARRAY_ITERATOR(ptr + f, s - f));
+ std::destroy(ptr + s - n, ptr + s);
} else {
memmove(static_cast<void *>(ptr + f), static_cast<const void *>(ptr + l), (s - l) * sizeof(T));
}
@@ -600,52 +670,27 @@ Q_OUTOFLINE_TEMPLATE typename QVarLengthArray<T, Prealloc>::iterator QVarLengthA
return ptr + f;
}
+#ifdef Q_QDOC
+// Fake definitions for qdoc, only the redeclaration is used.
template <typename T, qsizetype Prealloc1, qsizetype Prealloc2>
-QTypeTraits::compare_eq_result<T> operator==(const QVarLengthArray<T, Prealloc1> &l, const QVarLengthArray<T, Prealloc2> &r)
-{
- if (l.size() != r.size())
- return false;
- const T *rb = r.begin();
- const T *b = l.begin();
- const T *e = l.end();
- return std::equal(b, e, QT_MAKE_CHECKED_ARRAY_ITERATOR(rb, r.size()));
-}
-
+bool operator==(const QVarLengthArray<T, Prealloc1> &l, const QVarLengthArray<T, Prealloc2> &r)
+{ return bool{}; }
template <typename T, qsizetype Prealloc1, qsizetype Prealloc2>
-QTypeTraits::compare_eq_result<T> operator!=(const QVarLengthArray<T, Prealloc1> &l, const QVarLengthArray<T, Prealloc2> &r)
-{
- return !(l == r);
-}
-
+bool operator!=(const QVarLengthArray<T, Prealloc1> &l, const QVarLengthArray<T, Prealloc2> &r)
+{ return bool{}; }
template <typename T, qsizetype Prealloc1, qsizetype Prealloc2>
-QTypeTraits::compare_lt_result<T> operator<(const QVarLengthArray<T, Prealloc1> &lhs, const QVarLengthArray<T, Prealloc2> &rhs)
- noexcept(noexcept(std::lexicographical_compare(lhs.begin(), lhs.end(),
- rhs.begin(), rhs.end())))
-{
- return std::lexicographical_compare(lhs.begin(), lhs.end(),
- rhs.begin(), rhs.end());
-}
-
+bool operator< (const QVarLengthArray<T, Prealloc1> &l, const QVarLengthArray<T, Prealloc2> &r)
+{ return bool{}; }
template <typename T, qsizetype Prealloc1, qsizetype Prealloc2>
-QTypeTraits::compare_lt_result<T> operator>(const QVarLengthArray<T, Prealloc1> &lhs, const QVarLengthArray<T, Prealloc2> &rhs)
- noexcept(noexcept(lhs < rhs))
-{
- return rhs < lhs;
-}
-
+bool operator> (const QVarLengthArray<T, Prealloc1> &l, const QVarLengthArray<T, Prealloc2> &r)
+{ return bool{}; }
template <typename T, qsizetype Prealloc1, qsizetype Prealloc2>
-QTypeTraits::compare_lt_result<T> operator<=(const QVarLengthArray<T, Prealloc1> &lhs, const QVarLengthArray<T, Prealloc2> &rhs)
- noexcept(noexcept(lhs < rhs))
-{
- return !(lhs > rhs);
-}
-
+bool operator<=(const QVarLengthArray<T, Prealloc1> &l, const QVarLengthArray<T, Prealloc2> &r)
+{ return bool{}; }
template <typename T, qsizetype Prealloc1, qsizetype Prealloc2>
-QTypeTraits::compare_lt_result<T> operator>=(const QVarLengthArray<T, Prealloc1> &lhs, const QVarLengthArray<T, Prealloc2> &rhs)
- noexcept(noexcept(lhs < rhs))
-{
- return !(lhs < rhs);
-}
+bool operator>=(const QVarLengthArray<T, Prealloc1> &l, const QVarLengthArray<T, Prealloc2> &r)
+{ return bool{}; }
+#endif
template <typename T, qsizetype Prealloc>
size_t qHash(const QVarLengthArray<T, Prealloc> &key, size_t seed = 0)
diff --git a/src/corelib/tools/qvarlengtharray.qdoc b/src/corelib/tools/qvarlengtharray.qdoc
index 5970081d85..e454276f9d 100644
--- a/src/corelib/tools/qvarlengtharray.qdoc
+++ b/src/corelib/tools/qvarlengtharray.qdoc
@@ -874,7 +874,7 @@
\sa append(), operator<<()
*/
-/*! \fn template<class T, qsizetype Prealloc> qsizetype QVarLengthArray<T, Prealloc>::indexOf(const T &value, qsizetype from = 0) const
+/*! \fn template<class T, qsizetype Prealloc> template <typename AT = T> qsizetype QVarLengthArray<T, Prealloc>::indexOf(const AT &value, qsizetype from = 0) const
\since 5.3
Returns the index position of the first occurrence of \a value in
@@ -887,7 +887,7 @@
\sa lastIndexOf(), contains()
*/
-/*! \fn template<class T, qsizetype Prealloc> qsizetype QVarLengthArray<T, Prealloc>::lastIndexOf(const T &value, qsizetype from = -1) const
+/*! \fn template<class T, qsizetype Prealloc> template <typename AT = T> qsizetype QVarLengthArray<T, Prealloc>::lastIndexOf(const AT &value, qsizetype from = -1) const
\since 5.3
Returns the index position of the last occurrence of the value \a
@@ -901,7 +901,7 @@
\sa indexOf(), contains()
*/
-/*! \fn template<class T, qsizetype Prealloc> bool QVarLengthArray<T, Prealloc>::contains(const T &value) const
+/*! \fn template<class T, qsizetype Prealloc> template <typename AT = T> bool QVarLengthArray<T, Prealloc>::contains(const AT &value) const
\since 5.3
Returns \c true if the array contains an occurrence of \a value;
diff --git a/src/corelib/tools/qversionnumber.cpp b/src/corelib/tools/qversionnumber.cpp
index 517f026547..05c38c350f 100644
--- a/src/corelib/tools/qversionnumber.cpp
+++ b/src/corelib/tools/qversionnumber.cpp
@@ -328,8 +328,7 @@ QVersionNumber QVersionNumber::commonPrefix(const QVersionNumber &v1,
}
/*!
- \fn bool operator<(const QVersionNumber &lhs, const QVersionNumber &rhs)
- \relates QVersionNumber
+ \fn bool QVersionNumber::operator<(const QVersionNumber &lhs, const QVersionNumber &rhs)
Returns \c true if \a lhs is less than \a rhs; otherwise returns \c false.
@@ -337,8 +336,7 @@ QVersionNumber QVersionNumber::commonPrefix(const QVersionNumber &v1,
*/
/*!
- \fn bool operator<=(const QVersionNumber &lhs, const QVersionNumber &rhs)
- \relates QVersionNumber
+ \fn bool QVersionNumber::operator<=(const QVersionNumber &lhs, const QVersionNumber &rhs)
Returns \c true if \a lhs is less than or equal to \a rhs; otherwise
returns \c false.
@@ -347,8 +345,7 @@ QVersionNumber QVersionNumber::commonPrefix(const QVersionNumber &v1,
*/
/*!
- \fn bool operator>(const QVersionNumber &lhs, const QVersionNumber &rhs)
- \relates QVersionNumber
+ \fn bool QVersionNumber::operator>(const QVersionNumber &lhs, const QVersionNumber &rhs)
Returns \c true if \a lhs is greater than \a rhs; otherwise returns \c
false.
@@ -357,8 +354,7 @@ QVersionNumber QVersionNumber::commonPrefix(const QVersionNumber &v1,
*/
/*!
- \fn bool operator>=(const QVersionNumber &lhs, const QVersionNumber &rhs)
- \relates QVersionNumber
+ \fn bool QVersionNumber::operator>=(const QVersionNumber &lhs, const QVersionNumber &rhs)
Returns \c true if \a lhs is greater than or equal to \a rhs; otherwise
returns \c false.
@@ -367,8 +363,7 @@ QVersionNumber QVersionNumber::commonPrefix(const QVersionNumber &v1,
*/
/*!
- \fn bool operator==(const QVersionNumber &lhs, const QVersionNumber &rhs)
- \relates QVersionNumber
+ \fn bool QVersionNumber::operator==(const QVersionNumber &lhs, const QVersionNumber &rhs)
Returns \c true if \a lhs is equal to \a rhs; otherwise returns \c false.
@@ -376,8 +371,7 @@ QVersionNumber QVersionNumber::commonPrefix(const QVersionNumber &v1,
*/
/*!
- \fn bool operator!=(const QVersionNumber &lhs, const QVersionNumber &rhs)
- \relates QVersionNumber
+ \fn bool QVersionNumber::operator!=(const QVersionNumber &lhs, const QVersionNumber &rhs)
Returns \c true if \a lhs is not equal to \a rhs; otherwise returns
\c false.
@@ -578,7 +572,7 @@ size_t qHash(const QVersionNumber &key, size_t seed)
\fn template<typename Integer> static bool QTypeRevision::isValidSegment(Integer segment)
Returns true if the given number can be used as either major or minor
- version in a QTypeRevision. Valid segments need to be \c {>= 0} and \c {< 255}.
+ version in a QTypeRevision. The valid range for \a segment is \c {>= 0} and \c {< 255}.
*/
/*!
@@ -698,7 +692,7 @@ size_t qHash(const QVersionNumber &key, size_t seed)
Writes the revision \a revision to stream \a out.
*/
-QDataStream& operator<<(QDataStream &out, const QTypeRevision &revision)
+QDataStream &operator<<(QDataStream &out, const QTypeRevision &revision)
{
return out << revision.toEncodedVersion<quint16>();
}
@@ -710,7 +704,7 @@ QDataStream& operator<<(QDataStream &out, const QTypeRevision &revision)
Reads a revision from stream \a in and stores it in \a revision.
*/
-QDataStream& operator>>(QDataStream &in, QTypeRevision &revision)
+QDataStream &operator>>(QDataStream &in, QTypeRevision &revision)
{
quint16 value;
in >> value;
diff --git a/src/corelib/tools/qversionnumber.h b/src/corelib/tools/qversionnumber.h
index 4704db2c10..a026e40324 100644
--- a/src/corelib/tools/qversionnumber.h
+++ b/src/corelib/tools/qversionnumber.h
@@ -55,8 +55,8 @@ class QVersionNumber;
Q_CORE_EXPORT size_t qHash(const QVersionNumber &key, size_t seed = 0);
#ifndef QT_NO_DATASTREAM
-Q_CORE_EXPORT QDataStream& operator<<(QDataStream &out, const QVersionNumber &version);
-Q_CORE_EXPORT QDataStream& operator>>(QDataStream &in, QVersionNumber &version);
+Q_CORE_EXPORT QDataStream &operator<<(QDataStream &out, const QVersionNumber &version);
+Q_CORE_EXPORT QDataStream &operator>>(QDataStream &in, QVersionNumber &version);
#endif
class QVersionNumber
@@ -71,19 +71,20 @@ class QVersionNumber
enum {
// in little-endian, inline_segments[0] is shared with the pointer's LSB, while
// in big-endian, it's inline_segments[7]
- InlineSegmentMarker = Q_BYTE_ORDER == Q_LITTLE_ENDIAN ? 0 : sizeof(void*) - 1,
+ InlineSegmentMarker = Q_BYTE_ORDER == Q_LITTLE_ENDIAN ? 0 : sizeof(void *) - 1,
InlineSegmentStartIdx = !InlineSegmentMarker, // 0 for BE, 1 for LE
- InlineSegmentCount = sizeof(void*) - 1
+ InlineSegmentCount = sizeof(void *) - 1
};
static_assert(InlineSegmentCount >= 3); // at least major, minor, micro
- struct SegmentStorage {
+ struct SegmentStorage
+ {
// Note: we alias the use of dummy and inline_segments in the use of the
// union below. This is undefined behavior in C++98, but most compilers implement
// the C++11 behavior. The one known exception is older versions of Sun Studio.
union {
quintptr dummy;
- qint8 inline_segments[sizeof(void*)];
+ qint8 inline_segments[sizeof(void *)];
QList<int> *pointer_segments;
};
@@ -126,10 +127,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)
@@ -237,43 +239,62 @@ public:
inline explicit QVersionNumber(int maj, int min, int mic)
{ m_segments.setSegments(3, maj, min, mic); }
- Q_REQUIRED_RESULT inline bool isNull() const noexcept
+ [[nodiscard]] inline bool isNull() const noexcept
{ return segmentCount() == 0; }
- Q_REQUIRED_RESULT inline bool isNormalized() const noexcept
+ [[nodiscard]] inline bool isNormalized() const noexcept
{ return isNull() || segmentAt(segmentCount() - 1) != 0; }
- Q_REQUIRED_RESULT inline int majorVersion() const noexcept
+ [[nodiscard]] inline int majorVersion() const noexcept
{ return segmentAt(0); }
- Q_REQUIRED_RESULT inline int minorVersion() const noexcept
+ [[nodiscard]] inline int minorVersion() const noexcept
{ return segmentAt(1); }
- Q_REQUIRED_RESULT inline int microVersion() const noexcept
+ [[nodiscard]] inline int microVersion() const noexcept
{ return segmentAt(2); }
- Q_REQUIRED_RESULT Q_CORE_EXPORT QVersionNumber normalized() const;
+ [[nodiscard]] Q_CORE_EXPORT QVersionNumber normalized() const;
- Q_REQUIRED_RESULT Q_CORE_EXPORT QList<int> segments() const;
+ [[nodiscard]] Q_CORE_EXPORT QList<int> segments() const;
- Q_REQUIRED_RESULT inline int segmentAt(int index) const noexcept
+ [[nodiscard]] inline int segmentAt(int index) const noexcept
{ return (m_segments.size() > index) ? m_segments.at(index) : 0; }
- Q_REQUIRED_RESULT inline int segmentCount() const noexcept
+ [[nodiscard]] inline int segmentCount() const noexcept
{ return m_segments.size(); }
- Q_REQUIRED_RESULT Q_CORE_EXPORT bool isPrefixOf(const QVersionNumber &other) const noexcept;
+ [[nodiscard]] Q_CORE_EXPORT bool isPrefixOf(const QVersionNumber &other) const noexcept;
- Q_REQUIRED_RESULT Q_CORE_EXPORT static int compare(const QVersionNumber &v1, const QVersionNumber &v2) noexcept;
+ [[nodiscard]] Q_CORE_EXPORT static int compare(const QVersionNumber &v1, const QVersionNumber &v2) noexcept;
- Q_REQUIRED_RESULT Q_CORE_EXPORT static Q_DECL_PURE_FUNCTION QVersionNumber commonPrefix(const QVersionNumber &v1, const QVersionNumber &v2);
+ [[nodiscard]] Q_CORE_EXPORT static Q_DECL_PURE_FUNCTION QVersionNumber commonPrefix(const QVersionNumber &v1, const QVersionNumber &v2);
- Q_REQUIRED_RESULT Q_CORE_EXPORT QString toString() const;
+ [[nodiscard]] Q_CORE_EXPORT QString toString() const;
#if QT_STRINGVIEW_LEVEL < 2
- Q_REQUIRED_RESULT Q_CORE_EXPORT static Q_DECL_PURE_FUNCTION QVersionNumber fromString(const QString &string, int *suffixIndex = nullptr);
+ [[nodiscard]] Q_CORE_EXPORT static Q_DECL_PURE_FUNCTION QVersionNumber fromString(const QString &string, int *suffixIndex = nullptr);
#endif
- Q_REQUIRED_RESULT Q_CORE_EXPORT static Q_DECL_PURE_FUNCTION QVersionNumber fromString(QLatin1String string, int *suffixIndex = nullptr);
- Q_REQUIRED_RESULT Q_CORE_EXPORT static Q_DECL_PURE_FUNCTION QVersionNumber fromString(QStringView string, int *suffixIndex = nullptr);
+ [[nodiscard]] Q_CORE_EXPORT static Q_DECL_PURE_FUNCTION QVersionNumber fromString(QLatin1String string, int *suffixIndex = nullptr);
+ [[nodiscard]] Q_CORE_EXPORT static Q_DECL_PURE_FUNCTION QVersionNumber fromString(QStringView string, int *suffixIndex = nullptr);
+
+ [[nodiscard]] friend bool operator> (const QVersionNumber &lhs, const QVersionNumber &rhs) noexcept
+ { return compare(lhs, rhs) > 0; }
+
+ [[nodiscard]] friend bool operator>=(const QVersionNumber &lhs, const QVersionNumber &rhs) noexcept
+ { return compare(lhs, rhs) >= 0; }
+
+ [[nodiscard]] friend bool operator< (const QVersionNumber &lhs, const QVersionNumber &rhs) noexcept
+ { return compare(lhs, rhs) < 0; }
+
+ [[nodiscard]] friend bool operator<=(const QVersionNumber &lhs, const QVersionNumber &rhs) noexcept
+ { return compare(lhs, rhs) <= 0; }
+
+ [[nodiscard]] friend bool operator==(const QVersionNumber &lhs, const QVersionNumber &rhs) noexcept
+ { return compare(lhs, rhs) == 0; }
+
+ [[nodiscard]] friend bool operator!=(const QVersionNumber &lhs, const QVersionNumber &rhs) noexcept
+ { return compare(lhs, rhs) != 0; }
+
private:
#ifndef QT_NO_DATASTREAM
@@ -288,24 +309,6 @@ Q_DECLARE_TYPEINFO(QVersionNumber, Q_MOVABLE_TYPE);
Q_CORE_EXPORT QDebug operator<<(QDebug, const QVersionNumber &version);
#endif
-Q_REQUIRED_RESULT inline bool operator> (const QVersionNumber &lhs, const QVersionNumber &rhs) noexcept
-{ return QVersionNumber::compare(lhs, rhs) > 0; }
-
-Q_REQUIRED_RESULT inline bool operator>=(const QVersionNumber &lhs, const QVersionNumber &rhs) noexcept
-{ return QVersionNumber::compare(lhs, rhs) >= 0; }
-
-Q_REQUIRED_RESULT inline bool operator< (const QVersionNumber &lhs, const QVersionNumber &rhs) noexcept
-{ return QVersionNumber::compare(lhs, rhs) < 0; }
-
-Q_REQUIRED_RESULT inline bool operator<=(const QVersionNumber &lhs, const QVersionNumber &rhs) noexcept
-{ return QVersionNumber::compare(lhs, rhs) <= 0; }
-
-Q_REQUIRED_RESULT inline bool operator==(const QVersionNumber &lhs, const QVersionNumber &rhs) noexcept
-{ return QVersionNumber::compare(lhs, rhs) == 0; }
-
-Q_REQUIRED_RESULT inline bool operator!=(const QVersionNumber &lhs, const QVersionNumber &rhs) noexcept
-{ return QVersionNumber::compare(lhs, rhs) != 0; }
-
class QTypeRevision;
Q_CORE_EXPORT size_t qHash(const QTypeRevision &key, size_t seed = 0);
@@ -386,6 +389,52 @@ public:
return Integer(m_majorVersion << 8) | Integer(m_minorVersion);
}
+ [[nodiscard]] friend constexpr bool operator==(QTypeRevision lhs, QTypeRevision rhs)
+ {
+ return lhs.toEncodedVersion<quint16>() == rhs.toEncodedVersion<quint16>();
+ }
+
+ [[nodiscard]] friend constexpr bool operator!=(QTypeRevision lhs, QTypeRevision rhs)
+ {
+ return lhs.toEncodedVersion<quint16>() != rhs.toEncodedVersion<quint16>();
+ }
+
+ [[nodiscard]] friend constexpr bool operator<(QTypeRevision lhs, QTypeRevision rhs)
+ {
+ return (!lhs.hasMajorVersion() && rhs.hasMajorVersion())
+ // non-0 major > unspecified major > major 0
+ ? rhs.majorVersion() != 0
+ : ((lhs.hasMajorVersion() && !rhs.hasMajorVersion())
+ // major 0 < unspecified major < non-0 major
+ ? lhs.majorVersion() == 0
+ : (lhs.majorVersion() != rhs.majorVersion()
+ // both majors specified and non-0
+ ? lhs.majorVersion() < rhs.majorVersion()
+ : ((!lhs.hasMinorVersion() && rhs.hasMinorVersion())
+ // non-0 minor > unspecified minor > minor 0
+ ? rhs.minorVersion() != 0
+ : ((lhs.hasMinorVersion() && !rhs.hasMinorVersion())
+ // minor 0 < unspecified minor < non-0 minor
+ ? lhs.minorVersion() == 0
+ // both minors specified and non-0
+ : lhs.minorVersion() < rhs.minorVersion()))));
+ }
+
+ [[nodiscard]] friend constexpr bool operator>(QTypeRevision lhs, QTypeRevision rhs)
+ {
+ return lhs != rhs && !(lhs < rhs);
+ }
+
+ [[nodiscard]] friend constexpr bool operator<=(QTypeRevision lhs, QTypeRevision rhs)
+ {
+ return lhs == rhs || lhs < rhs;
+ }
+
+ [[nodiscard]] friend constexpr bool operator>=(QTypeRevision lhs, QTypeRevision rhs)
+ {
+ return lhs == rhs || !(lhs < rhs);
+ }
+
private:
enum { SegmentUnknown = 0xff };
@@ -404,52 +453,6 @@ private:
#endif
};
-inline constexpr bool operator==(QTypeRevision lhs, QTypeRevision rhs)
-{
- return lhs.toEncodedVersion<quint16>() == rhs.toEncodedVersion<quint16>();
-}
-
-inline constexpr bool operator!=(QTypeRevision lhs, QTypeRevision rhs)
-{
- return lhs.toEncodedVersion<quint16>() != rhs.toEncodedVersion<quint16>();
-}
-
-inline constexpr bool operator<(QTypeRevision lhs, QTypeRevision rhs)
-{
- return (!lhs.hasMajorVersion() && rhs.hasMajorVersion())
- // non-0 major > unspecified major > major 0
- ? rhs.majorVersion() != 0
- : ((lhs.hasMajorVersion() && !rhs.hasMajorVersion())
- // major 0 < unspecified major < non-0 major
- ? lhs.majorVersion() == 0
- : (lhs.majorVersion() != rhs.majorVersion()
- // both majors specified and non-0
- ? lhs.majorVersion() < rhs.majorVersion()
- : ((!lhs.hasMinorVersion() && rhs.hasMinorVersion())
- // non-0 minor > unspecified minor > minor 0
- ? rhs.minorVersion() != 0
- : ((lhs.hasMinorVersion() && !rhs.hasMinorVersion())
- // minor 0 < unspecified minor < non-0 minor
- ? lhs.minorVersion() == 0
- // both minors specified and non-0
- : lhs.minorVersion() < rhs.minorVersion()))));
-}
-
-inline constexpr bool operator>(QTypeRevision lhs, QTypeRevision rhs)
-{
- return lhs != rhs && !(lhs < rhs);
-}
-
-inline constexpr bool operator<=(QTypeRevision lhs, QTypeRevision rhs)
-{
- return lhs == rhs || lhs < rhs;
-}
-
-inline constexpr bool operator>=(QTypeRevision lhs, QTypeRevision rhs)
-{
- return lhs == rhs || !(lhs < rhs);
-}
-
static_assert(sizeof(QTypeRevision) == 2);
Q_DECLARE_TYPEINFO(QTypeRevision, Q_MOVABLE_TYPE);
@@ -462,4 +465,4 @@ QT_END_NAMESPACE
Q_DECLARE_METATYPE(QVersionNumber)
Q_DECLARE_METATYPE(QTypeRevision)
-#endif //QVERSIONNUMBER_H
+#endif // QVERSIONNUMBER_H
diff --git a/src/corelib/tools/tools.pri b/src/corelib/tools/tools.pri
index e57fa6e8ed..9c94da0969 100644
--- a/src/corelib/tools/tools.pri
+++ b/src/corelib/tools/tools.pri
@@ -34,7 +34,6 @@ HEADERS += \
tools/qrefcount.h \
tools/qscopeguard.h \
tools/qscopedpointer.h \
- tools/qscopedpointer_p.h \
tools/qscopedvaluerollback.h \
tools/qshareddata.h \
tools/qshareddata_impl.h \