diff options
author | Dennis Oberst <dennis.oberst@qt.io> | 2022-12-21 14:12:05 +0100 |
---|---|---|
committer | Dennis Oberst <dennis.oberst@qt.io> | 2023-02-08 21:13:08 +0100 |
commit | 7cbdc8abbda12488f51317313347bbc220b42fe0 (patch) | |
tree | 2babcf1fc2b0d53eaf56196477a6323935f6dc9c /src/corelib | |
parent | 65cda1f06aa24d9b75e81b37a5c23dcedbc53b92 (diff) |
QVarLengthArray: add STL-style assign()
Implemented assign() methods for QVarLengthArray to align
with the criteria of std::vector, addressing the previously
missing functionality.
Reference:
https://en.cppreference.com/w/cpp/container/vector/assign
[ChangeLog][QtCore][QVarLengthArray] Added assign().
Fixes: QTBUG-106200
Change-Id: If671069808ff561b0f4c77b6c7f7aca360a0c663
Reviewed-by: Marc Mutz <marc.mutz@qt.io>
Diffstat (limited to 'src/corelib')
-rw-r--r-- | src/corelib/tools/qvarlengtharray.h | 62 | ||||
-rw-r--r-- | src/corelib/tools/qvarlengtharray.qdoc | 40 |
2 files changed, 100 insertions, 2 deletions
diff --git a/src/corelib/tools/qvarlengtharray.h b/src/corelib/tools/qvarlengtharray.h index 27083442c5..f573855598 100644 --- a/src/corelib/tools/qvarlengtharray.h +++ b/src/corelib/tools/qvarlengtharray.h @@ -231,6 +231,10 @@ protected: } } + void assign_impl(qsizetype prealloc, void *array, qsizetype n, const T &t); + template <typename Iterator> + void assign_impl(qsizetype prealloc, void *array, Iterator first, Iterator last); + bool isValidIterator(const const_iterator &i) const { const std::less<const T *> less = {}; @@ -258,6 +262,8 @@ class QVarLengthArray template <typename U> using if_copyable = std::enable_if_t<std::is_copy_constructible_v<U>, bool>; + template <typename InputIterator> + using if_input_iterator = QtPrivate::IfIsInputIterator<InputIterator>; public: using size_type = typename Base::size_type; using value_type = typename Base::value_type; @@ -319,7 +325,7 @@ public: { } - template <typename InputIterator, QtPrivate::IfIsInputIterator<InputIterator> = true> + template <typename InputIterator, if_input_iterator<InputIterator> = true> inline QVarLengthArray(InputIterator first, InputIterator last) : QVarLengthArray() { @@ -480,6 +486,15 @@ public: void insert(qsizetype i, T &&t); void insert(qsizetype i, const T &t); void insert(qsizetype i, qsizetype n, const T &t); + + void assign(qsizetype n, const T &t) + { Base::assign_impl(Prealloc, this->array, n, t); } + template <typename InputIterator, if_input_iterator<InputIterator> = true> + void assign(InputIterator first, InputIterator last) + { Base::assign_impl(Prealloc, this->array, first, last); } + void assign(std::initializer_list<T> list) + { assign(list.begin(), list.end()); } + #ifdef Q_QDOC void replace(qsizetype i, const T &t); void remove(qsizetype i, qsizetype n = 1); @@ -732,6 +747,51 @@ Q_OUTOFLINE_TEMPLATE void QVLABase<T>::append_impl(qsizetype prealloc, void *arr } template <class T> +Q_OUTOFLINE_TEMPLATE void QVLABase<T>::assign_impl(qsizetype prealloc, void *array, qsizetype n, const T &t) +{ + Q_ASSERT(n >= 0); + if (n > capacity()) { + reallocate_impl(prealloc, array, 0, capacity()); // clear + resize_impl(prealloc, array, n, t); + } else { + auto mid = (std::min)(n, size()); + std::fill(data(), data() + mid, t); + std::uninitialized_fill(data() + mid, data() + n, t); + s = n; + erase(data() + n, data() + size()); + } +} + +template <class T> +template <typename Iterator> +Q_OUTOFLINE_TEMPLATE void QVLABase<T>::assign_impl(qsizetype prealloc, void *array, Iterator first, Iterator last) +{ + // This function only provides the basic exception guarantee. + if constexpr (std::is_convertible_v<typename std::iterator_traits<Iterator>::iterator_category, std::forward_iterator_tag>) { + const qsizetype n = std::distance(first, last); + if (n > capacity()) { + reallocate_impl(prealloc, array, 0, capacity()); // clear + reallocate_impl(prealloc, array, 0, n); // reserve n + } + } + + auto dst = begin(); + while (first != last && dst != end()) { + *dst = *first; // reuse initialized buffer + ++dst; + ++first; + } + + qsizetype n = dst - begin(); + while (first != last) { + emplace_back_impl(prealloc, array, *first); + ++first; + ++n; + } + erase(data() + n, data() + size()); +} + +template <class T> Q_OUTOFLINE_TEMPLATE void QVLABase<T>::reallocate_impl(qsizetype prealloc, void *array, qsizetype asize, qsizetype aalloc) { Q_ASSERT(aalloc >= asize); diff --git a/src/corelib/tools/qvarlengtharray.qdoc b/src/corelib/tools/qvarlengtharray.qdoc index 4f41304c03..3ad8a82857 100644 --- a/src/corelib/tools/qvarlengtharray.qdoc +++ b/src/corelib/tools/qvarlengtharray.qdoc @@ -103,11 +103,14 @@ lists. */ -/*! \fn template<class T, qsizetype Prealloc> template<typename InputIterator> QVarLengthArray<T, Prealloc>::QVarLengthArray(InputIterator first, InputIterator last) +/*! \fn template<class T, qsizetype Prealloc> template<typename InputIterator, if_input_iterator<InputIterator>> QVarLengthArray<T, Prealloc>::QVarLengthArray(InputIterator first, InputIterator last) \since 5.14 Constructs an array with the contents in the iterator range [\a first, \a last). + This constructor only participates in overload resolution if + \c InputIterator models the \c std::input_iterator concept. + The value type of \c InputIterator must be convertible to \c T. */ @@ -992,3 +995,38 @@ \sa erase() */ + +/*! \fn template <class T, qsizetype Prealloc> void QVarLengthArray<T, Prealloc>::assign(qsizetype n, const T &t) + \since 6.6 + + Replaces the contents of this container with \a n copies of \a t. + + The size of this container will be equal to \a n. This function will only + allocate memory if \a n exceeds the capacity of the container. +*/ + +/*! \fn template <class T, qsizetype Prealloc> template <typename InputIterator, if_input_iterator<InputIterator>> void QVarLengthArray<T, Prealloc>::assign(InputIterator first, InputIterator last) + \since 6.6 + + Replaces the contents of this container with a copy of the elements in the + iterator range [\a first, \a last). + + The size of this container will be equal to the number of elements in the + range [\a first, \a last). This function will only allocate memory if the + number of elements in the range exceeds the capacity of the container. + + This function overload only participates in overload resolution if + \c InputIterator models the \c std::input_iterator concept. + The behavior is undefined if either argument is an iterator into *this. +*/ + +/*! \fn template <class T, qsizetype Prealloc> void QVarLengthArray<T, Prealloc>::assign(std::initializer_list<T> list) + \since 6.6 + + Replaces the contents of this container with a copy of the elements of \a list. + + The size of this container will be equal to the number of elements in \a list. + + This function only allocates memory if the number of elements in \a list + exceeds the capacity of the container. +*/ |