diff options
Diffstat (limited to 'src/corelib/tools/qvector.h')
-rw-r--r-- | src/corelib/tools/qvector.h | 95 |
1 files changed, 75 insertions, 20 deletions
diff --git a/src/corelib/tools/qvector.h b/src/corelib/tools/qvector.h index e225ce1ecb..9a6e67cc0b 100644 --- a/src/corelib/tools/qvector.h +++ b/src/corelib/tools/qvector.h @@ -59,8 +59,6 @@ QT_BEGIN_NAMESPACE -class QRegion; - template <typename T> class QVector { @@ -74,7 +72,7 @@ public: inline QVector(const QVector<T> &v); inline ~QVector() { if (!d->ref.deref()) freeData(d); } QVector<T> &operator=(const QVector<T> &v); -#ifdef Q_COMPILER_RVALUE_REFS +#if defined(Q_COMPILER_RVALUE_REFS) || defined(Q_CLANG_QDOC) QVector(QVector<T> &&other) Q_DECL_NOTHROW : d(other.d) { other.d = Data::sharedNull(); } QVector<T> &operator=(QVector<T> &&other) Q_DECL_NOTHROW { QVector moved(std::move(other)); swap(moved); return *this; } @@ -135,11 +133,13 @@ public: T &operator[](int i); const T &operator[](int i) const; void append(const T &t); -#ifdef Q_COMPILER_RVALUE_REFS +#if defined(Q_COMPILER_RVALUE_REFS) || defined(Q_CLANG_QDOC) void append(T &&t); #endif inline void append(const QVector<T> &l) { *this += l; } + void prepend(T &&t); void prepend(const T &t); + void insert(int i, T &&t); void insert(int i, const T &t); void insert(int i, int n, const T &t); void replace(int i, const T &t); @@ -147,8 +147,8 @@ public: void remove(int i, int n); inline void removeFirst() { Q_ASSERT(!isEmpty()); erase(d->begin()); } inline void removeLast(); - inline T takeFirst() { Q_ASSERT(!isEmpty()); T r = first(); removeFirst(); return r; } - inline T takeLast() { Q_ASSERT(!isEmpty()); T r = last(); removeLast(); return r; } + T takeFirst() { Q_ASSERT(!isEmpty()); T r = std::move(first()); removeFirst(); return r; } + T takeLast() { Q_ASSERT(!isEmpty()); T r = std::move(last()); removeLast(); return r; } QVector<T> &fill(const T &t, int size = -1); @@ -181,7 +181,7 @@ public: return true; } int length() const { return size(); } - T takeAt(int i) { T t = at(i); remove(i); return t; } + T takeAt(int i) { T t = std::move((*this)[i]); remove(i); return t; } void move(int from, int to) { Q_ASSERT_X(from >= 0 && from < size(), "QVector::move(int,int)", "'from' is out-of-range"); @@ -201,7 +201,7 @@ public: typedef typename Data::const_iterator const_iterator; typedef std::reverse_iterator<iterator> reverse_iterator; typedef std::reverse_iterator<const_iterator> const_reverse_iterator; -#if !defined(QT_STRICT_ITERATORS) || defined(Q_QDOC) +#if !defined(QT_STRICT_ITERATORS) || defined(Q_CLANG_QDOC) inline iterator begin() { detach(); return d->begin(); } inline const_iterator begin() const Q_DECL_NOTHROW { return d->constBegin(); } inline const_iterator cbegin() const Q_DECL_NOTHROW { return d->constBegin(); } @@ -228,6 +228,7 @@ public: const_reverse_iterator crend() const Q_DECL_NOTHROW { return const_reverse_iterator(begin()); } iterator insert(iterator before, int n, const T &x); inline iterator insert(iterator before, const T &x) { return insert(before, 1, x); } + inline iterator insert(iterator before, T &&x); iterator erase(iterator begin, iterator end); inline iterator erase(iterator pos) { return erase(pos, pos+1); } @@ -257,8 +258,9 @@ public: typedef const_iterator ConstIterator; typedef int size_type; inline void push_back(const T &t) { append(t); } -#ifdef Q_COMPILER_RVALUE_REFS +#if defined(Q_COMPILER_RVALUE_REFS) || defined(Q_CLANG_QDOC) void push_back(T &&t) { append(std::move(t)); } + void push_front(T &&t) { prepend(std::move(t)); } #endif inline void push_front(const T &t) { prepend(t); } void pop_back() { removeLast(); } @@ -269,6 +271,7 @@ public: inline const_reference front() const { return first(); } inline reference back() { return last(); } inline const_reference back() const { return last(); } + void shrink_to_fit() { squeeze(); } // comfort QVector<T> &operator+=(const QVector<T> &l); @@ -290,8 +293,6 @@ public: inline std::vector<T> toStdVector() const { return std::vector<T>(d->begin(), d->end()); } private: - friend class QRegion; // Optimization for QRegion::rects() - // ### Qt6: remove const from int parameters void reallocData(const int size, const int alloc, QArrayData::AllocationOptions options = QArrayData::Default); void reallocData(const int sz) { reallocData(sz, d->alloc); } @@ -439,6 +440,10 @@ inline void QVector<T>::insert(int i, int n, const T &t) { Q_ASSERT_X(i >= 0 && i <= d->size, "QVector<T>::insert", "index out of range"); insert(begin() + i, n, t); } template <typename T> +inline void QVector<T>::insert(int i, T &&t) +{ Q_ASSERT_X(i >= 0 && i <= d->size, "QVector<T>::insert", "index out of range"); + insert(begin() + i, std::move(t)); } +template <typename T> inline void QVector<T>::remove(int i, int n) { Q_ASSERT_X(i >= 0 && n >= 0 && i + n <= d->size, "QVector<T>::remove", "index out of range"); erase(d->begin() + i, d->begin() + i + n); } @@ -449,6 +454,9 @@ inline void QVector<T>::remove(int i) template <typename T> inline void QVector<T>::prepend(const T &t) { insert(begin(), 1, t); } +template <typename T> +inline void QVector<T>::prepend(T &&t) +{ insert(begin(), std::move(t)); } template <typename T> inline void QVector<T>::replace(int i, const T &t) @@ -561,9 +569,19 @@ void QVector<T>::reallocData(const int asize, const int aalloc, QArrayData::Allo T *dst = x->begin(); if (!QTypeInfoQuery<T>::isRelocatable || (isShared && QTypeInfo<T>::isComplex)) { - // we can not move the data, we need to copy construct it - while (srcBegin != srcEnd) { - new (dst++) T(*srcBegin++); + QT_TRY { + if (isShared || !std::is_nothrow_move_constructible<T>::value) { + // we can not move the data, we need to copy construct it + while (srcBegin != srcEnd) + new (dst++) T(*srcBegin++); + } else { + while (srcBegin != srcEnd) + new (dst++) T(std::move(*srcBegin++)); + } + } QT_CATCH (...) { + // destruct already copied objects + destruct(x->begin(), dst); + QT_RETHROW; } } else { ::memcpy(static_cast<void *>(dst), static_cast<void *>(srcBegin), (srcEnd - srcBegin) * sizeof(T)); @@ -576,12 +594,17 @@ void QVector<T>::reallocData(const int asize, const int aalloc, QArrayData::Allo if (asize > d->size) { // construct all new objects when growing - QT_TRY { - defaultConstruct(dst, x->end()); - } QT_CATCH (...) { - // destruct already copied objects - destruct(x->begin(), dst); - QT_RETHROW; + if (!QTypeInfo<T>::isComplex) { + ::memset(static_cast<void *>(dst), 0, (static_cast<T *>(x->end()) - dst) * sizeof(T)); + } else { + QT_TRY { + while (dst != x->end()) + new (dst++) T(); + } QT_CATCH (...) { + // destruct already copied objects + destruct(x->begin(), dst); + QT_RETHROW; + } } } } QT_CATCH (...) { @@ -734,6 +757,36 @@ typename QVector<T>::iterator QVector<T>::insert(iterator before, size_type n, c } template <typename T> +typename QVector<T>::iterator QVector<T>::insert(iterator before, T &&t) +{ + Q_ASSERT_X(isValidIterator(before), "QVector::insert", "The specified iterator argument 'before' is invalid"); + + const auto offset = std::distance(d->begin(), before); + if (!isDetached() || d->size + 1 > int(d->alloc)) + reallocData(d->size, d->size + 1, QArrayData::Grow); + if (!QTypeInfoQuery<T>::isRelocatable) { + T *i = d->end(); + T *j = i + 1; + T *b = d->begin() + offset; + // The new end-element needs to be constructed, the rest must be move assigned + if (i != b) { + new (--j) T(std::move(*--i)); + while (i != b) + *--j = std::move(*--i); + *b = std::move(t); + } else { + new (b) T(std::move(t)); + } + } else { + T *b = d->begin() + offset; + memmove(b + 1, b, (d->size - offset) * sizeof(T)); + new (b) T(std::move(t)); + } + d->size += 1; + return d->begin() + offset; +} + +template <typename T> typename QVector<T>::iterator QVector<T>::erase(iterator abegin, iterator aend) { Q_ASSERT_X(isValidIterator(abegin), "QVector::erase", "The specified iterator argument 'abegin' is invalid"); @@ -1004,6 +1057,8 @@ Q_TEMPLATE_EXTERN template class Q_CORE_EXPORT QVector<QPointF>; Q_TEMPLATE_EXTERN template class Q_CORE_EXPORT QVector<QPoint>; #endif +QVector<uint> QStringView::toUcs4() const { return QtPrivate::convertToUcs4(*this); } + QT_END_NAMESPACE #endif // QVECTOR_H |