diff --git a/src/corelib/serialization/qjsonobject.cpp b/src/corelib/serialization/qjsonobject.cpp index 99f5507aa12..3e0857dc954 100644 --- a/src/corelib/serialization/qjsonobject.cpp +++ b/src/corelib/serialization/qjsonobject.cpp @@ -1445,7 +1445,7 @@ void QJsonObject::removeAt(qsizetype index) size_t qHash(const QJsonObject &object, size_t seed) { - QtPrivate::QHashCombine hash; + QtPrivate::QHashCombine hash(seed); for (auto it = object.begin(), end = object.end(); it != end; ++it) { const QString key = it.key(); const QJsonValue value = it.value(); diff --git a/src/corelib/tools/qhash.h b/src/corelib/tools/qhash.h index 24c014e2153..87713b93a77 100644 --- a/src/corelib/tools/qhash.h +++ b/src/corelib/tools/qhash.h @@ -2710,9 +2710,9 @@ template size_t qHash(const QHash &key, size_t seed = 0) noexcept(noexcept(qHash(std::declval())) && noexcept(qHash(std::declval()))) { + const QtPrivate::QHashCombine combine(seed); size_t hash = 0; for (auto it = key.begin(), end = key.end(); it != end; ++it) { - QtPrivate::QHashCombine combine; size_t h = combine(seed, it.key()); // use + to keep the result independent of the ordering of the keys hash += combine(h, it.value()); @@ -2724,9 +2724,9 @@ template inline size_t qHash(const QMultiHash &key, size_t seed = 0) noexcept(noexcept(qHash(std::declval())) && noexcept(qHash(std::declval()))) { + const QtPrivate::QHashCombine combine(seed); size_t hash = 0; for (auto it = key.begin(), end = key.end(); it != end; ++it) { - QtPrivate::QHashCombine combine; size_t h = combine(seed, it.key()); // use + to keep the result independent of the ordering of the keys hash += combine(h, it.value()); diff --git a/src/corelib/tools/qhashfunctions.h b/src/corelib/tools/qhashfunctions.h index c687cdaeb72..cbe217db11e 100644 --- a/src/corelib/tools/qhashfunctions.h +++ b/src/corelib/tools/qhashfunctions.h @@ -298,18 +298,40 @@ bool qHashEquals(const T1 &a, const T2 &b) } namespace QtPrivate { - -struct QHashCombine +template struct QHashCombiner : private Mixer { - typedef size_t result_type; + using result_type = typename Mixer::result_type ; + +#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0) || defined(QT_BOOTSTRAPPED) + // Qt 6.x didn't use to pass the seed; bootstrap has no seed + static constexpr size_t seed = 0; + constexpr QHashCombiner(result_type) noexcept {} + Q_DECL_DEPRECATED_X("pass the seed argument") constexpr QHashCombiner() noexcept {} +#else + size_t seed; + constexpr QHashCombiner(result_type s) : seed(s) noexcept {} +#endif + template - constexpr result_type operator()(size_t seed, const T &t) const + constexpr result_type operator()(result_type result, const T &t) const noexcept(noexcept(qHash(t, seed))) - // combiner taken from N3876 / boost::hash_combine - { return seed ^ (qHash(t, size_t(0)) + 0x9e3779b9 + (seed << 6) + (seed >> 2)); } + { + return Mixer::operator()(result, qHash(t, seed)); + } }; -struct QHashCombineCommutative +struct QHashCombineMixer +{ + typedef size_t result_type; + constexpr result_type operator()(result_type result, result_type hash) const noexcept + { + // combiner taken from N3876 / boost::hash_combine + return result ^ (hash + 0x9e3779b9 + (result << 6) + (result >> 2)); + } +}; +using QHashCombine = QHashCombiner; + +struct QHashCombineCommutativeMixer : std::plus { // QHashCombine is a good hash combiner, but is not commutative, // ie. it depends on the order of the input elements. That is @@ -317,11 +339,8 @@ struct QHashCombineCommutative // {1,3,0}. Except when it isn't (e.g. for QSet and // QHash). Therefore, provide a commutative combiner, too. typedef size_t result_type; - template - constexpr result_type operator()(size_t seed, const T &t) const - noexcept(noexcept(qHash(t, seed))) - { return seed + qHash(t, size_t(0)); } // don't use xor! }; +using QHashCombineCommutative = QHashCombiner; template using QHashMultiReturnType = decltype( @@ -356,7 +375,7 @@ QtPrivate::QHashMultiReturnType qHashMulti(size_t seed, const T &... args) noexcept(std::conjunction_v...>) { - QtPrivate::QHashCombine hash; + QtPrivate::QHashCombine hash(seed); return ((seed = hash(seed, args)), ...), seed; } @@ -370,7 +389,7 @@ QtPrivate::QHashMultiReturnType qHashMultiCommutative(size_t seed, const T &... args) noexcept(std::conjunction_v...>) { - QtPrivate::QHashCombineCommutative hash; + QtPrivate::QHashCombineCommutative hash(seed); return ((seed = hash(seed, args)), ...), seed; } @@ -378,14 +397,14 @@ template inline size_t qHashRange(InputIterator first, InputIterator last, size_t seed = 0) noexcept(noexcept(qHash(*first))) // assume iterator operations don't throw { - return std::accumulate(first, last, seed, QtPrivate::QHashCombine()); + return std::accumulate(first, last, seed, QtPrivate::QHashCombine(seed)); } template inline size_t qHashRangeCommutative(InputIterator first, InputIterator last, size_t seed = 0) noexcept(noexcept(qHash(*first))) // assume iterator operations don't throw { - return std::accumulate(first, last, seed, QtPrivate::QHashCombineCommutative()); + return std::accumulate(first, last, seed, QtPrivate::QHashCombineCommutative(seed)); } namespace QHashPrivate { diff --git a/src/corelib/tools/qmap.h b/src/corelib/tools/qmap.h index 01e614aa28b..ac2f04b8cd8 100644 --- a/src/corelib/tools/qmap.h +++ b/src/corelib/tools/qmap.h @@ -810,7 +810,7 @@ private: return seed; // don't use qHashRange to avoid its compile-time overhead: return std::accumulate(key.d->m.begin(), key.d->m.end(), seed, - QtPrivate::QHashCombine{}); + QtPrivate::QHashCombine{seed}); } #endif // !Q_QDOC }; diff --git a/src/gui/painting/qtransform.cpp b/src/gui/painting/qtransform.cpp index 1ea63f40965..66f1cf2a985 100644 --- a/src/gui/painting/qtransform.cpp +++ b/src/gui/painting/qtransform.cpp @@ -784,7 +784,7 @@ bool QTransform::operator==(const QTransform &o) const */ size_t qHash(const QTransform &key, size_t seed) noexcept { - QtPrivate::QHashCombine hash; + QtPrivate::QHashCombine hash(seed); seed = hash(seed, key.m11()); seed = hash(seed, key.m12()); seed = hash(seed, key.m21()); diff --git a/src/gui/rhi/qrhi.cpp b/src/gui/rhi/qrhi.cpp index 42e7753e4cb..0628d07ce73 100644 --- a/src/gui/rhi/qrhi.cpp +++ b/src/gui/rhi/qrhi.cpp @@ -6543,7 +6543,7 @@ bool operator!=(const QRhiShaderResourceBinding &a, const QRhiShaderResourceBind size_t qHash(const QRhiShaderResourceBinding &b, size_t seed) noexcept { const QRhiShaderResourceBinding::Data *d = QRhiImplementation::shaderResourceBindingData(b); - QtPrivate::QHashCombine hash; + QtPrivate::QHashCombine hash(seed); seed = hash(seed, d->binding); seed = hash(seed, d->stage); seed = hash(seed, d->type); diff --git a/src/gui/rhi/qrhi.h b/src/gui/rhi/qrhi.h index 5776554916a..66651dcf979 100644 --- a/src/gui/rhi/qrhi.h +++ b/src/gui/rhi/qrhi.h @@ -69,7 +69,7 @@ private: friend size_t qHash(const QRhiDepthStencilClearValue &v, size_t seed = 0) noexcept { - QtPrivate::QHashCombine hash; + QtPrivate::QHashCombine hash(seed); seed = hash(seed, v.m_d); seed = hash(seed, v.m_s); return seed; @@ -118,7 +118,7 @@ private: friend size_t qHash(const QRhiViewport &v, size_t seed = 0) noexcept { - QtPrivate::QHashCombine hash; + QtPrivate::QHashCombine hash(seed); seed = hash(seed, v.m_rect[0]); seed = hash(seed, v.m_rect[1]); seed = hash(seed, v.m_rect[2]); @@ -161,7 +161,7 @@ private: friend size_t qHash(const QRhiScissor &v, size_t seed = 0) noexcept { - QtPrivate::QHashCombine hash; + QtPrivate::QHashCombine hash(seed); seed = hash(seed, v.m_rect[0]); seed = hash(seed, v.m_rect[1]); seed = hash(seed, v.m_rect[2]); @@ -215,7 +215,7 @@ private: friend size_t qHash(const QRhiVertexInputBinding &v, size_t seed = 0) noexcept { - QtPrivate::QHashCombine hash; + QtPrivate::QHashCombine hash(seed); seed = hash(seed, v.m_stride); seed = hash(seed, v.m_classification); seed = hash(seed, v.m_instanceStepRate); @@ -303,7 +303,7 @@ private: friend size_t qHash(const QRhiVertexInputAttribute &v, size_t seed = 0) noexcept { - QtPrivate::QHashCombine hash; + QtPrivate::QHashCombine hash(seed); seed = hash(seed, v.m_binding); seed = hash(seed, v.m_location); seed = hash(seed, v.m_format); @@ -363,7 +363,7 @@ private: friend size_t qHash(const QRhiVertexInputLayout &v, size_t seed = 0) noexcept { - QtPrivate::QHashCombine hash; + QtPrivate::QHashCombine hash(seed); seed = hash(seed, v.m_bindings); seed = hash(seed, v.m_attributes); return seed; @@ -420,7 +420,7 @@ private: friend size_t qHash(const QRhiShaderStage &v, size_t seed = 0) noexcept { - QtPrivate::QHashCombine hash; + QtPrivate::QHashCombine hash(seed); seed = hash(seed, v.m_type); seed = hash(seed, v.m_shader); seed = hash(seed, v.m_shaderVariant); diff --git a/src/gui/rhi/qrhid3d12_p.h b/src/gui/rhi/qrhid3d12_p.h index 2381bb40d42..caa428c6cbc 100644 --- a/src/gui/rhi/qrhid3d12_p.h +++ b/src/gui/rhi/qrhid3d12_p.h @@ -507,7 +507,7 @@ struct Q_D3D12_SAMPLER_DESC friend size_t qHash(const Q_D3D12_SAMPLER_DESC &key, size_t seed = 0) noexcept { - QtPrivate::QHashCombine hash; + QtPrivate::QHashCombine hash(seed); seed = hash(seed, key.desc.Filter); seed = hash(seed, key.desc.AddressU); seed = hash(seed, key.desc.AddressV); diff --git a/src/gui/rhi/qshader.cpp b/src/gui/rhi/qshader.cpp index e1fe23c2a2f..5e967c62e40 100644 --- a/src/gui/rhi/qshader.cpp +++ b/src/gui/rhi/qshader.cpp @@ -812,7 +812,7 @@ bool operator==(const QShader &lhs, const QShader &rhs) noexcept size_t qHash(const QShader &s, size_t seed) noexcept { if (s.d) { - QtPrivate::QHashCombine hash; + QtPrivate::QHashCombine hash(seed); seed = hash(seed, s.stage()); if (!s.d->shaders.isEmpty()) { seed = hash(seed, s.d->shaders.firstKey()); diff --git a/src/gui/text/qfontdatabase_p.h b/src/gui/text/qfontdatabase_p.h index 58feb9457b9..cbfa02b2b7c 100644 --- a/src/gui/text/qfontdatabase_p.h +++ b/src/gui/text/qfontdatabase_p.h @@ -51,7 +51,7 @@ inline bool operator!=(const QtFontFallbacksCacheKey &lhs, const QtFontFallbacks inline size_t qHash(const QtFontFallbacksCacheKey &key, size_t seed = 0) noexcept { - QtPrivate::QHashCombine hash; + QtPrivate::QHashCombine hash(seed); seed = hash(seed, key.family); seed = hash(seed, int(key.style)); seed = hash(seed, int(key.styleHint)); diff --git a/src/gui/vulkan/qvulkaninstance.h b/src/gui/vulkan/qvulkaninstance.h index 819751025be..2728fc2e1b0 100644 --- a/src/gui/vulkan/qvulkaninstance.h +++ b/src/gui/vulkan/qvulkaninstance.h @@ -81,7 +81,7 @@ inline bool operator!=(const QVulkanLayer &lhs, const QVulkanLayer &rhs) noexcep inline size_t qHash(const QVulkanLayer &key, size_t seed = 0) noexcept { - QtPrivate::QHashCombine hash; + QtPrivate::QHashCombine hash(seed); seed = hash(seed, key.name); seed = hash(seed, key.version); seed = hash(seed, key.specVersion); @@ -104,7 +104,7 @@ inline bool operator!=(const QVulkanExtension &lhs, const QVulkanExtension &rhs) inline size_t qHash(const QVulkanExtension &key, size_t seed = 0) noexcept { - QtPrivate::QHashCombine hash; + QtPrivate::QHashCombine hash(seed); seed = hash(seed, key.name); seed = hash(seed, key.version); return seed;