diff options
author | Marc Mutz <marc.mutz@kdab.com> | 2016-07-11 11:14:34 +0200 |
---|---|---|
committer | Marc Mutz <marc.mutz@kdab.com> | 2016-07-14 06:53:48 +0000 |
commit | c2f4705f23ddccf075010edb0532fd73145b8b15 (patch) | |
tree | e35ca3cde5b3ae81b140dcb3d232067a988ee74e /src/corelib/tools/qhash.h | |
parent | 89152c57d864c6767daa5aead2adb3ae6bee482b (diff) |
Add qHash(QHash) and qHash(QMultiHash)
The hash function is carefully designed to give the same result
as the straight-forward implementation of qHash(unordered_map),
which we'll probably add at some point, namely: std::accumulate
over a container of std::pair.
This is one reason to use std:: and not QPair in the implemen-
tation of qHash(QHash). The other is that qHash(QPair) uses a
bad hash combiner, which may xor out the 'seed' from the result.
We can't fix that until Qt 6, but the qHash(std::pair) overload
uses the well-known boost::hash_combine algorithm (implemented
in Qt as QtPrivate::QHashCombine), so we can use that.
I also trust std::pair to work without problems with reference
template arguments, while QPair only very recently gained a very
basic auto-test for reference parameters.
[ChangeLog][QtCore] Added qHash() overloads for QHash, QMultiHash.
Change-Id: I90879d8a99cf1aadb6e84ecc0c3704f52f3691da
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Diffstat (limited to 'src/corelib/tools/qhash.h')
-rw-r--r-- | src/corelib/tools/qhash.h | 21 |
1 files changed, 21 insertions, 0 deletions
diff --git a/src/corelib/tools/qhash.h b/src/corelib/tools/qhash.h index 7abbeabeae..6a2d7bdd11 100644 --- a/src/corelib/tools/qhash.h +++ b/src/corelib/tools/qhash.h @@ -1095,6 +1095,27 @@ Q_INLINE_TEMPLATE int QMultiHash<Key, T>::count(const Key &key, const T &value) Q_DECLARE_ASSOCIATIVE_ITERATOR(Hash) Q_DECLARE_MUTABLE_ASSOCIATIVE_ITERATOR(Hash) +template <class Key, class T> +uint qHash(const QHash<Key, T> &key, uint seed = 0) + Q_DECL_NOEXCEPT_EXPR(noexcept(qHash(std::declval<Key&>())) && noexcept(qHash(std::declval<T&>()))) +{ + QtPrivate::QHashCombineCommutative hash; + 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)); + } + return seed; +} + +template <class Key, class T> +inline uint qHash(const QMultiHash<Key, T> &key, uint seed = 0) + Q_DECL_NOEXCEPT_EXPR(noexcept(qHash(std::declval<Key&>())) && noexcept(qHash(std::declval<T&>()))) +{ + const QHash<Key, T> &key2 = key; + return qHash(key2, seed); +} + QT_END_NAMESPACE #if defined(Q_CC_MSVC) |