mirror of
https://github.com/boostorg/functional.git
synced 2025-08-01 05:24:31 +02:00
Unordered/Hash: Merge from trunk.
[SVN r78319]
This commit is contained in:
@@ -123,4 +123,11 @@
|
||||
|
||||
* Avoid warning due with gcc's `-Wconversion` flag.
|
||||
|
||||
[h2 Boost 1.50.0]
|
||||
|
||||
* [@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.
|
||||
|
||||
[endsect]
|
||||
|
@@ -744,6 +744,25 @@ for(; first != last; ++first)
|
||||
<parameter name="val"><paramtype>std::type_index</paramtype></parameter>
|
||||
</signature>
|
||||
|
||||
<signature>
|
||||
<template>
|
||||
<template-type-parameter name="T"/>
|
||||
<template-nontype-parameter name="N">
|
||||
<type>std::size_t</type>
|
||||
</template-nontype-parameter>
|
||||
</template>
|
||||
<type>std::size_t</type>
|
||||
<parameter name="val"><paramtype>std::array<T, N> const&</paramtype></parameter>
|
||||
</signature>
|
||||
|
||||
<signature>
|
||||
<template>
|
||||
<template-type-parameter name="T" pack="1"/>
|
||||
</template>
|
||||
<type>std::size_t</type>
|
||||
<parameter name="val"><paramtype>std::tuple<T...></paramtype></parameter>
|
||||
</signature>
|
||||
|
||||
<description><para>
|
||||
Generally shouldn't be called directly by users, instead they should use
|
||||
<classname>boost::hash</classname>, <functionname>boost::hash_range</functionname>
|
||||
@@ -809,7 +828,8 @@ for(; first != last; ++first)
|
||||
<code>std::set<K, C, A></code>,
|
||||
<code>std::multiset<K, C, A></code>,
|
||||
<code>std::map<K, T, C, A></code>,
|
||||
<code>std::multimap<K, T, C, A></code>
|
||||
<code>std::multimap<K, T, C, A></code>,
|
||||
<code>std::array<T, N></code>
|
||||
</entry>
|
||||
<entry><code>hash_range(val.begin(), val.end())</code></entry>
|
||||
</row>
|
||||
@@ -818,6 +838,14 @@ for(; first != last; ++first)
|
||||
<entry><programlisting>size_t seed = 0;
|
||||
<functionname>hash_combine</functionname>(seed, val.first);
|
||||
<functionname>hash_combine</functionname>(seed, val.second);
|
||||
return seed;</programlisting></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><code>std::tuple<T...></code></entry>
|
||||
<entry><programlisting>size_t seed = 0;
|
||||
<functionname>hash_combine</functionname>(seed, get<0>(val));
|
||||
<functionname>hash_combine</functionname>(seed, get<1>(val));
|
||||
// ....
|
||||
return seed;</programlisting></entry>
|
||||
</row>
|
||||
<row>
|
||||
|
@@ -10,8 +10,8 @@ project hash-tests
|
||||
<warnings>all
|
||||
<toolset>intel:<warnings>on
|
||||
<toolset>intel:<cxxflags>-strict-ansi
|
||||
<toolset>gcc:<cxxflags>"-pedantic -Wstrict-aliasing -fstrict-aliasing -Wextra -Wsign-promo -Wunused-parameter -Wconversion"
|
||||
<toolset>darwin:<cxxflags>"-pedantic -Wstrict-aliasing -fstrict-aliasing -Wextra -Wsign-promo -Wunused-parameter -Wconversion"
|
||||
<toolset>gcc:<cxxflags>"-pedantic -Wstrict-aliasing -fstrict-aliasing -Wextra -Wsign-promo -Wunused-parameter -Wconversion -Wfloat-equal"
|
||||
<toolset>darwin:<cxxflags>"-pedantic -Wstrict-aliasing -fstrict-aliasing -Wextra -Wsign-promo -Wunused-parameter -Wconversion -Wfloat-equal"
|
||||
<toolset>msvc:<warnings-as-errors>on
|
||||
#<toolset>gcc:<warnings-as-errors>on
|
||||
#<toolset>darwin:<warnings-as-errors>on
|
||||
@@ -40,6 +40,8 @@ test-suite functional/hash
|
||||
[ run hash_map_test.cpp : : : <define>BOOST_HASH_NO_IMPLICIT_CASTS ]
|
||||
[ run hash_complex_test.cpp : : : <define>BOOST_HASH_NO_IMPLICIT_CASTS ]
|
||||
[ run hash_type_index_test.cpp : : : <define>BOOST_HASH_NO_IMPLICIT_CASTS ]
|
||||
[ run hash_std_array_test.cpp : : : <define>BOOST_HASH_NO_IMPLICIT_CASTS ]
|
||||
[ run hash_std_tuple_test.cpp : : : <define>BOOST_HASH_NO_IMPLICIT_CASTS ]
|
||||
[ run link_test.cpp link_test_2.cpp : : : <define>BOOST_HASH_NO_IMPLICIT_CASTS ]
|
||||
[ run link_ext_test.cpp link_no_ext_test.cpp : : : <define>BOOST_HASH_NO_IMPLICIT_CASTS ]
|
||||
[ run extensions_hpp_test.cpp : : : <define>BOOST_HASH_NO_IMPLICIT_CASTS ]
|
||||
|
@@ -35,6 +35,10 @@ int main() {}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__)
|
||||
#pragma GCC diagnostic ignored "-Wfloat-equal"
|
||||
#endif
|
||||
|
||||
#include <complex>
|
||||
#include <sstream>
|
||||
#include <boost/limits.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"; }
|
||||
|
@@ -27,7 +27,7 @@ using std::multimap;
|
||||
#define CONTAINER_TYPE multimap
|
||||
#include "./hash_map_test.hpp"
|
||||
|
||||
#endif // TEST_EXTENSTIONS
|
||||
#endif // TEST_EXTENSIONS
|
||||
|
||||
int main()
|
||||
{
|
||||
|
@@ -28,6 +28,10 @@
|
||||
#pragma warning(disable:4310) // cast truncates constant value
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__)
|
||||
#pragma GCC diagnostic ignored "-Wfloat-equal"
|
||||
#endif
|
||||
|
||||
template <class T>
|
||||
void numeric_test(T*)
|
||||
{
|
||||
|
103
hash/test/hash_std_array_test.cpp
Normal file
103
hash/test/hash_std_array_test.cpp
Normal file
@@ -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 <functional>
|
||||
# else
|
||||
# include <boost/functional/hash.hpp>
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
|
||||
#if defined(TEST_EXTENSIONS) && !defined(BOOST_NO_0X_HDR_ARRAY)
|
||||
#define TEST_ARRAY
|
||||
#include <array>
|
||||
#include <vector>
|
||||
#endif
|
||||
|
||||
#ifdef TEST_ARRAY
|
||||
|
||||
template <typename T>
|
||||
void array_tests(T const& v) {
|
||||
boost::hash<typename T::value_type> 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<std::array<int, 0> > empty_array_hash;
|
||||
std::array<int, 0> empty_array;
|
||||
BOOST_TEST(empty_array_hash(empty_array) == boost::hash_value(empty_array));
|
||||
*/
|
||||
}
|
||||
|
||||
void int_1_array_test()
|
||||
{
|
||||
std::vector<std::array<int, 1> > arrays;
|
||||
std::array<int, 1> val;
|
||||
val[0] = 0;
|
||||
arrays.push_back(val);
|
||||
val[0] = 1;
|
||||
arrays.push_back(val);
|
||||
val[0] = 2;
|
||||
arrays.push_back(val);
|
||||
array_tests(arrays);
|
||||
}
|
||||
|
||||
void string_1_array_test()
|
||||
{
|
||||
std::vector<std::array<std::string, 1> > arrays;
|
||||
std::array<std::string, 1> val;
|
||||
arrays.push_back(val);
|
||||
val[0] = "one";
|
||||
arrays.push_back(val);
|
||||
val[0] = "two";
|
||||
arrays.push_back(val);
|
||||
array_tests(arrays);
|
||||
}
|
||||
|
||||
void string_3_array_test()
|
||||
{
|
||||
std::vector<std::array<std::string,3 > > arrays;
|
||||
std::array<std::string, 3> val;
|
||||
arrays.push_back(val);
|
||||
val[0] = "one";
|
||||
arrays.push_back(val);
|
||||
val[0] = ""; val[1] = "one"; val[2] = "";
|
||||
arrays.push_back(val);
|
||||
val[0] = ""; val[1] = ""; val[2] = "one";
|
||||
arrays.push_back(val);
|
||||
val[0] = "one"; val[1] = "one"; val[2] = "one";
|
||||
arrays.push_back(val);
|
||||
val[0] = "one"; val[1] = "two"; val[2] = "three";
|
||||
arrays.push_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();
|
||||
}
|
77
hash/test/hash_std_tuple_test.cpp
Normal file
77
hash/test/hash_std_tuple_test.cpp
Normal file
@@ -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 <functional>
|
||||
# else
|
||||
# include <boost/functional/hash.hpp>
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
|
||||
#if defined(TEST_EXTENSIONS) && !defined(BOOST_NO_0X_HDR_TUPLE)
|
||||
#define TEST_TUPLE
|
||||
#include <tuple>
|
||||
#include <vector>
|
||||
#endif
|
||||
|
||||
#ifdef TEST_TUPLE
|
||||
|
||||
template <typename T>
|
||||
void tuple_tests(T const& v) {
|
||||
boost::hash<typename T::value_type> 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<std::tuple<> > 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<std::tuple<int> > 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<std::tuple<int, std::string> > int_string_tuples;
|
||||
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);
|
||||
}
|
||||
|
||||
#endif // TEST_TUPLE
|
||||
|
||||
int main()
|
||||
{
|
||||
#ifdef TEST_TUPLE
|
||||
empty_tuple_test();
|
||||
int_tuple_test();
|
||||
int_string_tuple_test();
|
||||
#endif
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
41
include/boost/functional/hash/detail/container_fwd_0x.hpp
Normal file
41
include/boost/functional/hash/detail/container_fwd_0x.hpp
Normal file
@@ -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 <boost/detail/container_fwd.hpp>
|
||||
|
||||
// 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 <array>
|
||||
# else
|
||||
namespace std {
|
||||
template <class, std::size_t> 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 <tuple>
|
||||
# else
|
||||
namespace std {
|
||||
template <typename...> class tuple;
|
||||
}
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#endif
|
@@ -86,10 +86,24 @@ namespace boost
|
||||
{
|
||||
namespace hash_detail
|
||||
{
|
||||
template <class T>
|
||||
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<T>()(v, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
template <class T>
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -14,7 +14,11 @@
|
||||
#define BOOST_FUNCTIONAL_HASH_EXTENSIONS_HPP
|
||||
|
||||
#include <boost/functional/hash/hash.hpp>
|
||||
#include <boost/detail/container_fwd.hpp>
|
||||
#include <boost/functional/hash/detail/container_fwd_0x.hpp>
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
#include <boost/preprocessor/repetition/repeat_from_to.hpp>
|
||||
#include <boost/preprocessor/repetition/enum_params.hpp>
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
# pragma once
|
||||
@@ -54,51 +58,51 @@ namespace boost
|
||||
std::size_t hash_value(std::pair<A, B> 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 <class T, class A>
|
||||
std::size_t hash_value(std::vector<T, A> const& v)
|
||||
{
|
||||
return hash_range(v.begin(), v.end());
|
||||
return boost::hash_range(v.begin(), v.end());
|
||||
}
|
||||
|
||||
template <class T, class A>
|
||||
std::size_t hash_value(std::list<T, A> const& v)
|
||||
{
|
||||
return hash_range(v.begin(), v.end());
|
||||
return boost::hash_range(v.begin(), v.end());
|
||||
}
|
||||
|
||||
template <class T, class A>
|
||||
std::size_t hash_value(std::deque<T, A> const& v)
|
||||
{
|
||||
return hash_range(v.begin(), v.end());
|
||||
return boost::hash_range(v.begin(), v.end());
|
||||
}
|
||||
|
||||
template <class K, class C, class A>
|
||||
std::size_t hash_value(std::set<K, C, A> const& v)
|
||||
{
|
||||
return hash_range(v.begin(), v.end());
|
||||
return boost::hash_range(v.begin(), v.end());
|
||||
}
|
||||
|
||||
template <class K, class C, class A>
|
||||
std::size_t hash_value(std::multiset<K, C, A> const& v)
|
||||
{
|
||||
return hash_range(v.begin(), v.end());
|
||||
return boost::hash_range(v.begin(), v.end());
|
||||
}
|
||||
|
||||
template <class K, class T, class C, class A>
|
||||
std::size_t hash_value(std::map<K, T, C, A> const& v)
|
||||
{
|
||||
return hash_range(v.begin(), v.end());
|
||||
return boost::hash_range(v.begin(), v.end());
|
||||
}
|
||||
|
||||
template <class K, class T, class C, class A>
|
||||
std::size_t hash_value(std::multimap<K, T, C, A> const& v)
|
||||
{
|
||||
return hash_range(v.begin(), v.end());
|
||||
return boost::hash_range(v.begin(), v.end());
|
||||
}
|
||||
|
||||
template <class T>
|
||||
@@ -110,6 +114,71 @@ namespace boost
|
||||
return seed;
|
||||
}
|
||||
|
||||
#if !defined(BOOST_NO_0X_HDR_ARRAY)
|
||||
template <class T, std::size_t N>
|
||||
std::size_t hash_value(std::array<T, N> const& v)
|
||||
{
|
||||
return boost::hash_range(v.begin(), v.end());
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_NO_0X_HDR_TUPLE)
|
||||
namespace hash_detail {
|
||||
template <std::size_t I, typename T>
|
||||
inline typename boost::enable_if_c<(I == std::tuple_size<T>::value),
|
||||
void>::type
|
||||
hash_combine_tuple(std::size_t&, T const&)
|
||||
{
|
||||
}
|
||||
|
||||
template <std::size_t I, typename T>
|
||||
inline typename boost::enable_if_c<(I < std::tuple_size<T>::value),
|
||||
void>::type
|
||||
hash_combine_tuple(std::size_t& seed, T const& v)
|
||||
{
|
||||
boost::hash_combine(seed, std::get<I>(v));
|
||||
boost::hash_detail::hash_combine_tuple<I + 1>(seed, v);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
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 <typename... T>
|
||||
inline std::size_t hash_value(std::tuple<T...> 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
|
||||
//
|
||||
|
Reference in New Issue
Block a user