Add a qHashEquals() method and use it to compare keys in QHash

In some cases, the default equality operator for a class is not suitable
for using in hashing (for example because it uses fuzzy comparisons).

Add a qHashEquals() method that by default uses the equality operator, but
allows to tailor the operations that should be used when using the class
as a key in QHash.

Task-number: QTBUG-88966
Change-Id: I346cf0e6e923277a8b42a79e50342a1c2511fd80
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
(cherry picked from commit 5d8b586e73e37070b0303bee24372550854637eb)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
Lars Knoll 2020-12-03 09:14:27 +01:00 committed by Qt Cherry-pick Bot
parent 6bc1a1ec2f
commit 8e7bcedb65
3 changed files with 22 additions and 1 deletions

View File

@ -1074,6 +1074,21 @@ size_t qHash(long double key, size_t seed) noexcept
Returns the hash value for the \a key, using \a seed to seed the calculation. Returns the hash value for the \a key, using \a seed to seed the calculation.
*/ */
/*! \fn template<typename T> bool qHashEquals(const T &a, const T &b)
\relates QHash
\since 6.0
\internal
This method is being used by QHash to compare two keys. Returns true if the
keys \a a and \a b are considered equal for hashing purposes.
The default implementation returns the result of (a == b). It can be reimplemented
for a certain type if the equality operator is not suitable for hashing purposes.
This is for example the case if the equality operator uses qFuzzyCompare to compare
floating point values.
*/
/*! /*!
\class QHash \class QHash
\inmodule QtCore \inmodule QtCore

View File

@ -560,7 +560,7 @@ struct Data
return iterator{ this, bucket }; return iterator{ this, bucket };
} else { } else {
Node &n = s.atOffset(offset); Node &n = s.atOffset(offset);
if (n.key == key) if (qHashEquals(n.key, key))
return iterator{ this, bucket }; return iterator{ this, bucket };
} }
bucket = nextBucket(bucket); bucket = nextBucket(bucket);

View File

@ -178,6 +178,12 @@ template <typename T, std::enable_if_t<QHashPrivate::HasQHashSingleArgOverload<T
size_t qHash(const T &t, size_t seed) noexcept(noexcept(qHash(t))) size_t qHash(const T &t, size_t seed) noexcept(noexcept(qHash(t)))
{ return qHash(t) ^ seed; } { return qHash(t) ^ seed; }
template<typename T>
bool qHashEquals(const T &a, const T &b)
{
return a == b;
}
namespace QtPrivate { namespace QtPrivate {
struct QHashCombine struct QHashCombine