QVarLengthArray: use new q20::construct_at instead of raw placement new

The former is much safer to use in the presence of overloaded operator
new, and forms a tiny step towards a fully C++20-constexpr QVLA in the
future.

Pick-to: 6.5
Change-Id: If1b31c06296a60c39f1c9f9da523e208ecb1248b
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
This commit is contained in:
Marc Mutz 2023-02-08 10:41:09 +01:00 committed by Dennis Oberst
parent ed26352a10
commit 230bc059ae

View File

@ -18,7 +18,7 @@
#include <algorithm> #include <algorithm>
#include <initializer_list> #include <initializer_list>
#include <iterator> #include <iterator>
#include <memory> #include <QtCore/q20memory.h>
#include <new> #include <new>
#include <string.h> #include <string.h>
@ -187,7 +187,7 @@ protected:
{ {
if (size() == capacity()) // ie. size() != 0 if (size() == capacity()) // ie. size() != 0
growBy(prealloc, array, 1); growBy(prealloc, array, 1);
reference r = *new (end()) T(std::forward<Args>(args)...); reference r = *q20::construct_at(end(), std::forward<Args>(args)...);
++s; ++s;
return r; return r;
} }
@ -213,7 +213,7 @@ protected:
{ {
reallocate_impl(prealloc, array, sz, qMax(sz, capacity())); reallocate_impl(prealloc, array, sz, qMax(sz, capacity()));
while (size() < sz) { while (size() < sz) {
new (data() + size()) T(v); q20::construct_at(data() + size(), v);
++s; ++s;
} }
} }
@ -223,7 +223,7 @@ protected:
if constexpr (QTypeInfo<T>::isComplex) { if constexpr (QTypeInfo<T>::isComplex) {
// call default constructor for new objects (which can throw) // call default constructor for new objects (which can throw)
while (size() < sz) { while (size() < sz) {
new (data() + size()) T; q20::construct_at(data() + size());
++s; ++s;
} }
} else { } else {
@ -674,7 +674,7 @@ Q_INLINE_TEMPLATE QVarLengthArray<T, Prealloc>::QVarLengthArray(qsizetype asize)
if constexpr (QTypeInfo<T>::isComplex) { if constexpr (QTypeInfo<T>::isComplex) {
T *i = end(); T *i = end();
while (i != begin()) while (i != begin())
new (--i) T; q20::construct_at(--i);
} }
} }
@ -909,17 +909,17 @@ Q_OUTOFLINE_TEMPLATE auto QVLABase<T>::emplace_impl(qsizetype prealloc, void *ar
T *j = i + 1; T *j = i + 1;
// The new end-element needs to be constructed, the rest must be move assigned // The new end-element needs to be constructed, the rest must be move assigned
if (i != b) { if (i != b) {
new (--j) T(std::move(*--i)); q20::construct_at(--j, std::move(*--i));
while (i != b) while (i != b)
*--j = std::move(*--i); *--j = std::move(*--i);
*b = T(std::forward<Args>(args)...); *b = T(std::forward<Args>(args)...);
} else { } else {
new (b) T(std::forward<Args>(args)...); q20::construct_at(b, std::forward<Args>(args)...);
} }
} else { } else {
T *b = begin() + offset; T *b = begin() + offset;
memmove(static_cast<void *>(b + 1), static_cast<const void *>(b), (size() - offset) * sizeof(T)); memmove(static_cast<void *>(b + 1), static_cast<const void *>(b), (size() - offset) * sizeof(T));
new (b) T(std::forward<Args>(args)...); q20::construct_at(b, std::forward<Args>(args)...);
} }
this->s += 1; this->s += 1;
return data() + offset; return data() + offset;
@ -948,7 +948,7 @@ Q_OUTOFLINE_TEMPLATE auto QVLABase<T>::insert_impl(qsizetype prealloc, void *arr
T *i = b + n; T *i = b + n;
memmove(static_cast<void *>(i), static_cast<const void *>(b), (size() - offset - n) * sizeof(T)); memmove(static_cast<void *>(i), static_cast<const void *>(b), (size() - offset - n) * sizeof(T));
while (i != b) while (i != b)
new (--i) T(copy); q20::construct_at(--i, copy);
} }
} }
return data() + offset; return data() + offset;