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_QString() { resize_impl<QString>(); }
|
||||||
void resize_QByteArray() { resize_impl<QByteArray>(); }
|
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:
|
private:
|
||||||
template <typename Container>
|
template <typename Container>
|
||||||
void assign_impl() const;
|
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>
|
template <typename Container>
|
||||||
void tst_ContainerApiSymmetry::assign_impl() const
|
void tst_ContainerApiSymmetry::assign_impl() const
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user