diff options
| author | crueter <crueter@eden-emu.dev> | 2026-08-31 02:58:09 +0200 |
|---|---|---|
| committer | crueter <crueter@eden-emu.dev> | 2026-08-31 02:58:09 +0200 |
| commit | 7fda6dde73ab9fa1eab40d43c90720a1d9ba054f (patch) | |
| tree | 12753135a33c3002ecb35734ac7c79adc5de85b7 /src/common/container_hash.h | |
| parent | 106a61c9434b8d61ab8cde0170f6fcac403b28f1 (diff) | |
[common] Switch to boost::unordered_flat containers (#4326)
Replaces all instances of ankerl's unordered map/set with boost's
`unordered_flat_*` classes. This uses std::hash since boost::hash is
actually a lot slower.
Also adds an abstraction layer in `Common` so future changes are quicker
and easier.
Other implementation details:
- ankerl provided hash specializations for tuple and pair, so those were
ported here
- std::erase_if doesn't work on boost, so just used the ADL'd erase_if
This should be about equal or superior performance as unordered_dense for everything except iteration.
Signed-off-by: crueter <crueter@eden-emu.dev>
- [x] I have read and followed the [Contribution Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/CONTRIBUTING.md#code-contributions).
- [x] I have read and followed the [AI Policy](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/AI.md)
- [x] I have read and followed the [Coding Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/Coding.md) to the best of my ability.
-------------------
Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4326
Reviewed-by: Lizzie and Samuel <lizzie@eden-emu.dev>
Reviewed-by: MaranBr <maranbr@eden-emu.dev>
Diffstat (limited to 'src/common/container_hash.h')
| -rw-r--r-- | src/common/container_hash.h | 33 |
1 files changed, 33 insertions, 0 deletions
diff --git a/src/common/container_hash.h b/src/common/container_hash.h index b6d8e02e26..d7477f7e4f 100644 --- a/src/common/container_hash.h +++ b/src/common/container_hash.h @@ -10,8 +10,11 @@ #include <array> #include <climits> #include <cstdint> +#include <functional> #include <limits> +#include <tuple> #include <type_traits> +#include <utility> #include <vector> namespace Common { @@ -69,10 +72,17 @@ struct HashCombineImpl<64> { } // namespace detail template <typename T> + requires std::is_unsigned_v<T> inline void HashCombine(std::size_t& seed, const T& v) { seed = detail::HashCombineImpl<sizeof(std::size_t) * CHAR_BIT>::fn(seed, detail::HashValue(v)); } +template <typename T> + requires (!std::is_unsigned_v<T>) +inline void HashCombine(std::size_t& seed, const T& v) { + seed = detail::HashCombineImpl<sizeof(std::size_t) * CHAR_BIT>::fn(seed, std::hash<T>{}(v)); +} + template <typename It> inline std::size_t HashRange(It first, It last) { std::size_t seed = 0; @@ -95,3 +105,26 @@ std::size_t HashValue(const std::vector<T, Allocator>& v) { } } // namespace Common + +namespace std { + +template <typename... Args> +struct hash<std::tuple<Args...>> { + std::size_t operator()(const std::tuple<Args...>& t) const noexcept { + std::size_t seed = 0; + std::apply([&seed](const Args&... args) { (Common::HashCombine(seed, args), ...); }, t); + return seed; + } +}; + +template <class A, class B> +struct hash<std::pair<A, B>> { + std::size_t operator()(const std::pair<A, B>& p) const noexcept { + std::size_t seed = 0; + Common::HashCombine(seed, p.first); + Common::HashCombine(seed, p.second); + return seed; + } +}; + +} // namespace std |
