From 21f2b5e1db1a118c83a3690055c110d0f5637da3 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Tue, 10 Aug 2021 18:38:41 +0300 Subject: [PATCH] Fix hash_combine_impl to only test for a specific bit width and not for concrete types --- include/boost/container_hash/hash.hpp | 75 ++++++++++++++------------- 1 file changed, 40 insertions(+), 35 deletions(-) diff --git a/include/boost/container_hash/hash.hpp b/include/boost/container_hash/hash.hpp index 6059fee..06fa8a3 100644 --- a/include/boost/container_hash/hash.hpp +++ b/include/boost/container_hash/hash.hpp @@ -26,6 +26,7 @@ #include #include #include +#include #if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) #include @@ -307,52 +308,56 @@ namespace boost return seed; } - template - inline void hash_combine_impl(SizeT& seed, SizeT value) + template struct hash_combine_impl { - seed ^= value + 0x9e3779b9 + (seed<<6) + (seed>>2); - } + template + inline static SizeT fn(SizeT seed, SizeT value) + { + seed ^= value + 0x9e3779b9 + (seed<<6) + (seed>>2); + return seed; + } + }; - inline void hash_combine_impl(boost::uint32_t& h1, - boost::uint32_t k1) + template<> struct hash_combine_impl<32> { - const uint32_t c1 = 0xcc9e2d51; - const uint32_t c2 = 0x1b873593; + inline static boost::uint32_t fn(boost::uint32_t h1, boost::uint32_t k1) + { + const boost::uint32_t c1 = 0xcc9e2d51; + const boost::uint32_t c2 = 0x1b873593; - k1 *= c1; - k1 = BOOST_FUNCTIONAL_HASH_ROTL32(k1,15); - k1 *= c2; + k1 *= c1; + k1 = BOOST_FUNCTIONAL_HASH_ROTL32(k1,15); + k1 *= c2; - h1 ^= k1; - h1 = BOOST_FUNCTIONAL_HASH_ROTL32(h1,13); - h1 = h1*5+0xe6546b64; - } + h1 ^= k1; + h1 = BOOST_FUNCTIONAL_HASH_ROTL32(h1,13); + h1 = h1*5+0xe6546b64; + return h1; + } + }; -// Don't define 64-bit hash combine on platforms without 64 bit integers, -// and also not for 32-bit gcc as it warns about the 64-bit constant. -#if !defined(BOOST_NO_INT64_T) && \ - !(defined(__GNUC__) && ULONG_MAX == 0xffffffff) - - inline void hash_combine_impl(boost::uint64_t& h, - boost::uint64_t k) + template<> struct hash_combine_impl<64> { - const boost::uint64_t m = UINT64_C(0xc6a4a7935bd1e995); - const int r = 47; + inline static boost::uint64_t fn(boost::uint64_t h, boost::uint64_t k) + { + const boost::uint64_t m = (boost::uint64_t(0xc6a4a793) << 32) + 0x5bd1e995; + const int r = 47; - k *= m; - k ^= k >> r; - k *= m; + k *= m; + k ^= k >> r; + k *= m; - h ^= k; - h *= m; + h ^= k; + h *= m; - // Completely arbitrary number, to prevent 0's - // from hashing to 0. - h += 0xe6546b64; - } + // Completely arbitrary number, to prevent 0's + // from hashing to 0. + h += 0xe6546b64; -#endif // BOOST_NO_INT64_T + return h; + } + }; } template @@ -413,7 +418,7 @@ namespace boost inline void hash_combine(std::size_t& seed, T const& v) { boost::hash hasher; - return boost::hash_detail::hash_combine_impl(seed, hasher(v)); + seed = boost::hash_detail::hash_combine_impl::fn(seed, hasher(v)); } #if defined(BOOST_MSVC)