diff --git a/src/corelib/tools/qhash.h b/src/corelib/tools/qhash.h index cee58a0f2f9..67b3e026df8 100644 --- a/src/corelib/tools/qhash.h +++ b/src/corelib/tools/qhash.h @@ -1848,21 +1848,28 @@ template size_t qHash(const QHash &key, size_t seed = 0) noexcept(noexcept(qHash(std::declval())) && noexcept(qHash(std::declval()))) { - QtPrivate::QHashCombineCommutative hash; + size_t hash = 0; for (auto it = key.begin(), end = key.end(); it != end; ++it) { - const Key &k = it.key(); - const T &v = it.value(); - seed = hash(seed, std::pair(k, v)); + QtPrivate::QHashCombine combine; + size_t h = combine(seed, it.key()); + // use + to keep the result independent of the ordering of the keys + hash += combine(h, it.value()); } - return seed; + return hash; } template inline size_t qHash(const QMultiHash &key, size_t seed = 0) noexcept(noexcept(qHash(std::declval())) && noexcept(qHash(std::declval()))) { - const QHash &key2 = key; - return qHash(key2, seed); + size_t hash = 0; + for (auto it = key.begin(), end = key.end(); it != end; ++it) { + QtPrivate::QHashCombine combine; + size_t h = combine(seed, it.key()); + // use + to keep the result independent of the ordering of the keys + hash += combine(h, it.value()); + } + return hash; } QT_END_NAMESPACE diff --git a/tests/auto/corelib/tools/qhash/tst_qhash.cpp b/tests/auto/corelib/tools/qhash/tst_qhash.cpp index d5a8db7553f..d63ed7043ec 100644 --- a/tests/auto/corelib/tools/qhash/tst_qhash.cpp +++ b/tests/auto/corelib/tools/qhash/tst_qhash.cpp @@ -73,6 +73,7 @@ private slots: void emplace(); void badHashFunction(); + void hashOfHash(); }; struct IdentityTracker { @@ -1754,5 +1755,14 @@ void tst_QHash::badHashFunction() } +void tst_QHash::hashOfHash() +{ + QHash hash; + (void)qHash(hash); + + QMultiHash multiHash; + (void)qHash(multiHash); +} + QTEST_APPLESS_MAIN(tst_QHash) #include "tst_qhash.moc"