summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/corelib/tools/qhashfunctions.h36
-rw-r--r--tests/auto/corelib/tools/qhashfunctions/tst_qhashfunctions.cpp36
2 files changed, 72 insertions, 0 deletions
diff --git a/src/corelib/tools/qhashfunctions.h b/src/corelib/tools/qhashfunctions.h
index 5e714806ff..2ff3464912 100644
--- a/src/corelib/tools/qhashfunctions.h
+++ b/src/corelib/tools/qhashfunctions.h
@@ -45,6 +45,7 @@
#include <QtCore/qpair.h>
#include <numeric> // for std::accumulate
+#include <functional> // for std::hash
#if 0
#pragma qt_class(QHashFunctions)
@@ -172,6 +173,41 @@ template <typename T1, typename T2> inline uint qHash(const std::pair<T1, T2> &k
return seed;
}
+#define QT_SPECIALIZE_STD_HASH_TO_CALL_QHASH(Class, Arguments) \
+ QT_BEGIN_INCLUDE_NAMESPACE \
+ namespace std { \
+ template <> \
+ struct hash< QT_PREPEND_NAMESPACE(Class) > { \
+ using argument_type = QT_PREPEND_NAMESPACE(Class); \
+ using result_type = size_t; \
+ size_t operator()(Arguments s) const \
+ noexcept(noexcept(QT_PREPEND_NAMESPACE(qHash)(s))) \
+ { \
+ /* this seeds qHash with the result of */ \
+ /* std::hash applied to an int, to reap */ \
+ /* any protection against predictable hash */ \
+ /* values the std implementation may provide */ \
+ return QT_PREPEND_NAMESPACE(qHash)(s, \
+ QT_PREPEND_NAMESPACE(qHash)( \
+ std::hash<int>{}(0))); \
+ } \
+ }; \
+ } \
+ QT_END_INCLUDE_NAMESPACE \
+ /*end*/
+
+#define QT_SPECIALIZE_STD_HASH_TO_CALL_QHASH_BY_CREF(Class) \
+ QT_SPECIALIZE_STD_HASH_TO_CALL_QHASH(Class, const argument_type &)
+#define QT_SPECIALIZE_STD_HASH_TO_CALL_QHASH_BY_VALUE(Class) \
+ QT_SPECIALIZE_STD_HASH_TO_CALL_QHASH(Class, argument_type)
+
+QT_SPECIALIZE_STD_HASH_TO_CALL_QHASH_BY_CREF(QString)
+QT_SPECIALIZE_STD_HASH_TO_CALL_QHASH_BY_CREF(QStringRef)
+QT_SPECIALIZE_STD_HASH_TO_CALL_QHASH_BY_VALUE(QStringView)
+QT_SPECIALIZE_STD_HASH_TO_CALL_QHASH_BY_VALUE(QLatin1String)
+QT_SPECIALIZE_STD_HASH_TO_CALL_QHASH_BY_CREF(QByteArray)
+QT_SPECIALIZE_STD_HASH_TO_CALL_QHASH_BY_CREF(QBitArray)
+
QT_END_NAMESPACE
#if defined(Q_CC_MSVC)
diff --git a/tests/auto/corelib/tools/qhashfunctions/tst_qhashfunctions.cpp b/tests/auto/corelib/tools/qhashfunctions/tst_qhashfunctions.cpp
index 124e3cdf00..f76f3aa0c6 100644
--- a/tests/auto/corelib/tools/qhashfunctions/tst_qhashfunctions.cpp
+++ b/tests/auto/corelib/tools/qhashfunctions/tst_qhashfunctions.cpp
@@ -34,6 +34,8 @@
#include <sstream>
#include <algorithm>
+#include <unordered_set>
+
class tst_QHashFunctions : public QObject
{
Q_OBJECT
@@ -59,6 +61,8 @@ private Q_SLOTS:
void range();
void rangeCommutative();
+ void stdHash();
+
void setGlobalQHashSeed();
};
@@ -281,6 +285,38 @@ void tst_QHashFunctions::rangeCommutative()
(void)qHashRangeCommutative(hashables, hashables + numHashables, seed);
}
+void tst_QHashFunctions::stdHash()
+{
+ {
+ std::unordered_set<QString> s = {QStringLiteral("Hello"), QStringLiteral("World")};
+ QCOMPARE(s.size(), 2UL);
+ s.insert(QStringLiteral("Hello"));
+ QCOMPARE(s.size(), 2UL);
+ }
+
+ {
+ std::unordered_set<QStringView> s = {QStringLiteral("Hello"), QStringLiteral("World")};
+ QCOMPARE(s.size(), 2UL);
+ s.insert(QStringLiteral("Hello"));
+ QCOMPARE(s.size(), 2UL);
+ }
+
+ {
+ std::unordered_set<QLatin1String> s = {QLatin1String("Hello"), QLatin1String("World")};
+ QCOMPARE(s.size(), 2UL);
+ s.insert(QLatin1String("Hello"));
+ QCOMPARE(s.size(), 2UL);
+ }
+
+ {
+ std::unordered_set<QByteArray> s = {QByteArrayLiteral("Hello"), QByteArrayLiteral("World")};
+ QCOMPARE(s.size(), 2UL);
+ s.insert(QByteArray("Hello"));
+ QCOMPARE(s.size(), 2UL);
+ }
+
+}
+
void tst_QHashFunctions::setGlobalQHashSeed()
{
// Setter works as advertised