summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarc Mutz <marc.mutz@qt.io>2021-11-26 16:31:59 +0100
committerMarc Mutz <marc.mutz@qt.io>2021-11-29 18:55:10 +0000
commitccaeffe5655cba23b4f708ec575e34f03cf08a1c (patch)
tree428371a2b2822c61b634ed61a5390d1bc32b6779
parent95ccdfa43276652f1b9ca5944a94b7e15c510dbd (diff)
QT_SPECIALIZE_STD_HASH_TO_CALL_QHASH: use unqualified qHash() lookup
... instead of QT_PREPEND_NAMESPACE(qHash), which is qualified (prepends at least '::'), and therefore disables ADL. This is not a problem as long as we wrote our qHash() overloads as free functions (incl. non-hidden friends), but it should™ fail for hidden friends, so use the old using-std::swap() trick to bring QT_PREPEND_NAMESPACE(qHash) into scope, proceeding with an unqualified lookup. Pick-to: 6.2 Change-Id: I00860b2313699849f86bfe3dd9f41db4ce993cd3 Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
-rw-r--r--src/corelib/tools/qhashfunctions.h11
-rw-r--r--tests/auto/corelib/tools/qhashfunctions/tst_qhashfunctions.cpp26
2 files changed, 33 insertions, 4 deletions
diff --git a/src/corelib/tools/qhashfunctions.h b/src/corelib/tools/qhashfunctions.h
index 4f8e4066ee9..4d0b2d95194 100644
--- a/src/corelib/tools/qhashfunctions.h
+++ b/src/corelib/tools/qhashfunctions.h
@@ -251,6 +251,9 @@ struct QNothrowHashable : std::false_type {};
template <typename T>
struct QNothrowHashable<T, std::enable_if_t<QNothrowHashableHelper_v<T>>> : std::true_type {};
+template <typename T>
+constexpr inline bool QNothrowHashable_v = QNothrowHashable<T>::value;
+
} // namespace QtPrivate
template <typename... T>
@@ -317,15 +320,15 @@ template <typename T1, typename T2> inline size_t qHash(const std::pair<T1, T2>
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))) \
+ noexcept(QT_PREPEND_NAMESPACE( \
+ QtPrivate::QNothrowHashable_v)<argument_type>) \
{ \
/* 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))); \
+ using QT_PREPEND_NAMESPACE(qHash); \
+ return qHash(s, qHash(std::hash<int>{}(0))); \
} \
}; \
} \
diff --git a/tests/auto/corelib/tools/qhashfunctions/tst_qhashfunctions.cpp b/tests/auto/corelib/tools/qhashfunctions/tst_qhashfunctions.cpp
index 86305b101fc..3281c4cefd5 100644
--- a/tests/auto/corelib/tools/qhashfunctions/tst_qhashfunctions.cpp
+++ b/tests/auto/corelib/tools/qhashfunctions/tst_qhashfunctions.cpp
@@ -303,9 +303,35 @@ void tst_QHashFunctions::rangeCommutative()
}
}
+// QVarLengthArray these days has a qHash() as a hidden friend.
+// This checks that QT_SPECIALIZE_STD_HASH_TO_CALL_QHASH can deal with that:
+
+QT_BEGIN_NAMESPACE
+QT_SPECIALIZE_STD_HASH_TO_CALL_QHASH_BY_CREF(QVarLengthArray<QVector<int>>)
+QT_END_NAMESPACE
+
void tst_QHashFunctions::stdHash()
{
{
+ std::unordered_set<QVarLengthArray<QVector<int>>> s = {
+ {
+ {0, 1, 2},
+ {42, 43, 44},
+ {},
+ }, {
+ {11, 12, 13},
+ {},
+ },
+ };
+ QCOMPARE(s.size(), 2UL);
+ s.insert({
+ {11, 12, 13},
+ {},
+ });
+ QCOMPARE(s.size(), 2UL);
+ }
+
+ {
std::unordered_set<QString> s = {QStringLiteral("Hello"), QStringLiteral("World")};
QCOMPARE(s.size(), 2UL);
s.insert(QStringLiteral("Hello"));