summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@qt.io>2020-10-26 09:18:00 +0100
committerLars Knoll <lars.knoll@qt.io>2020-11-03 16:28:14 +0100
commita9c52dbdf47a6a070b84c8d34ae3c0c29a8ac1e8 (patch)
tree7ff3b7ea17d1d2a6b860bd6eab60525ff05e25f5
parentba1266baec820ab82b4dccb45f7c248052e8962e (diff)
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 <thiago.macieira@intel.com>
-rw-r--r--src/corelib/tools/qhash.h21
-rw-r--r--tests/auto/corelib/tools/qhash/tst_qhash.cpp10
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 <class Key, class T>
size_t qHash(const QHash<Key, T> &key, size_t seed = 0)
noexcept(noexcept(qHash(std::declval<Key&>())) && noexcept(qHash(std::declval<T&>())))
{
- 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<const Key&, const T&>(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 <class Key, class T>
inline size_t qHash(const QMultiHash<Key, T> &key, size_t seed = 0)
noexcept(noexcept(qHash(std::declval<Key&>())) && noexcept(qHash(std::declval<T&>())))
{
- const QHash<Key, T> &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<int, int> hash;
+ (void)qHash(hash);
+
+ QMultiHash<int, int> multiHash;
+ (void)qHash(multiHash);
+}
+
QTEST_APPLESS_MAIN(tst_QHash)
#include "tst_qhash.moc"