QDuplicateTracker: bring back appendTo() &&

This reverts commit c19695ab95.

Just because QSet has limited API doesn't mean we can't provide this
in an efficient way for std::unordered_set :P

Added tests.

Pick-to: 6.2
Change-Id: I4f8f0e60c810acdc666cf34f929845227ed87f3b
Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
This commit is contained in:
Marc Mutz 2021-07-12 10:10:38 +02:00
parent 6b400e3147
commit 8c49ae522d
2 changed files with 56 additions and 8 deletions

View File

@ -105,6 +105,13 @@ class QDuplicateTracker {
#endif
Q_DISABLE_COPY_MOVE(QDuplicateTracker);
public:
static constexpr inline bool uses_pmr =
#ifdef __cpp_lib_memory_resource
true
#else
false
#endif
;
QDuplicateTracker() = default;
explicit QDuplicateTracker(qsizetype n)
#ifdef __cpp_lib_memory_resource
@ -125,11 +132,22 @@ public:
}
template <typename C>
void appendTo(C &c) const
void appendTo(C &c) const &
{
for (const auto &e : set)
c.push_back(e);
}
template <typename C>
void appendTo(C &c) &&
{
if constexpr (uses_pmr) {
while (!set.empty())
c.push_back(std::move(set.extract(set.begin()).value()));
} else {
return appendTo(c); // lvalue version
}
}
};
QT_END_NAMESPACE

View File

@ -94,9 +94,15 @@ void tst_QDuplicateTracker::appendTo()
QVERIFY(!tracker.hasSeen(2));
QList<int> c;
tracker.appendTo(c);
std::move(tracker).appendTo(c);
std::sort(c.begin(), c.end());
QCOMPARE(c, QList<int>({ 0, 1, 2 }));
if (QDuplicateTracker<int, 2>::uses_pmr) {
// the following is only true if we use the std container
QVERIFY(!tracker.hasSeen(0));
QVERIFY(!tracker.hasSeen(1));
QVERIFY(!tracker.hasSeen(2));
}
}
struct ConstructionCounted
@ -172,12 +178,36 @@ void tst_QDuplicateTracker::appendTo_special()
QVERIFY(!tracker.hasSeen(1));
QVERIFY(!tracker.hasSeen(2));
QVERIFY(!tracker.hasSeen(3));
QList<ConstructionCounted> a;
a.reserve(3);
tracker.appendTo(a);
for (const auto &counter : a) {
QCOMPARE(counter.moves, 1);
QCOMPARE(counter.copies, 1);
QVERIFY(tracker.hasSeen(1));
QVERIFY(tracker.hasSeen(2));
QVERIFY(tracker.hasSeen(3));
{
QList<ConstructionCounted> a;
a.reserve(3);
tracker.appendTo(a);
for (const auto &counter : a) {
QCOMPARE(counter.moves, 1);
QCOMPARE(counter.copies, 1);
}
}
QVERIFY(tracker.hasSeen(1));
QVERIFY(tracker.hasSeen(2));
QVERIFY(tracker.hasSeen(3));
{
QList<ConstructionCounted> a;
a.reserve(3);
std::move(tracker).appendTo(a);
if (QDuplicateTracker<ConstructionCounted>::uses_pmr) {
// the following is only true if we use the std container
for (const auto &counter : a) {
QCOMPARE(counter.moves, 2);
QCOMPARE(counter.copies, 0);
}
QVERIFY(!tracker.hasSeen(1));
QVERIFY(!tracker.hasSeen(2));
QVERIFY(!tracker.hasSeen(3));
}
}
}