summaryrefslogtreecommitdiffstats
path: root/src/corelib/tools
diff options
context:
space:
mode:
authorThiago Macieira <thiago.macieira@intel.com>2021-04-16 17:49:20 -0700
committerThiago Macieira <thiago.macieira@intel.com>2021-05-23 12:08:43 -0700
commit64bfc927b09b46bb7fc0dc6caf1bf1a4d4133ab4 (patch)
treed1b3bd74bc20ce817ea362fc5280bc0ce4f6c0bd /src/corelib/tools
parenta5ff71578da5f6441ab8b07ae1fbf736d7f1e3ba (diff)
QHash: fix qHash(std::pair)
There were two problems here: first, qHash(std::pair) must be declared before qHashMulti that might call back to qHash(std::pair) (i.e., a pair with one element that is also a pair). But moving the declaration above causes the second problem: the noexcept expression can't refer to qHash functions that aren't declared yet. So we forward-declare a constexpr function for that result, but implement it far below. Fixes: QTBUG-92910 Change-Id: Ia8e48103a54446509e3bfffd16767ed2e29b026c Reviewed-by: Christian Kandeler <christian.kandeler@qt.io> Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Diffstat (limited to 'src/corelib/tools')
-rw-r--r--src/corelib/tools/qhashfunctions.h17
1 files changed, 15 insertions, 2 deletions
diff --git a/src/corelib/tools/qhashfunctions.h b/src/corelib/tools/qhashfunctions.h
index 4c2eba3e53..4f8e4066ee 100644
--- a/src/corelib/tools/qhashfunctions.h
+++ b/src/corelib/tools/qhashfunctions.h
@@ -114,10 +114,15 @@ constexpr inline bool HasQHashSingleArgOverload<T, std::enable_if_t<
std::is_convertible_v<decltype(qHash(std::declval<const T &>())), size_t>
>> = true;
+template <typename T1, typename T2> static constexpr bool noexceptPairHash();
}
Q_CORE_EXPORT Q_DECL_PURE_FUNCTION size_t qHashBits(const void *p, size_t size, size_t seed = 0) noexcept;
+// implementation below qHashMulti
+template <typename T1, typename T2> inline size_t qHash(const std::pair<T1, T2> &key, size_t seed = 0)
+ noexcept(QHashPrivate::noexceptPairHash<T1, T2>());
+
// C++ builtin types
Q_DECL_CONST_FUNCTION constexpr inline size_t qHash(char key, size_t seed = 0) noexcept
{ return QHashPrivate::hash(size_t(key), seed); }
@@ -290,8 +295,16 @@ inline size_t qHashRangeCommutative(InputIterator first, InputIterator last, siz
return std::accumulate(first, last, seed, QtPrivate::QHashCombineCommutative());
}
-template <typename T1, typename T2> inline size_t qHash(const std::pair<T1, T2> &key, size_t seed = 0)
- noexcept(noexcept(qHash(key.first, seed)) && noexcept(qHash(key.second, seed)))
+namespace QHashPrivate {
+template <typename T1, typename T2> static constexpr bool noexceptPairHash()
+{
+ size_t seed = 0;
+ return noexcept(qHash(std::declval<T1>(), seed)) && noexcept(qHash(std::declval<T2>(), seed));
+}
+} // QHashPrivate
+
+template <typename T1, typename T2> inline size_t qHash(const std::pair<T1, T2> &key, size_t seed)
+ noexcept(QHashPrivate::noexceptPairHash<T1, T2>())
{
return qHashMulti(seed, key.first, key.second);
}