From b8e46fce5c70c399c615e1b846076f379db173c5 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Thu, 14 Aug 2014 11:22:23 +0200 Subject: [PATCH] Add qHash() overload for QSet ...using qHashRangeCommutative(). Also add a test. [ChangeLog][QtCore][QSet] Can now be used as the key in QSet, QHash. Change-Id: Ie7c81d257a3b324fc03d394fa7c9fcf0c6fb062a Reviewed-by: Thiago Macieira --- src/corelib/tools/qset.h | 9 +++++ src/corelib/tools/qset.qdoc | 11 ++++++ tests/auto/corelib/tools/qset/tst_qset.cpp | 45 ++++++++++++++++++++++ 3 files changed, 65 insertions(+) diff --git a/src/corelib/tools/qset.h b/src/corelib/tools/qset.h index 662afbf84a8..baa412a5501 100644 --- a/src/corelib/tools/qset.h +++ b/src/corelib/tools/qset.h @@ -237,6 +237,15 @@ private: } }; +template +uint qHash(const QSet &key, uint seed = 0) +Q_DECL_NOEXCEPT_EXPR(noexcept(qHashRangeCommutative(key.begin(), key.end(), seed))) +{ + return qHashRangeCommutative(key.begin(), key.end(), seed); +} + +// inline function implementations + template Q_INLINE_TEMPLATE void QSet::reserve(int asize) { q_hash.reserve(asize); } diff --git a/src/corelib/tools/qset.qdoc b/src/corelib/tools/qset.qdoc index ab7d72611ef..73599a2a721 100644 --- a/src/corelib/tools/qset.qdoc +++ b/src/corelib/tools/qset.qdoc @@ -968,3 +968,14 @@ \sa{Serializing Qt Data Types}{Format of the QDataStream operators} */ + +/*! + \fn uint qHash(const QSet &key, uint seed = 0) + \relates QHash + \since 5.5 + + Returns the hash value for the \a key, using \a seed to seed the calculation. + + The hash value is independent of the order of elements in \a key, that is, sets + that contain the same elements hash to the same value. +*/ diff --git a/tests/auto/corelib/tools/qset/tst_qset.cpp b/tests/auto/corelib/tools/qset/tst_qset.cpp index b86ee24ac75..b8e23d3fae3 100644 --- a/tests/auto/corelib/tools/qset/tst_qset.cpp +++ b/tests/auto/corelib/tools/qset/tst_qset.cpp @@ -72,6 +72,7 @@ private slots: void javaMutableIterator(); void makeSureTheComfortFunctionsCompile(); void initializerList(); + void qhash(); }; struct IdentityTracker { @@ -968,6 +969,50 @@ void tst_QSet::initializerList() #endif } +QT_BEGIN_NAMESPACE +extern Q_CORE_EXPORT QBasicAtomicInt qt_qhash_seed; // from qhash.cpp +QT_END_NAMESPACE + +void tst_QSet::qhash() +{ + // + // check that sets containing the same elements hash to the same value + // + { + QSet s1; + s1.reserve(4); + s1 << 400 << 300 << 200 << 100; + + // also change the seed: + qt_qhash_seed = qt_qhash_seed + 0x9e3779b9; + + QSet s2; + s2.reserve(100); // provoke different bucket counts + s2 << 100 << 200 << 300 << 400; // and insert elements in different order, too + + QVERIFY(s1.capacity() != s2.capacity()); + QCOMPARE(s1, s2); + QVERIFY(!std::equal(s1.cbegin(), s1.cend(), s2.cbegin())); // verify that the order _is_ different + QCOMPARE(qHash(s1), qHash(s2)); + } + + // + // check that sets of sets work: + // + { +#ifdef Q_COMPILER_INITIALIZER_LISTS + QSet > intSetSet = { { 0, 1, 2 }, { 0, 1 }, { 1, 2 } }; +#else + QSet > intSetSet; + QSet intSet01, intSet12; + intSet01 << 0 << 1; + intSet12 << 1 << 2; + intSetSet << intSet01 << intSet12 << (intSet01|intSet12); +#endif + QCOMPARE(intSetSet.size(), 3); + } +} + QTEST_APPLESS_MAIN(tst_QSet) #include "tst_qset.moc"