mirror of
https://github.com/boostorg/container_hash.git
synced 2026-03-07 14:34:11 +01:00
Compare commits
29 Commits
boost-1.48
...
boost-1.50
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dfe0ad3a60 | ||
|
|
c409903f5e | ||
|
|
033ef4b507 | ||
|
|
18b143cad1 | ||
|
|
346e62f53f | ||
|
|
9a38ebf8c3 | ||
|
|
a6f8c51afb | ||
|
|
903b1e409e | ||
|
|
eb040cb89b | ||
|
|
d92209d725 | ||
|
|
56293f4313 | ||
|
|
335930c652 | ||
|
|
da096ddf8c | ||
|
|
8c0e9a2b09 | ||
|
|
664522596f | ||
|
|
ce885af9b0 | ||
|
|
9e641187c6 | ||
|
|
7dc95d044d | ||
|
|
ad614b3d5f | ||
|
|
ed598f865e | ||
|
|
482f038837 | ||
|
|
a2e947588d | ||
|
|
982b350d71 | ||
|
|
577054de93 | ||
|
|
fc3b3863b4 | ||
|
|
906f632706 | ||
|
|
bbfb6fd32c | ||
|
|
38d131c158 | ||
|
|
2553a5fbdc |
@@ -123,4 +123,13 @@
|
||||
|
||||
* 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.
|
||||
* Add deprecation warning to the long deprecated
|
||||
`boost/functional/detail/container_fwd.hpp`.
|
||||
|
||||
[endsect]
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
[library Boost.Functional/Hash
|
||||
[quickbook 1.4]
|
||||
[quickbook 1.5]
|
||||
[authors [James, Daniel]]
|
||||
[copyright 2005 2006 2007 2008 Daniel James]
|
||||
[purpose A TR1 hash function object that can be extended to hash user
|
||||
|
||||
@@ -5,10 +5,10 @@
|
||||
|
||||
[section:rationale Rationale]
|
||||
|
||||
The rationale for the design can be found in the original design
|
||||
[footnote issue 6.18 of the __issues__ (page 63)], but an issue that
|
||||
occasionally comes up is the quality of the hash function, so that
|
||||
demands some more attention.
|
||||
The rationale can be found in the original design
|
||||
[footnote issue 6.18 of the __issues__ (page 63)].
|
||||
|
||||
[heading Quality of the hash function]
|
||||
|
||||
Many hash functions strive to have little correlation between the input
|
||||
and output values. They attempt to uniformally distribute the output
|
||||
@@ -16,23 +16,23 @@ values for very similar inputs. This hash function makes no such
|
||||
attempt. In fact, for integers, the result of the hash function is often
|
||||
just the input value. So similar but different input values will often
|
||||
result in similar but different output values.
|
||||
|
||||
This means that it is not appropriate as a general hash function. For
|
||||
example, a hash table may discard bits from the hash function resulting
|
||||
in likely collisions, or might have poor collision resolution when hash
|
||||
values are clustered together. In such cases this hash function will
|
||||
preform poorly.
|
||||
|
||||
So why not implement a higher quality hash function? Well, the standard
|
||||
makes no such guarantee, it just requires that the hashes of two
|
||||
different values are unlikely to collide. Containers or algorithms
|
||||
But the standard has no such requirement for the hash function,
|
||||
it just requires that the hashes of two different values are unlikely
|
||||
to collide. Containers or algorithms
|
||||
designed to work with the standard hash function will have to be
|
||||
implemented to work well when the hash function's output is correlated
|
||||
to its input. Since they are paying that cost a higher quality hash function
|
||||
would be wasteful.
|
||||
|
||||
For other use cases, if you do need a higher quality hash function,
|
||||
there are several options
|
||||
then neither the standard hash function or `boost::hash` are appropriate.
|
||||
There are several options
|
||||
available. One is to use a second hash on the output of this hash
|
||||
function, such as [@http://www.concentric.net/~ttwang/tech/inthash.htm
|
||||
Thomas Wang's hash function]. This this may not work as
|
||||
@@ -47,4 +47,4 @@ your data - providing that all equal values have an equal
|
||||
representation, which is not always the case (e.g. for floating point
|
||||
values).
|
||||
|
||||
[endsect]
|
||||
[endsect]
|
||||
|
||||
47
doc/ref.xml
47
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.
|
||||
</para>
|
||||
<para>
|
||||
Forward declared in
|
||||
<code><boost/functional/hash_fwd.hpp></code>
|
||||
</para>
|
||||
</notes>
|
||||
<throws><para>
|
||||
Only throws if
|
||||
@@ -451,6 +455,10 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
<para><functionname>hash_value</functionname> is called without
|
||||
qualification, so that overloads can be found via ADL.</para>
|
||||
<para>This is an extension to TR1</para>
|
||||
<para>
|
||||
Forward declared in
|
||||
<code><boost/functional/hash_fwd.hpp></code>
|
||||
</para>
|
||||
</notes>
|
||||
<throws>
|
||||
Only throws if <functionname>hash_value</functionname>(T) throws.
|
||||
@@ -499,15 +507,14 @@ for(; first != last; ++first)
|
||||
|
||||
return seed;
|
||||
</programlisting>
|
||||
</para>For the three arguments overload:
|
||||
</para>
|
||||
<para>For the three arguments overload:</para>
|
||||
<programlisting>
|
||||
for(; first != last; ++first)
|
||||
{
|
||||
<functionname>hash_combine</functionname>(seed, *first);
|
||||
}
|
||||
</programlisting>
|
||||
<para>
|
||||
</para>
|
||||
</effects>
|
||||
<notes>
|
||||
<para>
|
||||
@@ -516,6 +523,10 @@ for(; first != last; ++first)
|
||||
container.
|
||||
</para>
|
||||
<para>This is an extension to TR1</para>
|
||||
<para>
|
||||
Forward declared in
|
||||
<code><boost/functional/hash_fwd.hpp></code>
|
||||
</para>
|
||||
</notes>
|
||||
<throws><para>
|
||||
Only throws if <code><functionname>hash_value</functionname>(std::iterator_traits<It>::value_type)</code>
|
||||
@@ -744,6 +755,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 +839,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 +849,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>
|
||||
|
||||
@@ -198,5 +198,15 @@ To calculate the hash of an iterator range you can use [funcref boost::hash_rang
|
||||
std::vector<std::string> 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 `<boost/functional/hash_fwd.hpp>`
|
||||
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]
|
||||
|
||||
@@ -6,3 +6,4 @@
|
||||
run books.cpp ;
|
||||
run point.cpp ;
|
||||
run portable.cpp ;
|
||||
run template.cpp ;
|
||||
|
||||
18
examples/template.cpp
Normal file
18
examples/template.cpp
Normal file
@@ -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 <cassert>
|
||||
#include <boost/unordered_set.hpp>
|
||||
|
||||
int main()
|
||||
{
|
||||
typedef my_pair<int, float> pair;
|
||||
boost::unordered_set<pair> 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());
|
||||
}
|
||||
36
examples/template.hpp
Normal file
36
examples/template.hpp
Normal file
@@ -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 <boost/functional/hash_fwd.hpp>
|
||||
|
||||
template <typename A, typename B>
|
||||
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;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -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 <boost/detail/container_fwd.hpp>
|
||||
|
||||
#endif
|
||||
|
||||
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
|
||||
//
|
||||
|
||||
@@ -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 -Wshadow"
|
||||
<toolset>darwin:<cxxflags>"-pedantic -Wstrict-aliasing -fstrict-aliasing -Wextra -Wsign-promo -Wunused-parameter -Wconversion -Wfloat-equal -Wshadow"
|
||||
<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 ]
|
||||
@@ -48,6 +50,7 @@ test-suite functional/hash
|
||||
[ compile-fail implicit_fail_test.cpp : <define>BOOST_HASH_NO_IMPLICIT_CASTS ]
|
||||
[ run hash_no_ext_macro_1.cpp : : : <define>BOOST_HASH_NO_IMPLICIT_CASTS ]
|
||||
[ run hash_no_ext_macro_2.cpp : : : <define>BOOST_HASH_NO_IMPLICIT_CASTS ]
|
||||
[ compile deprecated_container_fwd.cpp ]
|
||||
;
|
||||
|
||||
test-suite functional/hash_implicit_casts
|
||||
|
||||
14
test/deprecated_container_fwd.cpp
Normal file
14
test/deprecated_container_fwd.cpp
Normal file
@@ -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 <boost/functional/detail/container_fwd.hpp>
|
||||
|
||||
typedef std::vector<int, std::allocator<int> > int_vector;
|
||||
|
||||
#include <vector>
|
||||
|
||||
int main() {
|
||||
int_vector x;
|
||||
}
|
||||
@@ -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
test/hash_std_array_test.cpp
Normal file
103
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
test/hash_std_tuple_test.cpp
Normal file
77
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();
|
||||
}
|
||||
@@ -18,12 +18,16 @@
|
||||
#include <typeindex>
|
||||
|
||||
void test_type_index() {
|
||||
HASH_NAMESPACE::hash<std::type_index> hasher;
|
||||
|
||||
#if defined(BOOST_NO_TYPEID)
|
||||
std::cout<<"Unable to test std::type_index, as typeid isn't available"
|
||||
<<std::endl;
|
||||
#else
|
||||
std::type_index int_index = typeid(int);
|
||||
std::type_index int2_index = typeid(int);
|
||||
std::type_index char_index = typeid(char);
|
||||
|
||||
HASH_NAMESPACE::hash<std::type_index> 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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user