From 81e893fb2d57b7f2d332f4f626e38f51acf43542 Mon Sep 17 00:00:00 2001 From: Giuseppe D'Angelo Date: Fri, 27 Nov 2020 17:39:10 +0100 Subject: QHash: support std::hash as hashing function In addition (and as a fallback) from requiring qHash, add support for std::hash specializations. This catches two birds with one stone: 1) users of Qt can simply specialize std::hash for their datatypes, and use them in both QHash and stdlib unordered associative containers; 2) we get QHash support for any (stdlib) datatype that is hashable without having to overload qHash for them. [ChangeLog][QtCore][QHash] QHash, QMultiHash and QSet now support for key types anything that can be hashed via std::hash, instead of always requiring a qHash() overload. Change-Id: Ib5ecba86e4b376d318389500bd24883ac6534c5f Reviewed-by: Fabian Kosmale Reviewed-by: Lars Knoll Reviewed-by: Andrei Golubev --- src/corelib/tools/qhash.cpp | 40 ++++++++++++++++++++++++++++++---------- 1 file changed, 30 insertions(+), 10 deletions(-) (limited to 'src/corelib/tools/qhash.cpp') diff --git a/src/corelib/tools/qhash.cpp b/src/corelib/tools/qhash.cpp index 112a492526..8a94695ec3 100644 --- a/src/corelib/tools/qhash.cpp +++ b/src/corelib/tools/qhash.cpp @@ -1194,22 +1194,26 @@ size_t qHash(long double key, size_t seed) noexcept instead, store a QWidget *. \target qHash - \section2 The qHash() hashing function + \section2 The hashing function A QHash's key type has additional requirements other than being an assignable data type: it must provide operator==(), and there must also be - a qHash() function in the type's namespace that returns a hash value for an - argument of the key's type. + a hashing function that returns a hash value for an argument of the + key's type. - The qHash() function computes a numeric value based on a key. It + The hashing function computes a numeric value based on a key. It can use any algorithm imaginable, as long as it always returns the same value if given the same argument. In other words, if - \c{e1 == e2}, then \c{qHash(e1) == qHash(e2)} must hold as well. - However, to obtain good performance, the qHash() function should + \c{e1 == e2}, then \c{hash(e1) == hash(e2)} must hold as well. + However, to obtain good performance, the hashing function should attempt to return different hash values for different keys to the largest extent possible. - For a key type \c{K}, the qHash function must have one of these signatures: + A hashing function for a key type \c{K} may be provided in two + different ways. + + The first way is by having an overload of \c{qHash()} in \c{K}'s + namespace. The \c{qHash()} function must have one of these signatures: \snippet code/src_corelib_tools_qhash.cpp 32 @@ -1220,6 +1224,20 @@ size_t qHash(long double key, size_t seed) noexcept the latter is used by QHash (note that you can simply define a two-arguments version, and use a default value for the seed parameter). + The second way to provide a hashing function is by specializing + the \c{std::hash} class for the key type \c{K}, and providing a + suitable function call operator for it: + + \snippet code/src_corelib_tools_qhash.cpp 33 + + The seed argument has the same meaning as for \c{qHash()}, + and may be left out. + + This second way allows to reuse the same hash function between + QHash and the C++ Standard Library unordered associative containers. + If both a \c{qHash()} overload and a \c{std::hash} specializations + are provided for a type, then the \c{qHash()} overload is preferred. + Here's a partial list of the C++ and Qt types that can serve as keys in a QHash: any integer type (char, unsigned long, etc.), any pointer type, QChar, QString, and QByteArray. For all of these, the \c header @@ -1228,9 +1246,11 @@ size_t qHash(long double key, size_t seed) noexcept the documentation of each class. If you want to use other types as the key, make sure that you provide - operator==() and a qHash() implementation. The convenience qHashMulti() - function can be used to implement qHash() for a custom type, where - one usually wants to produce a hash value from multiple fields: + operator==() and a hash implementation. + + The convenience qHashMulti() function can be used to implement + qHash() for a custom type, where one usually wants to produce a + hash value from multiple fields: Example: \snippet code/src_corelib_tools_qhash.cpp 13 -- cgit v1.2.3