diff options
author | Sérgio Martins <sergio.martins@kdab.com> | 2015-05-25 18:32:35 +0100 |
---|---|---|
committer | Marc Mutz <marc.mutz@kdab.com> | 2015-05-30 07:15:24 +0000 |
commit | 9eff0dd19d6507ec400f036dd27efe960e4e5f78 (patch) | |
tree | ed9cd2e3bffc0df9e6fcbb1daa4b52210aec347b /src/corelib/tools/qset.h | |
parent | fda08f3971e854ad1623fb99212746143c27e412 (diff) |
QSet: Introduce intersects().
The pattern "mySet.intersect(other).isEmpty()" has been spotted in
the wild and in Qt codebase. intersects() is much cheaper because it
bails out as soon as we find one common item and doesn't do any
allocations.
[ChangeLog][QtCore][QSet] Added intersects().
Change-Id: I44a350dc4cdb9deb835a23eee99fc99d6ca24c82
Reviewed-by: Marc Mutz <marc.mutz@kdab.com>
Diffstat (limited to 'src/corelib/tools/qset.h')
-rw-r--r-- | src/corelib/tools/qset.h | 30 |
1 files changed, 30 insertions, 0 deletions
diff --git a/src/corelib/tools/qset.h b/src/corelib/tools/qset.h index e4688711d6..5a9c75fe07 100644 --- a/src/corelib/tools/qset.h +++ b/src/corelib/tools/qset.h @@ -137,6 +137,7 @@ public: typedef QHash<T, QHashDummyValue> Hash; typename Hash::const_iterator i; friend class iterator; + friend class QSet<T>; public: typedef std::bidirectional_iterator_tag iterator_category; @@ -191,6 +192,7 @@ public: inline const_iterator constFind(const T &value) const { return find(value); } QSet<T> &unite(const QSet<T> &other); QSet<T> &intersect(const QSet<T> &other); + bool intersects(const QSet<T> &other) const; QSet<T> &subtract(const QSet<T> &other); // STL compatibility @@ -284,6 +286,34 @@ Q_INLINE_TEMPLATE QSet<T> &QSet<T>::intersect(const QSet<T> &other) } template <class T> +Q_INLINE_TEMPLATE bool QSet<T>::intersects(const QSet<T> &other) const +{ + const bool otherIsBigger = other.size() > size(); + const QSet &smallestSet = otherIsBigger ? *this : other; + const QSet &biggestSet = otherIsBigger ? other : *this; + const bool equalSeeds = q_hash.d->seed == other.q_hash.d->seed; + typename QSet::const_iterator i = smallestSet.cbegin(); + typename QSet::const_iterator e = smallestSet.cend(); + + if (Q_LIKELY(equalSeeds)) { + // If seeds are equal we take the fast path so no hash is recalculated. + while (i != e) { + if (*biggestSet.q_hash.findNode(*i, i.i.i->h) != biggestSet.q_hash.e) + return true; + ++i; + } + } else { + while (i != e) { + if (biggestSet.contains(*i)) + return true; + ++i; + } + } + + return false; +} + +template <class T> Q_INLINE_TEMPLATE QSet<T> &QSet<T>::subtract(const QSet<T> &other) { QSet<T> copy1(*this); |