#ifndef hash_hh_INCLUDED #define hash_hh_INCLUDED #include #include #include namespace Kakoune { size_t hash_data(const char* data, size_t len); template std::enable_if_t::value, size_t> constexpr hash_value(const Type& val) { return (size_t)val; } template std::enable_if_t::value, size_t> constexpr hash_value(const Type& val) { return hash_value((std::underlying_type_t)val); } template constexpr size_t hash_values(Type&& t) { return hash_value(std::forward(t)); } constexpr size_t combine_hash(size_t lhs, size_t rhs) { return lhs ^ (rhs + 0x9e3779b9 + (lhs << 6) + (lhs >> 2)); } template constexpr size_t hash_values(Type&& t, RemainingTypes&&... rt) { size_t seed = hash_values(std::forward(rt)...); return combine_hash(seed, hash_value(std::forward(t))); } template constexpr size_t hash_value(const std::pair& val) { return hash_values(val.first, val.second); } template struct Hash { constexpr size_t operator()(const Type& val) const { return hash_value(val); } }; // Traits specifying if two types have compatible hashing, that is, // if lhs == rhs => hash_value(lhs) == hash_value(rhs) template struct HashCompatible : std::false_type {}; template struct HashCompatible : std::true_type {}; template constexpr bool IsHashCompatible = HashCompatible::value; } #endif // hash_hh_INCLUDED