diff --git a/include/boost/container_hash/detail/is_contiguous_range.hpp b/include/boost/container_hash/detail/is_contiguous_range.hpp index 1f3731e..74dc8f8 100644 --- a/include/boost/container_hash/detail/is_contiguous_range.hpp +++ b/include/boost/container_hash/detail/is_contiguous_range.hpp @@ -53,14 +53,6 @@ template struct is_contiguous_range: false_type { }; -template struct is_contiguous_range< std::vector >: true_type -{ -}; - -template struct is_contiguous_range< std::vector const >: true_type -{ -}; - template struct is_contiguous_range< std::basic_string >: true_type { }; diff --git a/include/boost/container_hash/extensions.hpp b/include/boost/container_hash/extensions.hpp index c02d35f..fa4d4f8 100644 --- a/include/boost/container_hash/extensions.hpp +++ b/include/boost/container_hash/extensions.hpp @@ -19,38 +19,22 @@ #endif #include -#include #include #include - -#if !defined(BOOST_NO_CXX11_HDR_ARRAY) -# include -#endif +#include #if !defined(BOOST_NO_CXX11_HDR_TUPLE) -# include +# include #endif -#include +#if !defined(BOOST_NO_CXX11_SMART_PTR) +# include +#endif namespace boost { template std::size_t hash_value(std::pair const&); - template - std::size_t hash_value(std::vector const&); - template - std::size_t hash_value(std::list const& v); - template - std::size_t hash_value(std::deque const& v); - template - std::size_t hash_value(std::set const& v); - template - std::size_t hash_value(std::multiset const& v); - template - std::size_t hash_value(std::map const& v); - template - std::size_t hash_value(std::multimap const& v); template std::size_t hash_value(std::complex const&); @@ -64,48 +48,6 @@ namespace boost return seed; } - template - std::size_t hash_value(std::vector const& v) - { - return boost::hash_range(v.begin(), v.end()); - } - - template - std::size_t hash_value(std::list const& v) - { - return boost::hash_range(v.begin(), v.end()); - } - - template - std::size_t hash_value(std::deque const& v) - { - return boost::hash_range(v.begin(), v.end()); - } - - template - std::size_t hash_value(std::set const& v) - { - return boost::hash_range(v.begin(), v.end()); - } - - template - std::size_t hash_value(std::multiset const& v) - { - return boost::hash_range(v.begin(), v.end()); - } - - template - std::size_t hash_value(std::map const& v) - { - return boost::hash_range(v.begin(), v.end()); - } - - template - std::size_t hash_value(std::multimap const& v) - { - return boost::hash_range(v.begin(), v.end()); - } - template std::size_t hash_value(std::complex const& v) { @@ -115,14 +57,6 @@ namespace boost return seed; } -#if !defined(BOOST_NO_CXX11_HDR_ARRAY) - template - std::size_t hash_value(std::array const& v) - { - return boost::hash_range(v.begin(), v.end()); - } -#endif - #if !defined(BOOST_NO_CXX11_HDR_TUPLE) namespace hash_detail { template diff --git a/include/boost/container_hash/hash.hpp b/include/boost/container_hash/hash.hpp index 9ff31c5..b57c61c 100644 --- a/include/boost/container_hash/hash.hpp +++ b/include/boost/container_hash/hash.hpp @@ -1,7 +1,7 @@ - // Copyright 2005-2014 Daniel James. -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// Copyright 2021 Peter Dimov. +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt // Based on Peter Dimov's proposal // http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2005/n1756.pdf @@ -18,6 +18,9 @@ #include #include +#include +#include +#include #include #include #include @@ -61,70 +64,14 @@ namespace boost { - namespace hash_detail - { - template - struct hash_base - { - typedef T argument_type; - typedef std::size_t result_type; - }; - } - template - typename boost::enable_if, std::size_t>::type - hash_value(T); + // hash_value - template - typename boost::enable_if, std::size_t>::type - hash_value(T); - - template - typename boost::enable_if, std::size_t>::type - hash_value(T); - - template std::size_t hash_value(T* const&); - - template< class T, unsigned N > - std::size_t hash_value(const T (&x)[N]); - - template< class T, unsigned N > - std::size_t hash_value(T (&x)[N]); - - template - std::size_t hash_value( - std::basic_string, A> const&); - -#if !defined(BOOST_NO_CXX17_HDR_STRING_VIEW) - template - std::size_t hash_value( - std::basic_string_view > const&); -#endif - -#if !defined(BOOST_NO_CXX17_HDR_OPTIONAL) - template - std::size_t hash_value(std::optional const&); -#endif - -#if !defined(BOOST_NO_CXX17_HDR_VARIANT) - std::size_t hash_value(std::monostate); - template - std::size_t hash_value(std::variant const&); -#endif - -#if !defined(BOOST_NO_CXX11_HDR_TYPEINDEX) - std::size_t hash_value(std::type_index); -#endif - -#if !defined(BOOST_NO_CXX11_HDR_SYSTEM_ERROR) - std::size_t hash_value(std::error_code const&); - std::size_t hash_value(std::error_condition const&); -#endif - - // Implementation + // integral types namespace hash_detail { + template struct hash_integral_impl; template struct hash_integral_impl @@ -153,6 +100,168 @@ namespace boost } }; + } // namespace hash_detail + + template + typename boost::enable_if, std::size_t>::type + hash_value( T v ) + { + return hash_detail::hash_integral_impl sizeof(std::size_t)), (sizeof(std::size_t) * CHAR_BIT >= 64)>::fn( v ); + } + + // enumeration types + + template + typename boost::enable_if, std::size_t>::type + hash_value( T v ) + { + return static_cast( v ); + } + + // floating point types + + template + typename boost::enable_if, std::size_t>::type + hash_value( T v ) + { + return boost::hash_detail::float_hash_value( v ); + } + + // pointer types + + // Implementation by Alberto Barbati and Dave Harris. + template std::size_t hash_value( T* const& v ) + { + std::size_t x = static_cast( + reinterpret_cast(v)); + return x + (x >> 3); + } + + // array types + + template + inline std::size_t hash_value( T const (&x)[ N ] ) + { + return boost::hash_range( x, x + N ); + } + + template + inline std::size_t hash_value( T (&x)[ N ] ) + { + return boost::hash_range( x, x + N ); + } + + // ranges (list, set, deque...) + + template + typename boost::enable_if_c::value && !hash_detail::is_contiguous_range::value && !hash_detail::is_unordered_range::value, std::size_t>::type + hash_value( T const& v ) + { + return boost::hash_range( v.begin(), v.end() ); + } + + // contiguous ranges (string, vector, array) + + template + typename boost::enable_if, std::size_t>::type + hash_value( T const& v ) + { + return boost::hash_range( v.data(), v.data() + v.size() ); + } + + // unordered ranges (unordered_set, unordered_map) + + template + typename boost::enable_if, std::size_t>::type + hash_value( T const& v ) + { + return boost::hash_unordered_range( v.begin(), v.end() ); + } + + // std::type_index + +#if !defined(BOOST_NO_CXX11_HDR_TYPEINDEX) + + inline std::size_t hash_value( std::type_index const& v ) + { + return v.hash_code(); + } + +#endif + + // std::error_code, std::error_condition + +#if !defined(BOOST_NO_CXX11_HDR_SYSTEM_ERROR) + + inline std::size_t hash_value( std::error_code const& v ) + { + std::size_t seed = 0; + + boost::hash_combine( seed, v.value() ); + boost::hash_combine( seed, &v.category() ); + + return seed; + } + + inline std::size_t hash_value( std::error_condition const& v ) + { + std::size_t seed = 0; + + boost::hash_combine( seed, v.value() ); + boost::hash_combine( seed, &v.category() ); + + return seed; + } + +#endif + + // std::optional + +#if !defined(BOOST_NO_CXX17_HDR_OPTIONAL) + + template + std::size_t hash_value( std::optional const& v ) + { + if( !v ) + { + // Arbitray value for empty optional. + return 0x12345678; + } + else + { + return boost::hash()(*v); + } + } + +#endif + + // std::variant + +#if !defined(BOOST_NO_CXX17_HDR_VARIANT) + + inline std::size_t hash_value( std::monostate ) + { + return 0x87654321; + } + + template + std::size_t hash_value( std::variant const& v ) + { + std::size_t seed = 0; + + hash_combine( seed, v.index() ); + std::visit( [&seed](auto&& x) { hash_combine(seed, x); }, v ); + + return seed; + } + +#endif + + // hash_combine + + namespace hash_detail + { + template struct hash_combine_impl { template @@ -205,35 +314,6 @@ namespace boost }; } - template - typename boost::enable_if, std::size_t>::type - hash_value(T v) - { - return hash_detail::hash_integral_impl sizeof(std::size_t)), (sizeof(std::size_t) * CHAR_BIT >= 64)>::fn( v ); - } - - template - typename boost::enable_if, std::size_t>::type - hash_value(T v) - { - return static_cast(v); - } - - template - typename boost::enable_if, std::size_t>::type - hash_value(T v) - { - return boost::hash_detail::float_hash_value(v); - } - - // Implementation by Alberto Barbati and Dave Harris. - template std::size_t hash_value(T* const& v) - { - std::size_t x = static_cast( - reinterpret_cast(v)); - return x + (x >> 3); - } - #if defined(BOOST_MSVC) #pragma warning(push) #if BOOST_MSVC <= 1400 @@ -303,89 +383,20 @@ namespace boost } #endif - template< class T, unsigned N > - inline std::size_t hash_value(const T (&x)[N]) - { - return hash_range(x, x + N); - } - - template< class T, unsigned N > - inline std::size_t hash_value(T (&x)[N]) - { - return hash_range(x, x + N); - } - - template - inline std::size_t hash_value( - std::basic_string, A> const& v) - { - return hash_range(v.begin(), v.end()); - } - -#if !defined(BOOST_NO_CXX17_HDR_STRING_VIEW) - template - inline std::size_t hash_value( - std::basic_string_view > const& v) - { - return hash_range(v.begin(), v.end()); - } -#endif - -#if !defined(BOOST_NO_CXX17_HDR_OPTIONAL) - template - inline std::size_t hash_value(std::optional const& v) { - if (!v) { - // Arbitray value for empty optional. - return 0x12345678; - } else { - boost::hash hf; - return hf(*v); - } - } -#endif - -#if !defined(BOOST_NO_CXX17_HDR_VARIANT) - inline std::size_t hash_value(std::monostate) { - return 0x87654321; - } - - template - inline std::size_t hash_value(std::variant const& v) { - std::size_t seed = 0; - hash_combine(seed, v.index()); - std::visit([&seed](auto&& x) { hash_combine(seed, x); }, v); - return seed; - } -#endif - - -#if !defined(BOOST_NO_CXX11_HDR_TYPEINDEX) - inline std::size_t hash_value(std::type_index v) - { - return v.hash_code(); - } -#endif - -#if !defined(BOOST_NO_CXX11_HDR_SYSTEM_ERROR) - inline std::size_t hash_value(std::error_code const& v) { - std::size_t seed = 0; - hash_combine(seed, v.value()); - hash_combine(seed, &v.category()); - return seed; - } - - inline std::size_t hash_value(std::error_condition const& v) { - std::size_t seed = 0; - hash_combine(seed, v.value()); - hash_combine(seed, &v.category()); - return seed; - } -#endif - // // boost::hash // + namespace hash_detail + { + template + struct hash_base + { + typedef T argument_type; + typedef std::size_t result_type; + }; + } + // Define the specializations required by the standard. The general purpose // boost::hash is defined later in extensions.hpp if // BOOST_HASH_NO_EXTENSIONS is not defined. @@ -513,14 +524,7 @@ namespace boost { std::size_t operator()(T* v) const { -#if !BOOST_WORKAROUND(__SUNPRO_CC, <= 0x590) return boost::hash_value(v); -#else - std::size_t x = static_cast( - reinterpret_cast(v)); - - return x + (x >> 3); -#endif } }; } diff --git a/include/boost/container_hash/hash_fwd.hpp b/include/boost/container_hash/hash_fwd.hpp index 46340b3..dff947c 100644 --- a/include/boost/container_hash/hash_fwd.hpp +++ b/include/boost/container_hash/hash_fwd.hpp @@ -27,6 +27,9 @@ namespace boost template std::size_t hash_range(It, It); template void hash_range(std::size_t&, It, It); + template std::size_t hash_unordered_range(It, It); + template void hash_unordered_range(std::size_t&, It, It); + #if BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x551)) template inline std::size_t hash_range(T*, T*); template inline void hash_range(std::size_t&, T*, T*); diff --git a/test/detail_is_contiguous_range_test.cpp b/test/detail_is_contiguous_range_test.cpp index 9b495cd..99efba0 100644 --- a/test/detail_is_contiguous_range_test.cpp +++ b/test/detail_is_contiguous_range_test.cpp @@ -50,8 +50,11 @@ int main() BOOST_TEST_TRAIT_TRUE((is_contiguous_range)); BOOST_TEST_TRAIT_TRUE((is_contiguous_range)); +// std::vector doesn't have data() in C++03 +#if !defined(BOOST_NO_CXX11_DECLTYPE) && !defined(BOOST_NO_SFINAE_EXPR) && !BOOST_WORKAROUND(BOOST_GCC, < 40700) BOOST_TEST_TRAIT_TRUE((is_contiguous_range< std::vector >)); BOOST_TEST_TRAIT_TRUE((is_contiguous_range< std::vector const >)); +#endif BOOST_TEST_TRAIT_FALSE((is_contiguous_range< std::deque >)); BOOST_TEST_TRAIT_FALSE((is_contiguous_range< std::deque const >));