diff --git a/src/corelib/tools/qvarlengtharray.h b/src/corelib/tools/qvarlengtharray.h index 204364b52f..9377cc50b4 100644 --- a/src/corelib/tools/qvarlengtharray.h +++ b/src/corelib/tools/qvarlengtharray.h @@ -208,14 +208,27 @@ 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 reallocate_impl(qsizetype prealloc, void *array, qsizetype size, qsizetype alloc); void resize_impl(qsizetype prealloc, void *array, qsizetype sz, const T &v) { - reallocate_impl(prealloc, array, sz, qMax(sz, capacity()), &v); + 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::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 @@ -714,7 +727,7 @@ Q_OUTOFLINE_TEMPLATE void QVLABase::append_impl(qsizetype prealloc, void *arr } template -Q_OUTOFLINE_TEMPLATE void QVLABase::reallocate_impl(qsizetype prealloc, void *array, qsizetype asize, qsizetype aalloc, const T *v) +Q_OUTOFLINE_TEMPLATE void QVLABase::reallocate_impl(qsizetype prealloc, void *array, qsizetype asize, qsizetype aalloc) { Q_ASSERT(aalloc >= asize); Q_ASSERT(data()); @@ -755,26 +768,6 @@ Q_OUTOFLINE_TEMPLATE void QVLABase::reallocate_impl(qsizetype prealloc, void if (oldPtr != reinterpret_cast(array) && oldPtr != data()) free(oldPtr); - - if (v) { - if constexpr (std::is_copy_constructible_v) { - while (size() < asize) { - new (data() + size()) T(*v); - ++s; - } - } else { - Q_UNREACHABLE(); - } - } else if constexpr (QTypeInfo::isComplex) { - // call default constructor for new objects (which can throw) - while (size() < asize) { - new (data() + size()) T; - ++s; - } - } else { - s = asize; - } - } template diff --git a/tests/auto/corelib/tools/qvarlengtharray/tst_qvarlengtharray.cpp b/tests/auto/corelib/tools/qvarlengtharray/tst_qvarlengtharray.cpp index 81edb36916..105a3b27bf 100644 --- a/tests/auto/corelib/tools/qvarlengtharray/tst_qvarlengtharray.cpp +++ b/tests/auto/corelib/tools/qvarlengtharray/tst_qvarlengtharray.cpp @@ -92,6 +92,8 @@ private slots: void remove(); void erase(); + // special cases: + void copesWithCopyabilityOfMoveOnlyVector(); // QTBUG-109745 private: template void defaultConstructor(); @@ -1640,5 +1642,26 @@ void tst_QVarLengthArray::erase() QCOMPARE(arr, QVarLengthArray({ "val0" })); } +void tst_QVarLengthArray::copesWithCopyabilityOfMoveOnlyVector() +{ + // std::vector is_copyable + // (https://quuxplusone.github.io/blog/2020/02/05/vector-is-copyable-except-when-its-not/) + + QVarLengthArray>, 2> vla; + vla.emplace_back(42); + vla.emplace_back(43); + vla.emplace_back(44); // goes to the heap + QCOMPARE_EQ(vla.size(), 3); + QCOMPARE_EQ(vla.front().size(), 42U); + QCOMPARE_EQ(vla.front().front(), nullptr); + QCOMPARE_EQ(vla.back().size(), 44U); + + auto moved = std::move(vla); + QCOMPARE_EQ(moved.size(), 3); + QCOMPARE_EQ(moved.front().size(), 42U); + QCOMPARE_EQ(moved.front().front(), nullptr); + QCOMPARE_EQ(moved.back().size(), 44U); +} + QTEST_APPLESS_MAIN(tst_QVarLengthArray) #include "tst_qvarlengtharray.moc"