diff --git a/src/corelib/tools/qset.h b/src/corelib/tools/qset.h index 3cba1a2b15d..d8857925f7d 100644 --- a/src/corelib/tools/qset.h +++ b/src/corelib/tools/qset.h @@ -209,6 +209,8 @@ public: QList values() const; private: + static inline QSet intersected_helper(const QSet &lhs, const QSet &rhs); + Hash q_hash; }; @@ -242,23 +244,51 @@ Q_INLINE_TEMPLATE QSet &QSet::unite(const QSet &other) template Q_INLINE_TEMPLATE QSet &QSet::intersect(const QSet &other) { - QSet copy1; - QSet copy2; - if (size() <= other.size()) { - copy1 = *this; - copy2 = other; + if (q_hash.isSharedWith(other.q_hash)) { + // nothing to do + } else if (isEmpty() || other.isEmpty()) { + // any set intersected with the empty set is the empty set + clear(); + } else if (q_hash.isDetached()) { + // do it in-place: + removeIf([&other] (const T &e) { return !other.contains(e); }); } else { - copy1 = other; - copy2 = *this; - *this = copy1; - } - for (const auto &e : std::as_const(copy1)) { - if (!copy2.contains(e)) - remove(e); + // don't detach *this just to remove some items; create a new set + *this = intersected_helper(*this, other); } return *this; } +template +// static +auto QSet::intersected_helper(const QSet &lhs, const QSet &rhs) -> QSet +{ + QSet r; + + const auto l_size = lhs.size(); + const auto r_size = rhs.size(); + r.reserve((std::min)(l_size, r_size)); + + // Iterate the smaller of the two sets, but always take from lhs, for + // consistency with insert(): + + if (l_size <= r_size) { + // lhs is not larger + for (const auto &e : lhs) { + if (rhs.contains(e)) + r.insert(e); + } + } else { + // rhs is smaller + for (const auto &e : rhs) { + if (const auto it = lhs.find(e); it != lhs.end()) + r.insert(*it); + } + } + + return r; +} + template Q_INLINE_TEMPLATE bool QSet::intersects(const QSet &other) const { diff --git a/tests/auto/corelib/tools/qset/tst_qset.cpp b/tests/auto/corelib/tools/qset/tst_qset.cpp index 4e6dbab9f12..d28d9c43a5e 100644 --- a/tests/auto/corelib/tools/qset/tst_qset.cpp +++ b/tests/auto/corelib/tools/qset/tst_qset.cpp @@ -1304,11 +1304,9 @@ void tst_QSet::setOperationsPickEquivalentElementsFromLHSContainer_impl() QVERIFY(rhsCopy.contains(OneR)); - QEXPECT_FAIL("", "QTBUG-132536", Continue); QCOMPARE(rhsCopy.find(OneR)->id, OneR.id); QVERIFY(rhsCopy.contains(TwoR)); - QEXPECT_FAIL("", "QTBUG-132536", Continue); QCOMPARE(rhsCopy.find(TwoR)->id, TwoR.id); QVERIFY(!rhsCopy.contains(ThreeR));