Compare commits

..

1 Commits

Author SHA1 Message Date
nobody
42f5aeb552 This commit was manufactured by cvs2svn to create tag
'Version_1_34_0'.

[SVN r37679]
2007-05-12 21:59:40 +00:00
58 changed files with 4408 additions and 77 deletions

View File

@@ -1,72 +0,0 @@
# Copyright (C) 2016 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)
# Use Trusty to get a reasonably recent version of Boost.
sudo: required
dist: trusty
language: c++
addons:
apt:
packages:
- libboost-tools-dev
matrix:
include:
- compiler: gcc
env: |
USER_CONFIG="using gcc : : g++-4.8 -Werror --std=c++03 ;"
- compiler: gcc
env: |
USER_CONFIG="using gcc : : g++-4.8 -Werror --std=c++11 ;"
- compiler: clang
env: |
USER_CONFIG="using clang : : clang++ -Werror --std=c++03 ;"
- compiler: clang
env: |
USER_CONFIG="using clang : : clang++ -Werror --std=c++11 ;"
- compiler: clang
env: |
USER_CONFIG="using clang : : clang++ -Werror --std=c++11 -D_HAS_AUTO_PTR_ETC=0 ;"
before_script:
- export BOOST_VERSION=1.65.1
- export BOOST_FILENAME=boost_1_65_1
- export BOOST_ROOT=${HOME}/boost
- cd ${TRAVIS_BUILD_DIR}
- touch Jamroot.jam
- cd $HOME
- echo $USER_CONFIG > ~/user-config.jam
- cat ~/user-config.jam
- |
mkdir $HOME/download
mkdir $HOME/extract
cd $HOME/download
if [ "$TRAVIS_EVENT_TYPE" == "cron" ]
then
if [ "$TRAVIS_BRANCH" == "master" ]
then
snapshot_branch=master
else
snapshot_branch=develop
fi
download_url=$(curl https://api.bintray.com/packages/boostorg/$snapshot_branch/snapshot/files |
python -c "import os.path, sys, json; x = json.load(sys.stdin); print '\n'.join(a['path'] for a in x if os.path.splitext(a['path'])[1] == '.bz2')" |
head -n 1 |
sed "s/^/http:\/\/dl.bintray.com\/boostorg\/$snapshot_branch\//")
else
download_url=https://sourceforge.net/projects/boost/files/boost/${BOOST_VERSION}/${BOOST_FILENAME}.tar.bz2/download
fi
echo "Downloading ${download_url}"
wget -O boost.tar.bz2 $download_url
cd $HOME/extract
tar -xjf $HOME/download/boost.tar.bz2
mv * ${BOOST_ROOT}
- rm ${BOOST_ROOT}/boost/functional.hpp
- find ${BOOST_ROOT}/boost/functional -type f | grep -v hash | xargs -r rm
script:
- cd ${TRAVIS_BUILD_DIR}/test
- bjam -q ${BJAM_TOOLSET} include=${BOOST_ROOT} include=${TRAVIS_BUILD_DIR}/include

9
doc/Jamfile.v2 Normal file
View File

@@ -0,0 +1,9 @@
# Copyright Daniel James 2005. Use, modification, and distribution are
# subject to 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)
using quickbook ;
xml hash : hash.qbk ;
boostbook standalone : hash ;

32
doc/changes.qbk Normal file
View File

@@ -0,0 +1,32 @@
[/ Copyright 2005-2006 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) ]
[section:changes Change Log]
[h2 Boost 1.33.0]
* Initial Release
[h2 Changes in Boost 1.33.1]
* Fixed the points example, as pointed out by 沈慧峰.
[h2 Changes in Boost 1.34.0]
* Use declarations for standard classes, so that the library
doesn't need to include all of their headers
* Deprecated the `<boost/functional/hash/*.hpp>` headers. Now a single header,
<[headerref boost/functional/hash.hpp]> is used.
* Add support for the `BOOST_HASH_NO_EXTENSIONS` macro, which
disables the extensions to TR1
* Minor improvements to the hash functions for floating point numbers.
[h2 Future Developments]
* A more portable hash function, as described by Daniel Krügler in
[@http://lists.boost.org/boost-users/2005/08/13418.php a post to the boost users list].
* Implement `hash_value` for more classes, including `std::complex`.
[endsect]

29
doc/disable.qbk Normal file
View File

@@ -0,0 +1,29 @@
[/ Copyright 2005-2006 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) ]
[section:disable Disabling The Extensions]
While [classref boost::hash]'s extensions are generally useful, you might want
to turn them of in order to check that your code will work with other
implementations of TR1. To do this define the macro `BOOST_HASH_NO_EXTENSIONS`.
When this macro is defined, only the specialisations detailed
in TR1 will be declared. But, if you later undefine the macro and include
<[headerref boost/functional/hash.hpp]> then the non-specialised form will be defined
- activating the extensions.
It is strongly recommended that you never undefine the macro - and only define
it so that it applies to the complete translation unit, either by defining it
at the beginning of the main source file or, preferably, by using a compiler
switch or preference. And you really should never define it in header files.
If you are writing a library which has code in the header which requires the
extensions, then the best action is to tell users not to define the macro.
Their code won't ['require] the macro.
Translation units that are compiled with the macro defined will link with units
that were compiled without it. This feature has been designed to avoid ODR
violations.
[endsect]

24
doc/hash.qbk Normal file
View File

@@ -0,0 +1,24 @@
[library Boost.Functional/Hash
[quickbook 1.3]
[authors [James, Daniel]]
[copyright 2005 2006 Daniel James]
[purpose A TR1 hash function object that can be extended to hash user
defined types]
[category higher-order]
[id hash]
[dirname hash]
[license
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:hash intro.qbk]
[include:hash tutorial.qbk]
[include:hash portability.qbk]
[include:hash disable.qbk]
[include:hash changes.qbk]
[xinclude ref.xml]
[include:hash links.qbk]
[include:hash thanks.qbk]

44
doc/intro.qbk Normal file
View File

@@ -0,0 +1,44 @@
[/ Copyright 2005-2006 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) ]
[section:intro Introduction]
[def __tr1-full__
[@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1836.pdf
Draft Technical Report on C++ Library Extensions]]
[def __tr1__
[@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1836.pdf
TR1]]
[def __multi-index__ [@../../libs/multi_index/doc/index.html
Boost Multi-Index Containers Library]]
[def __multi-index-short__ [@../../libs/multi_index/doc/index.html
Boost.MultiIndex]]
[def __issues__
[@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1837.pdf
Library Extension Technical Report Issues List]]
[def __hash-function__ [@http://en.wikipedia.org/wiki/Hash_function hash function]]
[def __hash-table__ [@http://en.wikipedia.org/wiki/Hash_table hash table]]
[classref boost::hash] is an implementation of the __hash-function__ object
specified by the __tr1-full__ (TR1). It is intended for use as the default hash function
for unordered associative containers, and the __multi-index__'s hash indexes.
As it is compliant with __tr1__, it will work with:
* integers
* floats
* pointers
* strings
It also implements the extension proposed by Peter Dimov in issue 6.18 of the
__issues__ (page 63), this adds support for:
* arrays
* `std::pair`
* the standard containers.
* extending [classref boost::hash] for custom types.
[endsect]

27
doc/links.qbk Normal file
View File

@@ -0,0 +1,27 @@
[/ Copyright 2005-2006 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) ]
[section:links Links]
[*A Proposal to Add Hash Tables to the Standard Library]\n
[@http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2003/n1456.html]\n
The hash table proposal explains much of the design. The hash function object
is discussed in Section D.
[*The C++ Standard Library Technical Report.]\n
[@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1836.pdf]\n
Contains the hash function specification in section 6.3.2.
[*Library Extension Technical Report Issues List.]\n
[@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1837.pdf]\n
The library implements the extension described in Issue 6.18, pages 63-67.
[*Methods for Identifying Versioned and Plagiarised Documents]\n
Timothy C. Hoad, Justin Zobel\n
[@http://www.cs.rmit.edu.au/~jz/fulltext/jasist-tch.pdf]\n
Contains the hash function that [funcref boost::hash_combine] is based on.
[endsect]

105
doc/portability.qbk Normal file
View File

@@ -0,0 +1,105 @@
[/ Copyright 2005-2006 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) ]
[section:portability Portability]
[def __boost_hash__ [classref boost::hash]]
__boost_hash__ is written to be as portable as possible, but unfortunately, several
older compilers don't support argument dependent lookup (ADL) - the mechanism
used for customisation. On those compilers custom overloads for `hash_value`
need to be declared in the boost namespace.
On a strictly standards compliant compiler, an overload defined in the
boost namespace won't be found when __boost_hash__ is instantiated,
so for these compilers the overload should only be declared in the same
namespace as the class.
Let's say we have a simple custom type:
namespace foo
{
template <class T>
class custom_type
{
T value;
public:
custom_type(T x) : value(x) {}
friend std::size_t hash_value(custom_type x)
{
__boost_hash__<int> hasher;
return hasher(x.value);
}
};
}
On a compliant compiler, when `hash_value` is called for this type,
it will look at the namespace inside the type and find `hash_value`
but on a compiler which doesn't support ADL `hash_value` won't be found.
To make things worse, some compilers which do support ADL won't find
a friend class defined inside the class.
So first move the member function out of the class:
namespace foo
{
template <class T>
class custom_type
{
T value;
public:
custom_type(T x) : value(x) {}
std::size_t hash(custom_type x)
{
__boost_hash__<T> hasher;
return hasher(value);
}
};
template <class T>
inline std::size_t hash_value(custom_type<T> x)
{
return x.hash();
}
}
Unfortunately, I couldn't declare hash_value as a friend, as some compilers
don't support template friends, so instead I declared a member function to
calculate the hash, and called it from hash_value.
For compilers which don't support ADL, hash_value needs to be defined in the
boost namespace:
#ifdef BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP
namespace boost
#else
namespace foo
#endif
{
template <class T>
std::size_t hash_value(foo::custom_type<T> x)
{
return x.hash();
}
}
Full code for this example is at
[@../../libs/functional/hash/examples/portable.cpp /libs/functional/hash/examples/portable.cpp].
[h2 Other Issues]
On Visual C++ versions 6.5 and 7.0, `hash_value` isn't overloaded for built in
arrays. __boost_hash__, [funcref boost::hash_combine] and [funcref boost::hash_range] all use a workaround to
support built in arrays so this shouldn't be a problem in most cases.
On Visual C++ versions 6.5 and 7.0, function pointers aren't currently supported.
When using GCC on Solaris, `boost::hash_value(long double)` treats
`long double`s as `double`s - so the hash function doesn't take into account the
full range of values.
[endsect]

699
doc/ref.xml Normal file
View File

@@ -0,0 +1,699 @@
<!--
Copyright 2005-2006 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)
-->
<library-reference>
<section id="hash.reference.specification">
<para>For the full specification, see section 6.3 of the
<ulink url="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1836.pdf">C++ Standard Library Technical Report</ulink>
and issue 6.18 of the
<ulink url="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1837.pdf">Library Extension Technical Report Issues List</ulink> (page 63).
</para>
</section>
<header name="boost/functional/hash.hpp">
<para>
Defines <code><classname>boost::hash</classname></code>,
and helper functions.
</para>
<namespace name="boost">
<!--
boost::hash
-->
<struct name="hash">
<template>
<template-type-parameter name="T"/>
</template>
<inherit access="public">
<classname>std::unary_function&lt;T, std::size_t&gt;</classname>
</inherit>
<purpose>A <ulink url="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1836.pdf">TR1</ulink> compliant hash function object.</purpose>
<method name="operator()" cv="const">
<type>std::size_t</type>
<parameter name="val">
<paramtype>T const&amp;</paramtype>
</parameter>
<returns><para>
<programlisting><functionname>hash_value</functionname>(val)</programlisting>
</para></returns>
<notes>
<para>
The call to <code><functionname>hash_value</functionname></code>
is unqualified, so that custom overloads can be
found via argument dependent lookup.
</para>
<para>
This is not defined when the macro <code>BOOST_HASH_NO_EXTENSIONS</code>
is defined. The specializations are still defined, so only the specializations
required by TR1 are defined.
</para>
</notes>
<throws><para>
Only throws if
<code><functionname>hash_value</functionname>(T)</code> throws.
</para></throws>
</method>
</struct>
<struct-specialization name="hash">
<template></template>
<specialization>
<template-arg>bool</template-arg>
</specialization>
<method name="operator()" cv="const">
<type>std::size_t</type>
<parameter name="val">
<paramtype>bool</paramtype>
</parameter>
<returns>
<para>Unspecified in TR1, except that equal arguments yield the same result.</para>
<para><functionname>hash_value</functionname>(val) in Boost.</para>
</returns>
<throws><para>Doesn't throw</para></throws>
</method>
</struct-specialization>
<struct-specialization name="hash">
<template></template>
<specialization>
<template-arg>char</template-arg>
</specialization>
<method name="operator()" cv="const">
<type>std::size_t</type>
<parameter name="val">
<paramtype>char</paramtype>
</parameter>
<returns>
<para>Unspecified in TR1, except that equal arguments yield the same result.</para>
<para><functionname>hash_value</functionname>(val) in Boost.</para>
</returns>
<throws><para>Doesn't throw</para></throws>
</method>
</struct-specialization>
<struct-specialization name="hash">
<template></template>
<specialization>
<template-arg>signed char</template-arg>
</specialization>
<method name="operator()" cv="const">
<type>std::size_t</type>
<parameter name="val">
<paramtype>signed char</paramtype>
</parameter>
<returns>
<para>Unspecified in TR1, except that equal arguments yield the same result.</para>
<para><functionname>hash_value</functionname>(val) in Boost.</para>
</returns>
<throws><para>Doesn't throw</para></throws>
</method>
</struct-specialization>
<struct-specialization name="hash">
<template></template>
<specialization>
<template-arg>unsigned char</template-arg>
</specialization>
<method name="operator()" cv="const">
<type>std::size_t</type>
<parameter name="val">
<paramtype>unsigned char</paramtype>
</parameter>
<returns>
<para>Unspecified in TR1, except that equal arguments yield the same result.</para>
<para><functionname>hash_value</functionname>(val) in Boost.</para>
</returns>
<throws><para>Doesn't throw</para></throws>
</method>
</struct-specialization>
<struct-specialization name="hash">
<template></template>
<specialization>
<template-arg>wchar_t</template-arg>
</specialization>
<method name="operator()" cv="const">
<type>std::size_t</type>
<parameter name="val">
<paramtype>wchar_t</paramtype>
</parameter>
<returns>
<para>Unspecified in TR1, except that equal arguments yield the same result.</para>
<para><functionname>hash_value</functionname>(val) in Boost.</para>
</returns>
<throws><para>Doesn't throw</para></throws>
</method>
</struct-specialization>
<struct-specialization name="hash">
<template></template>
<specialization>
<template-arg>short</template-arg>
</specialization>
<method name="operator()" cv="const">
<type>std::size_t</type>
<parameter name="val">
<paramtype>short</paramtype>
</parameter>
<returns>
<para>Unspecified in TR1, except that equal arguments yield the same result.</para>
<para><functionname>hash_value</functionname>(val) in Boost.</para>
</returns>
<throws><para>Doesn't throw</para></throws>
</method>
</struct-specialization>
<struct-specialization name="hash">
<template></template>
<specialization>
<template-arg>unsigned short</template-arg>
</specialization>
<method name="operator()" cv="const">
<type>std::size_t</type>
<parameter name="val">
<paramtype>unsigned short</paramtype>
</parameter>
<returns>
<para>Unspecified in TR1, except that equal arguments yield the same result.</para>
<para><functionname>hash_value</functionname>(val) in Boost.</para>
</returns>
<throws><para>Doesn't throw</para></throws>
</method>
</struct-specialization>
<struct-specialization name="hash">
<template></template>
<specialization>
<template-arg>int</template-arg>
</specialization>
<method name="operator()" cv="const">
<type>std::size_t</type>
<parameter name="val">
<paramtype>int</paramtype>
</parameter>
<returns>
<para>Unspecified in TR1, except that equal arguments yield the same result.</para>
<para><functionname>hash_value</functionname>(val) in Boost.</para>
</returns>
<throws><para>Doesn't throw</para></throws>
</method>
</struct-specialization>
<struct-specialization name="hash">
<template></template>
<specialization>
<template-arg>unsigned int</template-arg>
</specialization>
<method name="operator()" cv="const">
<type>std::size_t</type>
<parameter name="val">
<paramtype>unsigned int</paramtype>
</parameter>
<returns>
<para>Unspecified in TR1, except that equal arguments yield the same result.</para>
<para><functionname>hash_value</functionname>(val) in Boost.</para>
</returns>
<throws><para>Doesn't throw</para></throws>
</method>
</struct-specialization>
<struct-specialization name="hash">
<template></template>
<specialization>
<template-arg>long</template-arg>
</specialization>
<method name="operator()" cv="const">
<type>std::size_t</type>
<parameter name="val">
<paramtype>long</paramtype>
</parameter>
<returns>
<para>Unspecified in TR1, except that equal arguments yield the same result.</para>
<para><functionname>hash_value</functionname>(val) in Boost.</para>
</returns>
<throws><para>Doesn't throw</para></throws>
</method>
</struct-specialization>
<struct-specialization name="hash">
<template></template>
<specialization>
<template-arg>unsigned long</template-arg>
</specialization>
<method name="operator()" cv="const">
<type>std::size_t</type>
<parameter name="val">
<paramtype>unsigned long</paramtype>
</parameter>
<returns>
<para>Unspecified in TR1, except that equal arguments yield the same result.</para>
<para><functionname>hash_value</functionname>(val) in Boost.</para>
</returns>
<throws><para>Doesn't throw</para></throws>
</method>
</struct-specialization>
<struct-specialization name="hash">
<template></template>
<specialization>
<template-arg>float</template-arg>
</specialization>
<method name="operator()" cv="const">
<type>std::size_t</type>
<parameter name="val">
<paramtype>float</paramtype>
</parameter>
<returns>
<para>Unspecified in TR1, except that equal arguments yield the same result.</para>
<para><functionname>hash_value</functionname>(val) in Boost.</para>
</returns>
<throws><para>Doesn't throw</para></throws>
</method>
</struct-specialization>
<struct-specialization name="hash">
<template></template>
<specialization>
<template-arg>double</template-arg>
</specialization>
<method name="operator()" cv="const">
<type>std::size_t</type>
<parameter name="val">
<paramtype>double</paramtype>
</parameter>
<returns>
<para>Unspecified in TR1, except that equal arguments yield the same result.</para>
<para><functionname>hash_value</functionname>(val) in Boost.</para>
</returns>
<throws><para>Doesn't throw</para></throws>
</method>
</struct-specialization>
<struct-specialization name="hash">
<template></template>
<specialization>
<template-arg>long double</template-arg>
</specialization>
<method name="operator()" cv="const">
<type>std::size_t</type>
<parameter name="val">
<paramtype>long double</paramtype>
</parameter>
<returns>
<para>Unspecified in TR1, except that equal arguments yield the same result.</para>
<para><functionname>hash_value</functionname>(val) in Boost.</para>
</returns>
<throws><para>Doesn't throw</para></throws>
</method>
</struct-specialization>
<struct-specialization name="hash">
<template></template>
<specialization>
<template-arg>std::string</template-arg>
</specialization>
<method name="operator()" cv="const">
<type>std::size_t</type>
<parameter name="val">
<paramtype>std::string const&amp;</paramtype>
</parameter>
<returns>
<para>Unspecified in TR1, except that equal arguments yield the same result.</para>
<para><functionname>hash_value</functionname>(val) in Boost.</para>
</returns>
<throws><para>Doesn't throw</para></throws>
</method>
</struct-specialization>
<struct-specialization name="hash">
<template></template>
<specialization>
<template-arg>std::wstring</template-arg>
</specialization>
<method name="operator()" cv="const">
<type>std::size_t</type>
<parameter name="val">
<paramtype>std::wstring const&amp;</paramtype>
</parameter>
<returns>
<para>Unspecified in TR1, except that equal arguments yield the same result.</para>
<para><functionname>hash_value</functionname>(val) in Boost.</para>
</returns>
<throws><para>Doesn't throw</para></throws>
</method>
</struct-specialization>
<struct-specialization name="hash">
<template>
<template-type-parameter name="T"/>
</template>
<specialization>
<template-arg>T*</template-arg>
</specialization>
<method name="operator()" cv="const">
<type>std::size_t</type>
<parameter name="val">
<paramtype>T*</paramtype>
</parameter>
<returns>
<para>Unspecified in TR1, except that equal arguments yield the same result.</para>
</returns>
<throws><para>Doesn't throw</para></throws>
</method>
</struct-specialization>
<!--
boost::hash_combine
-->
<function name="hash_combine">
<template>
<template-type-parameter name="T"/>
</template>
<type>void</type>
<parameter name="seed"><paramtype>size_t &amp;</paramtype></parameter>
<parameter name="v"><paramtype>T const&amp;</paramtype></parameter>
<purpose>
Called repeatedly to incrementally create a hash value from
several variables.
</purpose>
<effects><programlisting>seed ^= <functionname>hash_value</functionname>(v) + 0x9e3779b9 + (seed &lt;&lt; 6) + (seed &gt;&gt; 2);</programlisting></effects>
<notes>
<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>
</notes>
<throws>
Only throws if <functionname>hash_value</functionname>(T) throws.
Strong exception safety, as long as <functionname>hash_value</functionname>(T)
also has strong exception safety.
</throws>
</function>
<!--
boost::hash_range
-->
<overloaded-function name="hash_range">
<signature>
<template>
<template-type-parameter name="It"/>
</template>
<type>std::size_t</type>
<parameter name="first"><paramtype>It</paramtype></parameter>
<parameter name="last"><paramtype>It</paramtype></parameter>
</signature>
<signature>
<template>
<template-type-parameter name="It"/>
</template>
<type>void</type>
<parameter name="seed"><paramtype>std::size_t&amp;</paramtype></parameter>
<parameter name="first"><paramtype>It</paramtype></parameter>
<parameter name="last"><paramtype>It</paramtype></parameter>
</signature>
<purpose>
Calculate the combined hash value of the elements of an iterator
range.
</purpose>
<effects>
<para>For the two argument overload:
<programlisting>
size_t seed = 0;
for(; first != last; ++first)
{
<functionname>hash_combine</functionname>(seed, *first);
}
return seed;
</programlisting>
</para>For the three arguments overload:
<programlisting>
for(; first != last; ++first)
{
<functionname>hash_combine</functionname>(seed, *first);
}
</programlisting>
<para>
</para>
</effects>
<notes>
<para>
<code>hash_range</code> is sensitive to the order of the elements
so it wouldn't be appropriate to use this with an unordered
container.
</para>
<para>This is an extension to TR1</para>
</notes>
<throws><para>
Only throws if <code><functionname>hash_value</functionname>(std::iterator_traits&lt;It&gt;::value_type)</code>
throws. <code>hash_range(std::size_t&amp;, It, It)</code> has basic exception safety as long as
<code><functionname>hash_value</functionname>(std::iterator_traits&lt;It&gt;::value_type)</code>
has basic exception safety.
</para></throws>
</overloaded-function>
<!--
boost::hash_value - integers
-->
<overloaded-function name="hash_value">
<purpose>
Implementation of the hash function.
</purpose>
<signature>
<type>std::size_t</type>
<parameter name="val"><paramtype>int</paramtype></parameter>
</signature>
<signature>
<type>std::size_t</type>
<parameter name="val"><paramtype>unsigned int</paramtype></parameter>
</signature>
<signature>
<type>std::size_t</type>
<parameter name="val"><paramtype>long</paramtype></parameter>
</signature>
<signature>
<type>std::size_t</type>
<parameter name="val"><paramtype>unsigned long</paramtype></parameter>
</signature>
<signature>
<type>std::size_t</type>
<parameter name="val"><paramtype>float</paramtype></parameter>
</signature>
<signature>
<type>std::size_t</type>
<parameter name="val"><paramtype>double</paramtype></parameter>
</signature>
<signature>
<type>std::size_t</type>
<parameter name="val"><paramtype>long double</paramtype></parameter>
</signature>
<signature>
<template><template-type-parameter name="T"/></template>
<type>std::size_t</type>
<parameter name="val"><paramtype>T* const&amp;</paramtype></parameter>
</signature>
<signature>
<template>
<template-type-parameter name="T"/>
<template-nontype-parameter name="N"><type>unsigned</type></template-nontype-parameter>
</template>
<type>std::size_t</type>
<parameter><paramtype>T (&amp;val)[N]</paramtype></parameter>
</signature>
<signature>
<template>
<template-type-parameter name="T"/>
<template-nontype-parameter name="N"><type>unsigned</type></template-nontype-parameter>
</template>
<type>std::size_t</type>
<parameter><paramtype>const T (&amp;val)[N]</paramtype></parameter>
</signature>
<signature>
<template>
<template-type-parameter name="Ch"/>
<template-type-parameter name="A"/>
</template>
<type>std::size_t</type>
<parameter name="val">
<paramtype>std::basic_string&lt;Ch, std::char_traits&lt;Ch&gt;, A&gt; const&amp;</paramtype>
</parameter>
</signature>
<signature>
<template>
<template-type-parameter name="A"/>
<template-type-parameter name="B"/>
</template>
<type>std::size_t</type>
<parameter name="val"><paramtype>std::pair&lt;A, B&gt; const&amp;</paramtype></parameter>
</signature>
<signature>
<template>
<template-type-parameter name="T"/>
<template-type-parameter name="A"/>
</template>
<type>std::size_t</type>
<parameter name="val"><paramtype>std::vector&lt;T, A&gt; const&amp;</paramtype></parameter>
</signature>
<signature>
<template>
<template-type-parameter name="T"/>
<template-type-parameter name="A"/>
</template>
<type>std::size_t</type>
<parameter name="val"><paramtype>std::list&lt;T, A&gt; const&amp;</paramtype></parameter>
</signature>
<signature>
<template>
<template-type-parameter name="T"/>
<template-type-parameter name="A"/>
</template>
<type>std::size_t</type>
<parameter name="val"><paramtype>std::deque&lt;T, A&gt; const&amp;</paramtype></parameter>
</signature>
<signature>
<template>
<template-type-parameter name="K"/>
<template-type-parameter name="C"/>
<template-type-parameter name="A"/>
</template>
<type>std::size_t</type>
<parameter name="val"><paramtype>std::set&lt;K, C, A&gt; const&amp;</paramtype></parameter>
</signature>
<signature>
<template>
<template-type-parameter name="K"/>
<template-type-parameter name="C"/>
<template-type-parameter name="A"/>
</template>
<type>std::size_t</type>
<parameter name="val"><paramtype>std::multiset&lt;K, C, A&gt; const&amp;</paramtype></parameter>
</signature>
<signature>
<template>
<template-type-parameter name="K"/>
<template-type-parameter name="T"/>
<template-type-parameter name="C"/>
<template-type-parameter name="A"/>
</template>
<type>std::size_t</type>
<parameter name="val"><paramtype>std::map&lt;K, T, C, A&gt; const&amp;</paramtype></parameter>
</signature>
<signature>
<template>
<template-type-parameter name="K"/>
<template-type-parameter name="T"/>
<template-type-parameter name="C"/>
<template-type-parameter name="A"/>
</template>
<type>std::size_t</type>
<parameter name="val"><paramtype>std::multimap&lt;K, T, C, A&gt; const&amp;</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>
or <functionname>boost::hash_combine</functionname> which
call <code>hash_value</code> without namespace qualification so that overloads
for custom types are found via ADL.
</para></description>
<notes>
<para>This is an extension to TR1</para>
</notes>
<throws>
Only throws if a user supplied version of
<code><functionname>hash_value</functionname></code>
throws for an element of a container, or
one of the types stored in a pair.
</throws>
<returns>
<informaltable>
<tgroup cols="2">
<thead>
<row>
<entry>Types</entry>
<entry>Returns</entry>
</row>
</thead>
<tbody>
<row>
<entry><code>int</code>, <code>unsigned int</code>, <code>long</code>, <code>unsigned long</code></entry>
<entry><code>val</code></entry>
</row>
<row>
<entry><code>float</code>, <code>double</code>, <code>long double</code></entry>
<entry>An unspecified value, except that equal arguments shall yield the same result.</entry>
</row>
<row>
<entry><code>T*</code></entry>
<entry>An unspecified value, except that equal arguments shall yield the same result.</entry>
</row>
<row>
<entry>
<code>T&#160;val[N]</code>,
<code>const&#160;T&#160;val[N]</code>
</entry>
<entry><code>hash_range(val, val+N)</code></entry>
</row>
<row>
<entry>
<code>std:basic_string&lt;Ch,&#160;std::char_traits&lt;Ch&gt;,&#160;A&gt;</code>,
<code>std::vector&lt;T,&#160;A&gt;</code>,
<code>std::list&lt;T,&#160;A&gt;</code>,
<code>std::deque&lt;T,&#160;A&gt;</code>,
<code>std::set&lt;K,&#160;C,&#160;A&gt;</code>,
<code>std::multiset&lt;K,&#160;C,&#160;A&gt;</code>,
<code>std::map&lt;K,&#160;T,&#160;C,&#160;A&gt;</code>,
<code>std::multimap&lt;K,&#160;T,&#160;C,&#160;A&gt;</code>
</entry>
<entry><code>hash_range(val.begin(), val.end())</code></entry>
</row>
<row>
<entry><code>std::pair&lt;A, B&gt;</code></entry>
<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>
</tbody>
</tgroup>
</informaltable>
</returns>
</overloaded-function>
</namespace>
</header>
</library-reference>

29
doc/thanks.qbk Normal file
View File

@@ -0,0 +1,29 @@
[/ Copyright 2005-2006 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) ]
[section:acknowledgements Acknowledgements]
This library is based on the design by Peter Dimov's original design.
During the initial development Joaquín M López Muñoz made many useful
suggestions, contributed fixes.
The formal review was managed by Thorsten Ottosen, and the library reviewed by:
David Abrahams, Alberto Barbati, Topher Cooper, Caleb Epstein, Dave Harris,
Chris Jefferson, Bronek Kozicki, John Maddock, Tobias Swinger, Jaap Suter, Rob
Stewart and Pavel Vozenilek. Since then, there have been further contributions
from Daniel Krügler, Alexander Nasonov, 沈慧峰 and John Maddock.
The implementation of the hash function for pointers is based on suggestions
made by Alberto Barbati and Dave Harris. Dave Harris also suggested an
important improvement to [funcref boost::hash_combine] that was taken up.
Some useful improvements to the floating point hash algorithm were suggested
by Daniel Krügler.
The original implementation came from Jeremy B. Maitin-Shepard's hash table
library, although this is a complete rewrite.
[endsect]

202
doc/tutorial.qbk Normal file
View File

@@ -0,0 +1,202 @@
[/ Copyright 2005-2006 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) ]
[def __multi-index-short__ [@../../libs/multi_index/doc/index.html
Boost.MultiIndex]]
[section:tutorial Tutorial]
When using a hash index with __multi-index-short__, you don't need to do
anything to use [classref boost::hash] as it uses it by default.
To find out how to use a user-defined type, read the
[link hash.custom section on extending boost::hash for a custom data type].
If your standard library supplies its own implementation of the unordered
associative containers and you wish to use
[classref boost::hash], just use an extra template parameter:
std::unordered_multiset<int, ``[classref boost::hash]``<int> >
set_of_ints;
std::unordered_set<std::pair<int, int>, ``[classref boost::hash]``<std::pair<int, int> >
set_of_pairs;
std::unordered_map<int, std::string, ``[classref boost::hash]``<int> > map_int_to_string;
To use [classref boost::hash] directly, create an instance and call it as a function:
#include <``[headerref boost/functional/hash.hpp]``>
int main()
{
``[classref boost::hash]``<std::string> string_hash;
std::size_t h = string_hash("Hash me");
}
For an example of generic use, here is a function to generate a vector
containing the hashes of the elements of a container:
template <class Container>
std::vector<std::size_t> get_hashes(Container const& x)
{
std::vector<std::size_t> hashes;
std::transform(x.begin(), x.end(), std::insert_iterator(hashes),
``[classref boost::hash]``<typename Container::value_type>());
return hashes;
}
[endsect]
[section:custom Extending boost::hash for a custom data type]
[classref boost::hash] is implemented by calling the function
[funcref boost::hash_value hash_value].
The namespace isn't specified so that it can detect overloads via argument
dependant lookup. So if there is a free function `hash_value` in the same
namespace as a custom type, it will get called.
If you have a structure `library::book`, where each `book` is uniquely
defined by it's member `id`:
namespace library
{
struct book
{
int id;
std::string author;
std::string title;
// ....
};
bool operator==(book const& a, book const& b)
{
return a.id == b.id;
}
}
Then all you would need to do is write the function `library::hash_value`:
namespace library
{
std::size_t hash_value(book const& b)
{
``[classref boost::hash]``<int> hasher;
return hasher(b.id);
}
}
And you can now use [classref boost::hash] with book:
library::book knife(3458, "Zane Grey", "The Hash Knife Outfit");
library::book dandelion(1354, "Paul J. Shanley",
"Hash & Dandelion Greens");
``[classref boost::hash]``<library::book> book_hasher;
std::size_t knife_hash_value = book_hasher(knife);
// If std::unordered_set is available:
std::unordered_set<library::book, ``[classref boost::hash]``<library::book> > books;
books.insert(knife);
books.insert(library::book(2443, "Lindgren, Torgny", "Hash"));
books.insert(library::book(1953, "Snyder, Bernadette M.",
"Heavenly Hash: A Tasty Mix of a Mother's Meditations"));
assert(books.find(knife) != books.end());
assert(books.find(dandelion) == books.end());
The full example can be found in:
[@../../libs/functional/hash/examples/books.cpp /libs/functional/hash/examples/books.hpp]
and
[@../../libs/functional/hash/examples/books.cpp /libs/functional/hash/examples/books.cpp].
[tip
When writing a hash function, first look at how the equality function works.
Objects that are equal must generate the same hash value.
When objects are not equal they should generate different hash values.
In this object equality was based just on the id so the hash function
only hash the id. If it was based on the objects name and author
then the hash function should take them into account
(how to do this is discussed in the next section).
]
[endsect]
[section:combine Combining hash values]
Say you have a point class, representing a two dimensional location:
class point
{
int x;
int y;
public:
point() : x(0), y(0) {}
point(int x, int y) : x(x), y(y) {}
bool operator==(point const& other) const
{
return x == other.x && y == other.y;
}
};
and you wish to use it as the key for an `unordered_map`. You need to
customise the hash for this structure. To do this we need to combine
the hash values for `x` and `y`. The function
[funcref boost::hash_combine] is supplied for this purpose:
class point
{
...
friend std::size_t hash_value(point const& p)
{
std::size_t seed = 0;
``[funcref boost::hash_combine]``(seed, p.x);
``[funcref boost::hash_combine]``(seed, p.y);
return seed;
}
...
};
Calls to hash_combine incrementally build the hash from the different members
of point, it can be repeatedly called for any number of elements. It calls
[funcref boost::hash_value hash_value] on the supplied element, and combines it with the seed.
Full code for this example is at
[@../../libs/functional/hash/examples/point.cpp /libs/functional/hash/examples/point.cpp].
[note
When using [funcref boost::hash_combine] the order of the
calls matters.
'''
<programlisting>
std::size_t seed = 0;
boost::hash_combine(seed, 1);
boost::hash_combine(seed, 2);
</programlisting>
results in a different seed to:
<programlisting>
std::size_t seed = 0;
boost::hash_combine(seed, 2);
boost::hash_combine(seed, 1);
</programlisting>
'''
If you are calculating a hash value for data where the order of the data
doesn't matter in comparisons (e.g. a set) you will have to ensure that the
data is always supplied in the same order.
]
To calculate the hash of an iterator range you can use [funcref boost::hash_range]:
std::vector<std::string> some_strings;
std::size_t hash = ``[funcref boost::hash_range]``(some_strings.begin(), some_strings.end());
[endsect]

8
examples/Jamfile.v2 Normal file
View File

@@ -0,0 +1,8 @@
# Copyright Daniel James 2005. Use, modification, and distribution are
# subject to 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)
run books.cpp ;
run point.cpp ;
run portable.cpp ;

50
examples/books.cpp Normal file
View File

@@ -0,0 +1,50 @@
// Copyright Daniel James 2005-2006. Use, modification, and distribution are
// subject to 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 "./books.hpp"
#include <boost/functional/hash.hpp>
#include <cassert>
// If std::unordered_set was available:
//#include <unordered_set>
// This example illustrates how to use boost::hash with a custom hash function.
// For full details, see the tutorial.
int main()
{
library::book knife(3458, "Zane Grey", "The Hash Knife Outfit");
library::book dandelion(1354, "Paul J. Shanley", "Hash & Dandelion Greens");
boost::hash<library::book> book_hasher;
std::size_t knife_hash_value = book_hasher(knife);
// If std::unordered_set was available:
//
//std::unordered_set<library::book, boost::hash<library::book> > books;
//books.insert(knife);
//books.insert(library::book(2443, "Lindgren, Torgny", "Hash"));
//books.insert(library::book(1953, "Snyder, Bernadette M.",
// "Heavenly Hash: A Tasty Mix of a Mother's Meditations"));
//assert(books.find(knife) != books.end());
//assert(books.find(dandelion) == books.end());
return 0;
}
namespace library
{
bool operator==(book const& a, book const& b)
{
return a.id == b.id;
}
std::size_t hash_value(book const& b)
{
boost::hash<int> hasher;
return hasher(b.id);
}
}

26
examples/books.hpp Normal file
View File

@@ -0,0 +1,26 @@
// Copyright Daniel James 2005-2006. Use, modification, and distribution are
// subject to 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 example illustrates how to use boost::hash with a custom hash function.
// The implementation is contained in books.cpp
#include <cstddef>
#include <string>
namespace library
{
struct book
{
int id;
std::string author;
std::string title;
book(int i, std::string const& a, std::string const& t)
: id(i), author(a), title(t) {}
};
bool operator==(book const&, book const&);
std::size_t hash_value(book const&);
}

54
examples/point.cpp Normal file
View File

@@ -0,0 +1,54 @@
// Copyright Daniel James 2005. Use, modification, and distribution are
// subject to 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/hash.hpp>
#include <cassert>
// This example illustrates how to use boost::hash_combine to generate a hash
// value from the different members of a class. For full details see the hash
// tutorial.
class point
{
int x;
int y;
public:
point() : x(0), y(0) {}
point(int x, int y) : x(x), y(y) {}
bool operator==(point const& other) const
{
return x == other.x && y == other.y;
}
friend std::size_t hash_value(point const& p)
{
std::size_t seed = 0;
boost::hash_combine(seed, p.x);
boost::hash_combine(seed, p.y);
return seed;
}
};
int main()
{
boost::hash<point> point_hasher;
point p1(0, 0);
point p2(1, 2);
point p3(4, 1);
point p4 = p1;
assert(point_hasher(p1) == point_hasher(p4));
// These tests could legally fail, but if they did it'd be a pretty bad
// hash function.
assert(point_hasher(p1) != point_hasher(p2));
assert(point_hasher(p1) != point_hasher(p3));
return 0;
}

54
examples/portable.cpp Normal file
View File

@@ -0,0 +1,54 @@
// Copyright Daniel James 2005-2006. Use, modification, and distribution are
// subject to 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/hash.hpp>
#include <cassert>
// This example illustrates how to customise boost::hash portably, so that
// it'll work on both compilers that don't implement argument dependent lookup
// and compilers that implement strict two-phase template instantiation.
namespace foo
{
template <class T>
class custom_type
{
T value;
public:
custom_type(T x) : value(x) {}
std::size_t hash() const
{
boost::hash<T> hasher;
return hasher(value);
}
};
}
#ifdef BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP
namespace boost
#else
namespace foo
#endif
{
template <class T>
std::size_t hash_value(foo::custom_type<T> x)
{
return x.hash();
}
}
int main()
{
foo::custom_type<int> x(1), y(2), z(1);
boost::hash<foo::custom_type<int> > hasher;
assert(hasher(x) == hasher(x));
assert(hasher(x) != hasher(y));
assert(hasher(x) == hasher(z));
return 0;
}

View File

@@ -0,0 +1,95 @@
// Copyright Daniel James 2005-2006. Use, modification, and distribution are
// subject to 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_HPP)
#define BOOST_DETAIL_CONTAINER_FWD_HPP
#include <boost/config.hpp>
#include <boost/detail/workaround.hpp>
#if BOOST_WORKAROUND(__GNUC__, < 3) && !defined(__SGI_STL_PORT) && !defined(_STLPORT_VERSION)
#define BOOST_HASH_CHAR_TRAITS string_char_traits
#else
#define BOOST_HASH_CHAR_TRAITS char_traits
#endif
#if (defined(__GLIBCXX__) && defined(_GLIBCXX_DEBUG)) \
|| BOOST_WORKAROUND(__BORLANDC__, > 0x551) \
|| BOOST_WORKAROUND(__DMC__, BOOST_TESTED_AT(0x842)) \
|| (defined(__SGI_STL_PORT) || defined(_STLPORT_VERSION))
#include <deque>
#include <list>
#include <vector>
#include <map>
#include <set>
#include <bitset>
#include <string>
#include <complex>
#else
#include <cstddef>
#if !defined(__SGI_STL_PORT) && !defined(_STLPORT_VERSION) && \
defined(__STL_CONFIG_H)
#define BOOST_CONTAINER_FWD_BAD_BITSET
#if !defined(__STL_NON_TYPE_TMPL_PARAM_BUG)
#define BOOST_CONTAINER_FWD_BAD_DEQUE
#endif
#endif
#if defined(BOOST_CONTAINER_FWD_BAD_DEQUE)
#include <deque>
#endif
#if defined(BOOST_CONTAINER_FWD_BAD_BITSET)
#include <bitset>
#endif
#if defined(BOOST_MSVC)
#pragma warning(push)
#pragma warning(disable:4099) // struct/class mismatch in fwd declarations
#endif
namespace std
{
template <class T> class allocator;
template <class charT, class traits, class Allocator> class basic_string;
template <class charT> struct BOOST_HASH_CHAR_TRAITS;
template <class T> class complex;
}
// gcc 3.4 and greater
namespace std
{
#if !defined(BOOST_CONTAINER_FWD_BAD_DEQUE)
template <class T, class Allocator> class deque;
#endif
template <class T, class Allocator> class list;
template <class T, class Allocator> class vector;
template <class Key, class T, class Compare, class Allocator> class map;
template <class Key, class T, class Compare, class Allocator>
class multimap;
template <class Key, class Compare, class Allocator> class set;
template <class Key, class Compare, class Allocator> class multiset;
#if !defined(BOOST_CONTAINER_FWD_BAD_BITSET)
template <size_t N> class bitset;
#endif
template <class T1, class T2> struct pair;
}
#if defined(BOOST_MSVC)
#pragma warning(pop)
#endif
#endif
#endif

View File

@@ -0,0 +1,154 @@
// Copyright Daniel James 2005-2006. Use, modification, and distribution are
// subject to 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_FUNCTIONAL_DETAIL_FLOAT_FUNCTIONS_HPP)
#define BOOST_FUNCTIONAL_DETAIL_FLOAT_FUNCTIONS_HPP
#include <cmath>
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
// The C++ standard requires that the C float functions are overloarded
// for float, double and long double in the std namespace, but some of the older
// library implementations don't support this. On some that don't, the C99
// float functions (frexpf, frexpl, etc.) are available.
//
// Some of this is based on guess work. If I don't know any better I assume that
// the standard C++ overloaded functions are available. If they're not then this
// means that the argument is cast to a double and back, which is inefficient
// and will give pretty bad results for long doubles - so if you know better
// let me know.
// STLport:
#if defined(__SGI_STL_PORT) || defined(_STLPORT_VERSION)
# if (defined(__GNUC__) && __GNUC__ < 3 && (defined(linux) || defined(__linux) || defined(__linux__))) || defined(__DMC__)
# define BOOST_HASH_USE_C99_FLOAT_FUNCS
# elif defined(BOOST_MSVC) && BOOST_MSVC < 1300
# define BOOST_HASH_USE_C99_FLOAT_FUNCS
# else
# define BOOST_HASH_USE_OVERLOAD_FLOAT_FUNCS
# endif
// Roguewave:
//
// On borland 5.51, with roguewave 2.1.1 the standard C++ overloads aren't
// defined, but for the same version of roguewave on sunpro they are.
#elif defined(_RWSTD_VER)
# if defined(__BORLANDC__)
# define BOOST_HASH_USE_C99_FLOAT_FUNCS
# define BOOST_HASH_C99_NO_FLOAT_FUNCS
# elif defined(__DECCXX)
# define BOOST_HASH_USE_C99_FLOAT_FUNCS
# else
# define BOOST_HASH_USE_OVERLOAD_FLOAT_FUNCS
# endif
// libstdc++ (gcc 3.0 onwards, I think)
#elif defined(__GLIBCPP__) || defined(__GLIBCXX__)
# define BOOST_HASH_USE_OVERLOAD_FLOAT_FUNCS
// SGI:
#elif defined(__STL_CONFIG_H)
# if defined(linux) || defined(__linux) || defined(__linux__)
# define BOOST_HASH_USE_C99_FLOAT_FUNCS
# else
# define BOOST_HASH_USE_OVERLOAD_FLOAT_FUNCS
# endif
// Dinkumware.
#elif (defined(_YVALS) && !defined(__IBMCPP__)) || defined(_CPPLIB_VER)
// Overloaded float functions were probably introduced in an earlier version
// than this.
# if defined(_CPPLIB_VER) && (_CPPLIB_VER >= 402)
# define BOOST_HASH_USE_OVERLOAD_FLOAT_FUNCS
# else
# define BOOST_HASH_USE_C99_FLOAT_FUNCS
# endif
// Digital Mars
#elif defined(__DMC__)
# define BOOST_HASH_USE_C99_FLOAT_FUNCS
// Use overloaded float functions by default.
#else
# define BOOST_HASH_USE_OVERLOAD_FLOAT_FUNCS
#endif
namespace boost
{
namespace hash_detail
{
inline float call_ldexp(float v, int exp)
{
using namespace std;
#if defined(BOOST_HASH_USE_OVERLOAD_FLOAT_FUNCS) || \
defined(BOOST_HASH_C99_NO_FLOAT_FUNCS)
return ldexp(v, exp);
#else
return ldexpf(v, exp);
#endif
}
inline double call_ldexp(double v, int exp)
{
using namespace std;
return ldexp(v, exp);
}
inline long double call_ldexp(long double v, int exp)
{
using namespace std;
#if defined(BOOST_HASH_USE_OVERLOAD_FLOAT_FUNCS)
return ldexp(v, exp);
#else
return ldexpl(v, exp);
#endif
}
inline float call_frexp(float v, int* exp)
{
using namespace std;
#if defined(BOOST_HASH_USE_OVERLOAD_FLOAT_FUNCS) || \
defined(BOOST_HASH_C99_NO_FLOAT_FUNCS)
return frexp(v, exp);
#else
return frexpf(v, exp);
#endif
}
inline double call_frexp(double v, int* exp)
{
using namespace std;
return frexp(v, exp);
}
inline long double call_frexp(long double v, int* exp)
{
using namespace std;
#if defined(BOOST_HASH_USE_OVERLOAD_FLOAT_FUNCS)
return frexp(v, exp);
#else
return frexpl(v, exp);
#endif
}
}
}
#if defined(BOOST_HASH_USE_C99_FLOAT_FUNCS)
#undef BOOST_HASH_USE_C99_FLOAT_FUNCS
#endif
#if defined(BOOST_HASH_USE_OVERLOAD_FLOAT_FUNCS)
#undef BOOST_HASH_USE_OVERLOAD_FLOAT_FUNCS
#endif
#if defined(BOOST_HASH_C99_NO_FLOAT_FUNCS)
#undef BOOST_HASH_C99_NO_FLOAT_FUNCS
#endif
#endif

View File

@@ -0,0 +1,123 @@
// Copyright Daniel James 2005-2006. Use, modification, and distribution are
// subject to 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)
// Based on Peter Dimov's proposal
// http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2005/n1756.pdf
// issue 6.18.
#if !defined(BOOST_FUNCTIONAL_DETAIL_HASH_FLOAT_HEADER)
#define BOOST_FUNCTIONAL_DETAIL_HASH_FLOAT_HEADER
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <boost/functional/detail/float_functions.hpp>
#include <boost/limits.hpp>
#include <boost/assert.hpp>
#include <errno.h>
// Don't use fpclassify or _fpclass for stlport.
#if !defined(__SGI_STL_PORT) && !defined(_STLPORT_VERSION)
# if defined(__GLIBCPP__) || defined(__GLIBCXX__)
// GNU libstdc++ 3
# if (defined(__USE_ISOC99) || defined(_GLIBCXX_USE_C99_MATH)) && \
!(defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__))
# define BOOST_HASH_USE_FPCLASSIFY
# endif
# elif (defined(_YVALS) && !defined(__IBMCPP__)) || defined(_CPPLIB_VER)
// Dinkumware Library, on Visual C++
# if defined(BOOST_MSVC)
# define BOOST_HASH_USE_FPCLASS
# endif
# 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 <class T>
inline std::size_t float_hash_impl(T v)
{
int exp = 0;
errno = 0;
v = boost::hash_detail::call_frexp(v, &exp);
if(errno) return 0;
std::size_t seed = 0;
std::size_t const length
= (std::numeric_limits<T>::digits +
std::numeric_limits<int>::digits - 1)
/ std::numeric_limits<int>::digits;
for(std::size_t i = 0; i < length; ++i)
{
v = boost::hash_detail::call_ldexp(v, std::numeric_limits<int>::digits);
int const part = static_cast<int>(v);
v -= part;
hash_float_combine(seed, part);
}
hash_float_combine(seed, exp);
return seed;
}
template <class T>
inline std::size_t float_hash_value(T v)
{
#if defined(BOOST_HASH_USE_FPCLASSIFY)
using namespace std;
switch (fpclassify(v)) {
case FP_ZERO:
return 0;
case FP_INFINITE:
return (std::size_t)(v > 0 ? -1 : -2);
case FP_NAN:
return (std::size_t)(-3);
case FP_NORMAL:
case FP_SUBNORMAL:
return float_hash_impl(v);
default:
BOOST_ASSERT(0);
return 0;
}
#elif defined(BOOST_HASH_USE_FPCLASS)
switch(_fpclass(v)) {
case _FPCLASS_NZ:
case _FPCLASS_PZ:
return 0;
case _FPCLASS_PINF:
return (std::size_t)(-1);
case _FPCLASS_NINF:
return (std::size_t)(-2);
case _FPCLASS_SNAN:
case _FPCLASS_QNAN:
return (std::size_t)(-3);
case _FPCLASS_NN:
case _FPCLASS_ND:
return float_hash_impl(v);
case _FPCLASS_PD:
case _FPCLASS_PN:
return float_hash_impl(v);
default:
BOOST_ASSERT(0);
return 0;
}
#else
return float_hash_impl(v);
#endif
}
}
}
#endif

View File

@@ -0,0 +1,10 @@
// Copyright Daniel James 2005-2006. Use, modification, and distribution are
// subject to 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)
// Based on Peter Dimov's proposal
// http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2005/n1756.pdf
// issue 6.18.
#include <boost/functional/hash/hash.hpp>

View File

@@ -0,0 +1,592 @@
// Copyright Daniel James 2005-2006. Use, modification, and distribution are
// subject to 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)
// Based on Peter Dimov's proposal
// http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2005/n1756.pdf
// issue 6.18.
#if !defined(BOOST_FUNCTIONAL_HASH_HASH_HPP)
#define BOOST_FUNCTIONAL_HASH_HASH_HPP
#include <boost/functional/hash_fwd.hpp>
#include <functional>
#include <boost/functional/detail/hash_float.hpp>
#include <boost/functional/detail/container_fwd.hpp>
#include <string>
#if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
#include <boost/type_traits/is_pointer.hpp>
#endif
#if defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
#include <boost/type_traits/is_array.hpp>
#endif
#if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
#include <boost/type_traits/is_const.hpp>
#endif
namespace boost
{
#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551))
// Borland complains about an ambiguous function overload
// when compiling boost::hash<bool>.
std::size_t hash_value(bool);
#endif
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);
#if defined(BOOST_MSVC) && defined(_WIN64)
// On 64-bit windows std::size_t is a typedef for unsigned long long, which
// isn't due to be supported until Boost 1.35. So add support here.
// (Technically, Boost.Hash isn't actually documented as supporting
// std::size_t. But it would be pretty silly not to).
std::size_t hash_value(std::size_t);
#endif
#if !BOOST_WORKAROUND(__DMC__, <= 0x848)
template <class T> std::size_t hash_value(T* const&);
#else
template <class T> std::size_t hash_value(T*);
#endif
#if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
template< class T, unsigned N >
std::size_t hash_value(const T (&array)[N]);
template< class T, unsigned N >
std::size_t hash_value(T (&array)[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 <class Ch, class A>
std::size_t hash_value(std::basic_string<Ch, std::BOOST_HASH_CHAR_TRAITS<Ch>, A> const&);
template <class A, class B>
std::size_t hash_value(std::pair<A, B> const&);
template <class T, class A>
std::size_t hash_value(std::vector<T, A> const&);
template <class T, class A>
std::size_t hash_value(std::list<T, A> const& v);
template <class T, class A>
std::size_t hash_value(std::deque<T, A> const& v);
template <class K, class C, class A>
std::size_t hash_value(std::set<K, C, A> const& v);
template <class K, class C, class A>
std::size_t hash_value(std::multiset<K, C, A> const& v);
template <class K, class T, class C, class A>
std::size_t hash_value(std::map<K, T, C, A> const& v);
template <class K, class T, class C, class A>
std::size_t hash_value(std::multimap<K, T, C, A> const& v);
// Implementation
#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551))
inline std::size_t hash_value(bool v)
{
return static_cast<std::size_t>(v);
}
#endif
inline std::size_t hash_value(int v)
{
return static_cast<std::size_t>(v);
}
inline std::size_t hash_value(unsigned int v)
{
return static_cast<std::size_t>(v);
}
inline std::size_t hash_value(long v)
{
return static_cast<std::size_t>(v);
}
inline std::size_t hash_value(unsigned long v)
{
return static_cast<std::size_t>(v);
}
#if defined(_M_X64) && defined(_WIN64)
inline std::size_t hash_value(long long v)
{
return v;
}
inline std::size_t hash_value(unsigned long long v)
{
return v;
}
#endif
// Implementation by Alberto Barbati and Dave Harris.
#if !BOOST_WORKAROUND(__DMC__, <= 0x848)
template <class T> std::size_t hash_value(T* const& v)
#else
template <class T> std::size_t hash_value(T* v)
#endif
{
std::size_t x = static_cast<std::size_t>(
reinterpret_cast<std::ptrdiff_t>(v));
return x + (x >> 3);
}
#if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
template <class T>
inline void hash_combine(std::size_t& seed, T& v)
#else
template <class T>
inline void hash_combine(std::size_t& seed, T const& v)
#endif
{
boost::hash<T> hasher;
seed ^= hasher(v) + 0x9e3779b9 + (seed<<6) + (seed>>2);
}
template <class It>
inline std::size_t hash_range(It first, It last)
{
std::size_t seed = 0;
for(; first != last; ++first)
{
hash_combine(seed, *first);
}
return seed;
}
template <class It>
inline void hash_range(std::size_t& seed, It first, It last)
{
for(; first != last; ++first)
{
hash_combine(seed, *first);
}
}
#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551))
template <class T>
inline std::size_t hash_range(T* first, T* last)
{
std::size_t seed = 0;
for(; first != last; ++first)
{
boost::hash<T> hasher;
seed ^= hasher(*first) + 0x9e3779b9 + (seed<<6) + (seed>>2);
}
return seed;
}
template <class T>
inline void hash_range(std::size_t& seed, T* first, T* last)
{
for(; first != last; ++first)
{
boost::hash<T> hasher;
seed ^= hasher(*first) + 0x9e3779b9 + (seed<<6) + (seed>>2);
}
}
#endif
#if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
template< class T, unsigned N >
inline std::size_t hash_value(const T (&array)[N])
{
return hash_range(array, array + N);
}
template< class T, unsigned N >
inline std::size_t hash_value(T (&array)[N])
{
return hash_range(array, array + N);
}
#endif
template <class Ch, class A>
inline std::size_t hash_value(std::basic_string<Ch, std::BOOST_HASH_CHAR_TRAITS<Ch>, A> const& v)
{
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)
{
return boost::hash_detail::float_hash_value(v);
}
template <class A, class B>
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);
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());
}
template <class T, class A>
std::size_t hash_value(std::list<T, A> const& v)
{
return 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());
}
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());
}
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());
}
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());
}
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());
}
//
// boost::hash
//
#if !BOOST_WORKAROUND(BOOST_MSVC, < 1300)
#define BOOST_HASH_SPECIALIZE(type) \
template <> struct hash<type> \
: public std::unary_function<type, std::size_t> \
{ \
std::size_t operator()(type v) const \
{ \
return boost::hash_value(v); \
} \
};
#define BOOST_HASH_SPECIALIZE_REF(type) \
template <> struct hash<type> \
: public std::unary_function<type, std::size_t> \
{ \
std::size_t operator()(type const& v) const \
{ \
return boost::hash_value(v); \
} \
};
#else
#define BOOST_HASH_SPECIALIZE(type) \
template <> struct hash<type> \
: public std::unary_function<type, std::size_t> \
{ \
std::size_t operator()(type v) const \
{ \
return boost::hash_value(v); \
} \
}; \
\
template <> struct hash<const type> \
: public std::unary_function<const type, std::size_t> \
{ \
std::size_t operator()(const type v) const \
{ \
return boost::hash_value(v); \
} \
};
#define BOOST_HASH_SPECIALIZE_REF(type) \
template <> struct hash<type> \
: public std::unary_function<type, std::size_t> \
{ \
std::size_t operator()(type const& v) const \
{ \
return boost::hash_value(v); \
} \
}; \
\
template <> struct hash<const type> \
: public std::unary_function<const type, std::size_t> \
{ \
std::size_t operator()(type const& v) const \
{ \
return boost::hash_value(v); \
} \
};
#endif
BOOST_HASH_SPECIALIZE(bool)
BOOST_HASH_SPECIALIZE(char)
BOOST_HASH_SPECIALIZE(signed char)
BOOST_HASH_SPECIALIZE(unsigned char)
#if !defined(BOOST_NO_INTRINSIC_WCHAR_T)
BOOST_HASH_SPECIALIZE(wchar_t)
#endif
BOOST_HASH_SPECIALIZE(short)
BOOST_HASH_SPECIALIZE(unsigned short)
BOOST_HASH_SPECIALIZE(int)
BOOST_HASH_SPECIALIZE(unsigned int)
BOOST_HASH_SPECIALIZE(long)
BOOST_HASH_SPECIALIZE(unsigned long)
BOOST_HASH_SPECIALIZE(float)
BOOST_HASH_SPECIALIZE(double)
BOOST_HASH_SPECIALIZE(long double)
BOOST_HASH_SPECIALIZE_REF(std::string)
#if !defined(BOOST_NO_STD_WSTRING)
BOOST_HASH_SPECIALIZE_REF(std::wstring)
#endif
#undef BOOST_HASH_SPECIALIZE
#undef BOOST_HASH_SPECIALIZE_REF
#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
template <class T>
struct hash<T*>
: public std::unary_function<T*, std::size_t>
{
std::size_t operator()(T* v) const \
{ \
return boost::hash_value(v); \
} \
};
#else
namespace hash_detail
{
template <bool IsPointer>
struct hash_impl;
template <>
struct hash_impl<true>
{
template <class T>
struct inner
: public std::unary_function<T, std::size_t>
{
std::size_t operator()(T val) const
{
return boost::hash_value(val);
}
};
};
}
template <class T> struct hash
: public boost::hash_detail::hash_impl<boost::is_pointer<T>::value>
::BOOST_NESTED_TEMPLATE inner<T>
{
};
#endif
}
#endif // BOOST_FUNCTIONAL_HASH_HASH_HPP
////////////////////////////////////////////////////////////////////////////////
#if !defined(BOOST_HASH_NO_EXTENSIONS) \
&& !defined(BOOST_FUNCTIONAL_HASH_EXTENSIONS_HPP)
#define BOOST_FUNCTIONAL_HASH_EXTENSIONS_HPP
namespace boost
{
#if defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
namespace hash_detail
{
template <bool IsArray>
struct call_hash_impl
{
template <class T>
struct inner
{
static std::size_t call(T const& v)
{
using namespace boost;
return hash_value(v);
}
};
};
template <>
struct call_hash_impl<true>
{
template <class Array>
struct inner
{
#if !BOOST_WORKAROUND(BOOST_MSVC, < 1300)
static std::size_t call(Array const& v)
#else
static std::size_t call(Array& v)
#endif
{
const int size = sizeof(v) / sizeof(*v);
return boost::hash_range(v, v + size);
}
};
};
template <class T>
struct call_hash
: public call_hash_impl<boost::is_array<T>::value>
::BOOST_NESTED_TEMPLATE inner<T>
{
};
}
#endif // BOOST_NO_FUNCTION_TEMPLATE_ORDERING
#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
template <class T> struct hash
: std::unary_function<T, std::size_t>
{
#if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
std::size_t operator()(T const& val) const
{
return hash_value(val);
}
#else
std::size_t operator()(T const& val) const
{
return hash_detail::call_hash<T>::call(val);
}
#endif
};
#if BOOST_WORKAROUND(__DMC__, <= 0x848)
template <class T, unsigned int n> struct hash<T[n]>
: std::unary_function<T[n], std::size_t>
{
std::size_t operator()(const T* val) const
{
return boost::hash_range(val, val+n);
}
};
#endif
#else // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
// On compilers without partial specialization, boost::hash<T>
// has already been declared to deal with pointers, so just
// need to supply the non-pointer version.
namespace hash_detail
{
template <bool IsPointer>
struct hash_impl;
#if !BOOST_WORKAROUND(BOOST_MSVC, < 1300)
template <>
struct hash_impl<false>
{
template <class T>
struct inner
: std::unary_function<T, std::size_t>
{
#if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
std::size_t operator()(T const& val) const
{
return hash_value(val);
}
#else
std::size_t operator()(T const& val) const
{
return hash_detail::call_hash<T>::call(val);
}
#endif
};
};
#else // Visual C++ 6.5
// There's probably a more elegant way to Visual C++ 6.5 to work
// but I don't know what it is.
template <bool IsConst>
struct hash_impl_msvc
{
template <class T>
struct inner
: public std::unary_function<T, std::size_t>
{
std::size_t operator()(T const& val) const
{
return hash_detail::call_hash<T const>::call(val);
}
std::size_t operator()(T& val) const
{
return hash_detail::call_hash<T>::call(val);
}
};
};
template <>
struct hash_impl_msvc<true>
{
template <class T>
struct inner
: public std::unary_function<T, std::size_t>
{
std::size_t operator()(T& val) const
{
return hash_detail::call_hash<T>::call(val);
}
};
};
template <class T>
struct hash_impl_msvc2
: public hash_impl_msvc<boost::is_const<T>::value>
::BOOST_NESTED_TEMPLATE inner<T> {};
template <>
struct hash_impl<false>
{
template <class T>
struct inner : public hash_impl_msvc2<T> {};
};
#endif // Visual C++ 6.5
}
#endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
}
#endif

View File

@@ -0,0 +1,40 @@
// Copyright Daniel James 2005-2006. Use, modification, and distribution are
// subject to 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)
// Based on Peter Dimov's proposal
// http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2005/n1756.pdf
// issue 6.18.
#if !defined(BOOST_FUNCTIONAL_HASH_FWD_HPP)
#define BOOST_FUNCTIONAL_HASH_FWD_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <boost/config.hpp>
#include <cstddef>
#include <boost/detail/workaround.hpp>
namespace boost
{
template <class T> struct hash;
#if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
template <class T> void hash_combine(std::size_t& seed, T& v);
#else
template <class T> void hash_combine(std::size_t& seed, T const& v);
#endif
template <class It> std::size_t hash_range(It, It);
template <class It> void hash_range(std::size_t&, It, It);
#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551))
template <class T> inline std::size_t hash_range(T*, T*);
template <class T> inline void hash_range(std::size_t&, T*, T*);
#endif
}
#endif

View File

@@ -1,6 +1,6 @@
<!--
Copyright 2005-2007 Daniel James.
Copyright 2005-2006 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)
-->

View File

@@ -1,3 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<explicit-failures-markup>
</explicit-failures-markup>

View File

@@ -1 +0,0 @@
[]

41
test/Jamfile.v2 Normal file
View File

@@ -0,0 +1,41 @@
# Copyright Daniel James 2005-2006. Use, modification, and distribution are
# subject to 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 ;
project hash-tests
: requirements
<toolset>gcc:<define>_GLIBCXX_DEBUG
;
test-suite functional/hash
:
[ 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 : : : <test-info>always_show_run_output ]
[ 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 link_test.cpp link_test_2.cpp ]
[ run link_ext_test.cpp link_no_ext_test.cpp ]
[ run container_fwd_test.cpp ]
[ compile-fail hash_no_ext_fail_test.cpp ]
[ run hash_no_ext_macro_1.cpp ]
[ run hash_no_ext_macro_2.cpp ]
;
build-project ../examples ;

16
test/compile_time.hpp Normal file
View File

@@ -0,0 +1,16 @@
// Copyright Daniel James 2005-2006. Use, modification, and distribution are
// subject to 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/config.hpp>
#include <boost/static_assert.hpp>
#include <boost/type_traits/is_base_and_derived.hpp>
template <class T>
void compile_time_tests(T*)
{
BOOST_STATIC_ASSERT((boost::is_base_and_derived<
std::unary_function<T, std::size_t>, HASH_NAMESPACE::hash<T> >::value));
};

14
test/config.hpp Normal file
View File

@@ -0,0 +1,14 @@
// Copyright Daniel James 2005-2006. Use, modification, and distribution are
// subject to 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(TEST_STD)
# define TEST_STD_INCLUDES
# define HASH_NAMESPACE std::tr1
#else
# define HASH_NAMESPACE boost
# if !defined(BOOST_HASH_NO_EXTENSIONS)
# define TEST_EXTENSIONS
# endif
#endif

109
test/container_fwd_test.cpp Normal file
View File

@@ -0,0 +1,109 @@
// Copyright Daniel James 2005-2006. Use, modification, and distribution are
// subject to 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>
#if BOOST_WORKAROUND(__GNUC__, < 3) && !defined(__SGI_STL_PORT) && !defined(_STLPORT_VERSION)
template <class charT, class Allocator>
static void test(std::basic_string<charT, std::string_char_traits<charT>, Allocator> const&)
{
}
#else
template <class charT, class Allocator>
static void test(std::basic_string<charT, std::char_traits<charT>, Allocator> const&)
{
}
#endif
template <class T, class Allocator>
static void test(std::deque<T, Allocator> const&)
{
}
template <class T, class Allocator>
static void test(std::list<T, Allocator> const&)
{
}
template <class T, class Allocator>
static void test(std::vector<T, Allocator> const&)
{
}
template <class Key, class T, class Compare, class Allocator>
static void test(std::map<Key, T, Compare, Allocator> const&)
{
}
template <class Key, class T, class Compare, class Allocator>
static void test(std::multimap<Key, T, Compare, Allocator> const&)
{
}
template <class Key, class Compare, class Allocator>
static void test(std::set<Key, Compare, Allocator> const&)
{
}
template <class Key, class Compare, class Allocator>
static void test(std::multiset<Key, Compare, Allocator> const&)
{
}
template <std::size_t N>
static void test(std::bitset<N> const&)
{
}
template <class T>
static void test(std::complex<T> const&)
{
}
template <class X, class Y>
static void test(std::pair<X, Y> const&)
{
}
#include <deque>
#include <list>
#include <vector>
#include <map>
#include <set>
#include <bitset>
#include <string>
#include <complex>
#include <utility>
int main()
{
std::deque<int> x1;
std::list<std::string> x2;
std::vector<float> x3;
std::vector<bool> x4;
std::map<int, int> x5;
std::multimap<float, int*> x6;
std::set<std::string> x7;
std::multiset<std::vector<int> > x8;
std::bitset<10> x9;
std::string x10;
std::complex<double> x11;
std::pair<std::list<int>, char***> x12;
test(x1);
test(x2);
test(x3);
test(x4);
test(x5);
test(x6);
test(x7);
test(x8);
test(x9);
test(x10);
test(x11);
test(x12);
return 0;
}

View File

@@ -0,0 +1,75 @@
// Copyright Daniel James 2005-2006. Use, modification, and distribution are
// subject to 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/detail/lightweight_test.hpp>
#ifdef TEST_EXTENSIONS
void array_int_test()
{
const int length1 = 25;
int array1[25] = {
26, -43, 32, 65, 45,
12, 67, 32, 12, 23,
0, 0, 0, 0, 0,
8, -12, 23, 65, 45,
-1, 93, -54, 987, 3
};
HASH_NAMESPACE::hash<int[25]> hasher1;
const int length2 = 1;
int array2[1] = {3};
HASH_NAMESPACE::hash<int[1]> hasher2;
const int length3 = 2;
int array3[2] = {2, 3};
HASH_NAMESPACE::hash<int[2]> hasher3;
BOOST_TEST(hasher1(array1)
== HASH_NAMESPACE::hash_range(array1, array1 + length1));
BOOST_TEST(hasher2(array2)
== HASH_NAMESPACE::hash_range(array2, array2 + length2));
BOOST_TEST(hasher3(array3)
== HASH_NAMESPACE::hash_range(array3, array3 + length3));
}
void two_dimensional_array_test()
{
int array[3][2] = {{-5, 6}, {7, -3}, {26, 1}};
HASH_NAMESPACE::hash<int[3][2]> hasher;
std::size_t seed1 = 0;
for(int i = 0; i < 3; ++i)
{
std::size_t seed2 = 0;
for(int j = 0; j < 2; ++j)
HASH_NAMESPACE::hash_combine(seed2, array[i][j]);
HASH_NAMESPACE::hash_combine(seed1, seed2);
}
BOOST_TEST(hasher(array) == seed1);
BOOST_TEST(hasher(array) == HASH_NAMESPACE::hash_range(array, array + 3));
}
#endif // TEST_EXTENSIONS
int main()
{
#ifdef TEST_EXTENSIONS
array_int_test();
two_dimensional_array_test();
#endif
return boost::report_errors();
}

99
test/hash_custom_test.cpp Normal file
View File

@@ -0,0 +1,99 @@
// Copyright Daniel James 2005-2006. Use, modification, and distribution are
// subject to 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/config.hpp>
#include <cstddef>
namespace test
{
struct custom
{
int value_;
std::size_t hash() const
{
return value_ * 10;
}
#if !defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
friend std::size_t hash_value(custom const& x )
{
return x.hash();
}
#endif
custom(int x) : value_(x) {}
};
}
#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
namespace boost
{
std::size_t hash_value(test::custom x)
{
return x.hash();
}
}
#endif
#include "./config.hpp"
#ifdef TEST_EXTENSIONS
# ifdef TEST_STD_INCLUDES
# include <functional>
# else
# include <boost/functional/hash.hpp>
# endif
#endif
#include <boost/detail/lightweight_test.hpp>
#ifdef TEST_EXTENSIONS
#include <vector>
#include <string>
#include <cctype>
void custom_tests()
{
HASH_NAMESPACE::hash<test::custom> custom_hasher;
BOOST_TEST(custom_hasher(10) == 100u);
test::custom x(55);
BOOST_TEST(custom_hasher(x) == 550u);
{
using namespace HASH_NAMESPACE;
BOOST_TEST(custom_hasher(x) == hash_value(x));
}
std::vector<test::custom> custom_vector;
custom_vector.push_back(5);
custom_vector.push_back(25);
custom_vector.push_back(35);
std::size_t seed = 0;
HASH_NAMESPACE::hash_combine(seed, test::custom(5));
HASH_NAMESPACE::hash_combine(seed, test::custom(25));
HASH_NAMESPACE::hash_combine(seed, test::custom(35));
std::size_t seed2 = 0;
HASH_NAMESPACE::hash_combine(seed2, 50u);
HASH_NAMESPACE::hash_combine(seed2, 250u);
HASH_NAMESPACE::hash_combine(seed2, 350u);
BOOST_TEST(seed ==
HASH_NAMESPACE::hash_range(custom_vector.begin(), custom_vector.end()));
BOOST_TEST(seed == seed2);
}
#endif // TEST_EXTENSIONS
int main()
{
#ifdef TEST_EXTENSIONS
custom_tests();
#endif
return boost::report_errors();
}

35
test/hash_deque_test.cpp Normal file
View File

@@ -0,0 +1,35 @@
// Copyright Daniel James 2005-2006. Use, modification, and distribution are
// subject to 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/detail/lightweight_test.hpp>
#ifdef TEST_EXTENSIONS
#include <deque>
using std::deque;
#define CONTAINER_TYPE deque
#include "./hash_sequence_test.hpp"
#endif // TEST_EXTENSIONS
int main()
{
#ifdef TEST_EXTENSIONS
deque_tests::deque_hash_integer_tests();
#endif
return boost::report_errors();
}

228
test/hash_float_test.cpp Normal file
View File

@@ -0,0 +1,228 @@
// Copyright Daniel James 2005-2006. Use, modification, and distribution are
// subject to 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 <functional>
#else
# include <boost/functional/hash.hpp>
#endif
#include <boost/detail/lightweight_test.hpp>
#include <cmath>
#include <boost/limits.hpp>
#include <iostream>
template <class T>
void float_tests(char const* name, T* = 0)
{
std::cerr<<"\n"
<<"Testing " BOOST_STRINGIZE(HASH_NAMESPACE) "::hash<"<<name<<">\n"
<<"\n"
<<"std::numeric_limits<T>::digits = "
<<std::numeric_limits<T>::digits<<"\n"
<<"std::numeric_limits<int>::digits = "
<<std::numeric_limits<int>::digits<<"\n"
<<"std::numeric_limits<std::size_t>::digits = "
<<std::numeric_limits<std::size_t>::digits<<"\n"
<<"\n"
;
HASH_NAMESPACE::hash<T> x1;
T zero = 0;
T minus_zero = (T) -1 * zero;
BOOST_TEST(zero == minus_zero);
BOOST_TEST(x1(zero) == x1(minus_zero));
BOOST_TEST(x1(zero) == HASH_NAMESPACE::hash_value(zero));
BOOST_TEST(x1(minus_zero) == HASH_NAMESPACE::hash_value(minus_zero));
using namespace std;
// Doing anything with infinity causes borland to crash.
#if defined(__BORLANDC__)
std::cerr<<"Not running infinity checks on Borland, as it causes it to crash.\n";
#else
if(std::numeric_limits<T>::has_infinity) {
T infinity = -log(zero);
T infinity2 = (T) 1. / zero;
T infinity3 = (T) -1. / minus_zero;
T infinity4 = std::numeric_limits<T>::infinity();
T minus_infinity = log(zero);
T minus_infinity2 = (T) -1. / zero;
T minus_infinity3 = (T) 1. / minus_zero;
BOOST_TEST(x1(infinity) == HASH_NAMESPACE::hash_value(infinity));
BOOST_TEST(x1(minus_infinity)
== HASH_NAMESPACE::hash_value(minus_infinity));
if(infinity == infinity2)
BOOST_TEST(x1(infinity) == x1(infinity2));
if(infinity == infinity3);
BOOST_TEST(x1(infinity) == x1(infinity3));
if(infinity == infinity4)
BOOST_TEST(x1(infinity) == x1(infinity4));
if(minus_infinity == minus_infinity2)
BOOST_TEST(x1(minus_infinity) == x1(minus_infinity2));
if(minus_infinity == minus_infinity3)
BOOST_TEST(x1(minus_infinity) == x1(minus_infinity3));
BOOST_TEST(infinity != minus_infinity);
if(x1(infinity) == x1(minus_infinity)) {
std::cerr<<"x1(infinity) == x1(-infinity) == "<<x1(infinity)<<"\n";
}
// This should really be 'has_denorm == denorm_present' but some
// compilers don't have 'denorm_present'. See also a later use.
if(std::numeric_limits<T>::has_denorm) {
if(x1(std::numeric_limits<T>::denorm_min()) == x1(infinity)) {
std::cerr<<"x1(denorm_min) == x1(infinity) == "<<x1(infinity)<<"\n";
}
if(x1(std::numeric_limits<T>::denorm_min()) == x1(minus_infinity)) {
std::cerr<<"x1(denorm_min) == x1(-infinity) == "<<x1(minus_infinity)<<"\n";
}
}
if(std::numeric_limits<T>::has_quiet_NaN) {
if(x1(std::numeric_limits<T>::quiet_NaN()) == x1(infinity)) {
std::cerr<<"x1(quiet_NaN) == x1(infinity) == "<<x1(infinity)<<"\n";
}
if(x1(std::numeric_limits<T>::quiet_NaN()) == x1(minus_infinity)) {
std::cerr<<"x1(quiet_NaN) == x1(-infinity) == "<<x1(minus_infinity)<<"\n";
}
}
}
#endif
T max = (std::numeric_limits<T>::max)();
T half_max = max / 2;
T quarter_max = max / 4;
T three_quarter_max = max - quarter_max;
BOOST_TEST(x1(max) == HASH_NAMESPACE::hash_value(max));
BOOST_TEST(x1(half_max) == HASH_NAMESPACE::hash_value(half_max));
BOOST_TEST(x1(quarter_max) == HASH_NAMESPACE::hash_value(quarter_max));
BOOST_TEST(x1(three_quarter_max) == HASH_NAMESPACE::hash_value(three_quarter_max));
// The '!=' tests could legitimately fail, but with my hash it indicates a bug.
BOOST_TEST(x1(max) == x1(max));
BOOST_TEST(x1(max) != x1(quarter_max));
BOOST_TEST(x1(max) != x1(half_max));
BOOST_TEST(x1(max) != x1(three_quarter_max));
BOOST_TEST(x1(quarter_max) == x1(quarter_max));
BOOST_TEST(x1(quarter_max) != x1(half_max));
BOOST_TEST(x1(quarter_max) != x1(three_quarter_max));
BOOST_TEST(x1(half_max) == x1(half_max));
BOOST_TEST(x1(half_max) != x1(three_quarter_max));
BOOST_TEST(x1(three_quarter_max) == x1(three_quarter_max));
// Intel with gcc stdlib sometimes segfaults on calls to asin and acos.
#if !((defined(__INTEL_COMPILER) || defined(__ICL) || \
defined(__ICC) || defined(__ECC)) && \
(defined(__GLIBCPP__) || defined(__GLIBCXX__)))
T v1 = asin((T) 1);
T v2 = acos((T) 0);
if(v1 == v2)
BOOST_TEST(x1(v1) == x1(v2));
BOOST_TEST(x1(v1) == HASH_NAMESPACE::hash_value(v1));
BOOST_TEST(x1(v2) == HASH_NAMESPACE::hash_value(v2));
#endif
BOOST_TEST(x1(std::numeric_limits<T>::epsilon()) ==
HASH_NAMESPACE::hash_value(std::numeric_limits<T>::epsilon()));
BOOST_TEST(std::numeric_limits<T>::epsilon() != (T) 0);
if(x1(std::numeric_limits<T>::epsilon()) == x1((T) 0))
std::cerr<<"x1(epsilon) == x1(0) == "<<x1((T) 0)<<"\n";
BOOST_TEST(-std::numeric_limits<T>::epsilon() != (T) 0);
if(x1(-std::numeric_limits<T>::epsilon()) == x1((T) 0))
std::cerr<<"x1(-epsilon) == x1(0) == "<<x1((T) 0)<<"\n";
BOOST_TEST((T) 1 + std::numeric_limits<T>::epsilon() != (T) 1);
if(x1((T) 1 + std::numeric_limits<T>::epsilon()) == x1((T) 1))
std::cerr<<"x1(1 + epsilon) == x1(1) == "<<x1((T) 1)<<"\n";
BOOST_TEST((T) 1 - std::numeric_limits<T>::epsilon() != (T) 1);
if(x1((T) 1 - std::numeric_limits<T>::epsilon()) == x1((T) 1))
std::cerr<<"x1(1 - epsilon) == x1(1) == "<<x1((T) 1)<<"\n";
BOOST_TEST((T) -1 + std::numeric_limits<T>::epsilon() != (T) -1);
if(x1((T) -1 + std::numeric_limits<T>::epsilon()) == x1((T) -1))
std::cerr<<"x1(-1 + epsilon) == x1(-1) == "<<x1((T) -1)<<"\n";
BOOST_TEST((T) -1 - std::numeric_limits<T>::epsilon() != (T) -1);
if(x1((T) -1 - std::numeric_limits<T>::epsilon()) == x1((T) -1))
std::cerr<<"x1(-1 - epsilon) == x1(-1) == "<<x1((T) -1)<<"\n";
// As before.
if(std::numeric_limits<T>::has_denorm) {
if(x1(std::numeric_limits<T>::denorm_min()) == x1(zero)) {
std::cerr<<"x1(denorm_min) == x1(zero) == "<<x1(zero)<<"\n";
}
#if !BOOST_WORKAROUND(__DECCXX_VER,<70190006)
// The Tru64/CXX standard library prior to 7.1 contains a bug in the
// specialization of std::numeric_limits::denorm_min() for long
// doubles which causes this test to fail.
if(x1(std::numeric_limits<T>::denorm_min()) !=
HASH_NAMESPACE::hash_value(std::numeric_limits<T>::denorm_min()))
{
std::cerr<<"x1(std::numeric_limits<T>::denorm_min()) = "
<< x1(std::numeric_limits<T>::denorm_min())
<< "\nhash_value(std::numeric_limits<T>::denorm_min()) = "
<< HASH_NAMESPACE::hash_value(
std::numeric_limits<T>::denorm_min())
<< "\nx1(0) = "<<x1(0)<<"\n";
}
#endif
}
// NaN also causes borland to crash.
#if !defined(__BORLANDC__)
if(std::numeric_limits<T>::has_quiet_NaN) {
if(x1(std::numeric_limits<T>::quiet_NaN()) == x1(1.0)) {
std::cerr<<"x1(quiet_NaN) == x1(1.0) == "<<x1(1.0)<<"\n";
}
BOOST_TEST(x1(std::numeric_limits<T>::quiet_NaN()) ==
HASH_NAMESPACE::hash_value(std::numeric_limits<T>::quiet_NaN()));
}
#endif
}
void hash_float_tests()
{
std::cerr<<"Compiler: "<<BOOST_COMPILER<<"\n";
std::cerr<<"Platform: "<<BOOST_PLATFORM<<"\n";
std::cerr<<"Library: "<<BOOST_STDLIB<<"\n\n";
float_tests("float", (float*) 0);
}
void hash_double_tests()
{
float_tests("double", (double*) 0);
}
void hash_long_double_tests()
{
float_tests("long double", (long double*) 0);
}
int main()
{
hash_float_tests();
hash_double_tests();
hash_long_double_tests();
return boost::report_errors();
}

101
test/hash_friend_test.cpp Normal file
View File

@@ -0,0 +1,101 @@
// Copyright Daniel James 2006. Use, modification, and distribution are
// subject to 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/config.hpp>
#include <cstddef>
namespace test
{
template <class T>
struct custom
{
int value_;
std::size_t hash() const
{
return value_ * 10;
}
#if !defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
friend std::size_t hash_value(custom const& x)
{
return x.hash();
}
#endif
custom(int x) : value_(x) {}
};
}
#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
namespace boost
{
template <class T>
std::size_t hash_value(test::custom<T> x)
{
return x.hash();
}
}
#endif
#include "./config.hpp"
#ifdef TEST_EXTENSIONS
# ifdef TEST_STD_INCLUDES
# include <functional>
# else
# include <boost/functional/hash.hpp>
# endif
#endif
#include <boost/detail/lightweight_test.hpp>
#ifdef TEST_EXTENSIONS
#include <vector>
#include <string>
#include <cctype>
void custom_tests()
{
HASH_NAMESPACE::hash<test::custom<int> > custom_hasher;
BOOST_TEST(custom_hasher(10) == 100u);
test::custom<int> x(55);
BOOST_TEST(custom_hasher(x) == 550u);
{
using namespace HASH_NAMESPACE;
BOOST_TEST(custom_hasher(x) == hash_value(x));
}
std::vector<test::custom<int> > custom_vector;
custom_vector.push_back(5);
custom_vector.push_back(25);
custom_vector.push_back(35);
std::size_t seed = 0;
HASH_NAMESPACE::hash_combine(seed, test::custom<int>(5));
HASH_NAMESPACE::hash_combine(seed, test::custom<int>(25));
HASH_NAMESPACE::hash_combine(seed, test::custom<int>(35));
std::size_t seed2 = 0;
HASH_NAMESPACE::hash_combine(seed2, 50u);
HASH_NAMESPACE::hash_combine(seed2, 250u);
HASH_NAMESPACE::hash_combine(seed2, 350u);
BOOST_TEST(seed ==
HASH_NAMESPACE::hash_range(custom_vector.begin(), custom_vector.end()));
BOOST_TEST(seed == seed2);
}
#endif // TEST_EXTENSIONS
int main()
{
#ifdef TEST_EXTENSIONS
custom_tests();
#endif
return boost::report_errors();
}

View File

@@ -0,0 +1,62 @@
// Copyright Daniel James 2005-2006. Use, modification, and distribution are
// subject to 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 <functional>
#else
# include <boost/functional/hash.hpp>
#endif
#include <boost/detail/lightweight_test.hpp>
#include <boost/limits.hpp>
#include <boost/mpl/assert.hpp>
#include <boost/type_traits/is_base_and_derived.hpp>
#include "./compile_time.hpp"
void void_func1() { static int x = 1; ++x; }
void void_func2() { static int x = 2; --x; }
int int_func1(int) { return 0; }
int int_func2(int) { return 1; }
void function_pointer_tests()
{
compile_time_tests((void(**)()) 0);
compile_time_tests((int(**)(int)) 0);
HASH_NAMESPACE::hash<void(*)()> hasher_void;
HASH_NAMESPACE::hash<int(*)(int)> hasher_int;
BOOST_TEST(&void_func1 != &void_func2);
BOOST_TEST(&int_func1 != &int_func2);
BOOST_TEST(hasher_void(0) == hasher_void(0));
BOOST_TEST(hasher_void(&void_func1) == hasher_void(&void_func1));
BOOST_TEST(hasher_void(&void_func1) != hasher_void(&void_func2));
BOOST_TEST(hasher_void(&void_func1) != hasher_void(0));
BOOST_TEST(hasher_int(0) == hasher_int(0));
BOOST_TEST(hasher_int(&int_func1) == hasher_int(&int_func1));
BOOST_TEST(hasher_int(&int_func1) != hasher_int(&int_func2));
BOOST_TEST(hasher_int(&int_func1) != hasher_int(0));
#if defined(TEST_EXTENSIONS)
BOOST_TEST(hasher_void(&void_func1)
== HASH_NAMESPACE::hash_value(&void_func1));
BOOST_TEST(hasher_int(&int_func1)
== HASH_NAMESPACE::hash_value(&int_func1));
// This isn't specified in Peter's proposal:
BOOST_TEST(hasher_void(0) == 0);
#endif
}
int main()
{
function_pointer_tests();
return boost::report_errors();
}

102
test/hash_fwd_test.hpp Normal file
View File

@@ -0,0 +1,102 @@
// Copyright Daniel James 2006. Use, modification, and distribution are
// subject to 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"
#if defined(TEST_EXTENSIONS) && !defined(TEST_STD_INCLUDES)
#include <boost/functional/hash_fwd.hpp>
#include <boost/config.hpp>
#include <cstddef>
#include <vector>
namespace test {
template <class T>
struct test_type1
{
T value;
test_type1(T const& x) : value(x) {}
};
#if !defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
template <class T>
std::size_t hash_value(test_type1<T> const& x)
{
HASH_NAMESPACE::hash<T> hasher;
return hasher(x.value);
}
#endif
template <class T>
struct test_type2
{
T value1, value2;
test_type2(T const& x, T const& y) : value1(x), value2(y) {}
};
#if !defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
template <class T>
std::size_t hash_value(test_type2<T> const& x)
{
std::size_t seed = 0;
HASH_NAMESPACE::hash_combine(seed, x.value1);
HASH_NAMESPACE::hash_combine(seed, x.value2);
return seed;
}
#endif
template <class T>
struct test_type3
{
std::vector<T> values;
test_type3(typename std::vector<T>::iterator x,
typename std::vector<T>::iterator y) : values(x, y) {}
};
#if !defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
template <class T>
std::size_t hash_value(test_type3<T> const& x)
{
std::size_t seed = HASH_NAMESPACE::hash_range(x.values.begin(), x.values.end());
HASH_NAMESPACE::hash_range(seed, x.values.begin(), x.values.end());
return seed;
}
#endif
}
#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
namespace boost
{
template <class T>
std::size_t hash_value(test::test_type1<T> const& x)
{
HASH_NAMESPACE::hash<T> hasher;
return hasher(x.value);
}
template <class T>
std::size_t hash_value(test::test_type2<T> const& x)
{
std::size_t seed = 0;
HASH_NAMESPACE::hash_combine(seed, x.value1);
HASH_NAMESPACE::hash_combine(seed, x.value2);
return seed;
}
template <class T>
std::size_t hash_value(test::test_type3<T> const& x)
{
std::size_t seed = HASH_NAMESPACE::hash_range(x.values.begin(), x.values.end());
HASH_NAMESPACE::hash_range(seed, x.values.begin(), x.values.end());
return seed;
}
}
#endif
#endif

93
test/hash_fwd_test_1.cpp Normal file
View File

@@ -0,0 +1,93 @@
// Copyright Daniel James 2006. Use, modification, and distribution are
// subject to 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 checks that template code implemented using hash_fwd will work.
#include "./hash_fwd_test.hpp"
#include <boost/detail/lightweight_test.hpp>
#if defined(TEST_EXTENSIONS) && !defined(TEST_STD_INCLUDES)
#include <boost/functional/hash.hpp>
#include <string>
void fwd_test1()
{
test::test_type1<int> x(5);
test::test_type1<std::string> y("Test");
HASH_NAMESPACE::hash<int> hasher_int;
HASH_NAMESPACE::hash<std::string> hasher_string;
HASH_NAMESPACE::hash<test::test_type1<int> > hasher_test_int;
HASH_NAMESPACE::hash<test::test_type1<std::string> > hasher_test_string;
BOOST_TEST(hasher_int(5) == hasher_test_int(x));
BOOST_TEST(hasher_string("Test") == hasher_test_string(y));
}
void fwd_test2()
{
test::test_type2<int> x(5, 10);
test::test_type2<std::string> y("Test1", "Test2");
std::size_t seed1 = 0;
HASH_NAMESPACE::hash_combine(seed1, 5);
HASH_NAMESPACE::hash_combine(seed1, 10);
std::size_t seed2 = 0;
HASH_NAMESPACE::hash_combine(seed2, std::string("Test1"));
HASH_NAMESPACE::hash_combine(seed2, std::string("Test2"));
HASH_NAMESPACE::hash<test::test_type2<int> > hasher_test_int;
HASH_NAMESPACE::hash<test::test_type2<std::string> > hasher_test_string;
BOOST_TEST(seed1 == hasher_test_int(x));
BOOST_TEST(seed2 == hasher_test_string(y));
}
void fwd_test3()
{
std::vector<int> values1;
values1.push_back(10);
values1.push_back(15);
values1.push_back(20);
values1.push_back(3);
std::vector<std::string> values2;
values2.push_back("Chico");
values2.push_back("Groucho");
values2.push_back("Harpo");
values2.push_back("Gummo");
values2.push_back("Zeppo");
test::test_type3<int> x(values1.begin(), values1.end());
test::test_type3<std::string> y(values2.begin(), values2.end());
std::size_t seed1 = HASH_NAMESPACE::hash_range(values1.begin(), values1.end());
HASH_NAMESPACE::hash_range(seed1, values1.begin(), values1.end());
std::size_t seed2 = HASH_NAMESPACE::hash_range(values2.begin(), values2.end());
HASH_NAMESPACE::hash_range(seed2, values2.begin(), values2.end());
HASH_NAMESPACE::hash<test::test_type3<int> > hasher_test_int;
HASH_NAMESPACE::hash<test::test_type3<std::string> > hasher_test_string;
BOOST_TEST(seed1 == hasher_test_int(x));
BOOST_TEST(seed2 == hasher_test_string(y));
}
#endif
int main()
{
#ifdef TEST_EXTENSIONS
fwd_test1();
fwd_test2();
fwd_test3();
#endif
return boost::report_errors();
}

39
test/hash_fwd_test_2.cpp Normal file
View File

@@ -0,0 +1,39 @@
// Copyright Daniel James 2006. Use, modification, and distribution are
// subject to 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 test just makes sure a header which uses hash_fwd can compile without
// the main hash headers.
#include "./hash_fwd_test.hpp"
#include <boost/detail/lightweight_test.hpp>
template <class T> void unused(T const&) {}
void fwd_test()
{
test::test_type1<int> x1(3);
test::test_type1<std::string> y1("Black");
test::test_type2<int> x2(25, 16);
test::test_type2<std::string> y2("White", "Green");
std::vector<int> empty;
std::vector<std::string> empty2;
test::test_type3<int> x3(empty.begin(), empty.end());
test::test_type3<std::string> y3(empty2.begin(), empty2.end());
// Prevent gcc warnings:
unused(x1); unused(x2); unused(x3);
unused(y1); unused(y2); unused(y3);
}
int main()
{
fwd_test();
return boost::report_errors();
}

View File

@@ -0,0 +1,101 @@
// Copyright Daniel James 2006. Use, modification, and distribution are
// subject to 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 test demonstrates an ADL bug in Borland 5.5 where ADL isn't performed
// in the global namespace.
#include <boost/config.hpp>
#include <cstddef>
struct custom
{
int value_;
std::size_t hash() const
{
return value_ * 10;
}
#if !defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
friend std::size_t hash_value(custom const& x )
{
return x.hash();
}
#endif
custom(int x) : value_(x) {}
};
#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
namespace boost
{
std::size_t hash_value(custom x)
{
return x.hash();
}
}
#endif
#include "./config.hpp"
#ifdef TEST_EXTENSIONS
# ifdef TEST_STD_INCLUDES
# include <functional>
# else
# include <boost/functional/hash/hash.hpp>
# endif
#endif
#include <boost/detail/lightweight_test.hpp>
#ifdef TEST_EXTENSIONS
#include <vector>
#include <string>
#include <cctype>
void custom_tests()
{
HASH_NAMESPACE::hash<custom> custom_hasher;
BOOST_TEST(custom_hasher(10) == 100u);
custom x(55);
BOOST_TEST(custom_hasher(x) == 550u);
{
using namespace HASH_NAMESPACE;
BOOST_TEST(custom_hasher(x) == hash_value(x));
}
std::vector<custom> custom_vector;
custom_vector.push_back(5);
custom_vector.push_back(25);
custom_vector.push_back(35);
std::size_t seed = 0;
HASH_NAMESPACE::hash_combine(seed, custom(5));
HASH_NAMESPACE::hash_combine(seed, custom(25));
HASH_NAMESPACE::hash_combine(seed, custom(35));
std::size_t seed2 = 0;
HASH_NAMESPACE::hash_combine(seed2, 50u);
HASH_NAMESPACE::hash_combine(seed2, 250u);
HASH_NAMESPACE::hash_combine(seed2, 350u);
BOOST_TEST(seed ==
HASH_NAMESPACE::hash_range(custom_vector.begin(), custom_vector.end()));
BOOST_TEST(seed == seed2);
}
#endif // TEST_EXTENSIONS
int main()
{
#ifdef TEST_EXTENSIONS
custom_tests();
#endif
return boost::report_errors();
}

35
test/hash_list_test.cpp Normal file
View File

@@ -0,0 +1,35 @@
// Copyright Daniel James 2005-2006. Use, modification, and distribution are
// subject to 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/detail/lightweight_test.hpp>
#ifdef TEST_EXTENSIONS
#include <list>
using std::list;
#define CONTAINER_TYPE list
#include "./hash_sequence_test.hpp"
#endif // TEST_EXTENSIONS
int main()
{
#ifdef TEST_EXTENSIONS
list_tests::list_hash_integer_tests();
#endif
return boost::report_errors();
}

40
test/hash_map_test.cpp Normal file
View File

@@ -0,0 +1,40 @@
// Copyright Daniel James 2005-2006. Use, modification, and distribution are
// subject to 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/detail/lightweight_test.hpp>
#include <map>
#ifdef TEST_EXTENSIONS
using std::map;
#define CONTAINER_TYPE map
#include "./hash_map_test.hpp"
using std::multimap;
#define CONTAINER_TYPE multimap
#include "./hash_map_test.hpp"
#endif // TEST_EXTENSTIONS
int main()
{
#ifdef TEST_EXTENSIONS
map_tests::map_hash_integer_tests();
multimap_tests::multimap_hash_integer_tests();
#endif
return boost::report_errors();
}

64
test/hash_map_test.hpp Normal file
View File

@@ -0,0 +1,64 @@
// Copyright Daniel James 2005-2006. Use, modification, and distribution are
// subject to 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(CONTAINER_TYPE)
#error "CONTAINER_TYPE not defined"
#else
#include <boost/preprocessor/cat.hpp>
namespace BOOST_PP_CAT(CONTAINER_TYPE, _tests)
{
template <class T>
void integer_tests(T* = 0)
{
const int number_of_containers = 10;
T containers[number_of_containers];
typedef typename T::value_type pair;
for(int i = 0; i < 5; ++i) {
for(int j = 0; j < i; ++j)
containers[i].insert(pair(0, 0));
}
containers[6].insert(pair(1,0));
containers[7].insert(pair(1,0));
containers[7].insert(pair(1,0));
containers[8].insert(pair(-1,1));
containers[9].insert(pair(-1,3));
containers[9].insert(pair(-1,3));
HASH_NAMESPACE::hash<T> hasher;
for(int i2 = 0; i2 < number_of_containers; ++i2) {
BOOST_TEST(hasher(containers[i2]) == hasher(containers[i2]));
BOOST_TEST(hasher(containers[i2]) ==
HASH_NAMESPACE::hash_value(containers[i2]));
BOOST_TEST(hasher(containers[i2])
== HASH_NAMESPACE::hash_range(
containers[i2].begin(), containers[i2].end()));
for(int j2 = i2 + 1; j2 < number_of_containers; ++j2) {
BOOST_TEST(
(containers[i2] == containers[j2]) ==
(hasher(containers[i2]) == hasher(containers[j2]))
);
}
}
}
void BOOST_PP_CAT(CONTAINER_TYPE, _hash_integer_tests())
{
integer_tests((CONTAINER_TYPE<char, unsigned char>*) 0);
integer_tests((CONTAINER_TYPE<int, float>*) 0);
integer_tests((CONTAINER_TYPE<unsigned long, unsigned long>*) 0);
integer_tests((CONTAINER_TYPE<double, short>*) 0);
}
}
#undef CONTAINER_TYPE
#endif

View File

@@ -0,0 +1,19 @@
// Copyright Daniel James 2006. Use, modification, and distribution are
// subject to 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)
#define HASH_NAMESPACE boost
// Simple test to make sure BOOST_HASH_NO_EXTENSIONS does disable extensions
// (or at least one of them).
#define BOOST_HASH_NO_EXTENSIONS
#include <boost/functional/hash.hpp>
#include <boost/functional/hash.hpp>
int main()
{
HASH_NAMESPACE::hash< int[10] > hasher;
return 0;
}

View File

@@ -0,0 +1,25 @@
// Copyright Daniel James 2006. Use, modification, and distribution are
// subject to 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)
#define HASH_NAMESPACE boost
#include <boost/functional/hash.hpp>
#define BOOST_HASH_NO_EXTENSIONS
#include <boost/functional/hash.hpp>
#include <boost/detail/lightweight_test.hpp>
#include <deque>
#include <cassert>
int main()
{
std::deque<int> x;
x.push_back(1);
x.push_back(2);
HASH_NAMESPACE::hash<std::deque<int> > hasher;
BOOST_TEST(hasher(x) == HASH_NAMESPACE::hash_value(x));
return boost::report_errors();
}

View File

@@ -0,0 +1,25 @@
// Copyright Daniel James 2006. Use, modification, and distribution are
// subject to 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)
#define HASH_NAMESPACE boost
#define BOOST_HASH_NO_EXTENSIONS
#include <boost/functional/hash.hpp>
#undef BOOST_HASH_NO_EXTENSIONS
#include <boost/functional/hash.hpp>
#include <boost/detail/lightweight_test.hpp>
#include <map>
int main()
{
std::map<int, int> x;
x.insert(std::map<int, int>::value_type(53, -42));
x.insert(std::map<int, int>::value_type(14, -75));
HASH_NAMESPACE::hash<std::map<int, int> > hasher;
BOOST_TEST(hasher(x) == HASH_NAMESPACE::hash_value(x));
return boost::report_errors();
}

138
test/hash_number_test.cpp Normal file
View File

@@ -0,0 +1,138 @@
// Copyright Daniel James 2005-2006. Use, modification, and distribution are
// subject to 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 <functional>
#else
# include <boost/functional/hash.hpp>
#endif
#include <iostream>
#include <boost/detail/lightweight_test.hpp>
#include <boost/preprocessor/cat.hpp>
#include <boost/limits.hpp>
#include <boost/mpl/assert.hpp>
#include <boost/type_traits/is_base_and_derived.hpp>
#include "./compile_time.hpp"
template <class T>
void numeric_test(T*)
{
typedef std::numeric_limits<T> limits;
compile_time_tests((T*) 0);
HASH_NAMESPACE::hash<T> x1;
HASH_NAMESPACE::hash<T> x2;
T v1 = -5;
BOOST_TEST(x1(v1) == x2(v1));
BOOST_TEST(x1(T(-5)) == x2(T(-5)));
BOOST_TEST(x1(T(0)) == x2(T(0)));
BOOST_TEST(x1(T(10)) == x2(T(10)));
BOOST_TEST(x1(T(25)) == x2(T(25)));
BOOST_TEST(x1(T(5) - T(5)) == x2(T(0)));
BOOST_TEST(x1(T(6) + T(4)) == x2(T(10)));
#if defined(TEST_EXTENSIONS)
BOOST_TEST(x1(T(-5)) == HASH_NAMESPACE::hash_value(T(-5)));
BOOST_TEST(x1(T(0)) == HASH_NAMESPACE::hash_value(T(0)));
BOOST_TEST(x1(T(10)) == HASH_NAMESPACE::hash_value(T(10)));
BOOST_TEST(x1(T(25)) == HASH_NAMESPACE::hash_value(T(25)));
if (limits::is_integer)
{
BOOST_TEST(HASH_NAMESPACE::hash_value(T(-5)) == (std::size_t)T(-5));
BOOST_TEST(HASH_NAMESPACE::hash_value(T(0)) == (std::size_t)T(0u));
BOOST_TEST(HASH_NAMESPACE::hash_value(T(10)) == (std::size_t)T(10u));
BOOST_TEST(HASH_NAMESPACE::hash_value(T(25)) == (std::size_t)T(25u));
}
#endif
}
template <class T>
void limits_test(T*)
{
typedef std::numeric_limits<T> limits;
if(limits::is_specialized)
{
HASH_NAMESPACE::hash<T> x1;
HASH_NAMESPACE::hash<T> x2;
T min_value = (limits::min)();
T max_value = (limits::max)();
BOOST_TEST(x1(min_value) == x2((limits::min)()));
BOOST_TEST(x1(max_value) == x2((limits::max)()));
#if defined(TEST_EXTENSIONS)
BOOST_TEST(x1(min_value) == HASH_NAMESPACE::hash_value(min_value));
BOOST_TEST(x1(max_value) == HASH_NAMESPACE::hash_value(max_value));
if (limits::is_integer)
{
BOOST_TEST(HASH_NAMESPACE::hash_value(min_value)
== std::size_t(min_value));
BOOST_TEST(HASH_NAMESPACE::hash_value(max_value)
== std::size_t(max_value));
}
#endif
}
}
template <class T>
void poor_quality_tests(T*)
{
typedef std::numeric_limits<T> limits;
HASH_NAMESPACE::hash<T> x1;
HASH_NAMESPACE::hash<T> x2;
// A hash function can legally fail these tests, but it'll not be a good
// sign.
if(T(1) != T(-1))
BOOST_TEST(x1(T(1)) != x2(T(-1)));
if(T(1) != T(2))
BOOST_TEST(x1(T(1)) != x2(T(2)));
if((limits::max)() != (limits::max)() - 1)
BOOST_TEST(x1((limits::max)()) != x2((limits::max)() - 1));
}
#define NUMERIC_TEST(type, name) \
std::cerr<<"Testing: " BOOST_STRINGIZE(name) "\n"; \
numeric_test((type*) 0); \
limits_test((type*) 0); \
poor_quality_tests((type*) 0);
int main()
{
NUMERIC_TEST(bool, bool)
NUMERIC_TEST(char, char)
NUMERIC_TEST(signed char, schar)
NUMERIC_TEST(unsigned char, uchar)
#ifndef BOOST_NO_INTRINSIC_WCHAR_T
NUMERIC_TEST(wchar_t, wchar)
#endif
NUMERIC_TEST(short, short)
NUMERIC_TEST(unsigned short, ushort)
NUMERIC_TEST(int, int)
NUMERIC_TEST(unsigned int, uint)
NUMERIC_TEST(long, hash_long)
NUMERIC_TEST(unsigned long, ulong)
NUMERIC_TEST(float, float)
NUMERIC_TEST(double, double)
NUMERIC_TEST(long double, ldouble)
return boost::report_errors();
}

View File

@@ -0,0 +1,49 @@
// Copyright Daniel James 2005-2006. Use, modification, and distribution are
// subject to 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 <functional>
#else
# include <boost/functional/hash.hpp>
#endif
#include <boost/detail/lightweight_test.hpp>
#include <boost/limits.hpp>
#include <boost/mpl/assert.hpp>
#include <boost/type_traits/is_base_and_derived.hpp>
#include "./compile_time.hpp"
void pointer_tests()
{
compile_time_tests((int**) 0);
compile_time_tests((void**) 0);
HASH_NAMESPACE::hash<int*> x1;
HASH_NAMESPACE::hash<int*> x2;
int int1;
int int2;
BOOST_TEST(x1(0) == x2(0));
BOOST_TEST(x1(&int1) == x2(&int1));
BOOST_TEST(x1(&int2) == x2(&int2));
#if defined(TEST_EXTENSIONS)
BOOST_TEST(x1(&int1) == HASH_NAMESPACE::hash_value(&int1));
BOOST_TEST(x1(&int2) == HASH_NAMESPACE::hash_value(&int2));
// This isn't specified in Peter's proposal:
BOOST_TEST(x1(0) == 0);
#endif
}
int main()
{
pointer_tests();
return boost::report_errors();
}

85
test/hash_range_test.cpp Normal file
View File

@@ -0,0 +1,85 @@
// Copyright Daniel James 2005-2006. Use, modification, and distribution are
// subject to 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/detail/lightweight_test.hpp>
#ifdef TEST_EXTENSIONS
#include <boost/limits.hpp>
#include <boost/mpl/assert.hpp>
#include <boost/type_traits/is_base_and_derived.hpp>
#include <vector>
void hash_range_tests()
{
std::vector<int> empty, values1, values2, values3, values4, values5;
values1.push_back(0);
values2.push_back(10);
values3.push_back(10);
values3.push_back(20);
values4.push_back(15);
values4.push_back(75);
values5.push_back(10);
values5.push_back(20);
values5.push_back(15);
values5.push_back(75);
values5.push_back(10);
values5.push_back(20);
std::vector<int> x;
std::size_t x_seed = 0;
BOOST_TEST(x_seed == HASH_NAMESPACE::hash_range(x.begin(), x.end()));
BOOST_TEST(HASH_NAMESPACE::hash_range(empty.begin(), empty.end())
== HASH_NAMESPACE::hash_range(x.begin(), x.end()));
BOOST_TEST(HASH_NAMESPACE::hash_range(empty.begin(), empty.end())
!= HASH_NAMESPACE::hash_range(values1.begin(), values1.end()));
x.push_back(10);
HASH_NAMESPACE::hash_combine(x_seed, 10);
BOOST_TEST(x_seed == HASH_NAMESPACE::hash_range(x.begin(), x.end()));
BOOST_TEST(HASH_NAMESPACE::hash_range(empty.begin(), empty.end())
!= HASH_NAMESPACE::hash_range(x.begin(), x.end()));
BOOST_TEST(HASH_NAMESPACE::hash_range(values2.begin(), values2.end())
== HASH_NAMESPACE::hash_range(x.begin(), x.end()));
x.push_back(20);
HASH_NAMESPACE::hash_combine(x_seed, 20);
BOOST_TEST(x_seed == HASH_NAMESPACE::hash_range(x.begin(), x.end()));
BOOST_TEST(HASH_NAMESPACE::hash_range(empty.begin(), empty.end())
!= HASH_NAMESPACE::hash_range(x.begin(), x.end()));
BOOST_TEST(HASH_NAMESPACE::hash_range(values2.begin(), values2.end())
!= HASH_NAMESPACE::hash_range(x.begin(), x.end()));
BOOST_TEST(HASH_NAMESPACE::hash_range(values3.begin(), values3.end())
== HASH_NAMESPACE::hash_range(x.begin(), x.end()));
std::size_t seed = HASH_NAMESPACE::hash_range(values3.begin(), values3.end());
HASH_NAMESPACE::hash_range(seed, values4.begin(), values4.end());
HASH_NAMESPACE::hash_range(seed, x.begin(), x.end());
BOOST_TEST(seed == HASH_NAMESPACE::hash_range(values5.begin(), values5.end()));
}
#endif
int main()
{
hash_range_tests();
return boost::report_errors();
}

View File

@@ -0,0 +1,67 @@
// Copyright Daniel James 2005-2006. Use, modification, and distribution are
// subject to 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(CONTAINER_TYPE)
#error "CONTAINER_TYPE not defined"
#else
#include <boost/preprocessor/cat.hpp>
namespace BOOST_PP_CAT(CONTAINER_TYPE, _tests)
{
template <class T>
void integer_tests(T* = 0)
{
const int number_of_containers = 11;
T containers[number_of_containers];
for(int i = 0; i < 5; ++i) {
for(int j = 0; j < i; ++j)
containers[i].push_back(0);
}
containers[5].push_back(1);
containers[6].push_back(1);
containers[6].push_back(1);
containers[7].push_back(-1);
containers[8].push_back(-1);
containers[8].push_back(-1);
containers[9].push_back(1);
containers[9].push_back(-1);
containers[10].push_back(-1);
containers[10].push_back(1);
HASH_NAMESPACE::hash<T> hasher;
for(int i2 = 0; i2 < number_of_containers; ++i2) {
BOOST_TEST(hasher(containers[i2]) == hasher(containers[i2]));
BOOST_TEST(hasher(containers[i2]) ==
HASH_NAMESPACE::hash_value(containers[i2]));
BOOST_TEST(hasher(containers[i2])
== HASH_NAMESPACE::hash_range(
containers[i2].begin(), containers[i2].end()));
for(int j2 = i2 + 1; j2 < number_of_containers; ++j2) {
BOOST_TEST(
(containers[i2] == containers[j2]) ==
(hasher(containers[i2]) == hasher(containers[j2]))
);
}
}
}
void BOOST_PP_CAT(CONTAINER_TYPE, _hash_integer_tests())
{
integer_tests((CONTAINER_TYPE<char>*) 0);
integer_tests((CONTAINER_TYPE<int>*) 0);
integer_tests((CONTAINER_TYPE<unsigned long>*) 0);
integer_tests((CONTAINER_TYPE<double>*) 0);
}
}
#undef CONTAINER_TYPE
#endif

40
test/hash_set_test.cpp Normal file
View File

@@ -0,0 +1,40 @@
// Copyright Daniel James 2005-2006. Use, modification, and distribution are
// subject to 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/detail/lightweight_test.hpp>
#ifdef TEST_EXTENSIONS
#include <set>
using std::set;
#define CONTAINER_TYPE set
#include "./hash_set_test.hpp"
using std::multiset;
#define CONTAINER_TYPE multiset
#include "./hash_set_test.hpp"
#endif
int main()
{
#ifdef TEST_EXTENSIONS
set_tests::set_hash_integer_tests();
multiset_tests::multiset_hash_integer_tests();
#endif
return boost::report_errors();
}

65
test/hash_set_test.hpp Normal file
View File

@@ -0,0 +1,65 @@
// Copyright Daniel James 2005-2006. Use, modification, and distribution are
// subject to 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(CONTAINER_TYPE)
#error "CONTAINER_TYPE not defined"
#else
#include <boost/preprocessor/cat.hpp>
namespace BOOST_PP_CAT(CONTAINER_TYPE, _tests)
{
template <class T>
void integer_tests(T* = 0)
{
const int number_of_containers = 11;
T containers[number_of_containers];
for(int i = 0; i < 5; ++i) {
for(int j = 0; j < i; ++j)
containers[i].insert(0);
}
containers[6].insert(1);
containers[7].insert(1);
containers[7].insert(1);
containers[8].insert(-1);
containers[9].insert(-1);
containers[9].insert(-1);
containers[10].insert(-1);
containers[10].insert(1);
HASH_NAMESPACE::hash<T> hasher;
for(int i2 = 0; i2 < number_of_containers; ++i2) {
BOOST_TEST(hasher(containers[i2]) == hasher(containers[i2]));
BOOST_TEST(hasher(containers[i2]) ==
HASH_NAMESPACE::hash_value(containers[i2]));
BOOST_TEST(hasher(containers[i2])
== HASH_NAMESPACE::hash_range(
containers[i2].begin(), containers[i2].end()));
for(int j2 = i2 + 1; j2 < number_of_containers; ++j2) {
BOOST_TEST(
(containers[i2] == containers[j2]) ==
(hasher(containers[i2]) == hasher(containers[j2]))
);
}
}
}
void BOOST_PP_CAT(CONTAINER_TYPE, _hash_integer_tests())
{
integer_tests((CONTAINER_TYPE<char>*) 0);
integer_tests((CONTAINER_TYPE<int>*) 0);
integer_tests((CONTAINER_TYPE<unsigned long>*) 0);
integer_tests((CONTAINER_TYPE<double>*) 0);
}
}
#undef CONTAINER_TYPE
#endif

78
test/hash_string_test.cpp Normal file
View File

@@ -0,0 +1,78 @@
// Copyright Daniel James 2005-2006. Use, modification, and distribution are
// subject to 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 <functional>
#else
# include <boost/functional/hash.hpp>
#endif
#include <boost/detail/lightweight_test.hpp>
#include <boost/limits.hpp>
#include <boost/mpl/assert.hpp>
#include <boost/type_traits/is_base_and_derived.hpp>
#include <string>
#include "./compile_time.hpp"
void string_tests()
{
compile_time_tests((std::string*) 0);
HASH_NAMESPACE::hash<std::string> x1;
HASH_NAMESPACE::hash<std::string> x2;
BOOST_TEST(x1("Hello") == x2(std::string("Hel") + "lo"));
BOOST_TEST(x1("") == x2(std::string()));
#if defined(TEST_EXTENSIONS)
std::string value1;
std::string value2("Hello");
BOOST_TEST(x1(value1) == HASH_NAMESPACE::hash_value(value1));
BOOST_TEST(x1(value2) == HASH_NAMESPACE::hash_value(value2));
BOOST_TEST(HASH_NAMESPACE::hash_value(value1) ==
HASH_NAMESPACE::hash_range(value1.begin(), value1.end()));
BOOST_TEST(HASH_NAMESPACE::hash_value(value2) ==
HASH_NAMESPACE::hash_range(value2.begin(), value2.end()));
#endif
}
#if !defined(BOOST_NO_STD_WSTRING)
void wstring_tests()
{
compile_time_tests((std::wstring*) 0);
HASH_NAMESPACE::hash<std::wstring> x1;
HASH_NAMESPACE::hash<std::wstring> x2;
BOOST_TEST(x1(L"Hello") == x2(std::wstring(L"Hel") + L"lo"));
BOOST_TEST(x1(L"") == x2(std::wstring()));
#if defined(TEST_EXTENSIONS)
std::wstring value1;
std::wstring value2(L"Hello");
BOOST_TEST(x1(value1) == HASH_NAMESPACE::hash_value(value1));
BOOST_TEST(x1(value2) == HASH_NAMESPACE::hash_value(value2));
BOOST_TEST(HASH_NAMESPACE::hash_value(value1) ==
HASH_NAMESPACE::hash_range(value1.begin(), value1.end()));
BOOST_TEST(HASH_NAMESPACE::hash_value(value2) ==
HASH_NAMESPACE::hash_range(value2.begin(), value2.end()));
#endif
}
#endif
int main()
{
string_tests();
#if !defined(BOOST_NO_STD_WSTRING)
wstring_tests();
#endif
return boost::report_errors();
}

View File

@@ -0,0 +1,64 @@
// Copyright Daniel James 2005-2006. Use, modification, and distribution are
// subject to 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)
// On some compilers hash_value isn't available for arrays, so I test it
// separately from the main array tests.
#include "./config.hpp"
#ifdef TEST_EXTENSIONS
# ifdef TEST_STD_INCLUDES
# include <functional>
# else
# include <boost/functional/hash.hpp>
# endif
#endif
#include <boost/detail/lightweight_test.hpp>
#ifdef TEST_EXTENSIONS
void array_int_test()
{
const int array1[25] = {
26, -43, 32, 65, 45,
12, 67, 32, 12, 23,
0, 0, 0, 0, 0,
8, -12, 23, 65, 45,
-1, 93, -54, 987, 3
};
HASH_NAMESPACE::hash<int[25]> hasher1;
int array2[1] = {3};
HASH_NAMESPACE::hash<int[1]> hasher2;
int array3[2] = {2, 3};
HASH_NAMESPACE::hash<int[2]> hasher3;
BOOST_TEST(hasher1(array1) == HASH_NAMESPACE::hash_value(array1));
BOOST_TEST(hasher2(array2) == HASH_NAMESPACE::hash_value(array2));
BOOST_TEST(hasher3(array3) == HASH_NAMESPACE::hash_value(array3));
}
void two_dimensional_array_test()
{
int array[3][2] = {{-5, 6}, {7, -3}, {26, 1}};
HASH_NAMESPACE::hash<int[3][2]> hasher;
BOOST_TEST(hasher(array) == HASH_NAMESPACE::hash_value(array));
}
#endif
int main()
{
#ifdef TEST_EXTENSIONS
array_int_test();
two_dimensional_array_test();
#endif
return boost::report_errors();
}

35
test/hash_vector_test.cpp Normal file
View File

@@ -0,0 +1,35 @@
// Copyright Daniel James 2005-2006. Use, modification, and distribution are
// subject to 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/detail/lightweight_test.hpp>
#ifdef TEST_EXTENSIONS
#include <vector>
using std::vector;
#define CONTAINER_TYPE vector
#include "./hash_sequence_test.hpp"
#endif // TEST_EXTENSIONS
int main()
{
#ifdef TEST_EXTENSIONS
vector_tests::vector_hash_integer_tests();
#endif
return boost::report_errors();
}

22
test/link_ext_test.cpp Normal file
View File

@@ -0,0 +1,22 @@
// Copyright Daniel James 2006. Use, modification, and distribution are
// subject to 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)
#define HASH_NAMESPACE boost
#include <boost/functional/hash.hpp>
#include <boost/detail/lightweight_test.hpp>
#include <vector>
int f(std::size_t hash1, int* x1) {
// Check that HASH_NAMESPACE::hash<int*> works in both files.
HASH_NAMESPACE::hash<int*> ptr_hasher;
BOOST_TEST(hash1 == ptr_hasher(x1));
// Check that std::vector<std::size_t> is avaiable in this file.
std::vector<std::size_t> x;
x.push_back(*x1);
HASH_NAMESPACE::hash<std::vector<std::size_t> > vector_hasher;
return vector_hasher(x) != HASH_NAMESPACE::hash_value(x);
}

18
test/link_no_ext_test.cpp Normal file
View File

@@ -0,0 +1,18 @@
// Copyright Daniel James 2005-2006. Use, modification, and distribution are
// subject to 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)
#define HASH_NAMESPACE boost
#define BOOST_HASH_NO_EXTENSIONS
#include <boost/functional/hash.hpp>
#include <boost/detail/lightweight_test.hpp>
extern int f(std::size_t, int*);
int main() {
HASH_NAMESPACE::hash<int*> ptr_hasher;
int x = 55;
BOOST_TEST(!f(ptr_hasher(&x), &x));
return boost::report_errors();
}

9
test/link_test.cpp Normal file
View File

@@ -0,0 +1,9 @@
// Copyright Daniel James 2005-2006. Use, modification, and distribution are
// subject to 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/hash.hpp>
extern int f();
int main() { return f(); }

8
test/link_test_2.cpp Normal file
View File

@@ -0,0 +1,8 @@
// Copyright Daniel James 2005-2006. Use, modification, and distribution are
// subject to 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/hash.hpp>
int f() { return 0; }