#pragma once #include "StarBytes.hpp" namespace Star { // To avoid having to specialize std::hash in the std namespace, which is // slightly annoying, Star type wrappers use Star::hash, which just defaults to // std::hash. Star::hash also enables template specialization with a dummy // Enable parameter. template struct hash : public std::hash {}; inline void hashCombine(size_t& hash, size_t comb) { hash ^= comb * 2654435761 + 0x9e3779b9 + (hash << 6) + (hash >> 2); } // Paul Larson hashing algorithm, very very *cheap* hashing function. class PLHasher { public: PLHasher(size_t initial = 0) : m_hash(initial) {} template void put(T b) { m_hash = m_hash * 101 + (size_t)b; } size_t hash() const { return m_hash; } private: size_t m_hash; }; template class hash> { private: Star::hash firstHasher; Star::hash secondHasher; public: size_t operator()(std::pair const& a) const { size_t hashval = firstHasher(a.first); hashCombine(hashval, secondHasher(a.second)); return hashval; } }; template class hash> { private: typedef std::tuple Tuple; template size_t operator()(Tuple const&) const { return 0; } template size_t operator()(Tuple const& value) const { size_t hash = Star::hash()(std::get(value)); hashCombine(hash, operator()(value)); return hash; } public: size_t operator()(Tuple const& value) const { return operator()(value); } }; template struct hash::value>::type> { private: typedef typename std::underlying_type::type UnderlyingType; public: size_t operator()(EnumType e) const { return std::hash()((UnderlyingType)e); } }; template size_t hashOf(T const& t) { return Star::hash()(t); } template size_t hashOf(T1 const& t1, T2 const& t2, TL const&... rest) { size_t hash = hashOf(t1); hashCombine(hash, hashOf(t2, rest...)); return hash; }; }