@@ -330,41 +330,29 @@ struct hash<Enum, typename std::enable_if<std::is_enum<Enum>::value>::type> {
330
330
331
331
template <typename ... Args>
332
332
struct tuple_hash_helper {
333
+ // Converts the value into 64bit. If it is an integral type, just cast it. Mixing is doing the rest.
334
+ // If it isn't an integral we need to hash it.
333
335
template <typename Arg>
334
- [[nodiscard]] constexpr static auto calc_buf_size () {
335
- if constexpr (std::has_unique_object_representations_v <Arg>) {
336
- return sizeof (Arg );
336
+ [[nodiscard]] constexpr static auto to64 (Arg const & arg) -> uint64_t {
337
+ if constexpr (std::is_integral_v <Arg>) {
338
+ return static_cast < uint64_t >(arg );
337
339
} else {
338
- return sizeof ( hash<Arg>{}(std::declval<Arg>()) );
340
+ return hash<Arg>{}(arg );
339
341
}
340
342
}
341
343
342
- // Reads data from back to front. We do this so there's no need for bswap when multiple
343
- // bytes are read (on little endian). This should be a tiny bit faster.
344
- template <typename Arg>
345
- [[nodiscard]] constexpr static auto put (std::byte* pos, Arg const & arg) -> std::byte* {
346
- if constexpr (std::has_unique_object_representations_v<Arg>) {
347
- pos -= sizeof (Arg);
348
- std::memcpy (pos, &arg, sizeof (Arg));
349
- return pos;
350
- } else {
351
- auto x = hash<Arg>{}(arg);
352
- pos -= sizeof (x);
353
- std::memcpy (pos, &x, sizeof (x));
354
- return pos;
355
- }
344
+ [[nodiscard]] static auto mix64 (uint64_t state, uint64_t v) -> uint64_t {
345
+ return detail::wyhash::mix (state + v, uint64_t {0x9ddfea08eb382d69 });
356
346
}
357
347
358
348
// Creates a buffer that holds all the data from each element of the tuple. If possible we memcpy the data directly. If
359
349
// not, we hash the object and use this for the array. Size of the array is known at compile time, and memcpy is optimized
360
350
// away, so filling the buffer is highly efficient. Finally, call wyhash with this buffer.
361
351
template <typename T, std::size_t ... Idx>
362
352
[[nodiscard]] static auto calc_hash (T const & t, std::index_sequence<Idx...>) noexcept -> uint64_t {
363
- std::array<std::byte, (calc_buf_size<Args>() + ...)> tmp_buffer;
364
- auto * buf_ptr = tmp_buffer.data () + tmp_buffer.size ();
365
- ((buf_ptr = put (buf_ptr, std::get<Idx>(t))), ...);
366
- // at this point, buf_ptr==tmp_buffer.data()
367
- return ankerl::unordered_dense::detail::wyhash::hash (tmp_buffer.data (), tmp_buffer.size ());
353
+ auto h = uint64_t {};
354
+ ((h = mix64 (h, to64 (std::get<Idx>(t)))), ...);
355
+ return h;
368
356
}
369
357
};
370
358
0 commit comments