diff --git a/include/boost/container_hash/detail/hash_tuple.hpp b/include/boost/container_hash/detail/hash_tuple.hpp deleted file mode 100644 index 597cee9..0000000 --- a/include/boost/container_hash/detail/hash_tuple.hpp +++ /dev/null @@ -1,133 +0,0 @@ -// Copyright 2005-2009 Daniel James. -// Copyright 2021 Peter Dimov. -// Distributed under the Boost Software License, Version 1.0. -// https://www.boost.org/LICENSE_1_0.txt - -#ifndef BOOST_HASH_DETAIL_HASH_TUPLE_LIKE_HPP -#define BOOST_HASH_DETAIL_HASH_TUPLE_LIKE_HPP - -#include -#include -#include - -#if defined(BOOST_NO_CXX11_HDR_TUPLE) - -// no support - -#else - -#include - -namespace boost -{ -namespace hash_detail -{ - -template -inline typename boost::enable_if_<(I == std::tuple_size::value), - void>::type - hash_combine_tuple(std::size_t&, T const&) -{ -} - -template -inline typename boost::enable_if_<(I < std::tuple_size::value), - void>::type - hash_combine_tuple(std::size_t& seed, T const& v) -{ - boost::hash_combine(seed, std::get(v)); - boost::hash_detail::hash_combine_tuple(seed, v); -} - -template -inline std::size_t hash_tuple(T const& v) -{ - std::size_t seed = 0; - boost::hash_detail::hash_combine_tuple<0>(seed, v); - return seed; -} - -} // namespace hash_detail - -#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) - -template -inline std::size_t hash_value(std::tuple const& v) -{ - return boost::hash_detail::hash_tuple(v); -} - -#else - -inline std::size_t hash_value(std::tuple<> const& v) -{ - return boost::hash_detail::hash_tuple(v); -} - -template -inline std::size_t hash_value(std::tuple const& v) -{ - return boost::hash_detail::hash_tuple(v); -} - -template -inline std::size_t hash_value(std::tuple const& v) -{ - return boost::hash_detail::hash_tuple(v); -} - -template -inline std::size_t hash_value(std::tuple const& v) -{ - return boost::hash_detail::hash_tuple(v); -} - -template -inline std::size_t hash_value(std::tuple const& v) -{ - return boost::hash_detail::hash_tuple(v); -} - -template -inline std::size_t hash_value(std::tuple const& v) -{ - return boost::hash_detail::hash_tuple(v); -} - -template -inline std::size_t hash_value(std::tuple const& v) -{ - return boost::hash_detail::hash_tuple(v); -} - -template -inline std::size_t hash_value(std::tuple const& v) -{ - return boost::hash_detail::hash_tuple(v); -} - -template -inline std::size_t hash_value(std::tuple const& v) -{ - return boost::hash_detail::hash_tuple(v); -} - -template -inline std::size_t hash_value(std::tuple const& v) -{ - return boost::hash_detail::hash_tuple(v); -} - -template -inline std::size_t hash_value(std::tuple const& v) -{ - return boost::hash_detail::hash_tuple(v); -} - -#endif // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) - -} // namespace boost - -#endif // #if defined(BOOST_NO_CXX11_HDR_TUPLE) - -#endif // #ifndef BOOST_HASH_DETAIL_HASH_TUPLE_LIKE_HPP diff --git a/include/boost/container_hash/detail/hash_tuple_like.hpp b/include/boost/container_hash/detail/hash_tuple_like.hpp new file mode 100644 index 0000000..f9f5a5b --- /dev/null +++ b/include/boost/container_hash/detail/hash_tuple_like.hpp @@ -0,0 +1,156 @@ +// Copyright 2005-2009 Daniel James. +// Copyright 2021 Peter Dimov. +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#ifndef BOOST_HASH_DETAIL_HASH_TUPLE_LIKE_HPP +#define BOOST_HASH_DETAIL_HASH_TUPLE_LIKE_HPP + +#include +#include +#include +#include +#include +#include + +#if defined(BOOST_NO_CXX11_HDR_TUPLE) + +// no support for tuple-likes + +#else + +#include + +namespace boost +{ +namespace hash_detail +{ + +template +inline +typename boost::enable_if_<(I == std::tuple_size::value), void>::type + hash_combine_tuple_like( std::size_t&, T const& ) +{ +} + +template +inline +typename boost::enable_if_<(I < std::tuple_size::value), void>::type + hash_combine_tuple_like( std::size_t& seed, T const& v ) +{ + using std::get; + boost::hash_combine( seed, get( v ) ); + + boost::hash_detail::hash_combine_tuple_like( seed, v ); +} + +template +inline std::size_t hash_tuple_like( T const& v ) +{ + std::size_t seed = 0; + + boost::hash_detail::hash_combine_tuple_like<0>( seed, v ); + + return seed; +} + +} // namespace hash_detail + +#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + +#if !BOOST_WORKAROUND(BOOST_MSVC, <= 1800) + +template +inline +typename boost::enable_if_< + container_hash::is_tuple_like::value && !container_hash::is_range::value, +std::size_t>::type + hash_value( T const& v ) +{ + return boost::hash_detail::hash_tuple_like( v ); +} + +#else + +template +inline std::size_t hash_value( std::tuple const& v ) +{ + return boost::hash_detail::hash_tuple_like( v ); +} + +#endif + +#else + +inline std::size_t hash_value( std::tuple<> const& v ) +{ + return boost::hash_detail::hash_tuple_like( v ); +} + +template +inline std::size_t hash_value( std::tuple const& v ) +{ + return boost::hash_detail::hash_tuple_like( v ); +} + +template +inline std::size_t hash_value( std::tuple const& v ) +{ + return boost::hash_detail::hash_tuple_like( v ); +} + +template +inline std::size_t hash_value( std::tuple const& v ) +{ + return boost::hash_detail::hash_tuple_like( v ); +} + +template +inline std::size_t hash_value( std::tuple const& v ) +{ + return boost::hash_detail::hash_tuple_like( v ); +} + +template +inline std::size_t hash_value( std::tuple const& v ) +{ + return boost::hash_detail::hash_tuple_like( v ); +} + +template +inline std::size_t hash_value( std::tuple const& v ) +{ + return boost::hash_detail::hash_tuple_like( v ); +} + +template +inline std::size_t hash_value( std::tuple const& v ) +{ + return boost::hash_detail::hash_tuple_like( v ); +} + +template +inline std::size_t hash_value( std::tuple const& v ) +{ + return boost::hash_detail::hash_tuple_like( v ); +} + +template +inline std::size_t hash_value( std::tuple const& v ) +{ + return boost::hash_detail::hash_tuple_like( v ); +} + +template +inline std::size_t hash_value( std::tuple const& v ) +{ + return boost::hash_detail::hash_tuple_like( v ); +} + +#endif // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + +} // namespace boost + +#endif // #if defined(BOOST_NO_CXX11_HDR_TUPLE) + +#endif // #ifndef BOOST_HASH_DETAIL_HASH_TUPLE_LIKE_HPP diff --git a/include/boost/container_hash/hash.hpp b/include/boost/container_hash/hash.hpp index 6700b1e..64987f8 100644 --- a/include/boost/container_hash/hash.hpp +++ b/include/boost/container_hash/hash.hpp @@ -15,7 +15,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 85ca612..f4ded35 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -121,3 +121,4 @@ run hash_integral_test2.cpp ; run hash_nullptr_test.cpp ; run is_tuple_like_test.cpp ; +run hash_tuple_like_test.cpp ; diff --git a/test/hash_tuple_like_test.cpp b/test/hash_tuple_like_test.cpp new file mode 100644 index 0000000..d9b7fa0 --- /dev/null +++ b/test/hash_tuple_like_test.cpp @@ -0,0 +1,204 @@ +// Copyright 2022 Peter Dimov. +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#if defined(__clang__) +# pragma clang diagnostic ignored "-Wmismatched-tags" +#endif + +#include +#include +#include +#include +#include +#include +#include + +#if !defined(BOOST_NO_CXX11_HDR_TUPLE) + +# include + +namespace user +{ + +struct Y1 +{ + int a; + int b; +}; + +template int& get( Y1& v ); +template int const& get( Y1 const& v ); + +template<> int& get<0>( Y1& v ) +{ + return v.a; +} + +template<> int const& get<0>( Y1 const& v ) +{ + return v.a; +} + +template<> int& get<1>( Y1& v ) +{ + return v.b; +} + +template<> int const& get<1>( Y1 const& v ) +{ + return v.b; +} + +struct Y2 +{ + int a; + int b; + + template friend + typename boost::enable_if_::value, std::size_t>::type + hash_value( T const& v ) + { + std::size_t seed = 0; + + boost::hash_combine( seed, v.a ); + boost::hash_combine( seed, v.b ); + + return seed; + } +}; + +} // namespace user + +namespace std +{ + +template<> struct tuple_size: std::integral_constant +{ +}; + +template<> struct tuple_size: std::integral_constant +{ +}; + +} // namespace std + +namespace boost +{ +namespace container_hash +{ + + template<> struct is_tuple_like: boost::false_type {}; + +} // namespace container_hash +} // namespace boost + +#endif + +template std::size_t hv( T const& t ) +{ + return boost::hash()( t ); +} + +int main() +{ + { + std::pair tp( 1, 2 ); + int const a[] = { 1, 2 }; + + BOOST_TEST_EQ( hv(tp), hv(a) ); + } + +#if !defined(BOOST_NO_CXX11_HDR_TUPLE) + + { + std::tuple<> tp; + + BOOST_TEST_EQ( hv(tp), 0u ); + } + + { + std::tuple tp( 1 ); + int const a[] = { 1 }; + + BOOST_TEST_EQ( hv(tp), hv(a) ); + } + + { + std::tuple tp( 1, 2 ); + int const a[] = { 1, 2 }; + + BOOST_TEST_EQ( hv(tp), hv(a) ); + } + + { + std::tuple tp( 1, 2, 3 ); + int const a[] = { 1, 2, 3 }; + + BOOST_TEST_EQ( hv(tp), hv(a) ); + } + + { + std::tuple tp( 1, 2, 3, 4 ); + int const a[] = { 1, 2, 3, 4 }; + + BOOST_TEST_EQ( hv(tp), hv(a) ); + } + + { + std::tuple tp( 1, 2, 3, 4, 5 ); + int const a[] = { 1, 2, 3, 4, 5 }; + + BOOST_TEST_EQ( hv(tp), hv(a) ); + } + + { + std::tuple tp( 1, 2, 3, 4, 5, 6 ); + int const a[] = { 1, 2, 3, 4, 5, 6 }; + + BOOST_TEST_EQ( hv(tp), hv(a) ); + } + + { + std::tuple tp( 1, 2, 3, 4, 5, 6, 7 ); + int const a[] = { 1, 2, 3, 4, 5, 6, 7 }; + + BOOST_TEST_EQ( hv(tp), hv(a) ); + } + + { + std::tuple tp( 1, 2, 3, 4, 5, 6, 7, 8 ); + int const a[] = { 1, 2, 3, 4, 5, 6, 7, 8 }; + + BOOST_TEST_EQ( hv(tp), hv(a) ); + } + + { + std::tuple tp( 1, 2, 3, 4, 5, 6, 7, 8, 9 ); + int const a[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + + BOOST_TEST_EQ( hv(tp), hv(a) ); + } + +#if !BOOST_WORKAROUND(BOOST_MSVC, <= 1800) + + { + user::Y1 tp = { 1, 2 }; + int const a[] = { 1, 2 }; + + BOOST_TEST_EQ( hv(tp), hv(a) ); + } + +#endif + + { + user::Y2 tp = { 1, 2 }; + int const a[] = { 1, 2 }; + + BOOST_TEST_EQ( hv(tp), hv(a) ); + } + +#endif + + return boost::report_errors(); +}