diff options
Diffstat (limited to 'src/corelib/tools/qvarlengtharray.h')
-rw-r--r-- | src/corelib/tools/qvarlengtharray.h | 126 |
1 files changed, 54 insertions, 72 deletions
diff --git a/src/corelib/tools/qvarlengtharray.h b/src/corelib/tools/qvarlengtharray.h index 54603bcec1..6ae3cc8308 100644 --- a/src/corelib/tools/qvarlengtharray.h +++ b/src/corelib/tools/qvarlengtharray.h @@ -172,6 +172,13 @@ public: template <typename Predicate> qsizetype removeIf(Predicate pred); + void clear() + { + if constexpr (QTypeInfo<T>::isComplex) + std::destroy_n(data(), size()); + s = 0; + } + iterator erase(const_iterator begin, const_iterator end); iterator erase(const_iterator pos) { return erase(pos, pos + 1); } @@ -180,11 +187,13 @@ public: return qHashRange(begin(), end(), seed); } protected: + void growBy(qsizetype prealloc, void *array, qsizetype increment) + { reallocate_impl(prealloc, array, size(), (std::max)(size() * 2, size() + increment)); } template <typename...Args> reference emplace_back_impl(qsizetype prealloc, void *array, Args&&...args) { if (size() == capacity()) // ie. size() != 0 - reallocate_impl(prealloc, array, size(), size() << 1); + growBy(prealloc, array, 1); reference r = *new (end()) T(std::forward<Args>(args)...); ++s; return r; @@ -206,9 +215,32 @@ protected: } void append_impl(qsizetype prealloc, void *array, const T *buf, qsizetype n); - void reallocate_impl(qsizetype prealloc, void *array, qsizetype size, qsizetype alloc, const T *v = nullptr); - void resize_impl(qsizetype prealloc, void *array, qsizetype sz, const T *v = nullptr) - { reallocate_impl(prealloc, array, sz, qMax(sz, capacity()), v); } + void reallocate_impl(qsizetype prealloc, void *array, qsizetype size, qsizetype alloc); + void resize_impl(qsizetype prealloc, void *array, qsizetype sz, const T &v) + { + if (QtPrivate::q_points_into_range(&v, begin(), end())) { + resize_impl(prealloc, array, sz, T(v)); + return; + } + reallocate_impl(prealloc, array, sz, qMax(sz, capacity())); + while (size() < sz) { + new (data() + size()) T(v); + ++s; + } + } + void resize_impl(qsizetype prealloc, void *array, qsizetype sz) + { + reallocate_impl(prealloc, array, sz, qMax(sz, capacity())); + if constexpr (QTypeInfo<T>::isComplex) { + // call default constructor for new objects (which can throw) + while (size() < sz) { + new (data() + size()) T; + ++s; + } + } else { + s = sz; + } + } bool isValidIterator(const const_iterator &i) const { @@ -378,8 +410,11 @@ public: template <typename U = T, if_copyable<U> = true> #endif void resize(qsizetype sz, const T &v) - { Base::resize_impl(Prealloc, this->array, sz, &v); } + { Base::resize_impl(Prealloc, this->array, sz, v); } + using Base::clear; +#ifdef Q_QDOC inline void clear() { resize(0); } +#endif void squeeze() { reallocate(size(), size()); } using Base::capacity; @@ -695,7 +730,7 @@ Q_OUTOFLINE_TEMPLATE void QVLABase<T>::append_impl(qsizetype prealloc, void *arr const qsizetype asize = size() + increment; if (asize >= capacity()) - reallocate_impl(prealloc, array, size(), qMax(size() * 2, asize)); + growBy(prealloc, array, increment); if constexpr (QTypeInfo<T>::isComplex) std::uninitialized_copy_n(abuf, increment, end()); @@ -706,7 +741,7 @@ Q_OUTOFLINE_TEMPLATE void QVLABase<T>::append_impl(qsizetype prealloc, void *arr } template <class T> -Q_OUTOFLINE_TEMPLATE void QVLABase<T>::reallocate_impl(qsizetype prealloc, void *array, qsizetype asize, qsizetype aalloc, const T *v) +Q_OUTOFLINE_TEMPLATE void QVLABase<T>::reallocate_impl(qsizetype prealloc, void *array, qsizetype asize, qsizetype aalloc) { Q_ASSERT(aalloc >= asize); Q_ASSERT(data()); @@ -747,26 +782,6 @@ Q_OUTOFLINE_TEMPLATE void QVLABase<T>::reallocate_impl(qsizetype prealloc, void if (oldPtr != reinterpret_cast<T *>(array) && oldPtr != data()) free(oldPtr); - - if (v) { - if constexpr (std::is_copy_constructible_v<T>) { - while (size() < asize) { - new (data() + size()) T(*v); - ++s; - } - } else { - Q_UNREACHABLE(); - } - } else if constexpr (QTypeInfo<T>::isComplex) { - // call default constructor for new objects (which can throw) - while (size() < asize) { - new (data() + size()) T; - ++s; - } - } else { - s = asize; - } - } template <class T> @@ -834,29 +849,12 @@ Q_OUTOFLINE_TEMPLATE auto QVLABase<T>::emplace_impl(qsizetype prealloc, void *ar Q_ASSERT(size() <= capacity()); Q_ASSERT(capacity() > 0); - qsizetype offset = qsizetype(before - cbegin()); - if (size() == capacity()) - reallocate_impl(prealloc, array, size(), size() * 2); - if constexpr (!QTypeInfo<T>::isRelocatable) { - T *b = begin() + offset; - T *i = end(); - T *j = i + 1; - // 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 = T(std::forward<Args>(args)...); - } else { - new (b) T(std::forward<Args>(args)...); - } - } else { - T *b = begin() + offset; - memmove(static_cast<void *>(b + 1), static_cast<const void *>(b), (size() - offset) * sizeof(T)); - new (b) T(std::forward<Args>(args)...); - } - this->s += 1; - return data() + offset; + const qsizetype offset = qsizetype(before - cbegin()); + emplace_back_impl(prealloc, array, std::forward<Args>(args)...); + const auto b = begin() + offset; + const auto e = end(); + QtPrivate::q_rotate(b, e - 1, e); + return b; } template <class T> @@ -864,28 +862,12 @@ Q_OUTOFLINE_TEMPLATE auto QVLABase<T>::insert_impl(qsizetype prealloc, void *arr { Q_ASSERT_X(isValidIterator(before), "QVarLengthArray::insert", "The specified const_iterator argument 'before' is invalid"); - qsizetype offset = qsizetype(before - cbegin()); - if (n != 0) { - const T copy(t); // `t` could alias an element in [begin(), end()[ - resize_impl(prealloc, array, size() + n); - if constexpr (!QTypeInfo<T>::isRelocatable) { - T *b = begin() + offset; - T *j = end(); - T *i = j - n; - while (i != b) - *--j = *--i; - i = b + n; - while (i != b) - *--i = copy; - } else { - T *b = begin() + offset; - T *i = b + n; - memmove(static_cast<void *>(i), static_cast<const void *>(b), (size() - offset - n) * sizeof(T)); - while (i != b) - new (--i) T(copy); - } - } - return data() + offset; + const qsizetype offset = qsizetype(before - cbegin()); + resize_impl(prealloc, array, size() + n, t); + const auto b = begin() + offset; + const auto e = end(); + QtPrivate::q_rotate(b, e - n, e); + return b; } template <class T> |