80 lines
1.9 KiB
C++
80 lines
1.9 KiB
C++
#ifndef STD_HASH_HPP
|
|
#define STD_HASH_HPP
|
|
|
|
#include <cstddef>
|
|
#include <functional>
|
|
#include <tuple>
|
|
#include <utility>
|
|
#include <vector>
|
|
|
|
// this is largely inspired by boost's hash combine as can be found in
|
|
// "The C++ Standard Library" 2nd Edition. Nicolai M. Josuttis. 2012.
|
|
|
|
template <typename T> void hash_combine(std::size_t &seed, const T &val)
|
|
{
|
|
seed ^= std::hash<T>()(val) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
|
|
}
|
|
|
|
template <typename It> void hash_range(std::size_t &seed, It first, const It last)
|
|
{
|
|
for (; first != last; ++first)
|
|
{
|
|
hash_combine(seed, *first);
|
|
}
|
|
}
|
|
|
|
template <typename T> void hash_val(std::size_t &seed, const T &val) { hash_combine(seed, val); }
|
|
|
|
template <typename T, typename... Types>
|
|
void hash_val(std::size_t &seed, const T &val, const Types &...args)
|
|
{
|
|
hash_combine(seed, val);
|
|
hash_val(seed, args...);
|
|
}
|
|
|
|
template <typename... Types> std::size_t hash_val(const Types &...args)
|
|
{
|
|
std::size_t seed = 0;
|
|
hash_val(seed, args...);
|
|
return seed;
|
|
}
|
|
|
|
namespace std
|
|
{
|
|
template <typename... T> struct hash<std::tuple<T...>>
|
|
{
|
|
template <std::size_t... I>
|
|
static auto apply_tuple(const std::tuple<T...> &t, std::index_sequence<I...>)
|
|
{
|
|
std::size_t seed = 0;
|
|
return ((seed = hash_val(std::get<I>(t), seed)), ...);
|
|
}
|
|
|
|
auto operator()(const std::tuple<T...> &t) const
|
|
{
|
|
return apply_tuple(t, std::make_index_sequence<sizeof...(T)>());
|
|
}
|
|
};
|
|
|
|
template <typename T1, typename T2> struct hash<std::pair<T1, T2>>
|
|
{
|
|
std::size_t operator()(const std::pair<T1, T2> &pair) const
|
|
{
|
|
return hash_val(pair.first, pair.second);
|
|
}
|
|
};
|
|
|
|
template <typename T> struct hash<std::vector<T>>
|
|
{
|
|
auto operator()(const std::vector<T> &lane_description) const
|
|
{
|
|
std::size_t seed = 0;
|
|
hash_range(seed, lane_description.begin(), lane_description.end());
|
|
return seed;
|
|
}
|
|
};
|
|
|
|
} // namespace std
|
|
|
|
#endif // STD_HASH_HPP
|