summaryrefslogtreecommitdiffstats
path: root/src/corelib
diff options
context:
space:
mode:
authorDennis Oberst <dennis.oberst@qt.io>2022-12-21 14:12:05 +0100
committerDennis Oberst <dennis.oberst@qt.io>2023-02-08 21:13:08 +0100
commit7cbdc8abbda12488f51317313347bbc220b42fe0 (patch)
tree2babcf1fc2b0d53eaf56196477a6323935f6dc9c /src/corelib
parent65cda1f06aa24d9b75e81b37a5c23dcedbc53b92 (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.h62
-rw-r--r--src/corelib/tools/qvarlengtharray.qdoc40
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.
+*/