From a9c52dbdf47a6a070b84c8d34ae3c0c29a8ac1e8 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Mon, 26 Oct 2020 09:18:00 +0100 Subject: [PATCH] Fix qHash(QMultiHash) The old code was trying to convert a multi hash to a QHash. While that worked in Qt 5 it won't compile in Qt 6 anymore. QHashCombineCommutative also can't be used with a std::pair. ADL won't find the correct instance with a namespaced build, as qHash(std::pair) is defined after QHashCommutative. Fix the code to compile and work correctly. Change-Id: Ice2bc3ab4244e310cbbb5e0f31fc11eb14f5faf3 Reviewed-by: Thiago Macieira --- src/corelib/tools/qhash.h | 21 +++++++++++++------- tests/auto/corelib/tools/qhash/tst_qhash.cpp | 10 ++++++++++ 2 files changed, 24 insertions(+), 7 deletions(-) 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"