tst_ContainerApiSymmetry: check value_types with a const member
QVarLengthArray is the only Qt container currently known to be fine. std::vector is supposed to be fine, too, since C++14. Turns out that libstdc++ gets resize(n, v) wrong, though, because it never implemented the resolution to wg21.link/lwg2033. Known issue, linked in code comment. Worked around for the time being. Keeping std::vector in, though, because in this test suite we do cross-check with std::vector, and other platforms, and most of GCC's std::vector functions, adhere to the standard. Pick-to: 6.5 Change-Id: I26e11c4a100695c604cebcf7e14a1ae5078d9ec7 Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io> (cherry picked from commit 3c0fdd7341ed4bff9b5f041e9f4646265d142303) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
parent
d4eae78e6b
commit
283ec1055b
@ -331,6 +331,26 @@ private Q_SLOTS:
|
||||
void resize_QString() { resize_impl<QString>(); }
|
||||
void resize_QByteArray() { resize_impl<QByteArray>(); }
|
||||
|
||||
private:
|
||||
template <typename Container>
|
||||
void copesWithValueTypesWithConstMembers_impl();
|
||||
|
||||
struct ConstMember {
|
||||
#ifndef __cpp_aggregate_paren_init // also check that we can emplace aggregates (C++20 only)
|
||||
explicit ConstMember(int n) : n(n) {}
|
||||
#endif
|
||||
const int n;
|
||||
|
||||
friend bool operator==(const ConstMember &lhs, const ConstMember &rhs) noexcept
|
||||
{ return lhs.n == rhs.n; }
|
||||
friend bool operator!=(const ConstMember &lhs, const ConstMember &rhs) noexcept
|
||||
{ return !(lhs == rhs); }
|
||||
};
|
||||
|
||||
private Q_SLOTS:
|
||||
void copesWithValueTypesWithConstMembers_std_vector() { copesWithValueTypesWithConstMembers_impl<std::vector<ConstMember>>(); }
|
||||
void copesWithValueTypesWithConstMembers_QVarLengthArray() { copesWithValueTypesWithConstMembers_impl<QVarLengthArray<ConstMember, 2>>(); }
|
||||
|
||||
private:
|
||||
template <typename Container>
|
||||
void assign_impl() const;
|
||||
@ -772,6 +792,76 @@ void tst_ContainerApiSymmetry::resize_impl() const
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
constexpr bool is_vector_v = false;
|
||||
template <typename...Args>
|
||||
constexpr bool is_vector_v<std::vector<Args...>> = true;
|
||||
|
||||
template <typename Container>
|
||||
void tst_ContainerApiSymmetry::copesWithValueTypesWithConstMembers_impl()
|
||||
{
|
||||
// The problem:
|
||||
//
|
||||
// using V = ConstMember;
|
||||
// V v{42};
|
||||
// assert(v.n == 42); // OK
|
||||
// new (&v) V{24};
|
||||
// assert(v.n == 24); // UB in C++17: v.n could still be 42 (C++17 [basic.life]/8)
|
||||
// // OK in C++20 (C++20 [basic.life]/8)
|
||||
// assert(std::launder(&v)->n == 24); // OK
|
||||
// assert(v.n == 24); // _still_ UB!
|
||||
//
|
||||
// Containers:
|
||||
// - must not expose this problem
|
||||
// - must compile in the first place, even though V
|
||||
// - is not assignable
|
||||
// - is not default-constructible
|
||||
|
||||
using S = typename Container::size_type;
|
||||
using V = typename Container::value_type;
|
||||
|
||||
Container c;
|
||||
// the following are all functions that by rights should not require the type to be
|
||||
// - default-constructible
|
||||
// - assignable
|
||||
// make sure they work
|
||||
c.reserve(S(5));
|
||||
c.shrink_to_fit();
|
||||
#ifdef __GLIBCXX__ // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83981
|
||||
if constexpr (is_vector_v<Container>) {
|
||||
c.push_back(V(42));
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
c.resize(1, V(42));
|
||||
}
|
||||
QCOMPARE(c[0], V(42));
|
||||
#ifdef __GLIBCXX__ // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83981
|
||||
if constexpr (is_vector_v<Container>) {
|
||||
c.push_back(V(48));
|
||||
c.push_back(V(48));
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
c.resize(2, V(48));
|
||||
}
|
||||
QCOMPARE(c[0], V(42));
|
||||
QCOMPARE(c[1], V(48));
|
||||
c.clear();
|
||||
c.emplace_back(24);
|
||||
QCOMPARE(c.front(), V(24));
|
||||
c.push_back(V(41));
|
||||
QCOMPARE(c.back(), V(41));
|
||||
{
|
||||
const auto v142 = V(142);
|
||||
c.push_back(v142);
|
||||
}
|
||||
QCOMPARE(c.size(), S(3));
|
||||
QCOMPARE(c[0], V(24));
|
||||
QCOMPARE(c[1], V(41));
|
||||
QCOMPARE(c[2], V(142));
|
||||
}
|
||||
|
||||
template <typename Container>
|
||||
void tst_ContainerApiSymmetry::assign_impl() const
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user