@@ -330,41 +330,29 @@ struct hash<Enum, typename std::enable_if<std::is_enum<Enum>::value>::type> {
330330
331331template <typename ... Args>
332332struct 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.
333335 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 );
337339 } else {
338- return sizeof ( hash<Arg>{}(std::declval<Arg>()) );
340+ return hash<Arg>{}(arg );
339341 }
340342 }
341343
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 });
356346 }
357347
358348 // Creates a buffer that holds all the data from each element of the tuple. If possible we memcpy the data directly. If
359349 // not, we hash the object and use this for the array. Size of the array is known at compile time, and memcpy is optimized
360350 // away, so filling the buffer is highly efficient. Finally, call wyhash with this buffer.
361351 template <typename T, std::size_t ... Idx>
362352 [[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;
368356 }
369357};
370358
0 commit comments