Blender V5.0
BLI_hash.hh
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
5#pragma once
6
63
64#include <memory>
65#include <string>
66#include <utility>
67
68#include "BLI_hash_fwd.hh"
69#include "BLI_string_ref.hh"
70
71namespace blender {
72
83template<typename T> struct DefaultHash {
84 uint64_t operator()(const T &value) const
85 {
86 if constexpr (std::is_enum_v<T>) {
87 /* For enums use the value as hash directly. */
88 return uint64_t(value);
89 }
90 else {
91 /* Try to call the `hash()` function on the value. */
92 /* If this results in a compiler error, no hash function for the type has been found. */
93 return value.hash();
94 }
95 }
96
97 template<typename U> uint64_t operator()(const U &value) const
98 {
99 /* Try calling the static `T::hash_as(value)` function with the given value. The returned hash
100 * should be "compatible" with `T::hash()`. Usually that means that if `value` is converted to
101 * `T` its hash does not change. */
102 /* If this results in a compiler error, no hash function for the heterogeneous lookup has been
103 * found. */
104 return T::hash_as(value);
105 }
106};
107
111template<typename T> struct DefaultHash<const T> {
112 uint64_t operator()(const T &value) const
113 {
114 return DefaultHash<T>{}(value);
115 }
116};
117
118#define TRIVIAL_DEFAULT_INT_HASH(TYPE) \
119 template<> struct DefaultHash<TYPE> { \
120 uint64_t operator()(TYPE value) const \
121 { \
122 return uint64_t(value); \
123 } \
124 }
125
140
144template<> struct DefaultHash<float> {
145 uint64_t operator()(float value) const
146 {
147 /* Explicit `uint64_t` cast to suppress CPPCHECK warning. */
148 return uint64_t(*reinterpret_cast<uint32_t *>(&value));
149 }
150};
151
152template<> struct DefaultHash<double> {
153 uint64_t operator()(double value) const
154 {
155 return *reinterpret_cast<uint64_t *>(&value);
156 }
157};
158
159template<> struct DefaultHash<bool> {
160 uint64_t operator()(bool value) const
161 {
162 return uint64_t((value != false) * 1298191);
163 }
164};
165
167{
168 uint64_t hash = 5381;
169 for (char c : str) {
170 hash = hash * 33 + c;
171 }
172 return hash;
173}
174
175template<> struct DefaultHash<std::string> {
181 {
182 return hash_string(value);
183 }
184};
185
186template<> struct DefaultHash<StringRef> {
188 {
189 return hash_string(value);
190 }
191};
192
193template<> struct DefaultHash<StringRefNull> {
195 {
196 return hash_string(value);
197 }
198};
199
200template<> struct DefaultHash<std::string_view> {
202 {
203 return hash_string(value);
204 }
205};
206
210template<typename T> struct DefaultHash<T *> {
211 uint64_t operator()(const T *value) const
212 {
213 uintptr_t ptr = uintptr_t(value);
214 uint64_t hash = uint64_t(ptr >> 4);
215 return hash;
216 }
217};
218
219namespace detail {
220static constexpr std::array<uint64_t, 3> default_hash_factors = {19349669, 83492791, 3632623};
221
222template<size_t... I, typename... Args>
223inline uint64_t get_default_hash_array(std::index_sequence<I...> /*indices*/, const Args &...args)
224{
225 static_assert(sizeof...(Args) == sizeof...(I));
226 static_assert(sizeof...(Args) <= default_hash_factors.size());
227 return (0 ^ ... ^ (default_hash_factors[I] * DefaultHash<std::decay_t<Args>>{}(args)));
228}
229
230} // namespace detail
231
232template<typename T, typename... Args>
233inline uint64_t get_default_hash(const T &v, const Args &...args)
234{
235 return DefaultHash<std::decay_t<T>>{}(v) ^
236 detail::get_default_hash_array(std::make_index_sequence<sizeof...(Args)>(), args...);
237}
238
240template<typename T> struct PointerHashes {
241 template<typename U> uint64_t operator()(const U &value) const
242 {
243 return get_default_hash(&*value);
244 }
245};
246
247template<typename T> struct DefaultHash<std::unique_ptr<T>> : public PointerHashes<T> {};
248template<typename T> struct DefaultHash<std::shared_ptr<T>> : public PointerHashes<T> {};
249
250template<typename T> struct DefaultHash<std::reference_wrapper<T>> {
251 uint64_t operator()(const std::reference_wrapper<T> &value) const
252 {
253 return get_default_hash(value.get());
254 }
255};
256
257template<typename T1, typename T2> struct DefaultHash<std::pair<T1, T2>> {
258 uint64_t operator()(const std::pair<T1, T2> &value) const
259 {
260 return get_default_hash(value.first, value.second);
261 }
262};
263
264} // namespace blender
#define TRIVIAL_DEFAULT_INT_HASH(TYPE)
Definition BLI_hash.hh:118
#define U
ATTR_WARN_UNUSED_RESULT const BMVert * v
long long int int64_t
unsigned long long int uint64_t
nullptr float
#define str(s)
#define T
static constexpr std::array< uint64_t, 3 > default_hash_factors
Definition BLI_hash.hh:220
uint64_t get_default_hash_array(std::index_sequence< I... >, const Args &...args)
Definition BLI_hash.hh:223
uint64_t hash_string(StringRef str)
Definition BLI_hash.hh:166
uint64_t get_default_hash(const T &v, const Args &...args)
Definition BLI_hash.hh:233
#define I
#define hash
Definition noise_c.cc:154
uint64_t operator()(StringRef value) const
Definition BLI_hash.hh:194
uint64_t operator()(StringRef value) const
Definition BLI_hash.hh:187
uint64_t operator()(const T *value) const
Definition BLI_hash.hh:211
uint64_t operator()(bool value) const
Definition BLI_hash.hh:160
uint64_t operator()(const T &value) const
Definition BLI_hash.hh:112
uint64_t operator()(double value) const
Definition BLI_hash.hh:153
uint64_t operator()(float value) const
Definition BLI_hash.hh:145
uint64_t operator()(const std::pair< T1, T2 > &value) const
Definition BLI_hash.hh:258
uint64_t operator()(const std::reference_wrapper< T > &value) const
Definition BLI_hash.hh:251
uint64_t operator()(StringRef value) const
Definition BLI_hash.hh:180
uint64_t operator()(StringRef value) const
Definition BLI_hash.hh:201
uint64_t operator()(const T &value) const
Definition BLI_hash.hh:84
uint64_t operator()(const U &value) const
Definition BLI_hash.hh:97
uint64_t operator()(const U &value) const
Definition BLI_hash.hh:241
PointerRNA * ptr
Definition wm_files.cc:4238