85 lines
1.8 KiB
C++
85 lines
1.8 KiB
C++
#pragma once
|
|
|
|
#include <functional>
|
|
#include <tuple>
|
|
|
|
namespace psemek::util
|
|
{
|
|
|
|
constexpr void hash_combine(std::size_t & seed, std::size_t value)
|
|
{
|
|
constexpr std::size_t k = 0x9ddfea08eb382d69ULL;
|
|
std::size_t a = (value ^ seed) * k;
|
|
a ^= (a >> 47);
|
|
std::size_t b = (seed ^ a) * k;
|
|
b ^= (b >> 47);
|
|
seed = b * k;
|
|
}
|
|
|
|
template <typename Iterator, typename Hash = std::hash<std::decay_t<decltype(*std::declval<Iterator>())>>>
|
|
constexpr void hash_sequence(std::size_t & seed, Iterator begin, Iterator end, Hash hash = Hash{})
|
|
{
|
|
for (; begin != end; ++begin)
|
|
{
|
|
hash_combine(seed, hash(*begin));
|
|
}
|
|
}
|
|
|
|
struct any_hash
|
|
{
|
|
struct is_transparent{};
|
|
|
|
template <typename T>
|
|
std::size_t operator() (T const & x) const
|
|
{
|
|
return std::hash<T>{}(x);
|
|
}
|
|
};
|
|
|
|
template <typename ... T>
|
|
constexpr std::size_t hash_all(T const & ... x)
|
|
{
|
|
any_hash hash;
|
|
std::size_t seed = 0;
|
|
(hash_combine(seed, hash(x)), ...);
|
|
return seed;
|
|
}
|
|
|
|
}
|
|
|
|
namespace std
|
|
{
|
|
|
|
template <typename T, typename H>
|
|
struct hash<std::pair<T, H>>
|
|
: std::pair<std::hash<T>, std::hash<H>>
|
|
{
|
|
std::size_t operator()(std::pair<T, H> const & x) const
|
|
{
|
|
std::size_t seed = 0;
|
|
::psemek::util::hash_combine(seed, this->first(x.first));
|
|
::psemek::util::hash_combine(seed, this->second(x.second));
|
|
return seed;
|
|
}
|
|
};
|
|
|
|
template <typename ... Ts>
|
|
struct hash<std::tuple<Ts...>>
|
|
: std::tuple<std::hash<Ts>...>
|
|
{
|
|
std::size_t operator()(std::tuple<Ts...> const & t) const
|
|
{
|
|
return hash_impl(t, std::make_index_sequence<sizeof...(Ts)>{});
|
|
}
|
|
|
|
private:
|
|
template <std::size_t ... Is>
|
|
std::size_t hash_impl(std::tuple<Ts...> const & t, std::index_sequence<Is...>) const
|
|
{
|
|
std::size_t result = 0;
|
|
(::psemek::util::hash_combine(result, std::get<Is>(*this)(std::get<Is>(t))), ...);
|
|
return result;
|
|
}
|
|
};
|
|
|
|
}
|