Add util/hash header

This commit is contained in:
Nikita Lisitsa 2020-12-11 17:58:36 +03:00
parent f4908f2368
commit 0517609b8b
2 changed files with 41 additions and 42 deletions

View file

@ -20,50 +20,10 @@
#include <psemek/cg/convex_hull_2d/graham.hpp>
#include <psemek/util/to_string.hpp>
#include <psemek/util/hash.hpp>
#include <map>
void hash_combine(std::size_t & seed, std::size_t value)
{
seed ^= value + 0x9e3779b9 + (seed<<6) + (seed>>2);
}
namespace std
{
template <typename T1, typename T2>
struct hash<std::tuple<T1, T2>>
{
std::hash<T1> h1;
std::hash<T2> h2;
std::size_t operator() (std::tuple<T1, T2> const & t) const
{
std::size_t h = 0;
hash_combine(h, h1(std::get<0>(t)));
hash_combine(h, h2(std::get<1>(t)));
return h;
}
};
template <typename T1, typename T2, typename T3>
struct hash<std::tuple<T1, T2, T3>>
{
std::hash<T1> h1;
std::hash<T2> h2;
std::hash<T3> h3;
std::size_t operator() (std::tuple<T1, T2, T3> const & t) const
{
std::size_t h = 0;
hash_combine(h, h1(std::get<0>(t)));
hash_combine(h, h2(std::get<1>(t)));
hash_combine(h, h3(std::get<2>(t)));
return h;
}
};
}
#include <unordered_map>
namespace psemek::gfx
{

View file

@ -0,0 +1,39 @@
#pragma once
#include <functional>
#include <tuple>
namespace psemek::util
{
// based on boost::hash_combine
inline void hash_combine(std::size_t & seed, std::size_t value)
{
seed ^= value + 0x9e3779b9 + (seed<<6) + (seed>>2);
}
}
namespace std
{
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;
}
};
}