|
1 | | -#ifndef IRIS_HASH_HPP |
| 1 | +#ifndef IRIS_HASH_HPP |
2 | 2 | #define IRIS_HASH_HPP |
3 | 3 |
|
4 | 4 | // SPDX-License-Identifier: MIT |
|
7 | 7 | #include <iris/type_traits.hpp> |
8 | 8 |
|
9 | 9 | #include <functional> |
10 | | -#include <bit> |
| 10 | +#include <ranges> |
11 | 11 |
|
12 | 12 | #include <cstddef> |
13 | 13 |
|
@@ -111,18 +111,50 @@ template<> |
111 | 111 |
|
112 | 112 | } // detail |
113 | 113 |
|
| 114 | +template<class T> |
| 115 | +[[nodiscard]] constexpr std::size_t hash_combine(std::size_t const seed, T const& v) noexcept; |
| 116 | + |
| 117 | +template<class T> |
| 118 | +[[nodiscard]] constexpr std::size_t hash_value(T const& var) noexcept |
| 119 | +{ |
| 120 | + static_assert(is_hash_enabled_v<T>); |
| 121 | + return std::hash<T>{}(var); |
| 122 | +} |
| 123 | + |
| 124 | +template<std::ranges::input_range R> |
| 125 | +[[nodiscard]] constexpr std::size_t hash_value(R const& r) |
| 126 | + noexcept( |
| 127 | + noexcept(++std::ranges::begin(r)) && |
| 128 | + noexcept(std::ranges::end(r)) && |
| 129 | + std::is_nothrow_copy_assignable_v<std::ranges::iterator_t<R>> |
| 130 | + ) |
| 131 | +{ |
| 132 | + std::size_t seed = 0; |
| 133 | + for (auto it = std::ranges::begin(r), se = std::ranges::end(r); it != se; ++it) { |
| 134 | + seed = iris::hash_combine(seed, iris::hash_value(*it)); |
| 135 | + } |
| 136 | + return seed; |
| 137 | +} |
| 138 | + |
114 | 139 | // https://github.com/boostorg/container_hash/blob/5d8b8ac2b9d9d7cb3818f88fd7e6372e5f072ff5/include/boost/container_hash/hash.hpp#L472C53-L472C63 |
115 | 140 | // https://softwareengineering.stackexchange.com/questions/402542/where-do-magic-hashing-constants-like-0x9e3779b9-and-0x9e3779b1-come-from |
116 | 141 |
|
117 | 142 | template<class T> |
118 | 143 | [[nodiscard]] constexpr std::size_t hash_combine(std::size_t const seed, T const& v) noexcept |
119 | 144 | { |
120 | | - static_assert(is_hash_enabled_v<T>); |
121 | 145 | return detail::hash_mix<sizeof(std::size_t)>( |
122 | | - seed + 0x9e3779b97f4a7c55uz + std::hash<T>{}(v) |
| 146 | + seed + 0x9e3779b97f4a7c55uz + iris::hash_value(v) |
123 | 147 | ); |
124 | 148 | } |
125 | 149 |
|
| 150 | +template<class T, class... Ts> |
| 151 | +[[nodiscard]] constexpr std::size_t hash_all(T const& first, Ts const&... rest) noexcept |
| 152 | +{ |
| 153 | + std::size_t seed = iris::hash_value(first); |
| 154 | + ((seed = iris::hash_combine(seed, rest)), ...); |
| 155 | + return seed; |
| 156 | +} |
| 157 | + |
126 | 158 | } // iris |
127 | 159 |
|
128 | 160 | #endif |
0 commit comments