Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-08-25 09:17:49

0001 // Copyright (C) 2016 The Qt Company Ltd.
0002 // Copyright (C) 2015 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Marc Mutz <marc.mutz@kdab.com>
0003 // Copyright (C) 2024 Intel Corporation.
0004 // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
0005 // Qt-Security score:significant reason:default
0006 
0007 #ifndef QHASHFUNCTIONS_H
0008 #define QHASHFUNCTIONS_H
0009 
0010 #include <QtCore/qstring.h>
0011 #include <QtCore/qstringfwd.h>
0012 
0013 #include <numeric> // for std::accumulate
0014 #include <functional> // for std::hash
0015 #include <utility> // For std::pair
0016 
0017 #if 0
0018 #pragma qt_class(QHashFunctions)
0019 #endif
0020 
0021 #if defined(Q_CC_MSVC)
0022 #pragma warning( push )
0023 #pragma warning( disable : 4311 ) // disable pointer truncation warning
0024 #pragma warning( disable : 4127 ) // conditional expression is constant
0025 #endif
0026 
0027 QT_BEGIN_NAMESPACE
0028 
0029 class QBitArray;
0030 
0031 #if QT_DEPRECATED_SINCE(6,6)
0032 QT_DEPRECATED_VERSION_X_6_6("Use QHashSeed instead")
0033 Q_CORE_EXPORT int qGlobalQHashSeed();
0034 QT_DEPRECATED_VERSION_X_6_6("Use QHashSeed instead")
0035 Q_CORE_EXPORT void qSetGlobalQHashSeed(int newSeed);
0036 #endif
0037 
0038 struct QHashSeed
0039 {
0040     constexpr QHashSeed(size_t d = 0) : data(d) {}
0041     constexpr operator size_t() const noexcept { return data; }
0042 
0043     static Q_CORE_EXPORT QHashSeed globalSeed() noexcept;
0044     static Q_CORE_EXPORT void setDeterministicGlobalSeed();
0045     static Q_CORE_EXPORT void resetRandomGlobalSeed();
0046 private:
0047     size_t data;
0048 };
0049 
0050 // Whether, ∀ t of type T && ∀ seed, qHash(Key(t), seed) == qHash(t, seed)
0051 template <typename Key, typename T> struct QHashHeterogeneousSearch : std::false_type {};
0052 
0053 // Specializations
0054 template <> struct QHashHeterogeneousSearch<QString, QStringView> : std::true_type {};
0055 template <> struct QHashHeterogeneousSearch<QStringView, QString> : std::true_type {};
0056 template <> struct QHashHeterogeneousSearch<QByteArray, QByteArrayView> : std::true_type {};
0057 template <> struct QHashHeterogeneousSearch<QByteArrayView, QByteArray> : std::true_type {};
0058 #ifndef Q_PROCESSOR_ARM
0059 template <> struct QHashHeterogeneousSearch<QString, QLatin1StringView> : std::true_type {};
0060 template <> struct QHashHeterogeneousSearch<QStringView, QLatin1StringView> : std::true_type {};
0061 template <> struct QHashHeterogeneousSearch<QLatin1StringView, QString> : std::true_type {};
0062 template <> struct QHashHeterogeneousSearch<QLatin1StringView, QStringView> : std::true_type {};
0063 #endif
0064 
0065 namespace QHashPrivate {
0066 
0067 Q_DECL_CONST_FUNCTION constexpr size_t hash(size_t key, size_t seed) noexcept
0068 {
0069     key ^= seed;
0070     if constexpr (sizeof(size_t) == 4) {
0071         key ^= key >> 16;
0072         key *= UINT32_C(0x45d9f3b);
0073         key ^= key >> 16;
0074         key *= UINT32_C(0x45d9f3b);
0075         key ^= key >> 16;
0076         return key;
0077     } else {
0078         quint64 key64 = key;
0079         key64 ^= key64 >> 32;
0080         key64 *= UINT64_C(0xd6e8feb86659fd93);
0081         key64 ^= key64 >> 32;
0082         key64 *= UINT64_C(0xd6e8feb86659fd93);
0083         key64 ^= key64 >> 32;
0084         return size_t(key64);
0085     }
0086 }
0087 
0088 template <typename T1, typename T2> static constexpr bool noexceptPairHash();
0089 }
0090 
0091 Q_CORE_EXPORT Q_DECL_PURE_FUNCTION size_t qHashBits(const void *p, size_t size, size_t seed = 0) noexcept;
0092 
0093 // implementation below qHashMulti
0094 template <typename T1, typename T2> inline size_t qHash(const std::pair<T1, T2> &key, size_t seed = 0)
0095     noexcept(QHashPrivate::noexceptPairHash<T1, T2>());
0096 
0097 // C++ builtin types
0098 #define QT_MK_QHASH_COMPAT(X) \
0099     template <typename T, std::enable_if_t<std::is_same_v<T, X>, bool> = true> \
0100     constexpr size_t qHash(T key, size_t seed = 0) noexcept \
0101     /* QHashPrivate::hash() xors before mixing, while 1-to-2-arg adapter xors after */ \
0102     { return QHashPrivate::hash(size_t(key), 0 QT7_ONLY(+ seed)) QT6_ONLY(^ seed); } \
0103     /* end */
0104 QT_MK_QHASH_COMPAT(bool) // QTBUG-126674
0105 Q_DECL_CONST_FUNCTION constexpr inline size_t qHash(char key, size_t seed = 0) noexcept
0106 { return QHashPrivate::hash(size_t(key), seed); }
0107 Q_DECL_CONST_FUNCTION constexpr inline size_t qHash(uchar key, size_t seed = 0) noexcept
0108 { return QHashPrivate::hash(size_t(key), seed); }
0109 Q_DECL_CONST_FUNCTION constexpr inline size_t qHash(signed char key, size_t seed = 0) noexcept
0110 { return QHashPrivate::hash(size_t(key), seed); }
0111 Q_DECL_CONST_FUNCTION constexpr inline size_t qHash(ushort key, size_t seed = 0) noexcept
0112 { return QHashPrivate::hash(size_t(key), seed); }
0113 Q_DECL_CONST_FUNCTION constexpr inline size_t qHash(short key, size_t seed = 0) noexcept
0114 { return QHashPrivate::hash(size_t(key), seed); }
0115 Q_DECL_CONST_FUNCTION constexpr inline size_t qHash(uint key, size_t seed = 0) noexcept
0116 { return QHashPrivate::hash(size_t(key), seed); }
0117 Q_DECL_CONST_FUNCTION constexpr inline size_t qHash(int key, size_t seed = 0) noexcept
0118 { return QHashPrivate::hash(size_t(key), seed); }
0119 Q_DECL_CONST_FUNCTION constexpr inline size_t qHash(ulong key, size_t seed = 0) noexcept
0120 { return QHashPrivate::hash(size_t(key), seed); }
0121 Q_DECL_CONST_FUNCTION constexpr inline size_t qHash(long key, size_t seed = 0) noexcept
0122 { return QHashPrivate::hash(size_t(key), seed); }
0123 #undef QT_MK_QHASH_COMPAT
0124 Q_DECL_CONST_FUNCTION constexpr inline size_t qHash(quint64 key, size_t seed = 0) noexcept
0125 {
0126     if constexpr (sizeof(quint64) > sizeof(size_t))
0127         key ^= (key >> 32);
0128     return QHashPrivate::hash(size_t(key), seed);
0129 }
0130 Q_DECL_CONST_FUNCTION constexpr inline size_t qHash(qint64 key, size_t seed = 0) noexcept
0131 {
0132     if constexpr (sizeof(qint64) > sizeof(size_t)) {
0133         // Avoid QTBUG-116080: we XOR the top half with its own sign bit:
0134         // - if the qint64 is in range of qint32, then signmask ^ high == 0
0135         //   (for Qt 7 only)
0136         // - if the qint64 is in range of quint32, then signmask == 0 and we
0137         //   do the same as the quint64 overload above
0138         quint32 high = quint32(quint64(key) >> 32);
0139         quint32 low = quint32(quint64(key));
0140         quint32 signmask = qint32(high) >> 31;  // all zeroes or all ones
0141         signmask = QT_VERSION_MAJOR > 6 ? signmask : 0;
0142         low ^= signmask ^ high;
0143         return qHash(low, seed);
0144     }
0145     return qHash(quint64(key), seed);
0146 }
0147 #ifdef QT_SUPPORTS_INT128
0148 constexpr size_t qHash(quint128 key, size_t seed = 0) noexcept
0149 {
0150     return qHash(quint64(key + (key >> 64)), seed);
0151 }
0152 constexpr size_t qHash(qint128 key, size_t seed = 0) noexcept
0153 {
0154     // Avoid QTBUG-116080: same as above, but with double the sizes and without
0155     // the need for compatibility
0156     quint64 high = quint64(quint128(key) >> 64);
0157     quint64 low = quint64(quint128(key));
0158     quint64 signmask = qint64(high) >> 63; // all zeroes or all ones
0159     low += signmask ^ high;
0160     return qHash(low, seed);
0161 }
0162 #endif // QT_SUPPORTS_INT128
0163 Q_DECL_CONST_FUNCTION inline size_t qHash(float key, size_t seed = 0) noexcept
0164 {
0165     // ensure -0 gets mapped to 0
0166     key += 0.0f;
0167     uint k;
0168     memcpy(&k, &key, sizeof(float));
0169     return QHashPrivate::hash(k, seed);
0170 }
0171 Q_CORE_EXPORT Q_DECL_CONST_FUNCTION size_t qHash(double key, size_t seed = 0) noexcept;
0172 Q_CORE_EXPORT Q_DECL_CONST_FUNCTION size_t qHash(long double key, size_t seed = 0) noexcept;
0173 Q_DECL_CONST_FUNCTION constexpr inline size_t qHash(wchar_t key, size_t seed = 0) noexcept
0174 { return QHashPrivate::hash(size_t(key), seed); }
0175 Q_DECL_CONST_FUNCTION constexpr inline size_t qHash(char16_t key, size_t seed = 0) noexcept
0176 { return QHashPrivate::hash(size_t(key), seed); }
0177 Q_DECL_CONST_FUNCTION constexpr inline size_t qHash(char32_t key, size_t seed = 0) noexcept
0178 { return QHashPrivate::hash(size_t(key), seed); }
0179 #ifdef __cpp_char8_t
0180 Q_DECL_CONST_FUNCTION constexpr inline size_t qHash(char8_t key, size_t seed = 0) noexcept
0181 { return QHashPrivate::hash(size_t(key), seed); }
0182 #endif
0183 template <class T> inline size_t qHash(const T *key, size_t seed = 0) noexcept
0184 {
0185     return qHash(reinterpret_cast<quintptr>(key), seed);
0186 }
0187 #if QT_VERSION < QT_VERSION_CHECK(7, 0, 0) && !defined(QT_BOOTSTRAPPED)
0188 
0189 // this used to be matched by the 1-to-2-arg adapter, which mixed the seed in differently
0190 // in Qt 7, when the adapter is gone, this will use the const T* overload above instead
0191 template <class T> inline size_t qHash(T *key, size_t seed = 0) noexcept
0192 {
0193     return qHash(reinterpret_cast<quintptr>(key)) ^ seed;
0194 }
0195 #endif // Qt 6
0196 Q_DECL_CONST_FUNCTION constexpr inline size_t qHash(std::nullptr_t, size_t seed = 0) noexcept
0197 {
0198     return seed;
0199 }
0200 template <class Enum, std::enable_if_t<std::is_enum_v<Enum>, bool> = true>
0201 Q_DECL_CONST_FUNCTION constexpr inline size_t qHash(Enum e, size_t seed = 0) noexcept
0202 { return QHashPrivate::hash(qToUnderlying(e), seed); }
0203 
0204 // (some) Qt types
0205 Q_DECL_CONST_FUNCTION constexpr inline size_t qHash(const QChar key, size_t seed = 0) noexcept { return qHash(key.unicode(), seed); }
0206 
0207 #if QT_CORE_REMOVED_SINCE(6, 4)
0208 Q_CORE_EXPORT Q_DECL_PURE_FUNCTION size_t qHash(const QByteArray &key, size_t seed = 0) noexcept;
0209 Q_CORE_EXPORT Q_DECL_PURE_FUNCTION size_t qHash(const QByteArrayView &key, size_t seed = 0) noexcept;
0210 #else
0211 Q_CORE_EXPORT Q_DECL_PURE_FUNCTION size_t qHash(QByteArrayView key, size_t seed = 0) noexcept;
0212 inline Q_DECL_PURE_FUNCTION size_t qHash(const QByteArray &key, size_t seed = 0
0213         QT6_DECL_NEW_OVERLOAD_TAIL) noexcept
0214 { return qHash(qToByteArrayViewIgnoringNull(key), seed); }
0215 #endif
0216 
0217 Q_CORE_EXPORT Q_DECL_PURE_FUNCTION size_t qHash(QStringView key, size_t seed = 0) noexcept;
0218 inline Q_DECL_PURE_FUNCTION size_t qHash(const QString &key, size_t seed = 0) noexcept
0219 { return qHash(QStringView{key}, seed); }
0220 #ifndef QT_BOOTSTRAPPED
0221 Q_CORE_EXPORT Q_DECL_PURE_FUNCTION size_t qHash(const QBitArray &key, size_t seed = 0) noexcept;
0222 #endif
0223 Q_CORE_EXPORT Q_DECL_PURE_FUNCTION size_t qHash(QLatin1StringView key, size_t seed = 0) noexcept;
0224 Q_DECL_CONST_FUNCTION constexpr inline size_t qHash(QKeyCombination key, size_t seed = 0) noexcept
0225 { return qHash(key.toCombined(), seed); }
0226 Q_CORE_EXPORT Q_DECL_PURE_FUNCTION uint qt_hash(QStringView key, uint chained = 0) noexcept;
0227 
0228 template <typename Enum>
0229 Q_DECL_CONST_FUNCTION constexpr inline size_t qHash(QFlags<Enum> flags, size_t seed = 0) noexcept
0230 { return qHash(flags.toInt(), seed); }
0231 
0232 // ### Qt 7: remove this "catch-all" overload logic, and require users
0233 // to provide the two-argument version of qHash.
0234 #if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
0235 // Beware of moving this code from here. It needs to see all the
0236 // declarations of qHash overloads for C++ fundamental types *before*
0237 // its own declaration.
0238 namespace QHashPrivate {
0239 template <typename T, typename = void>
0240 constexpr inline bool HasQHashSingleArgOverload = false;
0241 
0242 template <typename T>
0243 constexpr inline bool HasQHashSingleArgOverload<T, std::enable_if_t<
0244     std::is_convertible_v<decltype(qHash(std::declval<const T &>())), size_t>
0245 >> = true;
0246 }
0247 
0248 // Add Args... to make this overload consistently a worse match than
0249 // original 2-arg qHash overloads (QTBUG-126659)
0250 template <typename T, typename...Args,
0251           std::enable_if_t<QHashPrivate::HasQHashSingleArgOverload<T>
0252                            && sizeof...(Args) == 0 && !std::is_enum_v<T>, bool> = true>
0253 constexpr size_t qHash(const T &t, size_t seed, Args&&...) noexcept(noexcept(qHash(t)))
0254 #ifdef QT_NO_SINGLE_ARGUMENT_QHASH_OVERLOAD
0255     = delete;
0256 #else
0257 { return qHash(t) ^ seed; }
0258 #endif // QT_NO_SINGLE_ARGUMENT_QHASH_OVERLOAD
0259 #endif // < Qt 7
0260 
0261 namespace QHashPrivate {
0262 
0263 // helper for qHash() calls that used to go via the above 1-to-2-arg adapter
0264 template <typename T>
0265 constexpr size_t ex1to2arg(const T &key, size_t seed)
0266 {
0267     return QT7_ONLY(qHash(key, seed)) QT6_ONLY(qHash(key, 0U) ^ seed);
0268 }
0269 
0270 namespace detail {
0271 // approximates std::equality_comparable_with
0272 template <typename T, typename U, typename = void>
0273 struct is_equality_comparable_with : std::false_type {};
0274 
0275 template <typename T, typename U>
0276 struct is_equality_comparable_with<T, U,
0277     std::void_t<
0278         decltype(bool(std::declval<T>() == std::declval<U>())),
0279         decltype(bool(std::declval<U>() == std::declval<T>())),
0280         decltype(bool(std::declval<T>() != std::declval<U>())),
0281         decltype(bool(std::declval<U>() != std::declval<T>()))
0282     >>
0283     : std::true_type {};
0284 }
0285 
0286 template <typename Key, typename T> struct HeterogeneouslySearchableWithHelper
0287     : std::conjunction<
0288         // if Key and T are not the same (member already exists)
0289         std::negation<std::is_same<Key, T>>,
0290         // but are comparable amongst each other
0291         detail::is_equality_comparable_with<Key, T>,
0292         // and supports heteregenous hashing
0293         QHashHeterogeneousSearch<Key, T>
0294     > {};
0295 
0296 template <typename Key, typename T>
0297 using HeterogeneouslySearchableWith = HeterogeneouslySearchableWithHelper<
0298         q20::remove_cvref_t<Key>,
0299         q20::remove_cvref_t<T>
0300 >;
0301 
0302 template <typename Key, typename K>
0303 using if_heterogeneously_searchable_with = std::enable_if_t<
0304         QHashPrivate::HeterogeneouslySearchableWith<Key, K>::value,
0305     bool>;
0306 
0307 }
0308 
0309 template<typename T>
0310 bool qHashEquals(const T &a, const T &b)
0311 {
0312     return a == b;
0313 }
0314 
0315 template <typename T1, typename T2, QHashPrivate::if_heterogeneously_searchable_with<T1, T2> = true>
0316 bool qHashEquals(const T1 &a, const T2 &b)
0317 {
0318     return a == b;
0319 }
0320 
0321 namespace QtPrivate {
0322 template <typename Mixer> struct QHashCombinerWithSeed : private Mixer
0323 {
0324     using result_type = typename Mixer::result_type;
0325     size_t seed;
0326     constexpr QHashCombinerWithSeed(result_type s) noexcept : seed(s) {}
0327 
0328     template <typename T>
0329     constexpr result_type operator()(result_type result, const T &t) const
0330         noexcept(noexcept(qHash(t, seed)))
0331     {
0332         return Mixer::operator()(result, qHash(t, seed));
0333     }
0334 };
0335 
0336 #if QT_VERSION < QT_VERSION_CHECK(7, 0, 0) || defined(QT_BOOTSTRAPPED)
0337 // Earlier Qt 6.x versions of qHashMulti() failed to pass the seed as the seed
0338 // argument of qHash(), so this class exists for compatibility with user and
0339 // inline code that relies on the old behavior. For Qt 7, we'll replace with
0340 // the above version, except for the bootstrapped tools (which have no seed).
0341 template <typename Mixer> struct QHashCombiner : private Mixer
0342 {
0343     using result_type = typename Mixer::result_type;
0344 
0345     static constexpr size_t seed = 0;
0346     constexpr QHashCombiner(result_type) noexcept {}
0347     Q_DECL_DEPRECATED_X("pass the seed argument") constexpr QHashCombiner() noexcept {}
0348 
0349     template <typename T>
0350     constexpr result_type operator()(result_type result, const T &t) const
0351         noexcept(noexcept(qHash(t, seed)))
0352     {
0353         return Mixer::operator()(result, qHash(t, seed));
0354     }
0355 };
0356 #else
0357 template <typename Mixer> using QHashCombiner = QHashCombinerWithSeed<Mixer>;
0358 #endif
0359 
0360 struct QHashCombineMixer
0361 {
0362     typedef size_t result_type;
0363     constexpr result_type operator()(result_type result, result_type hash) const noexcept
0364     {
0365         // combiner taken from N3876 / boost::hash_combine
0366         return result ^ (hash + 0x9e3779b9 + (result << 6) + (result >> 2));
0367     }
0368 };
0369 using QHashCombine = QHashCombiner<QHashCombineMixer>;
0370 using QHashCombineWithSeed = QHashCombinerWithSeed<QHashCombineMixer>;
0371 
0372 struct QHashCombineCommutativeMixer : std::plus<size_t>
0373 {
0374     // QHashCombine is a good hash combiner, but is not commutative,
0375     // ie. it depends on the order of the input elements. That is
0376     // usually what we want: {0,1,3} should hash differently than
0377     // {1,3,0}. Except when it isn't (e.g. for QSet and
0378     // QHash). Therefore, provide a commutative combiner, too.
0379     typedef size_t result_type;
0380 };
0381 using QHashCombineCommutative = QHashCombiner<QHashCombineCommutativeMixer>;
0382 using QHashCombineCommutativeWithSeed = QHashCombinerWithSeed<QHashCombineCommutativeMixer>;
0383 
0384 template <typename... T>
0385 using QHashMultiReturnType = decltype(
0386     std::declval< std::enable_if_t<(sizeof...(T) > 0)> >(),
0387     (qHash(std::declval<const T &>(), size_t(0)), ...),
0388     size_t{}
0389 );
0390 
0391 // workaround for a MSVC ICE,
0392 // https://developercommunity.visualstudio.com/content/problem/996540/internal-compiler-error-on-msvc-1924-when-doing-sf.html
0393 template <typename T>
0394 inline constexpr bool QNothrowHashableHelper_v = noexcept(qHash(std::declval<const T &>(), size_t(0)));
0395 
0396 template <typename T, typename Enable = void>
0397 struct QNothrowHashable : std::false_type {};
0398 
0399 template <typename T>
0400 struct QNothrowHashable<T, std::enable_if_t<QNothrowHashableHelper_v<T>>> : std::true_type {};
0401 
0402 template <typename T>
0403 constexpr inline bool QNothrowHashable_v = QNothrowHashable<T>::value;
0404 
0405 } // namespace QtPrivate
0406 
0407 template <typename... T>
0408 constexpr
0409 #ifdef Q_QDOC
0410 size_t
0411 #else
0412 QtPrivate::QHashMultiReturnType<T...>
0413 #endif
0414 qHashMulti(size_t seed, const T &... args)
0415     noexcept(std::conjunction_v<QtPrivate::QNothrowHashable<T>...>)
0416 {
0417     QtPrivate::QHashCombine hash(seed);
0418     return ((seed = hash(seed, args)), ...), seed;
0419 }
0420 
0421 template <typename... T>
0422 constexpr
0423 #ifdef Q_QDOC
0424 size_t
0425 #else
0426 QtPrivate::QHashMultiReturnType<T...>
0427 #endif
0428 qHashMultiCommutative(size_t seed, const T &... args)
0429     noexcept(std::conjunction_v<QtPrivate::QNothrowHashable<T>...>)
0430 {
0431     QtPrivate::QHashCombineCommutative hash(seed);
0432     return ((seed = hash(seed, args)), ...), seed;
0433 }
0434 
0435 template <typename InputIterator>
0436 inline size_t qHashRange(InputIterator first, InputIterator last, size_t seed = 0)
0437     noexcept(noexcept(qHash(*first, 0))) // assume iterator operations don't throw
0438 {
0439     return std::accumulate(first, last, seed, QtPrivate::QHashCombine(seed));
0440 }
0441 
0442 template <typename InputIterator>
0443 inline size_t qHashRangeCommutative(InputIterator first, InputIterator last, size_t seed = 0)
0444     noexcept(noexcept(qHash(*first, 0))) // assume iterator operations don't throw
0445 {
0446     return std::accumulate(first, last, seed, QtPrivate::QHashCombineCommutative(seed));
0447 }
0448 
0449 namespace QHashPrivate {
0450 template <typename T1, typename T2> static constexpr bool noexceptPairHash()
0451 {
0452     size_t seed = 0;
0453     return noexcept(qHash(std::declval<T1>(), seed)) && noexcept(qHash(std::declval<T2>(), seed));
0454 }
0455 } // QHashPrivate
0456 
0457 template <typename T1, typename T2> inline size_t qHash(const std::pair<T1, T2> &key, size_t seed)
0458     noexcept(QHashPrivate::noexceptPairHash<T1, T2>())
0459 {
0460     return qHashMulti(seed, key.first, key.second);
0461 }
0462 
0463 #define QT_SPECIALIZE_STD_HASH_TO_CALL_QHASH(Class, Arguments)      \
0464     QT_BEGIN_INCLUDE_NAMESPACE                                      \
0465     namespace std {                                                 \
0466         template <>                                                 \
0467         struct hash< QT_PREPEND_NAMESPACE(Class) > {                \
0468             using argument_type = QT_PREPEND_NAMESPACE(Class);      \
0469             using result_type = size_t;                             \
0470             size_t operator()(Arguments s) const                    \
0471               noexcept(QT_PREPEND_NAMESPACE(                        \
0472                      QtPrivate::QNothrowHashable_v)<argument_type>) \
0473             {                                                       \
0474                 /* this seeds qHash with the result of */           \
0475                 /* std::hash applied to an int, to reap */          \
0476                 /* any protection against predictable hash */       \
0477                 /* values the std implementation may provide */     \
0478                 using QT_PREPEND_NAMESPACE(qHash);                  \
0479                 return qHash(s, qHash(std::hash<int>{}(0)));        \
0480             }                                                       \
0481         };                                                          \
0482     }                                                               \
0483     QT_END_INCLUDE_NAMESPACE                                        \
0484     /*end*/
0485 
0486 #define QT_SPECIALIZE_STD_HASH_TO_CALL_QHASH_BY_CREF(Class) \
0487     QT_SPECIALIZE_STD_HASH_TO_CALL_QHASH(Class, const argument_type &)
0488 #define QT_SPECIALIZE_STD_HASH_TO_CALL_QHASH_BY_VALUE(Class) \
0489     QT_SPECIALIZE_STD_HASH_TO_CALL_QHASH(Class, argument_type)
0490 
0491 QT_SPECIALIZE_STD_HASH_TO_CALL_QHASH_BY_CREF(QString)
0492 QT_SPECIALIZE_STD_HASH_TO_CALL_QHASH_BY_VALUE(QStringView)
0493 QT_SPECIALIZE_STD_HASH_TO_CALL_QHASH_BY_VALUE(QLatin1StringView)
0494 QT_SPECIALIZE_STD_HASH_TO_CALL_QHASH_BY_VALUE(QByteArrayView)
0495 QT_SPECIALIZE_STD_HASH_TO_CALL_QHASH_BY_CREF(QByteArray)
0496 #ifndef QT_BOOTSTRAPPED
0497 QT_SPECIALIZE_STD_HASH_TO_CALL_QHASH_BY_CREF(QBitArray)
0498 #endif
0499 
0500 QT_END_NAMESPACE
0501 
0502 #if defined(Q_CC_MSVC)
0503 #pragma warning( pop )
0504 #endif
0505 
0506 #endif // QHASHFUNCTIONS_H