mirror of
https://github.com/boostorg/functional.git
synced 2025-08-01 05:24:31 +02:00
@@ -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]
|
||||
|
@@ -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>
|
||||
@@ -810,6 +829,7 @@ for(; first != last; ++first)
|
||||
<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::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>
|
||||
|
@@ -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 ]
|
||||
|
@@ -27,7 +27,7 @@ using std::multimap;
|
||||
#define CONTAINER_TYPE multimap
|
||||
#include "./hash_map_test.hpp"
|
||||
|
||||
#endif // TEST_EXTENSTIONS
|
||||
#endif // TEST_EXTENSIONS
|
||||
|
||||
int main()
|
||||
{
|
||||
|
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.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<std::array<std::string, 1> > arrays;
|
||||
std::array<std::string, 1> 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<std::array<std::string,3 > > arrays;
|
||||
std::array<std::string, 3> 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();
|
||||
}
|
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, "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();
|
||||
}
|
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
|
@@ -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