From f98a942e2e0af75ff027988f6615340a42d50165 Mon Sep 17 00:00:00 2001 From: Daniel James Date: Sun, 8 Apr 2012 15:29:15 +0000 Subject: [PATCH 01/29] Unordered/hash: Avoid a gcc warning. Refs #6771 [SVN r77832] --- .../boost/functional/hash/detail/hash_float.hpp | 16 +++++++++++++++- test/Jamfile.v2 | 4 ++-- test/hash_complex_test.cpp | 4 ++++ test/hash_float_test.hpp | 4 ++++ test/hash_number_test.cpp | 4 ++++ 5 files changed, 29 insertions(+), 3 deletions(-) diff --git a/include/boost/functional/hash/detail/hash_float.hpp b/include/boost/functional/hash/detail/hash_float.hpp index ea1bc25..194be1c 100644 --- a/include/boost/functional/hash/detail/hash_float.hpp +++ b/include/boost/functional/hash/detail/hash_float.hpp @@ -86,10 +86,24 @@ namespace boost { namespace hash_detail { + template + inline bool is_zero(T v) + { +#if !defined(__GNUC__) + return v == 0; +#else + // GCC's '-Wfloat-equal' will complain about comparing + // v to 0, but because it disables warnings for system + // headers it won't complain if you use std::equal_to to + // compare with 0. Resulting in this silliness: + return std::equal_to()(v, 0); +#endif + } + template inline std::size_t float_hash_value(T v) { - return v == 0 ? 0 : float_hash_impl(v); + return boost::hash_detail::is_zero(v) ? 0 : float_hash_impl(v); } } } diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 7b3ccd9..cf64ece 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -10,8 +10,8 @@ project hash-tests all intel:on intel:-strict-ansi - gcc:"-pedantic -Wstrict-aliasing -fstrict-aliasing -Wextra -Wsign-promo -Wunused-parameter -Wconversion" - darwin:"-pedantic -Wstrict-aliasing -fstrict-aliasing -Wextra -Wsign-promo -Wunused-parameter -Wconversion" + gcc:"-pedantic -Wstrict-aliasing -fstrict-aliasing -Wextra -Wsign-promo -Wunused-parameter -Wconversion -Wfloat-equal" + darwin:"-pedantic -Wstrict-aliasing -fstrict-aliasing -Wextra -Wsign-promo -Wunused-parameter -Wconversion -Wfloat-equal" msvc:on #gcc:on #darwin:on diff --git a/test/hash_complex_test.cpp b/test/hash_complex_test.cpp index 67e2aff..bb1592c 100644 --- a/test/hash_complex_test.cpp +++ b/test/hash_complex_test.cpp @@ -35,6 +35,10 @@ int main() {} #endif #endif +#if defined(__GNUC__) +#pragma GCC diagnostic ignored "-Wfloat-equal" +#endif + #include #include #include diff --git a/test/hash_float_test.hpp b/test/hash_float_test.hpp index dd1358e..c608915 100644 --- a/test/hash_float_test.hpp +++ b/test/hash_float_test.hpp @@ -30,6 +30,10 @@ #endif #endif +#if defined(__GNUC__) +#pragma GCC diagnostic ignored "-Wfloat-equal" +#endif + char const* float_type(float*) { return "float"; } char const* float_type(double*) { return "double"; } char const* float_type(long double*) { return "long double"; } diff --git a/test/hash_number_test.cpp b/test/hash_number_test.cpp index b989d22..b233c71 100644 --- a/test/hash_number_test.cpp +++ b/test/hash_number_test.cpp @@ -28,6 +28,10 @@ #pragma warning(disable:4310) // cast truncates constant value #endif +#if defined(__GNUC__) +#pragma GCC diagnostic ignored "-Wfloat-equal" +#endif + template void numeric_test(T*) { From c3d01123fae4a415e5a8cf6930ed1eae733dc4e5 Mon Sep 17 00:00:00 2001 From: Daniel James Date: Sun, 22 Apr 2012 19:45:58 +0000 Subject: [PATCH 02/29] Hash: Note about previous change. [SVN r78143] --- doc/changes.qbk | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/doc/changes.qbk b/doc/changes.qbk index eb6572f..41d6511 100644 --- a/doc/changes.qbk +++ b/doc/changes.qbk @@ -123,4 +123,8 @@ * Avoid warning due with gcc's `-Wconversion` flag. +[h2 Boost 1.50.0] + +* Avoid gcc's `-Wfloat-equal` warning. + [endsect] From 98953a28c7d15a6abf826452e633ab98e383c964 Mon Sep 17 00:00:00 2001 From: Daniel James Date: Sun, 22 Apr 2012 19:46:28 +0000 Subject: [PATCH 03/29] Hash: Support std::array and std::tuple. Refs #6806. [SVN r78144] --- doc/changes.qbk | 2 + doc/ref.xml | 28 +++++ .../hash/detail/container_fwd_0x.hpp | 41 +++++++ include/boost/functional/hash/extensions.hpp | 89 +++++++++++++-- test/Jamfile.v2 | 2 + test/hash_map_test.cpp | 2 +- test/hash_std_array_test.cpp | 103 ++++++++++++++++++ test/hash_std_tuple_test.cpp | 77 +++++++++++++ 8 files changed, 333 insertions(+), 11 deletions(-) create mode 100644 include/boost/functional/hash/detail/container_fwd_0x.hpp create mode 100644 test/hash_std_array_test.cpp create mode 100644 test/hash_std_tuple_test.cpp diff --git a/doc/changes.qbk b/doc/changes.qbk index 41d6511..1673b34 100644 --- a/doc/changes.qbk +++ b/doc/changes.qbk @@ -126,5 +126,7 @@ [h2 Boost 1.50.0] * Avoid gcc's `-Wfloat-equal` warning. +* [@http://svn.boost.org/trac/boost/ticket/6806 Ticket 6806]: + Support `std::array` and `std::tuple` when available. [endsect] diff --git a/doc/ref.xml b/doc/ref.xml index 318bf85..9256e98 100644 --- a/doc/ref.xml +++ b/doc/ref.xml @@ -744,6 +744,25 @@ for(; first != last; ++first) std::type_index + + + std::size_t + std::array<T, N> const& + + + + + std::size_t + std::tuple<T...> + + Generally shouldn't be called directly by users, instead they should use boost::hash, boost::hash_range @@ -810,6 +829,7 @@ for(; first != last; ++first) std::multiset<K, C, A>, std::map<K, T, C, A>, std::multimap<K, T, C, A> + std::array<T, N> hash_range(val.begin(), val.end()) @@ -818,6 +838,14 @@ for(; first != last; ++first) size_t seed = 0; hash_combine(seed, val.first); hash_combine(seed, val.second); +return seed; + + + std::tuple<T...> + size_t seed = 0; +hash_combine(seed, get<0>(val)); +hash_combine(seed, get<1>(val)); +// .... return seed; diff --git a/include/boost/functional/hash/detail/container_fwd_0x.hpp b/include/boost/functional/hash/detail/container_fwd_0x.hpp new file mode 100644 index 0000000..566f2af --- /dev/null +++ b/include/boost/functional/hash/detail/container_fwd_0x.hpp @@ -0,0 +1,41 @@ + +// Copyright 2012 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) + +#if !defined(BOOST_DETAIL_CONTAINER_FWD_0X_HPP) +#define BOOST_DETAIL_CONTAINER_FWD_0X_HPP + +#include + +// std::array + +#if !defined(BOOST_NO_0X_HDR_ARRAY) + // Don't forward declare std::array for Dinkumware, as it seems to be + // just 'using std::tr1::array'. +# if (defined(BOOST_DETAIL_NO_CONTAINER_FWD) && \ + !defined(BOOST_DETAIL_TEST_FORCE_CONTAINER_FWD)) || \ + (defined(_YVALS) && !defined(__IBMCPP__)) || defined(_CPPLIB_VER) +# include +# else +namespace std { + template class array; +} +# endif +#endif + +// std::tuple + +#if !defined(BOOST_NO_0X_HDR_TUPLE) +# if (defined(BOOST_DETAIL_NO_CONTAINER_FWD) && \ + !defined(BOOST_DETAIL_TEST_FORCE_CONTAINER_FWD)) || \ + defined(BOOST_NO_VARIADIC_TEMPLATES) +# include +# else +namespace std { + template class tuple; +} +# endif +#endif + +#endif diff --git a/include/boost/functional/hash/extensions.hpp b/include/boost/functional/hash/extensions.hpp index 3c587a3..1d873ed 100644 --- a/include/boost/functional/hash/extensions.hpp +++ b/include/boost/functional/hash/extensions.hpp @@ -14,7 +14,11 @@ #define BOOST_FUNCTIONAL_HASH_EXTENSIONS_HPP #include -#include +#include +#include +#include +#include +#include #if defined(_MSC_VER) && (_MSC_VER >= 1020) # pragma once @@ -54,51 +58,51 @@ namespace boost std::size_t hash_value(std::pair const& v) { std::size_t seed = 0; - hash_combine(seed, v.first); - hash_combine(seed, v.second); + boost::hash_combine(seed, v.first); + boost::hash_combine(seed, v.second); return seed; } template std::size_t hash_value(std::vector const& v) { - return hash_range(v.begin(), v.end()); + return boost::hash_range(v.begin(), v.end()); } template std::size_t hash_value(std::list const& v) { - return hash_range(v.begin(), v.end()); + return boost::hash_range(v.begin(), v.end()); } template std::size_t hash_value(std::deque const& v) { - return hash_range(v.begin(), v.end()); + return boost::hash_range(v.begin(), v.end()); } template std::size_t hash_value(std::set const& v) { - return hash_range(v.begin(), v.end()); + return boost::hash_range(v.begin(), v.end()); } template std::size_t hash_value(std::multiset const& v) { - return hash_range(v.begin(), v.end()); + return boost::hash_range(v.begin(), v.end()); } template std::size_t hash_value(std::map const& v) { - return hash_range(v.begin(), v.end()); + return boost::hash_range(v.begin(), v.end()); } template std::size_t hash_value(std::multimap const& v) { - return hash_range(v.begin(), v.end()); + return boost::hash_range(v.begin(), v.end()); } template @@ -110,6 +114,71 @@ namespace boost return seed; } +#if !defined(BOOST_NO_0X_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_0X_HDR_TUPLE) + namespace hash_detail { + template + inline typename boost::enable_if_c<(I == std::tuple_size::value), + void>::type + hash_combine_tuple(std::size_t&, T const&) + { + } + + template + inline typename boost::enable_if_c<(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; + } + } + +#if !defined(BOOST_NO_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); + } + +# define BOOST_HASH_TUPLE_F(z, n, _) \ + template< \ + BOOST_PP_ENUM_PARAMS_Z(z, n, typename A) \ + > \ + inline std::size_t hash_value(std::tuple< \ + BOOST_PP_ENUM_PARAMS_Z(z, n, A) \ + > const& v) \ + { \ + return boost::hash_detail::hash_tuple(v); \ + } + + BOOST_PP_REPEAT_FROM_TO(1, 11, BOOST_HASH_TUPLE_F, _) +# undef BOOST_HASH_TUPLE_F +#endif + +#endif + // // call_hash_impl // diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index cf64ece..af24329 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -40,6 +40,8 @@ test-suite functional/hash [ run hash_map_test.cpp : : : BOOST_HASH_NO_IMPLICIT_CASTS ] [ run hash_complex_test.cpp : : : BOOST_HASH_NO_IMPLICIT_CASTS ] [ run hash_type_index_test.cpp : : : BOOST_HASH_NO_IMPLICIT_CASTS ] + [ run hash_std_array_test.cpp : : : BOOST_HASH_NO_IMPLICIT_CASTS ] + [ run hash_std_tuple_test.cpp : : : BOOST_HASH_NO_IMPLICIT_CASTS ] [ run link_test.cpp link_test_2.cpp : : : BOOST_HASH_NO_IMPLICIT_CASTS ] [ run link_ext_test.cpp link_no_ext_test.cpp : : : BOOST_HASH_NO_IMPLICIT_CASTS ] [ run extensions_hpp_test.cpp : : : BOOST_HASH_NO_IMPLICIT_CASTS ] diff --git a/test/hash_map_test.cpp b/test/hash_map_test.cpp index 2f813c3..7e117c7 100644 --- a/test/hash_map_test.cpp +++ b/test/hash_map_test.cpp @@ -27,7 +27,7 @@ using std::multimap; #define CONTAINER_TYPE multimap #include "./hash_map_test.hpp" -#endif // TEST_EXTENSTIONS +#endif // TEST_EXTENSIONS int main() { diff --git a/test/hash_std_array_test.cpp b/test/hash_std_array_test.cpp new file mode 100644 index 0000000..5e8a3d4 --- /dev/null +++ b/test/hash_std_array_test.cpp @@ -0,0 +1,103 @@ + +// Copyright 2012 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) + +#include "./config.hpp" + +#ifdef TEST_EXTENSIONS +# ifdef TEST_STD_INCLUDES +# include +# else +# include +# endif +#endif + +#include +#include + +#if defined(TEST_EXTENSIONS) && !defined(BOOST_NO_0X_HDR_ARRAY) +#define TEST_ARRAY +#include +#include +#endif + +#ifdef TEST_ARRAY + +template +void array_tests(T const& v) { + boost::hash hf; + for(typename T::const_iterator i = v.begin(); i != v.end(); ++i) { + for(typename T::const_iterator j = v.begin(); j != v.end(); ++j) { + if (i != j) + BOOST_TEST(hf(*i) != hf(*j)); + else + BOOST_TEST(hf(*i) == hf(*j)); + } + } +} + +void empty_array_test() { +/* + boost::hash > empty_array_hash; + std::array empty_array; + BOOST_TEST(empty_array_hash(empty_array) == boost::hash_value(empty_array)); +*/ +} + +void int_1_array_test() +{ + std::vector > arrays; + std::array val; + val[0] = 0; + arrays.emplace_back(val); + val[0] = 1; + arrays.emplace_back(val); + val[0] = 2; + arrays.emplace_back(val); + array_tests(arrays); +} + +void string_1_array_test() +{ + std::vector > arrays; + std::array val; + arrays.emplace_back(val); + val[0] = "one"; + arrays.emplace_back(val); + val[0] = "two"; + arrays.emplace_back(val); + array_tests(arrays); +} + +void string_3_array_test() +{ + std::vector > arrays; + std::array val; + arrays.emplace_back(val); + val[0] = "one"; + arrays.emplace_back(val); + val[0] = ""; val[1] = "one"; val[2] = ""; + arrays.emplace_back(val); + val[0] = ""; val[1] = ""; val[2] = "one"; + arrays.emplace_back(val); + val[0] = "one"; val[1] = "one"; val[2] = "one"; + arrays.emplace_back(val); + val[0] = "one"; val[1] = "two"; val[2] = "three"; + arrays.emplace_back(val); + array_tests(arrays); +} + +#endif // TEST_ARRAY + +int main() +{ +#ifdef TEST_ARRAY + empty_array_test(); + int_1_array_test(); + string_1_array_test(); + string_3_array_test(); +#endif + + return boost::report_errors(); +} diff --git a/test/hash_std_tuple_test.cpp b/test/hash_std_tuple_test.cpp new file mode 100644 index 0000000..84aae75 --- /dev/null +++ b/test/hash_std_tuple_test.cpp @@ -0,0 +1,77 @@ + +// Copyright 2012 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) + +#include "./config.hpp" + +#ifdef TEST_EXTENSIONS +# ifdef TEST_STD_INCLUDES +# include +# else +# include +# endif +#endif + +#include +#include + +#if defined(TEST_EXTENSIONS) && !defined(BOOST_NO_0X_HDR_TUPLE) +#define TEST_TUPLE +#include +#include +#endif + +#ifdef TEST_TUPLE + +template +void tuple_tests(T const& v) { + boost::hash hf; + for(typename T::const_iterator i = v.begin(); i != v.end(); ++i) { + for(typename T::const_iterator j = v.begin(); j != v.end(); ++j) { + if (i != j) + BOOST_TEST(hf(*i) != hf(*j)); + else + BOOST_TEST(hf(*i) == hf(*j)); + } + } +} + +void empty_tuple_test() { + boost::hash > empty_tuple_hash; + std::tuple<> empty_tuple; + BOOST_TEST(empty_tuple_hash(empty_tuple) == boost::hash_value(empty_tuple)); +} + +void int_tuple_test() { + std::vector > int_tuples; + int_tuples.push_back(std::make_tuple(0)); + int_tuples.push_back(std::make_tuple(1)); + int_tuples.push_back(std::make_tuple(2)); + tuple_tests(int_tuples); +} + +void int_string_tuple_test() { + std::vector > int_string_tuples; + int_string_tuples.push_back(std::make_tuple(0, "zero")); + int_string_tuples.push_back(std::make_tuple(1, "one")); + int_string_tuples.push_back(std::make_tuple(2, "two")); + int_string_tuples.push_back(std::make_tuple(0, "one")); + int_string_tuples.push_back(std::make_tuple(1, "zero")); + int_string_tuples.push_back(std::make_tuple(0, "")); + int_string_tuples.push_back(std::make_tuple(1, "")); + tuple_tests(int_string_tuples); +} + +#endif // TEST_TUPLE + +int main() +{ +#ifdef TEST_TUPLE + empty_tuple_test(); + int_tuple_test(); + int_string_tuple_test(); +#endif + + return boost::report_errors(); +} From 4f3265079dab5a6f2f7c0f62b2f7da1cbfac2b7b Mon Sep 17 00:00:00 2001 From: Daniel James Date: Sun, 22 Apr 2012 19:49:41 +0000 Subject: [PATCH 04/29] Hash: Missing comma. [SVN r78145] --- doc/ref.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/ref.xml b/doc/ref.xml index 9256e98..fa29fcd 100644 --- a/doc/ref.xml +++ b/doc/ref.xml @@ -828,7 +828,7 @@ for(; first != last; ++first) std::set<K, C, A>, std::multiset<K, C, A>, std::map<K, T, C, A>, - std::multimap<K, T, C, A> + std::multimap<K, T, C, A>, std::array<T, N> hash_range(val.begin(), val.end()) From 441cea413d1df5f3da39a1bc2f790e31fcc98d4d Mon Sep 17 00:00:00 2001 From: Daniel James Date: Mon, 23 Apr 2012 20:49:30 +0000 Subject: [PATCH 05/29] Hash: Some formatting. [SVN r78164] --- include/boost/functional/hash/extensions.hpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/include/boost/functional/hash/extensions.hpp b/include/boost/functional/hash/extensions.hpp index 1d873ed..e61c2f3 100644 --- a/include/boost/functional/hash/extensions.hpp +++ b/include/boost/functional/hash/extensions.hpp @@ -162,15 +162,15 @@ namespace boost return boost::hash_detail::hash_tuple(v); } -# define BOOST_HASH_TUPLE_F(z, n, _) \ - template< \ - BOOST_PP_ENUM_PARAMS_Z(z, n, typename A) \ - > \ - inline std::size_t hash_value(std::tuple< \ - BOOST_PP_ENUM_PARAMS_Z(z, n, A) \ - > const& v) \ - { \ - return boost::hash_detail::hash_tuple(v); \ +# define BOOST_HASH_TUPLE_F(z, n, _) \ + template< \ + BOOST_PP_ENUM_PARAMS_Z(z, n, typename A) \ + > \ + inline std::size_t hash_value(std::tuple< \ + BOOST_PP_ENUM_PARAMS_Z(z, n, A) \ + > const& v) \ + { \ + return boost::hash_detail::hash_tuple(v); \ } BOOST_PP_REPEAT_FROM_TO(1, 11, BOOST_HASH_TUPLE_F, _) From f3229da836ede5bc0efd2a51531b27ac9c0bb1c0 Mon Sep 17 00:00:00 2001 From: Daniel James Date: Mon, 23 Apr 2012 20:51:21 +0000 Subject: [PATCH 06/29] Hash: fix tests for older C++0x libraries. [SVN r78165] --- test/hash_std_array_test.cpp | 24 ++++++++++++------------ test/hash_std_tuple_test.cpp | 14 +++++++------- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/test/hash_std_array_test.cpp b/test/hash_std_array_test.cpp index 5e8a3d4..540b676 100644 --- a/test/hash_std_array_test.cpp +++ b/test/hash_std_array_test.cpp @@ -50,11 +50,11 @@ void int_1_array_test() std::vector > arrays; std::array val; val[0] = 0; - arrays.emplace_back(val); + arrays.push_back(val); val[0] = 1; - arrays.emplace_back(val); + arrays.push_back(val); val[0] = 2; - arrays.emplace_back(val); + arrays.push_back(val); array_tests(arrays); } @@ -62,11 +62,11 @@ void string_1_array_test() { std::vector > arrays; std::array val; - arrays.emplace_back(val); + arrays.push_back(val); val[0] = "one"; - arrays.emplace_back(val); + arrays.push_back(val); val[0] = "two"; - arrays.emplace_back(val); + arrays.push_back(val); array_tests(arrays); } @@ -74,17 +74,17 @@ void string_3_array_test() { std::vector > arrays; std::array val; - arrays.emplace_back(val); + arrays.push_back(val); val[0] = "one"; - arrays.emplace_back(val); + arrays.push_back(val); val[0] = ""; val[1] = "one"; val[2] = ""; - arrays.emplace_back(val); + arrays.push_back(val); val[0] = ""; val[1] = ""; val[2] = "one"; - arrays.emplace_back(val); + arrays.push_back(val); val[0] = "one"; val[1] = "one"; val[2] = "one"; - arrays.emplace_back(val); + arrays.push_back(val); val[0] = "one"; val[1] = "two"; val[2] = "three"; - arrays.emplace_back(val); + arrays.push_back(val); array_tests(arrays); } diff --git a/test/hash_std_tuple_test.cpp b/test/hash_std_tuple_test.cpp index 84aae75..15ef483 100644 --- a/test/hash_std_tuple_test.cpp +++ b/test/hash_std_tuple_test.cpp @@ -53,13 +53,13 @@ void int_tuple_test() { void int_string_tuple_test() { std::vector > int_string_tuples; - int_string_tuples.push_back(std::make_tuple(0, "zero")); - int_string_tuples.push_back(std::make_tuple(1, "one")); - int_string_tuples.push_back(std::make_tuple(2, "two")); - int_string_tuples.push_back(std::make_tuple(0, "one")); - int_string_tuples.push_back(std::make_tuple(1, "zero")); - int_string_tuples.push_back(std::make_tuple(0, "")); - int_string_tuples.push_back(std::make_tuple(1, "")); + int_string_tuples.push_back(std::make_tuple(0, std::string("zero"))); + int_string_tuples.push_back(std::make_tuple(1, std::string("one"))); + int_string_tuples.push_back(std::make_tuple(2, std::string("two"))); + int_string_tuples.push_back(std::make_tuple(0, std::string("one"))); + int_string_tuples.push_back(std::make_tuple(1, std::string("zero"))); + int_string_tuples.push_back(std::make_tuple(0, std::string(""))); + int_string_tuples.push_back(std::make_tuple(1, std::string(""))); tuple_tests(int_string_tuples); } From 963d06acb8524a74bdb843733e5498f24661bcf1 Mon Sep 17 00:00:00 2001 From: Daniel James Date: Thu, 3 May 2012 21:35:51 +0000 Subject: [PATCH 07/29] Unordered/Hash: Release notes. [SVN r78318] --- doc/changes.qbk | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/changes.qbk b/doc/changes.qbk index 1673b34..c47bd56 100644 --- a/doc/changes.qbk +++ b/doc/changes.qbk @@ -125,7 +125,8 @@ [h2 Boost 1.50.0] -* Avoid gcc's `-Wfloat-equal` warning. +* [@http://svn.boost.org/trac/boost/ticket/6771 Ticket 6771]: + Avoid gcc's `-Wfloat-equal` warning. * [@http://svn.boost.org/trac/boost/ticket/6806 Ticket 6806]: Support `std::array` and `std::tuple` when available. From 5611f4238e2035d6a8eea0ec88a6f578693a2f49 Mon Sep 17 00:00:00 2001 From: Daniel James Date: Mon, 7 May 2012 10:57:35 +0000 Subject: [PATCH 08/29] Unordered: Avoid `-Wshadow` warnings. Refs #6190. [SVN r78364] --- test/Jamfile.v2 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index af24329..2d1a527 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -10,8 +10,8 @@ project hash-tests all intel:on intel:-strict-ansi - gcc:"-pedantic -Wstrict-aliasing -fstrict-aliasing -Wextra -Wsign-promo -Wunused-parameter -Wconversion -Wfloat-equal" - darwin:"-pedantic -Wstrict-aliasing -fstrict-aliasing -Wextra -Wsign-promo -Wunused-parameter -Wconversion -Wfloat-equal" + gcc:"-pedantic -Wstrict-aliasing -fstrict-aliasing -Wextra -Wsign-promo -Wunused-parameter -Wconversion -Wfloat-equal -Wshadow" + darwin:"-pedantic -Wstrict-aliasing -fstrict-aliasing -Wextra -Wsign-promo -Wunused-parameter -Wconversion -Wfloat-equal -Wshadow" msvc:on #gcc:on #darwin:on From 68f0d9bc6b3b073c5488231ba8e40bbe5b7d6a54 Mon Sep 17 00:00:00 2001 From: Daniel James Date: Mon, 7 May 2012 10:58:55 +0000 Subject: [PATCH 09/29] Hash: Add some notes about forwarding header. Refs #6849. [SVN r78366] --- doc/ref.xml | 17 ++++++++++++++--- doc/tutorial.qbk | 12 +++++++++++- examples/Jamfile.v2 | 1 + examples/template.cpp | 18 ++++++++++++++++++ examples/template.hpp | 36 ++++++++++++++++++++++++++++++++++++ 5 files changed, 80 insertions(+), 4 deletions(-) create mode 100644 examples/template.cpp create mode 100644 examples/template.hpp diff --git a/doc/ref.xml b/doc/ref.xml index fa29fcd..d7c427c 100644 --- a/doc/ref.xml +++ b/doc/ref.xml @@ -55,6 +55,10 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) is defined. The specializations are still defined, so only the specializations required by TR1 are defined. + + Forward declared in + <boost/functional/hash_fwd.hpp> + Only throws if @@ -451,6 +455,10 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) hash_value is called without qualification, so that overloads can be found via ADL. This is an extension to TR1 + + Forward declared in + <boost/functional/hash_fwd.hpp> + Only throws if hash_value(T) throws. @@ -499,15 +507,14 @@ for(; first != last; ++first) return seed; - For the three arguments overload: + + For the three arguments overload: for(; first != last; ++first) { hash_combine(seed, *first); } - - @@ -516,6 +523,10 @@ for(; first != last; ++first) container. This is an extension to TR1 + + Forward declared in + <boost/functional/hash_fwd.hpp> + Only throws if hash_value(std::iterator_traits<It>::value_type) diff --git a/doc/tutorial.qbk b/doc/tutorial.qbk index 81c1b15..916ab93 100644 --- a/doc/tutorial.qbk +++ b/doc/tutorial.qbk @@ -198,5 +198,15 @@ To calculate the hash of an iterator range you can use [funcref boost::hash_rang std::vector some_strings; std::size_t hash = ``[funcref boost::hash_range]``(some_strings.begin(), some_strings.end()); -[endsect] +Note that when writing template classes, you might not want to include the main +hash header as it's quite an expensive include that brings in a lot of other +headers, so instead you can include the `` +header which forward declares [classref boost::hash], +[funcref boost::hash_range] and [funcref boost::hash_combine]. You'll need to +include the main header before instantiating [classref boost::hash]. When using +a container that uses [classref boost::hash] it should do that for you, so your +type will work fine with the boost hash containers. There's an example of this +in [@boost:/libs/unordered/examples/template.hpp template.hpp] and +[@boost:/libs/unordered/examples/template.cpp template.cpp]. +[endsect] diff --git a/examples/Jamfile.v2 b/examples/Jamfile.v2 index dc5bdce..6291621 100644 --- a/examples/Jamfile.v2 +++ b/examples/Jamfile.v2 @@ -6,3 +6,4 @@ run books.cpp ; run point.cpp ; run portable.cpp ; +run template.cpp ; diff --git a/examples/template.cpp b/examples/template.cpp new file mode 100644 index 0000000..d74f0a9 --- /dev/null +++ b/examples/template.cpp @@ -0,0 +1,18 @@ + +// Copyright 2012 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) + +#include "template.hpp" +#include +#include + +int main() +{ + typedef my_pair pair; + boost::unordered_set pair_set; + pair_set.emplace(10, 0.5f); + + assert(pair_set.find(pair(10, 0.5f)) != pair_set.end()); + assert(pair_set.find(pair(10, 0.6f)) == pair_set.end()); +} diff --git a/examples/template.hpp b/examples/template.hpp new file mode 100644 index 0000000..b630704 --- /dev/null +++ b/examples/template.hpp @@ -0,0 +1,36 @@ + +// Copyright 2012 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) + +// This is an example of how to write a hash function for a template +// class. + +#include + +template +class my_pair +{ + A value1; + B value2; +public: + my_pair(A const& v1, B const& v2) + : value1(v1), value2(v2) + {} + + bool operator==(my_pair const& other) const + { + return value1 == other.value1 && + value2 == other.value2; + } + + friend std::size_t hash_value(my_pair const& p) + { + std::size_t seed = 0; + boost::hash_combine(seed, p.value1); + boost::hash_combine(seed, p.value2); + + return seed; + } +}; + From 8bc410f57198762e3a1d26e766cd096ebb8d48cc Mon Sep 17 00:00:00 2001 From: Daniel James Date: Tue, 8 May 2012 22:24:46 +0000 Subject: [PATCH 10/29] Hash: Use SFINAE to avoid implicit casts to numbers. [SVN r78391] --- include/boost/functional/hash/hash.hpp | 160 +++++++----------- test/Jamfile.v2 | 76 ++++----- ...plicit_fail_test.cpp => implicit_test.cpp} | 0 3 files changed, 91 insertions(+), 145 deletions(-) rename test/{implicit_fail_test.cpp => implicit_test.cpp} (100%) diff --git a/include/boost/functional/hash/hash.hpp b/include/boost/functional/hash/hash.hpp index 51ec860..7559e56 100644 --- a/include/boost/functional/hash/hash.hpp +++ b/include/boost/functional/hash/hash.hpp @@ -16,10 +16,6 @@ #include #include -#if defined(BOOST_HASH_NO_IMPLICIT_CASTS) -#include -#endif - #if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) #include #endif @@ -37,38 +33,63 @@ namespace boost { -#if defined(BOOST_HASH_NO_IMPLICIT_CASTS) + namespace hash_detail + { + struct enable_hash_value { typedef std::size_t type; }; - // If you get a static assertion here, it's because hash_value - // isn't declared for your type. - template - std::size_t hash_value(T const&) { - BOOST_STATIC_ASSERT((T*) 0 && false); - return 0; - } + template struct basic_numbers {}; + template struct long_numbers {}; + template struct ulong_numbers {}; + template struct float_numbers {}; -#endif - - std::size_t hash_value(bool); - std::size_t hash_value(char); - std::size_t hash_value(unsigned char); - std::size_t hash_value(signed char); - std::size_t hash_value(short); - std::size_t hash_value(unsigned short); - std::size_t hash_value(int); - std::size_t hash_value(unsigned int); - std::size_t hash_value(long); - std::size_t hash_value(unsigned long); + template <> struct basic_numbers : + boost::hash_detail::enable_hash_value {}; + template <> struct basic_numbers : + boost::hash_detail::enable_hash_value {}; + template <> struct basic_numbers : + boost::hash_detail::enable_hash_value {}; + template <> struct basic_numbers : + boost::hash_detail::enable_hash_value {}; + template <> struct basic_numbers : + boost::hash_detail::enable_hash_value {}; + template <> struct basic_numbers : + boost::hash_detail::enable_hash_value {}; + template <> struct basic_numbers : + boost::hash_detail::enable_hash_value {}; + template <> struct basic_numbers : + boost::hash_detail::enable_hash_value {}; + template <> struct basic_numbers : + boost::hash_detail::enable_hash_value {}; + template <> struct basic_numbers : + boost::hash_detail::enable_hash_value {}; #if !defined(BOOST_NO_INTRINSIC_WCHAR_T) - std::size_t hash_value(wchar_t); + template <> struct basic_numbers : + boost::hash_detail::enable_hash_value {}; #endif - + #if !defined(BOOST_NO_LONG_LONG) - std::size_t hash_value(boost::long_long_type); - std::size_t hash_value(boost::ulong_long_type); + template <> struct long_numbers : + boost::hash_detail::enable_hash_value {}; + template <> struct ulong_numbers : + boost::hash_detail::enable_hash_value {}; #endif + template <> struct float_numbers : + boost::hash_detail::enable_hash_value {}; + template <> struct float_numbers : + boost::hash_detail::enable_hash_value {}; + template <> struct float_numbers : + boost::hash_detail::enable_hash_value {}; + } + + template + typename boost::hash_detail::basic_numbers::type hash_value(T); + template + typename boost::hash_detail::long_numbers::type hash_value(T); + template + typename boost::hash_detail::ulong_numbers::type hash_value(T); + #if !BOOST_WORKAROUND(__DMC__, <= 0x848) template std::size_t hash_value(T* const&); #else @@ -83,14 +104,13 @@ namespace boost std::size_t hash_value(T (&x)[N]); #endif - std::size_t hash_value(float v); - std::size_t hash_value(double v); - std::size_t hash_value(long double v); - template std::size_t hash_value( std::basic_string, A> const&); + template + typename boost::hash_detail::float_numbers::type hash_value(T); + #if !defined(BOOST_NO_0X_HDR_TYPEINDEX) std::size_t hash_value(std::type_index); #endif @@ -141,74 +161,23 @@ namespace boost } } - inline std::size_t hash_value(bool v) + template + typename boost::hash_detail::basic_numbers::type hash_value(T v) { return static_cast(v); } - inline std::size_t hash_value(char v) - { - return static_cast(v); - } - - inline std::size_t hash_value(unsigned char v) - { - return static_cast(v); - } - - inline std::size_t hash_value(signed char v) - { - return static_cast(v); - } - - inline std::size_t hash_value(short v) - { - return static_cast(v); - } - - inline std::size_t hash_value(unsigned short v) - { - return static_cast(v); - } - - inline std::size_t hash_value(int v) - { - return static_cast(v); - } - - inline std::size_t hash_value(unsigned int v) - { - return static_cast(v); - } - - inline std::size_t hash_value(long v) - { - return static_cast(v); - } - - inline std::size_t hash_value(unsigned long v) - { - return static_cast(v); - } - -#if !defined(BOOST_NO_INTRINSIC_WCHAR_T) - inline std::size_t hash_value(wchar_t v) - { - return static_cast(v); - } -#endif - -#if !defined(BOOST_NO_LONG_LONG) - inline std::size_t hash_value(boost::long_long_type v) + template + typename boost::hash_detail::long_numbers::type hash_value(T v) { return hash_detail::hash_value_signed(v); } - inline std::size_t hash_value(boost::ulong_long_type v) + template + typename boost::hash_detail::ulong_numbers::type hash_value(T v) { return hash_detail::hash_value_unsigned(v); } -#endif // Implementation by Alberto Barbati and Dave Harris. #if !BOOST_WORKAROUND(__DMC__, <= 0x848) @@ -324,17 +293,8 @@ namespace boost return hash_range(v.begin(), v.end()); } - inline std::size_t hash_value(float v) - { - return boost::hash_detail::float_hash_value(v); - } - - inline std::size_t hash_value(double v) - { - return boost::hash_detail::float_hash_value(v); - } - - inline std::size_t hash_value(long double v) + template + typename boost::hash_detail::float_numbers::type hash_value(T v) { return boost::hash_detail::float_hash_value(v); } diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 2d1a527..0d85829 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -19,51 +19,37 @@ project hash-tests test-suite functional/hash : - [ run hash_fwd_test_1.cpp : : : BOOST_HASH_NO_IMPLICIT_CASTS ] - [ run hash_fwd_test_2.cpp : : : BOOST_HASH_NO_IMPLICIT_CASTS ] - [ run hash_number_test.cpp : : : BOOST_HASH_NO_IMPLICIT_CASTS ] - [ run hash_pointer_test.cpp : : : BOOST_HASH_NO_IMPLICIT_CASTS ] - [ run hash_function_pointer_test.cpp : : : BOOST_HASH_NO_IMPLICIT_CASTS ] - [ run hash_float_test.cpp : : : BOOST_HASH_NO_IMPLICIT_CASTS ] - [ run hash_long_double_test.cpp : : : BOOST_HASH_NO_IMPLICIT_CASTS ] - [ run hash_string_test.cpp : : : BOOST_HASH_NO_IMPLICIT_CASTS ] - [ run hash_range_test.cpp : : : BOOST_HASH_NO_IMPLICIT_CASTS ] - [ run hash_custom_test.cpp : : : BOOST_HASH_NO_IMPLICIT_CASTS ] - [ run hash_global_namespace_test.cpp : : : BOOST_HASH_NO_IMPLICIT_CASTS ] - [ run hash_friend_test.cpp : : : BOOST_HASH_NO_IMPLICIT_CASTS ] - [ run hash_built_in_array_test.cpp : : : BOOST_HASH_NO_IMPLICIT_CASTS ] - [ run hash_value_array_test.cpp : : : BOOST_HASH_NO_IMPLICIT_CASTS ] - [ run hash_vector_test.cpp : : : BOOST_HASH_NO_IMPLICIT_CASTS ] - [ run hash_list_test.cpp : : : BOOST_HASH_NO_IMPLICIT_CASTS ] - [ run hash_deque_test.cpp : : : BOOST_HASH_NO_IMPLICIT_CASTS ] - [ run hash_set_test.cpp : : : BOOST_HASH_NO_IMPLICIT_CASTS ] - [ run hash_map_test.cpp : : : BOOST_HASH_NO_IMPLICIT_CASTS ] - [ run hash_complex_test.cpp : : : BOOST_HASH_NO_IMPLICIT_CASTS ] - [ run hash_type_index_test.cpp : : : BOOST_HASH_NO_IMPLICIT_CASTS ] - [ run hash_std_array_test.cpp : : : BOOST_HASH_NO_IMPLICIT_CASTS ] - [ run hash_std_tuple_test.cpp : : : BOOST_HASH_NO_IMPLICIT_CASTS ] - [ run link_test.cpp link_test_2.cpp : : : BOOST_HASH_NO_IMPLICIT_CASTS ] - [ run link_ext_test.cpp link_no_ext_test.cpp : : : BOOST_HASH_NO_IMPLICIT_CASTS ] - [ run extensions_hpp_test.cpp : : : BOOST_HASH_NO_IMPLICIT_CASTS ] - [ compile-fail hash_no_ext_fail_test.cpp : BOOST_HASH_NO_IMPLICIT_CASTS ] - [ compile-fail namespace_fail_test.cpp : BOOST_HASH_NO_IMPLICIT_CASTS ] - [ compile-fail implicit_fail_test.cpp : BOOST_HASH_NO_IMPLICIT_CASTS ] - [ run hash_no_ext_macro_1.cpp : : : BOOST_HASH_NO_IMPLICIT_CASTS ] - [ run hash_no_ext_macro_2.cpp : : : BOOST_HASH_NO_IMPLICIT_CASTS ] - ; - -test-suite functional/hash_implicit_casts - : - [ run hash_number_test.cpp : : : : implicit_number ] - [ run hash_pointer_test.cpp : : : : implicit_pointer ] - [ run hash_function_pointer_test.cpp : : : : implicit_function_pointer ] - [ run hash_float_test.cpp : : : : implicit_float ] - [ run hash_string_test.cpp : : : : implicit_string ] - [ run hash_range_test.cpp : : : : implicit_range ] - [ run hash_custom_test.cpp : : : : implicit_custom ] - [ run hash_built_in_array_test.cpp : : : : implicit_built_in_array ] - [ run link_test.cpp link_test_2.cpp : : : : implicit_link ] - [ run implicit_fail_test.cpp : : : : implicit_test ] + [ run hash_fwd_test_1.cpp ] + [ run hash_fwd_test_2.cpp ] + [ run hash_number_test.cpp ] + [ run hash_pointer_test.cpp ] + [ run hash_function_pointer_test.cpp ] + [ run hash_float_test.cpp ] + [ run hash_long_double_test.cpp ] + [ run hash_string_test.cpp ] + [ run hash_range_test.cpp ] + [ run hash_custom_test.cpp ] + [ run hash_global_namespace_test.cpp ] + [ run hash_friend_test.cpp ] + [ run hash_built_in_array_test.cpp ] + [ run hash_value_array_test.cpp ] + [ run hash_vector_test.cpp ] + [ run hash_list_test.cpp ] + [ run hash_deque_test.cpp ] + [ run hash_set_test.cpp ] + [ run hash_map_test.cpp ] + [ run hash_complex_test.cpp ] + [ run hash_type_index_test.cpp ] + [ run hash_std_array_test.cpp ] + [ run hash_std_tuple_test.cpp ] + [ run link_test.cpp link_test_2.cpp ] + [ run link_ext_test.cpp link_no_ext_test.cpp ] + [ run extensions_hpp_test.cpp ] + [ compile-fail hash_no_ext_fail_test.cpp ] + [ compile-fail namespace_fail_test.cpp ] + [ run implicit_test.cpp ] + [ run hash_no_ext_macro_1.cpp ] + [ run hash_no_ext_macro_2.cpp ] ; test-suite functional/hash_no_ext diff --git a/test/implicit_fail_test.cpp b/test/implicit_test.cpp similarity index 100% rename from test/implicit_fail_test.cpp rename to test/implicit_test.cpp From 0d4c55854b6ba16c09531e946c2c9ac453354004 Mon Sep 17 00:00:00 2001 From: Daniel James Date: Mon, 21 May 2012 21:58:18 +0000 Subject: [PATCH 11/29] Add warning to deprecated header `boost/functional/detail/container_fwd.hpp`. Should have done this years ago, removing this header should make modularization a tad bit cleaner. [SVN r78533] --- include/boost/functional/detail/container_fwd.hpp | 14 +++++++++++--- test/Jamfile.v2 | 1 + test/deprecated_container_fwd.cpp | 14 ++++++++++++++ 3 files changed, 26 insertions(+), 3 deletions(-) create mode 100644 test/deprecated_container_fwd.cpp diff --git a/include/boost/functional/detail/container_fwd.hpp b/include/boost/functional/detail/container_fwd.hpp index 9a69d15..dd55571 100644 --- a/include/boost/functional/detail/container_fwd.hpp +++ b/include/boost/functional/detail/container_fwd.hpp @@ -1,11 +1,11 @@ -// Copyright 2005-2008 Daniel James. +// Copyright 2005-2012 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) // Forwarding header for container_fwd.hpp's new location. -// This header is deprecated, I'll be adding a warning in a future release, -// then converting it to an error and finally removing this header completely. +// This header is deprecated, I'll change the warning to an error in a future +// release, and then later remove the header completely. #if !defined(BOOST_FUNCTIONAL_DETAIL_CONTAINER_FWD_HPP) #define BOOST_FUNCTIONAL_DETAIL_CONTAINER_FWD_HPP @@ -14,6 +14,14 @@ # pragma once #endif +#if defined(__EDG__) +#elif defined(_MSC_VER) || defined(__BORLANDC__) || defined(__DMC__) +#pragma message("Warning: boost/functional/detail/container_fwd.hpp is deprecated, use boost/detail/container_fwd.hpp instead."); +#elif defined(__GNUC__) || defined(__HP_aCC) || \ + defined(__SUNPRO_CC) || defined(__IBMCPP__) +#warning "boost/functional/detail/container_fwd.hpp is deprecated, use boost/detail/container_fwd.hpp instead." +#endif + #include #endif diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 0d85829..47f0a95 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -50,6 +50,7 @@ test-suite functional/hash [ run implicit_test.cpp ] [ run hash_no_ext_macro_1.cpp ] [ run hash_no_ext_macro_2.cpp ] + [ compile deprecated_container_fwd.cpp ] ; test-suite functional/hash_no_ext diff --git a/test/deprecated_container_fwd.cpp b/test/deprecated_container_fwd.cpp new file mode 100644 index 0000000..1c6e12b --- /dev/null +++ b/test/deprecated_container_fwd.cpp @@ -0,0 +1,14 @@ + +// Copyright 2012 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) + +#include + +typedef std::vector > int_vector; + +#include + +int main() { + int_vector x; +} From 6be66ba09231a4843ae01f09fb17e09b6bc82317 Mon Sep 17 00:00:00 2001 From: Daniel James Date: Sat, 26 May 2012 15:02:26 +0000 Subject: [PATCH 12/29] Hash: Remove stary semicolon from deprecation pragma. [SVN r78635] --- include/boost/functional/detail/container_fwd.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/functional/detail/container_fwd.hpp b/include/boost/functional/detail/container_fwd.hpp index dd55571..e2bf865 100644 --- a/include/boost/functional/detail/container_fwd.hpp +++ b/include/boost/functional/detail/container_fwd.hpp @@ -16,7 +16,7 @@ #if defined(__EDG__) #elif defined(_MSC_VER) || defined(__BORLANDC__) || defined(__DMC__) -#pragma message("Warning: boost/functional/detail/container_fwd.hpp is deprecated, use boost/detail/container_fwd.hpp instead."); +#pragma message("Warning: boost/functional/detail/container_fwd.hpp is deprecated, use boost/detail/container_fwd.hpp instead.") #elif defined(__GNUC__) || defined(__HP_aCC) || \ defined(__SUNPRO_CC) || defined(__IBMCPP__) #warning "boost/functional/detail/container_fwd.hpp is deprecated, use boost/detail/container_fwd.hpp instead." From 8ef04ed8075500c531e845c3f88a8244bea650ed Mon Sep 17 00:00:00 2001 From: Daniel James Date: Sun, 27 May 2012 20:55:14 +0000 Subject: [PATCH 13/29] Hash: Extra changelog note. [SVN r78696] --- doc/changes.qbk | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/changes.qbk b/doc/changes.qbk index c47bd56..3aa3dee 100644 --- a/doc/changes.qbk +++ b/doc/changes.qbk @@ -129,5 +129,7 @@ Avoid gcc's `-Wfloat-equal` warning. * [@http://svn.boost.org/trac/boost/ticket/6806 Ticket 6806]: Support `std::array` and `std::tuple` when available. +* Add deprecation warning to the long deprecated + `boost/functional/detail/container_fwd.hpp`. [endsect] From 806abd0ddfaafee2bee37720802a11d4d9df7c76 Mon Sep 17 00:00:00 2001 From: Daniel James Date: Tue, 29 May 2012 19:41:19 +0000 Subject: [PATCH 14/29] Hash: Only use typeid when available. [SVN r78755] --- test/hash_type_index_test.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/test/hash_type_index_test.cpp b/test/hash_type_index_test.cpp index 7892918..917bca9 100644 --- a/test/hash_type_index_test.cpp +++ b/test/hash_type_index_test.cpp @@ -18,12 +18,16 @@ #include void test_type_index() { + HASH_NAMESPACE::hash hasher; + +#if defined(BOOST_NO_TYPEID) + std::cout<<"Unable to test std::type_index, as typeid isn't available" + < hasher; - BOOST_TEST(hasher(int_index) == int_index.hash_code()); BOOST_TEST(hasher(int_index) == int2_index.hash_code()); BOOST_TEST(hasher(char_index) == char_index.hash_code()); @@ -33,6 +37,7 @@ void test_type_index() { BOOST_TEST(hasher(int_index) == hasher(int2_index)); BOOST_TEST(hasher(int_index) != hasher(char_index)); +#endif } #endif From af3a31090c50f43a845916eecd2a3160fd3e9a4c Mon Sep 17 00:00:00 2001 From: Marshall Clow Date: Mon, 9 Jul 2012 20:12:04 +0000 Subject: [PATCH 15/29] Switch from deprecated macros to new shiny ones; no functionality change [SVN r79392] --- include/boost/functional/hash/detail/container_fwd_0x.hpp | 4 ++-- include/boost/functional/hash/extensions.hpp | 4 ++-- include/boost/functional/hash/hash.hpp | 8 ++++---- test/hash_std_array_test.cpp | 2 +- test/hash_std_tuple_test.cpp | 2 +- test/hash_type_index_test.cpp | 4 ++-- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/include/boost/functional/hash/detail/container_fwd_0x.hpp b/include/boost/functional/hash/detail/container_fwd_0x.hpp index 566f2af..442ec6c 100644 --- a/include/boost/functional/hash/detail/container_fwd_0x.hpp +++ b/include/boost/functional/hash/detail/container_fwd_0x.hpp @@ -10,7 +10,7 @@ // std::array -#if !defined(BOOST_NO_0X_HDR_ARRAY) +#if !defined(BOOST_NO_CXX11_HDR_ARRAY) // Don't forward declare std::array for Dinkumware, as it seems to be // just 'using std::tr1::array'. # if (defined(BOOST_DETAIL_NO_CONTAINER_FWD) && \ @@ -26,7 +26,7 @@ namespace std { // std::tuple -#if !defined(BOOST_NO_0X_HDR_TUPLE) +#if !defined(BOOST_NO_CXX11_HDR_TUPLE) # if (defined(BOOST_DETAIL_NO_CONTAINER_FWD) && \ !defined(BOOST_DETAIL_TEST_FORCE_CONTAINER_FWD)) || \ defined(BOOST_NO_VARIADIC_TEMPLATES) diff --git a/include/boost/functional/hash/extensions.hpp b/include/boost/functional/hash/extensions.hpp index e61c2f3..9c4a6be 100644 --- a/include/boost/functional/hash/extensions.hpp +++ b/include/boost/functional/hash/extensions.hpp @@ -114,7 +114,7 @@ namespace boost return seed; } -#if !defined(BOOST_NO_0X_HDR_ARRAY) +#if !defined(BOOST_NO_CXX11_HDR_ARRAY) template std::size_t hash_value(std::array const& v) { @@ -122,7 +122,7 @@ namespace boost } #endif -#if !defined(BOOST_NO_0X_HDR_TUPLE) +#if !defined(BOOST_NO_CXX11_HDR_TUPLE) namespace hash_detail { template inline typename boost::enable_if_c<(I == std::tuple_size::value), diff --git a/include/boost/functional/hash/hash.hpp b/include/boost/functional/hash/hash.hpp index 7559e56..c179fab 100644 --- a/include/boost/functional/hash/hash.hpp +++ b/include/boost/functional/hash/hash.hpp @@ -20,7 +20,7 @@ #include #endif -#if !defined(BOOST_NO_0X_HDR_TYPEINDEX) +#if !defined(BOOST_NO_CXX11_HDR_TYPEINDEX) #include #endif @@ -111,7 +111,7 @@ namespace boost template typename boost::hash_detail::float_numbers::type hash_value(T); -#if !defined(BOOST_NO_0X_HDR_TYPEINDEX) +#if !defined(BOOST_NO_CXX11_HDR_TYPEINDEX) std::size_t hash_value(std::type_index); #endif @@ -299,7 +299,7 @@ namespace boost return boost::hash_detail::float_hash_value(v); } -#if !defined(BOOST_NO_0X_HDR_TYPEINDEX) +#if !defined(BOOST_NO_CXX11_HDR_TYPEINDEX) inline std::size_t hash_value(std::type_index v) { return v.hash_code(); @@ -410,7 +410,7 @@ namespace boost BOOST_HASH_SPECIALIZE(boost::ulong_long_type) #endif -#if !defined(BOOST_NO_0X_HDR_TYPEINDEX) +#if !defined(BOOST_NO_CXX11_HDR_TYPEINDEX) BOOST_HASH_SPECIALIZE(std::type_index) #endif diff --git a/test/hash_std_array_test.cpp b/test/hash_std_array_test.cpp index 540b676..6f67a67 100644 --- a/test/hash_std_array_test.cpp +++ b/test/hash_std_array_test.cpp @@ -16,7 +16,7 @@ #include #include -#if defined(TEST_EXTENSIONS) && !defined(BOOST_NO_0X_HDR_ARRAY) +#if defined(TEST_EXTENSIONS) && !defined(BOOST_NO_CXX11_HDR_ARRAY) #define TEST_ARRAY #include #include diff --git a/test/hash_std_tuple_test.cpp b/test/hash_std_tuple_test.cpp index 15ef483..9314336 100644 --- a/test/hash_std_tuple_test.cpp +++ b/test/hash_std_tuple_test.cpp @@ -16,7 +16,7 @@ #include #include -#if defined(TEST_EXTENSIONS) && !defined(BOOST_NO_0X_HDR_TUPLE) +#if defined(TEST_EXTENSIONS) && !defined(BOOST_NO_CXX11_HDR_TUPLE) #define TEST_TUPLE #include #include diff --git a/test/hash_type_index_test.cpp b/test/hash_type_index_test.cpp index 917bca9..27fcfff 100644 --- a/test/hash_type_index_test.cpp +++ b/test/hash_type_index_test.cpp @@ -13,7 +13,7 @@ #include #include -#if !defined(BOOST_NO_0X_HDR_TYPEINDEX) +#if !defined(BOOST_NO_CXX11_HDR_TYPEINDEX) #include @@ -43,7 +43,7 @@ void test_type_index() { int main() { -#if !defined(BOOST_NO_0X_HDR_TYPEINDEX) +#if !defined(BOOST_NO_CXX11_HDR_TYPEINDEX) test_type_index(); #else std::cout<<" not available."< Date: Sat, 14 Jul 2012 22:32:29 +0000 Subject: [PATCH 16/29] Hash: `std::shared_ptr`, `std::unique_ptr` support. [SVN r79516] --- .../hash/detail/container_fwd_0x.hpp | 14 ++++ include/boost/functional/hash/extensions.hpp | 12 +++ test/Jamfile.v2 | 1 + test/hash_std_smart_ptr_test.cpp | 80 +++++++++++++++++++ 4 files changed, 107 insertions(+) create mode 100644 test/hash_std_smart_ptr_test.cpp diff --git a/include/boost/functional/hash/detail/container_fwd_0x.hpp b/include/boost/functional/hash/detail/container_fwd_0x.hpp index 442ec6c..4e2dd7e 100644 --- a/include/boost/functional/hash/detail/container_fwd_0x.hpp +++ b/include/boost/functional/hash/detail/container_fwd_0x.hpp @@ -38,4 +38,18 @@ namespace std { # endif #endif +// std::shared_ptr/std::unique_ptr + +#if !defined(BOOST_NO_CXX11_HDR_MEMORY) +# if (defined(BOOST_DETAIL_NO_CONTAINER_FWD) && \ + !defined(BOOST_DETAIL_TEST_FORCE_CONTAINER_FWD)) +# include +# else +namespace std { + template class shared_ptr; + template class unique_ptr; +} +# endif +#endif + #endif diff --git a/include/boost/functional/hash/extensions.hpp b/include/boost/functional/hash/extensions.hpp index 9c4a6be..dc59b45 100644 --- a/include/boost/functional/hash/extensions.hpp +++ b/include/boost/functional/hash/extensions.hpp @@ -177,6 +177,18 @@ namespace boost # undef BOOST_HASH_TUPLE_F #endif +#endif + +#if !defined(BOOST_NO_CXX11_HDR_MEMORY) + template + inline std::size_t hash_value(std::shared_ptr const& x) { + return boost::hash_value(x.get()); + } + + template + inline std::size_t hash_value(std::unique_ptr const& x) { + return boost::hash_value(x.get()); + } #endif // diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 47f0a95..fc731d2 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -42,6 +42,7 @@ test-suite functional/hash [ run hash_type_index_test.cpp ] [ run hash_std_array_test.cpp ] [ run hash_std_tuple_test.cpp ] + [ run hash_std_smart_ptr_test.cpp ] [ run link_test.cpp link_test_2.cpp ] [ run link_ext_test.cpp link_no_ext_test.cpp ] [ run extensions_hpp_test.cpp ] diff --git a/test/hash_std_smart_ptr_test.cpp b/test/hash_std_smart_ptr_test.cpp new file mode 100644 index 0000000..83e705b --- /dev/null +++ b/test/hash_std_smart_ptr_test.cpp @@ -0,0 +1,80 @@ + +// Copyright 2012 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) + +#include "./config.hpp" + +#ifdef TEST_STD_INCLUDES +# include +#else +# include +#endif + +#include +#include "./compile_time.hpp" + +#if defined(TEST_EXTENSIONS) && !defined(BOOST_NO_CXX11_HDR_TUPLE) +#define TEST_SMART_PTRS +#include +#endif + +#ifdef TEST_SMART_PTRS + +void shared_ptr_tests() +{ + std::shared_ptr x; + compile_time_tests(&x); + + HASH_NAMESPACE::hash > x1; + HASH_NAMESPACE::hash > x2; + + std::shared_ptr ptr1(new int(10)); + std::shared_ptr ptr2; + + BOOST_TEST(x1(x) == x2(ptr2)); + BOOST_TEST(x1(x) != x2(ptr1)); + ptr2.reset(new int(10)); + BOOST_TEST(x1(ptr1) == x2(ptr1)); + BOOST_TEST(x1(ptr1) != x2(ptr2)); + ptr2 = ptr1; + BOOST_TEST(x1(ptr1) == x2(ptr2)); +#if defined(TEST_EXTENSIONS) + BOOST_TEST(x1(x) == HASH_NAMESPACE::hash_value(x)); + BOOST_TEST(x1(ptr1) == HASH_NAMESPACE::hash_value(ptr2)); +#endif +} + +void unique_ptr_tests() +{ + std::unique_ptr x; + compile_time_tests(&x); + + HASH_NAMESPACE::hash > x1; + HASH_NAMESPACE::hash > x2; + + std::unique_ptr ptr1(new int(10)); + std::unique_ptr ptr2; + + BOOST_TEST(x1(x) == x2(ptr2)); + BOOST_TEST(x1(x) != x2(ptr1)); + ptr2.reset(new int(10)); + BOOST_TEST(x1(ptr1) == x2(ptr1)); + BOOST_TEST(x1(ptr1) != x2(ptr2)); + +#if defined(TEST_EXTENSIONS) + BOOST_TEST(x1(x) == HASH_NAMESPACE::hash_value(x)); +#endif +} + +#endif + +int main() +{ +#ifdef TEST_SMART_PTRS + shared_ptr_tests(); + unique_ptr_tests(); +#endif + + return boost::report_errors(); +} From 5ebe3ad87df60711c4a59b8936c76f643b8be216 Mon Sep 17 00:00:00 2001 From: Daniel James Date: Sun, 15 Jul 2012 07:43:40 +0000 Subject: [PATCH 17/29] Hash: Fix smart pointer macro check. [SVN r79527] --- include/boost/functional/hash/extensions.hpp | 2 +- test/hash_std_smart_ptr_test.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/boost/functional/hash/extensions.hpp b/include/boost/functional/hash/extensions.hpp index dc59b45..4358736 100644 --- a/include/boost/functional/hash/extensions.hpp +++ b/include/boost/functional/hash/extensions.hpp @@ -179,7 +179,7 @@ namespace boost #endif -#if !defined(BOOST_NO_CXX11_HDR_MEMORY) +#if !defined(BOOST_NO_CXX11_SMART_PTR) template inline std::size_t hash_value(std::shared_ptr const& x) { return boost::hash_value(x.get()); diff --git a/test/hash_std_smart_ptr_test.cpp b/test/hash_std_smart_ptr_test.cpp index 83e705b..7452585 100644 --- a/test/hash_std_smart_ptr_test.cpp +++ b/test/hash_std_smart_ptr_test.cpp @@ -14,7 +14,7 @@ #include #include "./compile_time.hpp" -#if defined(TEST_EXTENSIONS) && !defined(BOOST_NO_CXX11_HDR_TUPLE) +#if defined(TEST_EXTENSIONS) && !defined(BOOST_NO_CXX11_SMART_PTR) #define TEST_SMART_PTRS #include #endif From 92fe67f7146f0c96090ca83e5584f6d76a10c00a Mon Sep 17 00:00:00 2001 From: Daniel James Date: Sun, 22 Jul 2012 07:15:34 +0000 Subject: [PATCH 18/29] Compile error for deprecated header `boost/functional/detail/container_fwd.hpp`. [SVN r79652] --- .../boost/functional/detail/container_fwd.hpp | 19 +------------------ test/Jamfile.v2 | 2 +- test/deprecated_container_fwd.cpp | 8 -------- 3 files changed, 2 insertions(+), 27 deletions(-) diff --git a/include/boost/functional/detail/container_fwd.hpp b/include/boost/functional/detail/container_fwd.hpp index e2bf865..6970472 100644 --- a/include/boost/functional/detail/container_fwd.hpp +++ b/include/boost/functional/detail/container_fwd.hpp @@ -7,21 +7,4 @@ // This header is deprecated, I'll change the warning to an error in a future // release, and then later remove the header completely. -#if !defined(BOOST_FUNCTIONAL_DETAIL_CONTAINER_FWD_HPP) -#define BOOST_FUNCTIONAL_DETAIL_CONTAINER_FWD_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1020) -# pragma once -#endif - -#if defined(__EDG__) -#elif defined(_MSC_VER) || defined(__BORLANDC__) || defined(__DMC__) -#pragma message("Warning: boost/functional/detail/container_fwd.hpp is deprecated, use boost/detail/container_fwd.hpp instead.") -#elif defined(__GNUC__) || defined(__HP_aCC) || \ - defined(__SUNPRO_CC) || defined(__IBMCPP__) -#warning "boost/functional/detail/container_fwd.hpp is deprecated, use boost/detail/container_fwd.hpp instead." -#endif - -#include - -#endif +#error "boost/functional/detail/container_fwd.hpp is deprecated, use boost/detail/container_fwd.hpp instead." diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index fc731d2..07df1a0 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -51,7 +51,7 @@ test-suite functional/hash [ run implicit_test.cpp ] [ run hash_no_ext_macro_1.cpp ] [ run hash_no_ext_macro_2.cpp ] - [ compile deprecated_container_fwd.cpp ] + [ compile-fail deprecated_container_fwd.cpp ] ; test-suite functional/hash_no_ext diff --git a/test/deprecated_container_fwd.cpp b/test/deprecated_container_fwd.cpp index 1c6e12b..8238bda 100644 --- a/test/deprecated_container_fwd.cpp +++ b/test/deprecated_container_fwd.cpp @@ -4,11 +4,3 @@ // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) #include - -typedef std::vector > int_vector; - -#include - -int main() { - int_vector x; -} From 0757aea7cba2eff39a5e45147ef6883b4dc97aa9 Mon Sep 17 00:00:00 2001 From: Daniel James Date: Wed, 25 Jul 2012 23:42:41 +0000 Subject: [PATCH 19/29] Hash: Fix links to examples. [SVN r79749] --- doc/tutorial.qbk | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/tutorial.qbk b/doc/tutorial.qbk index 916ab93..59067a7 100644 --- a/doc/tutorial.qbk +++ b/doc/tutorial.qbk @@ -206,7 +206,7 @@ header which forward declares [classref boost::hash], include the main header before instantiating [classref boost::hash]. When using a container that uses [classref boost::hash] it should do that for you, so your type will work fine with the boost hash containers. There's an example of this -in [@boost:/libs/unordered/examples/template.hpp template.hpp] and -[@boost:/libs/unordered/examples/template.cpp template.cpp]. +in [@boost:/libs/functional/hash/examples/template.hpp template.hpp] and +[@boost:/libs/functional/hash/examples/template.cpp template.cpp]. [endsect] From 9119b2646b51a38835e0afefbb2d8cc0abe0b3dc Mon Sep 17 00:00:00 2001 From: Daniel James Date: Tue, 14 Aug 2012 20:06:07 +0000 Subject: [PATCH 20/29] Hash: Remove C++11 forward declarations. It seems that on Visual C++ Dinkumware declares shared_ptr in std, but for Intel C++ it imports it from std::tr1. I was thinking of doing a macro check for this, but since we're close to release, just change it to always include the headers and never forward declare the C++11 classes, which is much safer. I might restore the forward declarations in the future, although I'm tempted not to. I'm not sure the improvement in compile time is worth the hassle. [SVN r80038] --- .../hash/detail/container_fwd_0x.hpp | 32 ++----------------- 1 file changed, 3 insertions(+), 29 deletions(-) diff --git a/include/boost/functional/hash/detail/container_fwd_0x.hpp b/include/boost/functional/hash/detail/container_fwd_0x.hpp index 4e2dd7e..bed7730 100644 --- a/include/boost/functional/hash/detail/container_fwd_0x.hpp +++ b/include/boost/functional/hash/detail/container_fwd_0x.hpp @@ -11,45 +11,19 @@ // std::array #if !defined(BOOST_NO_CXX11_HDR_ARRAY) - // Don't forward declare std::array for Dinkumware, as it seems to be - // just 'using std::tr1::array'. -# if (defined(BOOST_DETAIL_NO_CONTAINER_FWD) && \ - !defined(BOOST_DETAIL_TEST_FORCE_CONTAINER_FWD)) || \ - (defined(_YVALS) && !defined(__IBMCPP__)) || defined(_CPPLIB_VER) -# include -# else -namespace std { - template class array; -} -# endif +# include #endif // std::tuple #if !defined(BOOST_NO_CXX11_HDR_TUPLE) -# if (defined(BOOST_DETAIL_NO_CONTAINER_FWD) && \ - !defined(BOOST_DETAIL_TEST_FORCE_CONTAINER_FWD)) || \ - defined(BOOST_NO_VARIADIC_TEMPLATES) -# include -# else -namespace std { - template class tuple; -} -# endif +# include #endif // std::shared_ptr/std::unique_ptr #if !defined(BOOST_NO_CXX11_HDR_MEMORY) -# if (defined(BOOST_DETAIL_NO_CONTAINER_FWD) && \ - !defined(BOOST_DETAIL_TEST_FORCE_CONTAINER_FWD)) -# include -# else -namespace std { - template class shared_ptr; - template class unique_ptr; -} -# endif +# include #endif #endif From 05f16beaf0092298018e35d2bb42682b4b3b1b6b Mon Sep 17 00:00:00 2001 From: Daniel James Date: Wed, 22 Aug 2012 11:40:27 +0000 Subject: [PATCH 21/29] Hash: Quick attempt at supporting enums. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Thanks to Filip Konvička. [SVN r80139] --- include/boost/functional/hash/hash.hpp | 13 ++++++ test/Jamfile.v2 | 1 + test/hash_enum_test.cpp | 59 ++++++++++++++++++++++++++ 3 files changed, 73 insertions(+) create mode 100644 test/hash_enum_test.cpp diff --git a/include/boost/functional/hash/hash.hpp b/include/boost/functional/hash/hash.hpp index c179fab..647fd68 100644 --- a/include/boost/functional/hash/hash.hpp +++ b/include/boost/functional/hash/hash.hpp @@ -15,6 +15,8 @@ #include #include #include +#include +#include #if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) #include @@ -90,6 +92,10 @@ namespace boost template typename boost::hash_detail::ulong_numbers::type hash_value(T); + template + typename boost::enable_if, std::size_t>::type + hash_value(T); + #if !BOOST_WORKAROUND(__DMC__, <= 0x848) template std::size_t hash_value(T* const&); #else @@ -179,6 +185,13 @@ namespace boost return hash_detail::hash_value_unsigned(v); } + template + typename boost::enable_if, std::size_t>::type + hash_value(T v) + { + return static_cast(v); + } + // Implementation by Alberto Barbati and Dave Harris. #if !BOOST_WORKAROUND(__DMC__, <= 0x848) template std::size_t hash_value(T* const& v) diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 07df1a0..0f41d3e 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -22,6 +22,7 @@ test-suite functional/hash [ run hash_fwd_test_1.cpp ] [ run hash_fwd_test_2.cpp ] [ run hash_number_test.cpp ] + [ run hash_enum_test.cpp ] [ run hash_pointer_test.cpp ] [ run hash_function_pointer_test.cpp ] [ run hash_float_test.cpp ] diff --git a/test/hash_enum_test.cpp b/test/hash_enum_test.cpp new file mode 100644 index 0000000..d17b608 --- /dev/null +++ b/test/hash_enum_test.cpp @@ -0,0 +1,59 @@ + +// Copyright 2012 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) + +#include "./config.hpp" + +#ifdef TEST_STD_INCLUDES +# include +#else +# include +#endif + +#include + +#include +#include + +namespace test { + enum enum_override { enum_override1, enum_override2 }; + std::size_t hash_value(enum_override x) { return -896532; } + + enum enum1 { enum1a }; + enum enum2 { enum2a, enum2b }; + enum enum3 { enum3a = 574, enum3b }; + enum enum4 { enum4a = -12574, enum4b }; +} + +int main() { + boost::hash hash1; + boost::hash hash2; + boost::hash hash3; + boost::hash hash4; + + BOOST_TEST(hash1(test::enum1a) == hash1(test::enum1a)); + + BOOST_TEST(hash2(test::enum2a) == hash2(test::enum2a)); + BOOST_TEST(hash2(test::enum2a) != hash2(test::enum2b)); + BOOST_TEST(hash2(test::enum2b) == hash2(test::enum2b)); + + BOOST_TEST(hash3(test::enum3a) == hash3(test::enum3a)); + BOOST_TEST(hash3(test::enum3a) != hash3(test::enum3b)); + BOOST_TEST(hash3(test::enum3b) == hash3(test::enum3b)); + + BOOST_TEST(hash4(test::enum4a) == hash4(test::enum4a)); + BOOST_TEST(hash4(test::enum4a) != hash4(test::enum4b)); + BOOST_TEST(hash4(test::enum4b) == hash4(test::enum4b)); + + boost::hash hash_override; + + BOOST_TEST(hash_override(test::enum_override1) == + hash_override(test::enum_override1)); + BOOST_TEST(hash_override(test::enum_override1) == + hash_override(test::enum_override2)); + BOOST_TEST(hash_override(test::enum_override1) == + hash_override(test::enum_override1)); + + return boost::report_errors(); +} From f1de57554627ed278ff09ea5e013b2866ae0535c Mon Sep 17 00:00:00 2001 From: Daniel James Date: Thu, 23 Aug 2012 12:18:18 +0000 Subject: [PATCH 22/29] Hash: Clean up some unit tests. - Remove some unnecessary headers. - Try to fix warning in enum tests. - Compile tests + hash namespace in enum tests. [SVN r80154] --- test/hash_enum_test.cpp | 22 +++++++++++++--------- test/hash_function_pointer_test.cpp | 4 ---- test/hash_number_test.cpp | 2 -- test/hash_pointer_test.cpp | 4 ---- test/hash_range_test.cpp | 3 --- test/hash_string_test.cpp | 4 ---- 6 files changed, 13 insertions(+), 26 deletions(-) diff --git a/test/hash_enum_test.cpp b/test/hash_enum_test.cpp index d17b608..30444e5 100644 --- a/test/hash_enum_test.cpp +++ b/test/hash_enum_test.cpp @@ -12,13 +12,11 @@ #endif #include - -#include -#include +#include "./compile_time.hpp" namespace test { enum enum_override { enum_override1, enum_override2 }; - std::size_t hash_value(enum_override x) { return -896532; } + std::size_t hash_value(enum_override) { return 896532; } enum enum1 { enum1a }; enum enum2 { enum2a, enum2b }; @@ -27,10 +25,16 @@ namespace test { } int main() { - boost::hash hash1; - boost::hash hash2; - boost::hash hash3; - boost::hash hash4; + compile_time_tests((test::enum1*) 0); + compile_time_tests((test::enum2*) 0); + compile_time_tests((test::enum3*) 0); + compile_time_tests((test::enum4*) 0); + compile_time_tests((test::enum_override*) 0); + + HASH_NAMESPACE::hash hash1; + HASH_NAMESPACE::hash hash2; + HASH_NAMESPACE::hash hash3; + HASH_NAMESPACE::hash hash4; BOOST_TEST(hash1(test::enum1a) == hash1(test::enum1a)); @@ -46,7 +50,7 @@ int main() { BOOST_TEST(hash4(test::enum4a) != hash4(test::enum4b)); BOOST_TEST(hash4(test::enum4b) == hash4(test::enum4b)); - boost::hash hash_override; + HASH_NAMESPACE::hash hash_override; BOOST_TEST(hash_override(test::enum_override1) == hash_override(test::enum_override1)); diff --git a/test/hash_function_pointer_test.cpp b/test/hash_function_pointer_test.cpp index 73719e2..a73b718 100644 --- a/test/hash_function_pointer_test.cpp +++ b/test/hash_function_pointer_test.cpp @@ -12,10 +12,6 @@ #endif #include - -#include -#include - #include "./compile_time.hpp" void void_func1() { static int x = 1; ++x; } diff --git a/test/hash_number_test.cpp b/test/hash_number_test.cpp index b233c71..2645dfa 100644 --- a/test/hash_number_test.cpp +++ b/test/hash_number_test.cpp @@ -16,8 +16,6 @@ #include #include -#include -#include #include "./compile_time.hpp" diff --git a/test/hash_pointer_test.cpp b/test/hash_pointer_test.cpp index 5fcbc27..b255a28 100644 --- a/test/hash_pointer_test.cpp +++ b/test/hash_pointer_test.cpp @@ -12,11 +12,7 @@ #endif #include - #include -#include -#include - #include "./compile_time.hpp" void pointer_tests() diff --git a/test/hash_range_test.cpp b/test/hash_range_test.cpp index 8743e1e..f5fdb2a 100644 --- a/test/hash_range_test.cpp +++ b/test/hash_range_test.cpp @@ -18,10 +18,7 @@ int main() {} #endif #include - #include -#include -#include #include void hash_range_tests() diff --git a/test/hash_string_test.cpp b/test/hash_string_test.cpp index b3b8394..29ff28e 100644 --- a/test/hash_string_test.cpp +++ b/test/hash_string_test.cpp @@ -12,11 +12,7 @@ #endif #include - -#include -#include #include - #include "./compile_time.hpp" void string_tests() From eec47991f9b25684b82d4be2ca99d47dd396c98e Mon Sep 17 00:00:00 2001 From: Daniel James Date: Fri, 24 Aug 2012 22:52:42 +0000 Subject: [PATCH 23/29] Hash: A single unified algorithm for hashing floats. Attempts to automatically use a binary hash for floats where it's known to work, and then use the generic hash algorithm as a fallback. [SVN r80177] --- .../functional/hash/detail/hash_float.hpp | 182 ++++++++++++++++-- .../hash/detail/hash_float_generic.hpp | 91 --------- .../functional/hash/detail/hash_float_x86.hpp | 56 ------ test/Jamfile.v2 | 15 +- 4 files changed, 182 insertions(+), 162 deletions(-) delete mode 100644 include/boost/functional/hash/detail/hash_float_generic.hpp delete mode 100644 include/boost/functional/hash/detail/hash_float_x86.hpp diff --git a/include/boost/functional/hash/detail/hash_float.hpp b/include/boost/functional/hash/detail/hash_float.hpp index 194be1c..7ccfb80 100644 --- a/include/boost/functional/hash/detail/hash_float.hpp +++ b/include/boost/functional/hash/detail/hash_float.hpp @@ -1,5 +1,5 @@ -// Copyright 2005-2009 Daniel James. +// Copyright 2005-2012 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) @@ -13,21 +13,19 @@ #include #include #include +#include #include #include #include +#include +#include -// Include hash implementation for the current platform. - -// Cygwn -#if defined(__CYGWIN__) -# if defined(__i386__) || defined(_M_IX86) -# include -# else -# include -# endif -#else -# include +#if defined(BOOST_MSVC) +#pragma warning(push) +#if BOOST_MSVC >= 1400 +#pragma warning(disable:6294) // Ill-defined for-loop: initial condition does + // not satisfy test. Loop body not executed +#endif #endif // Can we use fpclassify? @@ -50,6 +48,158 @@ # define BOOST_HASH_USE_FPCLASSIFY 0 #endif +namespace boost +{ + namespace hash_detail + { + inline void hash_float_combine(std::size_t& seed, std::size_t value) + { + seed ^= value + (seed<<6) + (seed>>2); + } + + //////////////////////////////////////////////////////////////////////// + // Binary hash function + // + // Only used for floats with known iec559 floats, and certain values in + // numeric_limits + + inline std::size_t hash_binary(char* ptr, std::size_t length) + { + std::size_t seed = 0; + + if (length >= sizeof(std::size_t)) { + seed = *(std::size_t*) ptr; + length -= sizeof(std::size_t); + ptr += sizeof(std::size_t); + + while(length >= sizeof(std::size_t)) { + hash_float_combine(seed, *(std::size_t*) ptr); + length -= sizeof(std::size_t); + ptr += sizeof(std::size_t); + } + } + + if (length > 0) { + std::size_t buffer = 0; + std::memcpy(&buffer, ptr, length); + hash_float_combine(seed, buffer); + } + + return seed; + } + + template + inline std::size_t float_hash_impl(Float v, + BOOST_DEDUCED_TYPENAME boost::enable_if_c< + std::numeric_limits::is_iec559 && + std::numeric_limits::digits == 24 && + std::numeric_limits::radix == 2 && + std::numeric_limits::max_exponent == 128, + int>::type + ) + { + boost::uint32_t* ptr = (boost::uint32_t*)&v; + return (std::size_t) *ptr; + } + + + template + inline std::size_t float_hash_impl(Float v, + BOOST_DEDUCED_TYPENAME boost::enable_if_c< + std::numeric_limits::is_iec559 && + std::numeric_limits::digits == 53 && + std::numeric_limits::radix == 2 && + std::numeric_limits::max_exponent == 1024, + int>::type + ) + { + return hash_binary((char*) &v, 8); + } + + template + inline std::size_t float_hash_impl(Float v, + BOOST_DEDUCED_TYPENAME boost::enable_if_c< + std::numeric_limits::is_iec559 && + std::numeric_limits::digits == 64 && + std::numeric_limits::radix == 2 && + std::numeric_limits::max_exponent == 16384, + int>::type + ) + { + return hash_binary((char*) &v, 10); + } + + template + inline std::size_t float_hash_impl(Float v, + BOOST_DEDUCED_TYPENAME boost::enable_if_c< + std::numeric_limits::is_iec559 && + std::numeric_limits::digits == 113 && + std::numeric_limits::radix == 2 && + std::numeric_limits::max_exponent == 16384, + int>::type + ) + { + return hash_binary((char*) &v, 16); + } + + //////////////////////////////////////////////////////////////////////// + // Portable hash function + // + // Used as a fallback when the binary hash function isn't supported. + + template + inline std::size_t float_hash_impl2(T v) + { + boost::hash_detail::call_frexp frexp; + boost::hash_detail::call_ldexp ldexp; + + int exp = 0; + + v = frexp(v, &exp); + + // A postive value is easier to hash, so combine the + // sign with the exponent and use the absolute value. + if(v < 0) { + v = -v; + exp += limits::max_exponent - + limits::min_exponent; + } + + v = ldexp(v, limits::digits); + std::size_t seed = static_cast(v); + v -= static_cast(seed); + + // ceiling(digits(T) * log2(radix(T))/ digits(size_t)) - 1; + std::size_t const length + = (limits::digits * + boost::static_log2::radix>::value + + limits::digits - 1) + / limits::digits; + + for(std::size_t i = 0; i != length; ++i) + { + v = ldexp(v, limits::digits); + std::size_t part = static_cast(v); + v -= static_cast(part); + hash_float_combine(seed, part); + } + + hash_float_combine(seed, exp); + + return seed; + } + +#if !defined(BOOST_HASH_DETAIL_TEST_WITHOUT_GENERIC) + template + inline std::size_t float_hash_impl(T v, ...) + { + typedef BOOST_DEDUCED_TYPENAME select_hash_type::type type; + return float_hash_impl2(static_cast(v)); + } +#endif + } +} + #if BOOST_HASH_USE_FPCLASSIFY #include @@ -71,7 +221,7 @@ namespace boost return (std::size_t)(-3); case FP_NORMAL: case FP_SUBNORMAL: - return float_hash_impl(v); + return float_hash_impl(v, 0); default: BOOST_ASSERT(0); return 0; @@ -103,7 +253,7 @@ namespace boost template inline std::size_t float_hash_value(T v) { - return boost::hash_detail::is_zero(v) ? 0 : float_hash_impl(v); + return boost::hash_detail::is_zero(v) ? 0 : float_hash_impl(v, 0); } } } @@ -112,4 +262,8 @@ namespace boost #undef BOOST_HASH_USE_FPCLASSIFY +#if defined(BOOST_MSVC) +#pragma warning(pop) +#endif + #endif diff --git a/include/boost/functional/hash/detail/hash_float_generic.hpp b/include/boost/functional/hash/detail/hash_float_generic.hpp deleted file mode 100644 index 1278c2f..0000000 --- a/include/boost/functional/hash/detail/hash_float_generic.hpp +++ /dev/null @@ -1,91 +0,0 @@ - -// Copyright 2005-2009 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) - -// A general purpose hash function for non-zero floating point values. - -#if !defined(BOOST_FUNCTIONAL_HASH_DETAIL_HASH_FLOAT_GENERIC_HEADER) -#define BOOST_FUNCTIONAL_HASH_DETAIL_HASH_FLOAT_GENERIC_HEADER - -#include -#include -#include - -#if defined(_MSC_VER) && (_MSC_VER >= 1020) -# pragma once -#endif - -#if defined(BOOST_MSVC) -#pragma warning(push) -#if BOOST_MSVC >= 1400 -#pragma warning(disable:6294) // Ill-defined for-loop: initial condition does - // not satisfy test. Loop body not executed -#endif -#endif - -namespace boost -{ - namespace hash_detail - { - inline void hash_float_combine(std::size_t& seed, std::size_t value) - { - seed ^= value + (seed<<6) + (seed>>2); - } - - template - inline std::size_t float_hash_impl2(T v) - { - boost::hash_detail::call_frexp frexp; - boost::hash_detail::call_ldexp ldexp; - - int exp = 0; - - v = frexp(v, &exp); - - // A postive value is easier to hash, so combine the - // sign with the exponent and use the absolute value. - if(v < 0) { - v = -v; - exp += limits::max_exponent - - limits::min_exponent; - } - - v = ldexp(v, limits::digits); - std::size_t seed = static_cast(v); - v -= static_cast(seed); - - // ceiling(digits(T) * log2(radix(T))/ digits(size_t)) - 1; - std::size_t const length - = (limits::digits * - boost::static_log2::radix>::value - + limits::digits - 1) - / limits::digits; - - for(std::size_t i = 0; i != length; ++i) - { - v = ldexp(v, limits::digits); - std::size_t part = static_cast(v); - v -= static_cast(part); - hash_float_combine(seed, part); - } - - hash_float_combine(seed, exp); - - return seed; - } - - template - inline std::size_t float_hash_impl(T v) - { - typedef BOOST_DEDUCED_TYPENAME select_hash_type::type type; - return float_hash_impl2(static_cast(v)); - } - } -} - -#if defined(BOOST_MSVC) -#pragma warning(pop) -#endif - -#endif diff --git a/include/boost/functional/hash/detail/hash_float_x86.hpp b/include/boost/functional/hash/detail/hash_float_x86.hpp deleted file mode 100644 index b39bb0d..0000000 --- a/include/boost/functional/hash/detail/hash_float_x86.hpp +++ /dev/null @@ -1,56 +0,0 @@ - -// Copyright 2005-2009 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) - -// A non-portable hash function form non-zero floats on x86. -// -// Even if you're on an x86 platform, this might not work if their floating -// point isn't set up as this expects. So this should only be used if it's -// absolutely certain that it will work. - -#if !defined(BOOST_FUNCTIONAL_HASH_DETAIL_HASH_FLOAT_X86_HEADER) -#define BOOST_FUNCTIONAL_HASH_DETAIL_HASH_FLOAT_X86_HEADER - -#include - -#if defined(_MSC_VER) && (_MSC_VER >= 1020) -# pragma once -#endif - -namespace boost -{ - namespace hash_detail - { - inline void hash_float_combine(std::size_t& seed, std::size_t value) - { - seed ^= value + (seed<<6) + (seed>>2); - } - - inline std::size_t float_hash_impl(float v) - { - boost::uint32_t* ptr = (boost::uint32_t*)&v; - std::size_t seed = *ptr; - return seed; - } - - inline std::size_t float_hash_impl(double v) - { - boost::uint32_t* ptr = (boost::uint32_t*)&v; - std::size_t seed = *ptr++; - hash_float_combine(seed, *ptr); - return seed; - } - - inline std::size_t float_hash_impl(long double v) - { - boost::uint32_t* ptr = (boost::uint32_t*)&v; - std::size_t seed = *ptr++; - hash_float_combine(seed, *ptr++); - hash_float_combine(seed, *(boost::uint16_t*)ptr); - return seed; - } - } -} - -#endif diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 0f41d3e..5b7c39a 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -1,5 +1,5 @@ -# Copyright 2005-2011 Daniel James. +# Copyright 2005-2012 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) @@ -66,4 +66,17 @@ test-suite functional/hash_no_ext [ run link_test.cpp link_test_2.cpp : : : BOOST_HASH_NO_EXTENSIONS : no_ext_link_test ] ; +# Tests to see if the floating point hash is using the binary hash. +# Not run normally because on some platforms these should fail. +test-suite functional/hash_no_generic_float + : + [ run hash_float_test.cpp + : : : BOOST_HASH_DETAIL_TEST_WITHOUT_GENERIC + : hash_float_test_no_generic ] + [ run hash_long_double_test.cpp + : : : BOOST_HASH_DETAIL_TEST_WITHOUT_GENERIC + : hash_long_double_test_no_generic ] + ; +explicit functional/hash_no_generic_float ; + build-project ../examples ; From 7b2f73c2257df2f0393649b1aa891a189c88c77c Mon Sep 17 00:00:00 2001 From: Daniel James Date: Sat, 25 Aug 2012 20:54:10 +0000 Subject: [PATCH 24/29] Hash: Avoid type punning warning. [SVN r80217] --- include/boost/functional/hash/detail/hash_float.hpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/include/boost/functional/hash/detail/hash_float.hpp b/include/boost/functional/hash/detail/hash_float.hpp index 7ccfb80..3edc6ab 100644 --- a/include/boost/functional/hash/detail/hash_float.hpp +++ b/include/boost/functional/hash/detail/hash_float.hpp @@ -98,8 +98,7 @@ namespace boost int>::type ) { - boost::uint32_t* ptr = (boost::uint32_t*)&v; - return (std::size_t) *ptr; + return hash_binary((char*) &v, 4); } From 853a713cf2fd9dc47cc1c773c8191377c4f5a597 Mon Sep 17 00:00:00 2001 From: Daniel James Date: Tue, 28 Aug 2012 17:43:05 +0000 Subject: [PATCH 25/29] Remove deprecated header `boost/functional/detail/container_fwd.hpp` [SVN r80288] --- include/boost/functional/detail/container_fwd.hpp | 10 ---------- test/Jamfile.v2 | 1 - test/deprecated_container_fwd.cpp | 6 ------ 3 files changed, 17 deletions(-) delete mode 100644 include/boost/functional/detail/container_fwd.hpp delete mode 100644 test/deprecated_container_fwd.cpp diff --git a/include/boost/functional/detail/container_fwd.hpp b/include/boost/functional/detail/container_fwd.hpp deleted file mode 100644 index 6970472..0000000 --- a/include/boost/functional/detail/container_fwd.hpp +++ /dev/null @@ -1,10 +0,0 @@ - -// Copyright 2005-2012 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) - -// Forwarding header for container_fwd.hpp's new location. -// This header is deprecated, I'll change the warning to an error in a future -// release, and then later remove the header completely. - -#error "boost/functional/detail/container_fwd.hpp is deprecated, use boost/detail/container_fwd.hpp instead." diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 5b7c39a..34b69e6 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -52,7 +52,6 @@ test-suite functional/hash [ run implicit_test.cpp ] [ run hash_no_ext_macro_1.cpp ] [ run hash_no_ext_macro_2.cpp ] - [ compile-fail deprecated_container_fwd.cpp ] ; test-suite functional/hash_no_ext diff --git a/test/deprecated_container_fwd.cpp b/test/deprecated_container_fwd.cpp deleted file mode 100644 index 8238bda..0000000 --- a/test/deprecated_container_fwd.cpp +++ /dev/null @@ -1,6 +0,0 @@ - -// Copyright 2012 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) - -#include From acf1f3bc481fee0c1e1a7ba4f6e51fa55e5df1f8 Mon Sep 17 00:00:00 2001 From: Daniel James Date: Sun, 30 Sep 2012 11:56:13 +0000 Subject: [PATCH 26/29] Hash: Update change log [SVN r80777] --- doc/changes.qbk | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/doc/changes.qbk b/doc/changes.qbk index 3aa3dee..c98bd86 100644 --- a/doc/changes.qbk +++ b/doc/changes.qbk @@ -132,4 +132,17 @@ * Add deprecation warning to the long deprecated `boost/functional/detail/container_fwd.hpp`. +[h2 Boost 1.51.0] + +* Support the standard smart pointers. +* `hash_value` now implemented using SFINAE to avoid implicit casts to built + in types when calling it. +* Updated to use the new config macros. + +[h2 Boost 1.52.0] + +* Restore `enum` support, which was accidentally removed in the last version. +* New floating point hasher - will hash the binary representation on more + platforms, which should be faster. + [endsect] From a2756e75e8cd2e14d6bfb54251af62668a66aa95 Mon Sep 17 00:00:00 2001 From: Marshall Clow Date: Wed, 31 Oct 2012 17:14:43 +0000 Subject: [PATCH 27/29] Narrower 'using'; Refs #7470 [SVN r81122] --- include/boost/functional/hash/detail/hash_float.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/functional/hash/detail/hash_float.hpp b/include/boost/functional/hash/detail/hash_float.hpp index 3edc6ab..5fcac60 100644 --- a/include/boost/functional/hash/detail/hash_float.hpp +++ b/include/boost/functional/hash/detail/hash_float.hpp @@ -210,7 +210,7 @@ namespace boost template inline std::size_t float_hash_value(T v) { - using namespace std; + using namespace std::fpclassify; switch (fpclassify(v)) { case FP_ZERO: return 0; From dfd48ef4988ba09f7677e230dbf9b39823fbff95 Mon Sep 17 00:00:00 2001 From: Daniel James Date: Wed, 31 Oct 2012 19:05:25 +0000 Subject: [PATCH 28/29] Hash: Revert r81122. Refs #7470. I'll get back to this later, it probably requires compiler specific changes. [SVN r81124] --- include/boost/functional/hash/detail/hash_float.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/functional/hash/detail/hash_float.hpp b/include/boost/functional/hash/detail/hash_float.hpp index 5fcac60..3edc6ab 100644 --- a/include/boost/functional/hash/detail/hash_float.hpp +++ b/include/boost/functional/hash/detail/hash_float.hpp @@ -210,7 +210,7 @@ namespace boost template inline std::size_t float_hash_value(T v) { - using namespace std::fpclassify; + using namespace std; switch (fpclassify(v)) { case FP_ZERO: return 0; From 7f7ecfc71713aa9f5b86fe8cf6a9aa97419dc1d4 Mon Sep 17 00:00:00 2001 From: Daniel James Date: Mon, 5 Nov 2012 18:33:54 +0000 Subject: [PATCH 29/29] Hash: Extra test to check different platform's floating point functions. [SVN r81210] --- test/extra/Jamfile.v2 | 13 +++++++ test/extra/check_float_funcs.cpp | 58 ++++++++++++++++++++++++++++++++ 2 files changed, 71 insertions(+) create mode 100644 test/extra/Jamfile.v2 create mode 100644 test/extra/check_float_funcs.cpp diff --git a/test/extra/Jamfile.v2 b/test/extra/Jamfile.v2 new file mode 100644 index 0000000..243c1b1 --- /dev/null +++ b/test/extra/Jamfile.v2 @@ -0,0 +1,13 @@ + +# Copyright 2012 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) + +import testing ; + +build-project .. ; + +test-suite functional/hash/config + : + [ compile check_float_funcs.cpp ] + ; \ No newline at end of file diff --git a/test/extra/check_float_funcs.cpp b/test/extra/check_float_funcs.cpp new file mode 100644 index 0000000..a937082 --- /dev/null +++ b/test/extra/check_float_funcs.cpp @@ -0,0 +1,58 @@ + +// Copyright 2012 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) + +#include +#include +#include +#include + +namespace test +{ + template + struct check_return_type + { + template + static void equals(T2) + { + BOOST_STATIC_ASSERT((boost::is_same::value)); + } + + template + static void equals_ref(T2&) + { + BOOST_STATIC_ASSERT((boost::is_same::value)); + } + + template + static void convertible(T2) + { + BOOST_STATIC_ASSERT((boost::is_convertible::value)); + } + }; +} + +int main() { + float f = 0; + double d = 0; + long double l = 0; + + test::check_return_type::equals(std::ldexp(f, 0)); + test::check_return_type::equals(std::ldexp(d, 0)); + test::check_return_type::equals(std::ldexp(l, 0)); + + int dummy = 0; + + test::check_return_type::equals(std::frexp(f, &dummy)); + test::check_return_type::equals(std::frexp(d, &dummy)); + test::check_return_type::equals(std::frexp(l, &dummy)); + +#if BOOST_HASH_USE_FPCLASSIFY + + int (*fpc1)(float) = std::fpclassify; + int (*fpc2)(double) = std::fpclassify; + int (*fpc3)(long double) = std::fpclassify; + +#endif +} \ No newline at end of file