Warning, file /include/QtCore/qhashfunctions.h was not indexed
or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001
0002
0003
0004
0005 #ifndef QHASHFUNCTIONS_H
0006 #define QHASHFUNCTIONS_H
0007
0008 #include <QtCore/qstring.h>
0009 #include <QtCore/qstringfwd.h>
0010
0011 #include <numeric> // for std::accumulate
0012 #include <functional> // for std::hash
0013 #include <utility> // For std::pair
0014
0015 #if 0
0016 #pragma qt_class(QHashFunctions)
0017 #endif
0018
0019 #if defined(Q_CC_MSVC)
0020 #pragma warning( push )
0021 #pragma warning( disable : 4311 )
0022 #pragma warning( disable : 4127 )
0023 #endif
0024
0025 QT_BEGIN_NAMESPACE
0026
0027 class QBitArray;
0028
0029 #if QT_DEPRECATED_SINCE(6,6)
0030 QT_DEPRECATED_VERSION_X_6_6("Use QHashSeed instead")
0031 Q_CORE_EXPORT int qGlobalQHashSeed();
0032 QT_DEPRECATED_VERSION_X_6_6("Use QHashSeed instead")
0033 Q_CORE_EXPORT void qSetGlobalQHashSeed(int newSeed);
0034 #endif
0035
0036 struct QHashSeed
0037 {
0038 constexpr QHashSeed(size_t d = 0) : data(d) {}
0039 constexpr operator size_t() const noexcept { return data; }
0040
0041 static Q_CORE_EXPORT QHashSeed globalSeed() noexcept;
0042 static Q_CORE_EXPORT void setDeterministicGlobalSeed();
0043 static Q_CORE_EXPORT void resetRandomGlobalSeed();
0044 private:
0045 size_t data;
0046 };
0047
0048 namespace QHashPrivate {
0049
0050 Q_DECL_CONST_FUNCTION constexpr size_t hash(size_t key, size_t seed) noexcept
0051 {
0052 key ^= seed;
0053 if constexpr (sizeof(size_t) == 4) {
0054 key ^= key >> 16;
0055 key *= UINT32_C(0x45d9f3b);
0056 key ^= key >> 16;
0057 key *= UINT32_C(0x45d9f3b);
0058 key ^= key >> 16;
0059 return key;
0060 } else {
0061 quint64 key64 = key;
0062 key64 ^= key64 >> 32;
0063 key64 *= UINT64_C(0xd6e8feb86659fd93);
0064 key64 ^= key64 >> 32;
0065 key64 *= UINT64_C(0xd6e8feb86659fd93);
0066 key64 ^= key64 >> 32;
0067 return size_t(key64);
0068 }
0069 }
0070
0071 template <typename T1, typename T2> static constexpr bool noexceptPairHash();
0072 }
0073
0074 Q_CORE_EXPORT Q_DECL_PURE_FUNCTION size_t qHashBits(const void *p, size_t size, size_t seed = 0) noexcept;
0075
0076
0077 template <typename T1, typename T2> inline size_t qHash(const std::pair<T1, T2> &key, size_t seed = 0)
0078 noexcept(QHashPrivate::noexceptPairHash<T1, T2>());
0079
0080
0081 Q_DECL_CONST_FUNCTION constexpr inline size_t qHash(char key, size_t seed = 0) noexcept
0082 { return QHashPrivate::hash(size_t(key), seed); }
0083 Q_DECL_CONST_FUNCTION constexpr inline size_t qHash(uchar key, size_t seed = 0) noexcept
0084 { return QHashPrivate::hash(size_t(key), seed); }
0085 Q_DECL_CONST_FUNCTION constexpr inline size_t qHash(signed char key, size_t seed = 0) noexcept
0086 { return QHashPrivate::hash(size_t(key), seed); }
0087 Q_DECL_CONST_FUNCTION constexpr inline size_t qHash(ushort key, size_t seed = 0) noexcept
0088 { return QHashPrivate::hash(size_t(key), seed); }
0089 Q_DECL_CONST_FUNCTION constexpr inline size_t qHash(short key, size_t seed = 0) noexcept
0090 { return QHashPrivate::hash(size_t(key), seed); }
0091 Q_DECL_CONST_FUNCTION constexpr inline size_t qHash(uint key, size_t seed = 0) noexcept
0092 { return QHashPrivate::hash(size_t(key), seed); }
0093 Q_DECL_CONST_FUNCTION constexpr inline size_t qHash(int key, size_t seed = 0) noexcept
0094 { return QHashPrivate::hash(size_t(key), seed); }
0095 Q_DECL_CONST_FUNCTION constexpr inline size_t qHash(ulong key, size_t seed = 0) noexcept
0096 { return QHashPrivate::hash(size_t(key), seed); }
0097 Q_DECL_CONST_FUNCTION constexpr inline size_t qHash(long key, size_t seed = 0) noexcept
0098 { return QHashPrivate::hash(size_t(key), seed); }
0099 Q_DECL_CONST_FUNCTION constexpr inline size_t qHash(quint64 key, size_t seed = 0) noexcept
0100 {
0101 if constexpr (sizeof(quint64) > sizeof(size_t))
0102 key ^= (key >> 32);
0103 return QHashPrivate::hash(size_t(key), seed);
0104 }
0105 Q_DECL_CONST_FUNCTION constexpr inline size_t qHash(qint64 key, size_t seed = 0) noexcept { return qHash(quint64(key), seed); }
0106 Q_DECL_CONST_FUNCTION inline size_t qHash(float key, size_t seed = 0) noexcept
0107 {
0108
0109 key += 0.0f;
0110 uint k;
0111 memcpy(&k, &key, sizeof(float));
0112 return QHashPrivate::hash(k, seed);
0113 }
0114 Q_CORE_EXPORT Q_DECL_CONST_FUNCTION size_t qHash(double key, size_t seed = 0) noexcept;
0115 Q_CORE_EXPORT Q_DECL_CONST_FUNCTION size_t qHash(long double key, size_t seed = 0) noexcept;
0116 Q_DECL_CONST_FUNCTION constexpr inline size_t qHash(wchar_t key, size_t seed = 0) noexcept
0117 { return QHashPrivate::hash(size_t(key), seed); }
0118 Q_DECL_CONST_FUNCTION constexpr inline size_t qHash(char16_t key, size_t seed = 0) noexcept
0119 { return QHashPrivate::hash(size_t(key), seed); }
0120 Q_DECL_CONST_FUNCTION constexpr inline size_t qHash(char32_t key, size_t seed = 0) noexcept
0121 { return QHashPrivate::hash(size_t(key), seed); }
0122 #ifdef __cpp_char8_t
0123 Q_DECL_CONST_FUNCTION constexpr inline size_t qHash(char8_t key, size_t seed = 0) noexcept
0124 { return QHashPrivate::hash(size_t(key), seed); }
0125 #endif
0126 template <class T> inline size_t qHash(const T *key, size_t seed = 0) noexcept
0127 {
0128 return qHash(reinterpret_cast<quintptr>(key), seed);
0129 }
0130 Q_DECL_CONST_FUNCTION constexpr inline size_t qHash(std::nullptr_t, size_t seed = 0) noexcept
0131 {
0132 return seed;
0133 }
0134 template <class Enum, std::enable_if_t<std::is_enum_v<Enum>, bool> = true>
0135 Q_DECL_CONST_FUNCTION constexpr inline size_t qHash(Enum e, size_t seed = 0) noexcept
0136 { return QHashPrivate::hash(qToUnderlying(e), seed); }
0137
0138
0139 Q_DECL_CONST_FUNCTION constexpr inline size_t qHash(const QChar key, size_t seed = 0) noexcept { return qHash(key.unicode(), seed); }
0140
0141 #if QT_CORE_REMOVED_SINCE(6, 4)
0142 Q_CORE_EXPORT Q_DECL_PURE_FUNCTION size_t qHash(const QByteArray &key, size_t seed = 0) noexcept;
0143 Q_CORE_EXPORT Q_DECL_PURE_FUNCTION size_t qHash(const QByteArrayView &key, size_t seed = 0) noexcept;
0144 #else
0145 Q_CORE_EXPORT Q_DECL_PURE_FUNCTION size_t qHash(QByteArrayView key, size_t seed = 0) noexcept;
0146 inline Q_DECL_PURE_FUNCTION size_t qHash(const QByteArray &key, size_t seed = 0
0147 QT6_DECL_NEW_OVERLOAD_TAIL) noexcept
0148 { return qHash(qToByteArrayViewIgnoringNull(key), seed); }
0149 #endif
0150
0151 Q_CORE_EXPORT Q_DECL_PURE_FUNCTION size_t qHash(QStringView key, size_t seed = 0) noexcept;
0152 inline Q_DECL_PURE_FUNCTION size_t qHash(const QString &key, size_t seed = 0) noexcept
0153 { return qHash(QStringView{key}, seed); }
0154 #ifndef QT_BOOTSTRAPPED
0155 Q_CORE_EXPORT Q_DECL_PURE_FUNCTION size_t qHash(const QBitArray &key, size_t seed = 0) noexcept;
0156 #endif
0157 Q_CORE_EXPORT Q_DECL_PURE_FUNCTION size_t qHash(QLatin1StringView key, size_t seed = 0) noexcept;
0158 Q_DECL_CONST_FUNCTION constexpr inline size_t qHash(QKeyCombination key, size_t seed = 0) noexcept
0159 { return qHash(key.toCombined(), seed); }
0160 Q_CORE_EXPORT Q_DECL_PURE_FUNCTION uint qt_hash(QStringView key, uint chained = 0) noexcept;
0161
0162 template <typename Enum>
0163 Q_DECL_CONST_FUNCTION constexpr inline size_t qHash(QFlags<Enum> flags, size_t seed = 0) noexcept
0164 { return qHash(flags.toInt(), seed); }
0165
0166
0167
0168 #if (QT_VERSION < QT_VERSION_CHECK(7, 0, 0))
0169
0170
0171
0172 namespace QHashPrivate {
0173 template <typename T, typename = void>
0174 constexpr inline bool HasQHashSingleArgOverload = false;
0175
0176 template <typename T>
0177 constexpr inline bool HasQHashSingleArgOverload<T, std::enable_if_t<
0178 std::is_convertible_v<decltype(qHash(std::declval<const T &>())), size_t>
0179 >> = true;
0180 }
0181
0182 template <typename T, std::enable_if_t<QHashPrivate::HasQHashSingleArgOverload<T> && !std::is_enum_v<T>, bool> = true>
0183 size_t qHash(const T &t, size_t seed) noexcept(noexcept(qHash(t)))
0184 { return qHash(t) ^ seed; }
0185 #endif
0186
0187 template<typename T>
0188 bool qHashEquals(const T &a, const T &b)
0189 {
0190 return a == b;
0191 }
0192
0193 namespace QtPrivate {
0194
0195 struct QHashCombine
0196 {
0197 typedef size_t result_type;
0198 template <typename T>
0199 constexpr result_type operator()(size_t seed, const T &t) const noexcept(noexcept(qHash(t)))
0200
0201 { return seed ^ (qHash(t) + 0x9e3779b9 + (seed << 6) + (seed >> 2)) ; }
0202 };
0203
0204 struct QHashCombineCommutative
0205 {
0206
0207
0208
0209
0210
0211 typedef size_t result_type;
0212 template <typename T>
0213 constexpr result_type operator()(size_t seed, const T &t) const noexcept(noexcept(qHash(t)))
0214 { return seed + qHash(t); }
0215 };
0216
0217 template <typename... T>
0218 using QHashMultiReturnType = decltype(
0219 std::declval< std::enable_if_t<(sizeof...(T) > 0)> >(),
0220 (qHash(std::declval<const T &>()), ...),
0221 size_t{}
0222 );
0223
0224
0225
0226 template <typename T>
0227 inline constexpr bool QNothrowHashableHelper_v = noexcept(qHash(std::declval<const T &>()));
0228
0229 template <typename T, typename Enable = void>
0230 struct QNothrowHashable : std::false_type {};
0231
0232 template <typename T>
0233 struct QNothrowHashable<T, std::enable_if_t<QNothrowHashableHelper_v<T>>> : std::true_type {};
0234
0235 template <typename T>
0236 constexpr inline bool QNothrowHashable_v = QNothrowHashable<T>::value;
0237
0238 }
0239
0240 template <typename... T>
0241 constexpr
0242 #ifdef Q_QDOC
0243 size_t
0244 #else
0245 QtPrivate::QHashMultiReturnType<T...>
0246 #endif
0247 qHashMulti(size_t seed, const T &... args)
0248 noexcept(std::conjunction_v<QtPrivate::QNothrowHashable<T>...>)
0249 {
0250 QtPrivate::QHashCombine hash;
0251 return ((seed = hash(seed, args)), ...), seed;
0252 }
0253
0254 template <typename... T>
0255 constexpr
0256 #ifdef Q_QDOC
0257 size_t
0258 #else
0259 QtPrivate::QHashMultiReturnType<T...>
0260 #endif
0261 qHashMultiCommutative(size_t seed, const T &... args)
0262 noexcept(std::conjunction_v<QtPrivate::QNothrowHashable<T>...>)
0263 {
0264 QtPrivate::QHashCombineCommutative hash;
0265 return ((seed = hash(seed, args)), ...), seed;
0266 }
0267
0268 template <typename InputIterator>
0269 inline size_t qHashRange(InputIterator first, InputIterator last, size_t seed = 0)
0270 noexcept(noexcept(qHash(*first)))
0271 {
0272 return std::accumulate(first, last, seed, QtPrivate::QHashCombine());
0273 }
0274
0275 template <typename InputIterator>
0276 inline size_t qHashRangeCommutative(InputIterator first, InputIterator last, size_t seed = 0)
0277 noexcept(noexcept(qHash(*first)))
0278 {
0279 return std::accumulate(first, last, seed, QtPrivate::QHashCombineCommutative());
0280 }
0281
0282 namespace QHashPrivate {
0283 template <typename T1, typename T2> static constexpr bool noexceptPairHash()
0284 {
0285 size_t seed = 0;
0286 return noexcept(qHash(std::declval<T1>(), seed)) && noexcept(qHash(std::declval<T2>(), seed));
0287 }
0288 }
0289
0290 template <typename T1, typename T2> inline size_t qHash(const std::pair<T1, T2> &key, size_t seed)
0291 noexcept(QHashPrivate::noexceptPairHash<T1, T2>())
0292 {
0293 return qHashMulti(seed, key.first, key.second);
0294 }
0295
0296 #define QT_SPECIALIZE_STD_HASH_TO_CALL_QHASH(Class, Arguments) \
0297 QT_BEGIN_INCLUDE_NAMESPACE \
0298 namespace std { \
0299 template <> \
0300 struct hash< QT_PREPEND_NAMESPACE(Class) > { \
0301 using argument_type = QT_PREPEND_NAMESPACE(Class); \
0302 using result_type = size_t; \
0303 size_t operator()(Arguments s) const \
0304 noexcept(QT_PREPEND_NAMESPACE( \
0305 QtPrivate::QNothrowHashable_v)<argument_type>) \
0306 { \
0307 \
0308 \
0309 \
0310 \
0311 using QT_PREPEND_NAMESPACE(qHash); \
0312 return qHash(s, qHash(std::hash<int>{}(0))); \
0313 } \
0314 }; \
0315 } \
0316 QT_END_INCLUDE_NAMESPACE \
0317
0318
0319 #define QT_SPECIALIZE_STD_HASH_TO_CALL_QHASH_BY_CREF(Class) \
0320 QT_SPECIALIZE_STD_HASH_TO_CALL_QHASH(Class, const argument_type &)
0321 #define QT_SPECIALIZE_STD_HASH_TO_CALL_QHASH_BY_VALUE(Class) \
0322 QT_SPECIALIZE_STD_HASH_TO_CALL_QHASH(Class, argument_type)
0323
0324 QT_SPECIALIZE_STD_HASH_TO_CALL_QHASH_BY_CREF(QString)
0325 QT_SPECIALIZE_STD_HASH_TO_CALL_QHASH_BY_VALUE(QStringView)
0326 QT_SPECIALIZE_STD_HASH_TO_CALL_QHASH_BY_VALUE(QLatin1StringView)
0327 QT_SPECIALIZE_STD_HASH_TO_CALL_QHASH_BY_VALUE(QByteArrayView)
0328 QT_SPECIALIZE_STD_HASH_TO_CALL_QHASH_BY_CREF(QByteArray)
0329 #ifndef QT_BOOTSTRAPPED
0330 QT_SPECIALIZE_STD_HASH_TO_CALL_QHASH_BY_CREF(QBitArray)
0331 #endif
0332
0333 QT_END_NAMESPACE
0334
0335 #if defined(Q_CC_MSVC)
0336 #pragma warning( pop )
0337 #endif
0338
0339 #endif