Compare commits

...

148 Commits

Author SHA1 Message Date
Peter Dimov
06e1b613f0 Add benchmark/char_seq.cpp 2022-06-08 17:48:06 +03:00
Peter Dimov
12be64b71e Update benchmark/unordered.cpp 2022-06-08 14:18:28 +03:00
Peter Dimov
4e2811c4e1 Add old_boost_hash to benchmark/unordered.cpp 2022-06-07 02:33:18 +03:00
Peter Dimov
2dc57b745f Output number of collisions in benchmark/unordered.cpp 2022-06-07 02:08:00 +03:00
Peter Dimov
de618bf974 Add benchmark/unordered.cpp 2022-06-06 22:45:49 +03:00
Peter Dimov
87c9eefe6e Add ubuntu-22.04 to posix-cmake jobs 2022-06-04 18:17:35 +03:00
Peter Dimov
98bbd2ba56 Disable hash_fs_path_test for msvc-14.0 cxxstd=latest 2022-06-04 15:53:54 +03:00
Peter Dimov
08ea1677be Disable -Wshadow and -Wconversion for the fs path tests because of gcc-4.8 2022-06-04 14:25:47 +03:00
Peter Dimov
3d3350646f Disable use of <filesystem> under MinGW (fails on GHA) 2022-06-04 14:19:01 +03:00
Peter Dimov
884ce4b708 Disable -Wsign-conversion for GCC 8 2022-06-04 02:01:50 +03:00
Peter Dimov
db1e23b611 Disable -Wsign-conversion for GCC in hash_reference_values.cpp 2022-06-04 01:49:26 +03:00
Peter Dimov
5ddcd7c8e7 Disable detail_is_range_test2.cpp under CMake 2022-06-03 22:44:32 +03:00
Peter Dimov
0e2e911df5 Attempt to fix -Wsign-conversion warnings under some GCC versions 2022-06-03 22:43:04 +03:00
Peter Dimov
b3c9b35a13 Disable -Wc99-extensions for Clang 2022-06-03 21:38:02 +03:00
Peter Dimov
c9c77cb104 Update warning suppressions 2022-06-03 20:59:41 +03:00
Peter Dimov
873a60d009 Disable -Wvariadic-macros for Clang as well 2022-06-03 20:19:01 +03:00
Peter Dimov
b8d315fac5 Update is_range, disable -Wvariadic-macros for GCC 2022-06-03 20:14:07 +03:00
Peter Dimov
e0e86a1413 Add detail_is_range_test2.cpp 2022-06-03 20:01:26 +03:00
Peter Dimov
866bd60dd3 Reject ranges that have themselves as their value_type (e.g. filesystem::path) 2022-06-03 19:52:03 +03:00
Peter Dimov
6781cff622 Add hash_fs_path_test.cpp 2022-06-03 19:31:33 +03:00
Peter Dimov
dd605d0d1c Link CMake tests to Boost::utility 2022-05-30 03:05:54 +03:00
Peter Dimov
dd172db079 Remove infinity special cases for libstdc++ 2022-05-30 02:52:22 +03:00
Peter Dimov
e04ca1f442 Match floating point hash values in 32 bit mode 2022-05-30 02:35:00 +03:00
Peter Dimov
0eada2ae93 Revert hash_combine for floats 2022-05-30 02:26:12 +03:00
Peter Dimov
943ef0ab82 Avoid -Wconversion with is_signed and enums 2022-05-30 02:19:54 +03:00
Peter Dimov
14f8934bff Revert integral hashing 2022-05-30 01:57:56 +03:00
Peter Dimov
f08204e29a Revert hash_value for std::complex 2022-05-29 21:59:17 +03:00
Peter Dimov
7ad0365048 Merge branch 'develop' into feature/refresh 2022-05-12 18:00:03 +03:00
Peter Dimov
b3e424b650 Add gcc-12, clang-13, clang-14 to GHA 2022-05-11 22:23:41 +03:00
Peter Dimov
d2986d9a64 Test boost::core::string_view in hash_string_test2 2022-04-29 02:01:46 +03:00
Peter Dimov
000276988f Add hash_string_test2 2022-04-28 21:13:23 +03:00
Peter Dimov
355603c0c2 Update ci.yml 2022-03-09 16:36:40 +02:00
Peter Dimov
33cd0a5964 Merge pull request #21 from cmazakas/doc-fixes
Doc fixes
2022-02-09 00:06:51 +02:00
Christian Mazakas
fc11122353 Refactor links to no longer open up a new tab 2022-02-08 13:18:06 -08:00
Christian Mazakas
cb233af718 Update [listing]s to become proper source code blocks 2022-02-08 13:18:01 -08:00
Christian Mazakas
8d820ee7d0 Remove unnecessary cross-references 2022-02-08 13:17:19 -08:00
Peter Dimov
3800d712d5 Merge pull request #20 from cmazakas/qbk-cleanup
Remove unneeded QuickBook and sample files from docs
2022-02-08 01:36:02 +02:00
Christian Mazakas
dee871f45c Remove unneeded QuickBook and sample files from docs 2022-02-07 13:11:32 -08:00
Peter Dimov
143a55ea3b Add doc/.gitignore 2022-02-05 02:13:07 +02:00
Peter Dimov
4ab431f12f Update index.html 2022-02-05 02:12:27 +02:00
Christian Mazakas
773307fe1c Add Reference section to AsciiDoc 2022-02-04 15:16:18 -08:00
Christian Mazakas
06db43a56a Add Copyright section to AsciiDoc 2022-02-04 15:16:18 -08:00
Christian Mazakas
5906cba1a0 Add Acknowledgements section 2022-02-04 15:16:18 -08:00
Christian Mazakas
b2222c2755 Add Links section to AsciiDoc 2022-02-04 15:16:18 -08:00
Christian Mazakas
6600a26460 Add Rationale to AsciiDoc 2022-02-04 15:16:18 -08:00
Christian Mazakas
c95e02fe85 Add Change List to AsciiDoc 2022-02-04 15:16:18 -08:00
Christian Mazakas
334eac8166 Add Disabling section to AsciiDoc 2022-02-04 15:16:18 -08:00
Christian Mazakas
21dbdb9b47 Add Portability section to AsciiDoc 2022-02-04 15:16:18 -08:00
Christian Mazakas
74f9abe52c Add Combining Hashes section to AsciiDoc 2022-02-04 15:16:18 -08:00
Christian Mazakas
37f3e6fcb7 Add Extending boost::hash section to AsciiDoc 2022-02-04 15:16:18 -08:00
Christian Mazakas
301c76646c Add Tutorial section to AsciiDoc 2022-02-04 15:16:18 -08:00
Christian Mazakas
a67e350fd9 Add Introduction section to AsciiDoc 2022-02-04 15:16:18 -08:00
Christian Mazakas
2d23e7e056 Update Jamfile to produce AsciiDoc and add corresponding file stubs 2022-02-03 15:33:02 -08:00
Peter Dimov
9bdebb3df4 Merge branch 'develop' into feature/refresh 2021-10-19 17:37:20 +03:00
Peter Dimov
e9ffeceeab Merge branch 'develop' into feature/reference 2021-10-19 01:57:24 +03:00
Peter Dimov
4a685b2b16 Add address-model=32 tests to ci.yml 2021-10-19 01:07:05 +03:00
Peter Dimov
8315ec2ba7 Comment out (uint128)-1 test under GCC 9 and below 2021-10-18 03:20:23 +03:00
Peter Dimov
1a4888cdb4 Add (uint128)-1 comment 2021-10-18 03:01:41 +03:00
Peter Dimov
9e938aca41 Revert "Update (uint128)-1 test"
This reverts commit cab5c6c8d7.
2021-10-18 03:00:17 +03:00
Peter Dimov
7abcf22762 Update long double infinity reference values for 32 bit GCC-like without fpclassify 2021-10-18 02:38:25 +03:00
Peter Dimov
dbb410b7ef Update long double reference values for 32 bit GCC 2021-10-18 02:31:06 +03:00
Peter Dimov
cab5c6c8d7 Update (uint128)-1 test 2021-10-18 02:21:58 +03:00
Peter Dimov
526e4d472d Add reference values for std::complex 2021-10-18 02:16:50 +03:00
Peter Dimov
fca37b0d43 Fix long double infinity 2021-10-18 01:11:24 +03:00
Peter Dimov
0a795c62a3 Update (uint128)-1 and long double infinity values 2021-10-18 00:55:31 +03:00
Peter Dimov
4ff953b568 Fix clang 2021-10-18 00:37:46 +03:00
Peter Dimov
cfbc94b128 Update infinity reference values 2021-10-18 00:15:16 +03:00
Peter Dimov
f0bed67909 Update long double values for g++ 64 bit 2021-10-18 00:01:15 +03:00
Peter Dimov
1c27af1e2e Add hash_reference_values.cpp 2021-10-17 23:54:39 +03:00
Peter Dimov
ebac66dc1e Print hash_info output in ci.yml 2021-10-17 20:22:06 +03:00
Peter Dimov
f0e75dd010 Reenable clang-win in appveyor.yml 2021-10-17 20:20:57 +03:00
Peter Dimov
5959103346 Extend __GNUC__ warning suppression to __clang__ 2021-10-17 20:13:56 +03:00
Peter Dimov
3c3948ccdb Take care of size_t -> int warnings under g++ 4.8 2021-10-17 19:54:23 +03:00
Peter Dimov
998d8da8c8 Disable warning in test/check_float_funcs.cpp 2021-10-17 19:54:12 +03:00
Peter Dimov
bdc2840738 Update test/Jamfile 2021-10-17 19:52:16 +03:00
Peter Dimov
56f790d896 Add hash_integral_test.cpp 2021-10-17 19:36:53 +03:00
Peter Dimov
355c1cd7a4 Add hash_number_test2 2021-10-17 19:28:51 +03:00
Peter Dimov
c9b2d6fc90 Reenable clang-win in appveyor.yml 2021-10-17 19:08:15 +03:00
Peter Dimov
2424ada9f9 Bias integral values so that small integers hash to themselves even when having a wide type 2021-10-17 19:03:15 +03:00
Peter Dimov
faea988310 Revert change to hash_number_test.cpp 2021-10-17 17:49:10 +03:00
Peter Dimov
64c367734d Print hash_info output in ci.yml 2021-10-17 16:45:40 +03:00
Peter Dimov
6d84f9a41b Print size_t and floating point widths in hash_info 2021-10-17 16:43:02 +03:00
Peter Dimov
aaa1f441ac GCC 32 bit under Windows has an 80 bit long double in 12 bytes, not 16 2021-10-17 16:17:44 +03:00
Peter Dimov
3487450f62 Add CMake tests to ci.yml 2021-10-17 08:46:35 +03:00
Peter Dimov
8f163568f4 Add test/CMakeLists.txt 2021-10-17 08:37:07 +03:00
Peter Dimov
a4cbaa95b3 Regenerate CMakeLists.txt 2021-10-17 08:35:11 +03:00
Peter Dimov
6ffc99adb7 Update test/Jamfile 2021-10-17 08:22:24 +03:00
Peter Dimov
bb99a2b1ae Leave detail/limits.hpp a stub; update test 2021-10-17 08:15:10 +03:00
Peter Dimov
f05e8840d2 Remove float support files 2021-10-17 08:14:35 +03:00
Peter Dimov
dff8843bb2 Remove unnecessary include 2021-10-17 07:52:03 +03:00
Peter Dimov
15ae39e176 Implement floating point hashing inline in hash.hpp 2021-10-17 07:47:34 +03:00
Peter Dimov
39e4a4f184 Switch to type_traits/enable_if to eliminate the Core dependency 2021-10-17 07:10:47 +03:00
Peter Dimov
88fbad7438 Remove Borland workarounds 2021-10-17 04:00:10 +03:00
Peter Dimov
0737c56fec Move boost::hash into hash.hpp, delete specializations 2021-10-17 03:54:41 +03:00
Peter Dimov
2b9251069f Move std::tuple support to detail/hash_tuple.hpp 2021-10-17 02:40:29 +03:00
Peter Dimov
a63c85007f Move std::unique_ptr, std::shared_ptr support into hash.hpp 2021-10-17 02:14:19 +03:00
Peter Dimov
7a29dee42a Move std::pair support into hash.hpp 2021-10-17 02:11:51 +03:00
Peter Dimov
a0a6fa0616 Move std::complex support to hash.hpp 2021-10-17 02:03:50 +03:00
Peter Dimov
fe66085fbc Add hash_forward_list_test.cpp 2021-10-17 01:15:01 +03:00
Peter Dimov
24598bd45f Take care of g++ warning on 4294967291 2021-10-17 00:47:28 +03:00
Peter Dimov
7f2a43226e Take care of size_t -> int warnings under g++ 4.8 2021-10-17 00:31:08 +03:00
Peter Dimov
668f28660d Disable warning in test/check_float_funcs.cpp 2021-10-17 00:17:01 +03:00
Peter Dimov
9348a89fb4 Fix msvc-14.1 errors caused by their unconstrained stdext::hash_value overload (!) 2021-10-17 00:09:20 +03:00
Peter Dimov
3f2612d36e Update test/Jamfile, turn warnings-as-errors=on, fix g++ warning 2021-10-16 22:22:29 +03:00
Peter Dimov
3cf502b34c Add generic hash_value functions for ranges to hash.hpp, remove those from extensions.hpp 2021-10-16 22:12:31 +03:00
Peter Dimov
b2e3beea3f Remove unnecessary warning suppression 2021-10-16 21:02:28 +03:00
Peter Dimov
d308495a67 Add detail/is_unordered_range.hpp 2021-10-16 21:01:07 +03:00
Peter Dimov
00c837d523 Add detail/is_contiguous_range.hpp 2021-10-16 20:54:51 +03:00
Peter Dimov
415f2fafe2 Add detail/is_range.hpp 2021-10-16 20:44:32 +03:00
Peter Dimov
9bbedce029 Add missing include 2021-10-16 18:46:00 +03:00
Peter Dimov
2fc970b6ae Simplify hash_value for integrals 2021-10-16 17:29:02 +03:00
Peter Dimov
4e11c855cb Remove use of <functional> 2021-10-16 16:55:27 +03:00
Peter Dimov
bd379e1a46 Remove VMS workaround 2021-10-16 16:54:08 +03:00
Peter Dimov
b201ff97a8 Use Config macros for detecting C++17 headers 2021-10-16 16:43:11 +03:00
Peter Dimov
e89fe04479 Remove more BOOST_NO_FUNCTION_TEMPLATE_ORDERING workarounds 2021-10-16 16:26:42 +03:00
Peter Dimov
7ce3f759ec Remove __DMC__ workarounds 2021-10-16 16:24:56 +03:00
Peter Dimov
917ac6a88a Remove BOOST_HASH_CHAR_TRAITS 2021-10-16 16:22:33 +03:00
Peter Dimov
9782883434 Remove BOOST_NO_FUNCTION_TEMPLATE_ORDERING workarounds 2021-10-16 16:20:54 +03:00
Peter Dimov
f0ef7b8e84 Remove BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION workarounds 2021-10-16 16:18:02 +03:00
Peter Dimov
21f2b5e1db Fix hash_combine_impl to only test for a specific bit width and not for concrete types 2021-10-12 19:52:37 +03:00
Peter Dimov
b55fbc9252 Update key in libraries.json 2021-10-12 19:51:11 +03:00
Peter Dimov
a0465807c7 Switch to 18.04 in ci.yml 2021-10-12 19:06:13 +03:00
Peter Dimov
e03c31c9bc Add -I examples to depinst 2021-10-12 17:56:31 +03:00
Peter Dimov
c4d9a95b82 Update appveyor.yml 2021-10-12 17:40:47 +03:00
Peter Dimov
5f5a5d0648 Merge pull request #14 from eldiener/develop
[skip ci] Add "cxxstd" json field
2021-10-12 17:33:26 +03:00
Peter Dimov
fd2781afc9 Update ci.yml 2021-08-10 17:56:49 +03:00
Peter Dimov
d045cf2ecb Update ci.yml 2021-08-10 17:48:23 +03:00
Peter Dimov
b4e4bf577f Add -I examples to depinst 2021-08-10 17:37:22 +03:00
Peter Dimov
310ca091a2 Add .github/workflows/ci.yml 2021-08-10 17:32:10 +03:00
Peter Dimov
e69c4c830e Update CMakeLists.txt 2021-06-10 01:18:25 +03:00
Edward Diener
aaf0d2525f [skip ci] Add "cxxstd" json field. The "cxxstd" json field is being added to each Boost library's meta json information for libraries in order to specify the minumum C++ standard compilation level. The value of this field matches one of the values for 'cxxstd' in Boost.Build. The purpose of doing this is to provide information for the Boost website documentation for each library which will specify the minimum C++ standard compilation that an end-user must employ in order to use the particular library. This will aid end-users who want to know if they can successfully use a Boost library based on their C++ compiler's compilation level, without having to search the library's documentation to find this out. 2021-01-19 12:42:27 -05:00
Glen Fernandes
171c012d47 Merge pull request #11 from boostorg/mclow-patch-1
Remove use of non-existant Boost.Config macro BOOST_NO_CXX11_HDR_MEMORY
2020-10-25 14:06:10 -04:00
Marshall Clow
e0331c0bd4 Remove use of non-existant Boost.Config macro BOOST_NO_CXX11_HDR_MEMORY
Thanks to Jeff Trull for the catch.
2020-09-10 20:09:23 -07:00
Marshall Clow
e30bbab19f Merge pull request #9 from eldiener/develop
Changes for Embarcadero C++ clang-based compilers, targeting Boost 1.74. Change __BORLANDC__ to BOOST_BORLANDC, which is defined in Boost conf…
2020-04-16 07:53:06 -07:00
Edward Diener
1818113f4c Change __BORLANDC__ to BOOST_BORLANDC, which is defined in Boost config for the Embarcadero non-clang-based compilers. 2020-03-23 11:50:36 -04:00
Peter Dimov
8a7fc581ed Merge branch 'develop' 2019-12-23 17:21:52 +02:00
Marshall Clow
5048576921 Merge pull request #6 from andrascii/develop
Fixed compiler guards for use of `std::unary_function` for C++17 compliance
2019-08-12 23:14:49 -07:00
Andrey
5f858645a0 Removed usage of std::unary_function for C++17 compliance 2019-08-10 12:37:49 +03:00
Andrey
fd310d2706 Removed usage of std::unary_function for C++17 compliance 2019-08-10 11:59:22 +03:00
Andrey
90a0e36638 Removed usage of std::unary_function for C++17 compliance 2019-08-09 17:23:16 +03:00
Peter Dimov
1ce57acc41 Merge pull request #5 from Mike-Devel/min_cmake
[CMake] Add minimal cmake file
2019-01-23 19:23:08 +02:00
Mike Dev
81a65eb01c [CMake] Add minimal cmake file
Only supports "add_subdirectory" workflow and doesn't
run unit-tests. It generates a INTERFACE cmake target
that other libraries can use to express their dependency
on Boost.ContainerHash and get usage requiremments,
such as the include directory.
2019-01-02 23:04:19 +01:00
Daniel James
9fbda1a98a Fix appveyor build (cherry-pick) 2018-04-16 06:43:14 +01:00
Daniel James
62f29ea201 Merge branch 'develop' (early part) 2018-04-16 06:42:45 +01:00
Daniel James
f054fe932f Fix appveyor build 2018-04-15 23:29:47 +01:00
Daniel James
83a874ed49 More general purpose support for iterators with odd reference type (trac #13501)
In the last release I added explicit support for `vector<bool>` which wasn't
working with libc++ because the iterator's `operator*` returned a proxy
reference type. Other implementations return a `bool` for const iterators, so
they happened to work okay.

This solves the problem in a more general purpose way by instantiating
`hash_combine` for the iterator `value_type`. So the type returned by
`operator*` will be implicitly casted to the correct type.
2018-04-15 22:44:33 +01:00
Daniel James
59f9543c10 Use boost 1.67.0 in travis and appveyor 2018-04-15 22:44:19 +01:00
Daniel James
a6da082784 Stop using -Werror
So that there aren't any failures because of warnings in other modules.
2018-04-15 22:44:19 +01:00
71 changed files with 4047 additions and 3647 deletions

View File

@@ -1,4 +1,5 @@
# Copyright 2017 Daniel James
# Copyright 2016-2021 Peter Dimov
# Distributed under the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at http://boost.org/LICENSE_1_0.txt)
@@ -6,31 +7,66 @@ version: 1.0.{build}-{branch}
shallow_clone: true
branches:
only:
- master
- develop
- /feature\/.*/
environment:
matrix:
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013
TOOLSET: msvc-10.0,msvc-11.0,msvc-12.0
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
TOOLSET: msvc-14.0
TOOLSET: msvc-9.0,msvc-10.0,msvc-11.0
ADDRMD: 32
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
TOOLSET: msvc-12.0,msvc-14.0
ADDRMD: 32,64
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
TOOLSET: msvc-14.1
CXXSTD: 14,17
ADDRMD: 32,64
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
TOOLSET: msvc-14.2
CXXSTD: 14,17,latest
ADDRMD: 32,64
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
TOOLSET: clang-win
CXXSTD: 14,17,latest
ADDRMD: 64
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
ADDPATH: C:\cygwin\bin;
TOOLSET: gcc
CXXSTD: 03,11,14,1z
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
ADDPATH: C:\cygwin64\bin;
TOOLSET: gcc
CXXSTD: 03,11,14,1z
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
ADDPATH: C:\mingw\bin;
TOOLSET: gcc
CXXSTD: 03,11,14,1z
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
ADDPATH: C:\mingw-w64\x86_64-6.3.0-posix-seh-rt_v5-rev1\mingw64\bin;
TOOLSET: gcc
CXXSTD: 03,11,14,1z
install:
- cd c:\projects
- curl -sSL -o boost.7z https://dl.bintray.com/boostorg/release/1.66.0/source/boost_1_66_0.7z
- 7z x boost.7z
- set BOOST_ROOT=c:\projects\boost_1_66_0
- rd /s /q %BOOST_ROOT%\boost\functional\hash
- cd %BOOST_ROOT%\tools\build
- set BOOST_BRANCH=develop
- if "%APPVEYOR_REPO_BRANCH%" == "master" set BOOST_BRANCH=master
- cd ..
- git clone -b %BOOST_BRANCH% --depth 1 https://github.com/boostorg/boost.git boost-root
- cd boost-root
- git submodule update --init tools/boostdep
- xcopy /s /e /q %APPVEYOR_BUILD_FOLDER% libs\container_hash\
- python tools/boostdep/depinst/depinst.py -I examples container_hash
- cmd /c bootstrap
- cd %APPVEYOR_BUILD_FOLDER%
- echo. 2>Jamroot.jam
- b2 -d0 headers
build: off
test_script:
- PATH=%ADDPATH%%PATH%
- if not "%CXXSTD%" == "" set CXXSTD=cxxstd=%CXXSTD%
- cd %APPVEYOR_BUILD_FOLDER%\test
- cmd /c %BOOST_ROOT%\tools\build\b2 -j 3 toolset=%TOOLSET% %CXXSTD% include=%APPVEYOR_BUILD_FOLDER%\include include=%BOOST_ROOT% --verbose-test hash_info
- cmd /c %BOOST_ROOT%\tools\build\b2 -j 3 toolset=%TOOLSET% %CXXSTD% include=%APPVEYOR_BUILD_FOLDER%\include include=%BOOST_ROOT%
- if not "%ADDRMD%" == "" set ADDRMD=address-model=%ADDRMD%
- b2 -j3 --verbose-test libs/container_hash/test//hash_info toolset=%TOOLSET% %CXXSTD% %ADDRMD% variant=debug,release embed-manifest-via=linker
- b2 -j3 libs/container_hash/test toolset=%TOOLSET% %CXXSTD% %ADDRMD% variant=debug,release embed-manifest-via=linker

386
.github/workflows/ci.yml vendored Normal file
View File

@@ -0,0 +1,386 @@
name: CI
on:
pull_request:
push:
branches:
- master
- develop
- feature/**
env:
UBSAN_OPTIONS: print_stacktrace=1
jobs:
posix:
strategy:
fail-fast: false
matrix:
include:
- toolset: gcc-4.8
cxxstd: "03,11"
os: ubuntu-18.04
install: g++-4.8-multilib
address-model: 32,64
- toolset: gcc-5
cxxstd: "03,11,14,1z"
os: ubuntu-18.04
install: g++-5-multilib
address-model: 32,64
- toolset: gcc-6
cxxstd: "03,11,14,1z"
os: ubuntu-18.04
install: g++-6-multilib
address-model: 32,64
- toolset: gcc-7
cxxstd: "03,11,14,17"
os: ubuntu-18.04
install: g++-7-multilib
address-model: 32,64
- toolset: gcc-8
cxxstd: "03,11,14,17,2a"
os: ubuntu-18.04
install: g++-8-multilib
address-model: 32,64
- toolset: gcc-9
cxxstd: "03,11,14,17,2a"
os: ubuntu-20.04
install: g++-9-multilib
address-model: 32,64
- toolset: gcc-10
cxxstd: "03,11,14,17,2a"
os: ubuntu-20.04
install: g++-10-multilib
address-model: 32,64
- toolset: gcc-11
cxxstd: "03,11,14,17,20"
os: ubuntu-20.04
install: g++-11-multilib
address-model: 32,64
- toolset: gcc-12
cxxstd: "03,11,14,17,20"
os: ubuntu-22.04
install: g++-12-multilib
address-model: 32,64
- toolset: clang
compiler: clang++-3.9
cxxstd: "03,11,14"
os: ubuntu-18.04
install: clang-3.9
- toolset: clang
compiler: clang++-4.0
cxxstd: "03,11,14"
os: ubuntu-18.04
install: clang-4.0
- toolset: clang
compiler: clang++-5.0
cxxstd: "03,11,14,1z"
os: ubuntu-18.04
install: clang-5.0
- toolset: clang
compiler: clang++-6.0
cxxstd: "03,11,14,17"
os: ubuntu-18.04
install: clang-6.0
- toolset: clang
compiler: clang++-7
cxxstd: "03,11,14,17"
os: ubuntu-18.04
install: clang-7
- toolset: clang
compiler: clang++-8
cxxstd: "03,11,14,17"
os: ubuntu-20.04
install: clang-8
- toolset: clang
compiler: clang++-9
cxxstd: "03,11,14,17,2a"
os: ubuntu-20.04
install: clang-9
- toolset: clang
compiler: clang++-10
cxxstd: "03,11,14,17,2a"
os: ubuntu-20.04
- toolset: clang
compiler: clang++-11
cxxstd: "03,11,14,17,2a"
os: ubuntu-20.04
- toolset: clang
compiler: clang++-12
cxxstd: "03,11,14,17,20"
os: ubuntu-20.04
- toolset: clang
compiler: clang++-13
cxxstd: "03,11,14,17,20"
os: ubuntu-22.04
install: clang-13
- toolset: clang
compiler: clang++-14
cxxstd: "03,11,14,17,20"
os: ubuntu-22.04
install: clang-14
- toolset: clang
cxxstd: "03,11,14,17,2a"
os: macos-10.15
runs-on: ${{matrix.os}}
steps:
- uses: actions/checkout@v2
- name: Install packages
if: matrix.install
run: sudo apt install ${{matrix.install}}
- name: Setup Boost
run: |
echo GITHUB_REPOSITORY: $GITHUB_REPOSITORY
LIBRARY=${GITHUB_REPOSITORY#*/}
echo LIBRARY: $LIBRARY
echo "LIBRARY=$LIBRARY" >> $GITHUB_ENV
echo GITHUB_BASE_REF: $GITHUB_BASE_REF
echo GITHUB_REF: $GITHUB_REF
REF=${GITHUB_BASE_REF:-$GITHUB_REF}
REF=${REF#refs/heads/}
echo REF: $REF
BOOST_BRANCH=develop && [ "$REF" == "master" ] && BOOST_BRANCH=master || true
echo BOOST_BRANCH: $BOOST_BRANCH
cd ..
git clone -b $BOOST_BRANCH --depth 1 https://github.com/boostorg/boost.git boost-root
cd boost-root
cp -r $GITHUB_WORKSPACE/* libs/$LIBRARY
git submodule update --init tools/boostdep
python tools/boostdep/depinst/depinst.py -I examples --git_args "--jobs 3" $LIBRARY
./bootstrap.sh
./b2 -d0 headers
- name: Create user-config.jam
if: matrix.compiler
run: |
echo "using ${{matrix.toolset}} : : ${{matrix.compiler}} ;" > ~/user-config.jam
- name: Run tests
run: |
cd ../boost-root
export ADDRMD=${{matrix.address-model}}
./b2 -j3 --verbose-test libs/$LIBRARY/test//hash_info toolset=${{matrix.toolset}} cxxstd=${{matrix.cxxstd}} ${ADDRMD:+address-model=$ADDRMD} variant=debug,release
./b2 -j3 libs/$LIBRARY/test toolset=${{matrix.toolset}} cxxstd=${{matrix.cxxstd}} ${ADDRMD:+address-model=$ADDRMD} variant=debug,release
windows:
strategy:
fail-fast: false
matrix:
include:
- toolset: msvc-14.0
cxxstd: 14,latest
addrmd: 32,64
os: windows-2019
- toolset: msvc-14.2
cxxstd: "14,17,20,latest"
addrmd: 32,64
os: windows-2019
- toolset: msvc-14.3
cxxstd: "14,17,20,latest"
addrmd: 32,64
os: windows-2022
- toolset: clang-win
cxxstd: "14,17,latest"
addrmd: 32,64
os: windows-2022
- toolset: gcc
cxxstd: "03,11,14,17,2a"
addrmd: 64
os: windows-2019
runs-on: ${{matrix.os}}
steps:
- uses: actions/checkout@v2
- name: Setup Boost
shell: cmd
run: |
echo GITHUB_REPOSITORY: %GITHUB_REPOSITORY%
for /f %%i in ("%GITHUB_REPOSITORY%") do set LIBRARY=%%~nxi
echo LIBRARY: %LIBRARY%
echo LIBRARY=%LIBRARY%>>%GITHUB_ENV%
echo GITHUB_BASE_REF: %GITHUB_BASE_REF%
echo GITHUB_REF: %GITHUB_REF%
if "%GITHUB_BASE_REF%" == "" set GITHUB_BASE_REF=%GITHUB_REF%
set BOOST_BRANCH=develop
for /f %%i in ("%GITHUB_BASE_REF%") do if "%%~nxi" == "master" set BOOST_BRANCH=master
echo BOOST_BRANCH: %BOOST_BRANCH%
cd ..
git clone -b %BOOST_BRANCH% --depth 1 https://github.com/boostorg/boost.git boost-root
cd boost-root
xcopy /s /e /q %GITHUB_WORKSPACE% libs\%LIBRARY%\
git submodule update --init tools/boostdep
python tools/boostdep/depinst/depinst.py -I examples --git_args "--jobs 3" %LIBRARY%
cmd /c bootstrap
b2 -d0 headers
- name: Run tests
shell: cmd
run: |
cd ../boost-root
b2 -j3 --verbose-test libs/%LIBRARY%/test//hash_info toolset=${{matrix.toolset}} cxxstd=${{matrix.cxxstd}} address-model=${{matrix.addrmd}} variant=debug,release embed-manifest-via=linker
b2 -j3 libs/%LIBRARY%/test toolset=${{matrix.toolset}} cxxstd=${{matrix.cxxstd}} address-model=${{matrix.addrmd}} variant=debug,release embed-manifest-via=linker
posix-cmake-subdir:
strategy:
fail-fast: false
matrix:
include:
- os: ubuntu-18.04
- os: ubuntu-20.04
- os: ubuntu-22.04
- os: macos-10.15
runs-on: ${{matrix.os}}
steps:
- uses: actions/checkout@v2
- name: Install packages
if: matrix.install
run: sudo apt install ${{matrix.install}}
- name: Setup Boost
run: |
echo GITHUB_REPOSITORY: $GITHUB_REPOSITORY
LIBRARY=${GITHUB_REPOSITORY#*/}
echo LIBRARY: $LIBRARY
echo "LIBRARY=$LIBRARY" >> $GITHUB_ENV
echo GITHUB_BASE_REF: $GITHUB_BASE_REF
echo GITHUB_REF: $GITHUB_REF
REF=${GITHUB_BASE_REF:-$GITHUB_REF}
REF=${REF#refs/heads/}
echo REF: $REF
BOOST_BRANCH=develop && [ "$REF" == "master" ] && BOOST_BRANCH=master || true
echo BOOST_BRANCH: $BOOST_BRANCH
cd ..
git clone -b $BOOST_BRANCH --depth 1 https://github.com/boostorg/boost.git boost-root
cd boost-root
cp -r $GITHUB_WORKSPACE/* libs/$LIBRARY
git submodule update --init tools/boostdep
python tools/boostdep/depinst/depinst.py --git_args "--jobs 3" $LIBRARY
- name: Use library with add_subdirectory
run: |
cd ../boost-root/libs/$LIBRARY/test/cmake_subdir_test
mkdir __build__ && cd __build__
cmake ..
cmake --build .
ctest --output-on-failure --no-tests=error
posix-cmake-install:
strategy:
fail-fast: false
matrix:
include:
- os: ubuntu-18.04
- os: ubuntu-20.04
- os: ubuntu-22.04
- os: macos-10.15
runs-on: ${{matrix.os}}
steps:
- uses: actions/checkout@v2
- name: Install packages
if: matrix.install
run: sudo apt install ${{matrix.install}}
- name: Setup Boost
run: |
echo GITHUB_REPOSITORY: $GITHUB_REPOSITORY
LIBRARY=${GITHUB_REPOSITORY#*/}
echo LIBRARY: $LIBRARY
echo "LIBRARY=$LIBRARY" >> $GITHUB_ENV
echo GITHUB_BASE_REF: $GITHUB_BASE_REF
echo GITHUB_REF: $GITHUB_REF
REF=${GITHUB_BASE_REF:-$GITHUB_REF}
REF=${REF#refs/heads/}
echo REF: $REF
BOOST_BRANCH=develop && [ "$REF" == "master" ] && BOOST_BRANCH=master || true
echo BOOST_BRANCH: $BOOST_BRANCH
cd ..
git clone -b $BOOST_BRANCH --depth 1 https://github.com/boostorg/boost.git boost-root
cd boost-root
cp -r $GITHUB_WORKSPACE/* libs/$LIBRARY
git submodule update --init tools/boostdep
python tools/boostdep/depinst/depinst.py --git_args "--jobs 3" $LIBRARY
- name: Configure
run: |
cd ../boost-root
mkdir __build__ && cd __build__
cmake -DBOOST_INCLUDE_LIBRARIES=$LIBRARY -DCMAKE_INSTALL_PREFIX=~/.local ..
- name: Install
run: |
cd ../boost-root/__build__
cmake --build . --target install
- name: Use the installed library
run: |
cd ../boost-root/libs/$LIBRARY/test/cmake_install_test && mkdir __build__ && cd __build__
cmake -DCMAKE_INSTALL_PREFIX=~/.local ..
cmake --build .
ctest --output-on-failure --no-tests=error
posix-cmake-test:
strategy:
fail-fast: false
matrix:
include:
- os: ubuntu-18.04
- os: ubuntu-20.04
- os: ubuntu-22.04
- os: macos-10.15
runs-on: ${{matrix.os}}
steps:
- uses: actions/checkout@v2
- name: Install packages
if: matrix.install
run: sudo apt install ${{matrix.install}}
- name: Setup Boost
run: |
echo GITHUB_REPOSITORY: $GITHUB_REPOSITORY
LIBRARY=${GITHUB_REPOSITORY#*/}
echo LIBRARY: $LIBRARY
echo "LIBRARY=$LIBRARY" >> $GITHUB_ENV
echo GITHUB_BASE_REF: $GITHUB_BASE_REF
echo GITHUB_REF: $GITHUB_REF
REF=${GITHUB_BASE_REF:-$GITHUB_REF}
REF=${REF#refs/heads/}
echo REF: $REF
BOOST_BRANCH=develop && [ "$REF" == "master" ] && BOOST_BRANCH=master || true
echo BOOST_BRANCH: $BOOST_BRANCH
cd ..
git clone -b $BOOST_BRANCH --depth 1 https://github.com/boostorg/boost.git boost-root
cd boost-root
cp -r $GITHUB_WORKSPACE/* libs/$LIBRARY
git submodule update --init tools/boostdep
python tools/boostdep/depinst/depinst.py --git_args "--jobs 3" $LIBRARY
- name: Configure
run: |
cd ../boost-root
mkdir __build__ && cd __build__
cmake -DBOOST_INCLUDE_LIBRARIES=$LIBRARY -DBUILD_TESTING=ON ..
- name: Build tests
run: |
cd ../boost-root/__build__
cmake --build . --target tests
- name: Run tests
run: |
cd ../boost-root/__build__
ctest --output-on-failure --no-tests=error

View File

@@ -12,11 +12,11 @@ matrix:
include:
- compiler: gcc
env: |
USER_CONFIG="using gcc : : g++-4.8 -Werror ;"
USER_CONFIG="using gcc : : g++-4.8 ;"
CXXSTD=03,11
- compiler: g++-7
env: |
USER_CONFIG="using gcc : : g++-7 -Werror ;"
USER_CONFIG="using gcc : : g++-7 ;"
CXXSTD=11,14,17
addons:
apt:
@@ -26,16 +26,16 @@ matrix:
- ubuntu-toolchain-r-test
- compiler: clang
env: |
USER_CONFIG="using clang : : clang++ -Werror ;"
USER_CONFIG="using clang : : clang++ ;"
CXXSTD=03,11
- compiler: clang
env: |
USER_CONFIG="using clang : : clang++ -Werror -D_HAS_AUTO_PTR_ETC=0 ;"
USER_CONFIG="using clang : : clang++ -D_HAS_AUTO_PTR_ETC=0 ;"
CXXSTD=11
before_script:
- export BOOST_VERSION=1.66.0
- export BOOST_FILENAME=boost_1_66_0
- export BOOST_VERSION=1.67.0
- export BOOST_FILENAME=boost_1_67_0
- export BOOST_ROOT=${HOME}/boost
- cd ${TRAVIS_BUILD_DIR}
- touch Jamroot.jam

25
CMakeLists.txt Normal file
View File

@@ -0,0 +1,25 @@
# Generated by `boostdep --cmake container_hash`
# Copyright 2020, 2021 Peter Dimov
# Distributed under the Boost Software License, Version 1.0.
# https://www.boost.org/LICENSE_1_0.txt
cmake_minimum_required(VERSION 3.5...3.20)
project(boost_container_hash VERSION "${BOOST_SUPERPROJECT_VERSION}" LANGUAGES CXX)
add_library(boost_container_hash INTERFACE)
add_library(Boost::container_hash ALIAS boost_container_hash)
target_include_directories(boost_container_hash INTERFACE include)
target_link_libraries(boost_container_hash
INTERFACE
Boost::config
Boost::type_traits
)
if(BUILD_TESTING AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/test/CMakeLists.txt")
add_subdirectory(test)
endif()

101
benchmark/char_seq.cpp Normal file
View File

@@ -0,0 +1,101 @@
// Copyright 2022 Peter Dimov.
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#define _CRT_SECURE_NO_WARNINGS
#include <boost/container_hash/hash.hpp>
#include <boost/core/detail/splitmix64.hpp>
#include <boost/core/type_name.hpp>
#include <boost/config.hpp>
#include <cstddef>
#include <cstdio>
#include <cstdint>
#include <string>
#include <vector>
#include <deque>
#include <list>
#include <chrono>
// test_hash_speed
template<class T, class V> void test_hash_speed( int N, V const& v )
{
std::vector<T> w;
w.reserve( N );
for( int i = 0; i < N; ++i )
{
w.emplace_back( v[i].begin(), v[i].end() );
}
typedef std::chrono::steady_clock clock_type;
clock_type::time_point t1 = clock_type::now();
std::size_t q = 0;
boost::hash<T> const h;
for( int i = 0; i < N; ++i )
{
q += h( w[i] );
}
clock_type::time_point t2 = clock_type::now();
long long ms1 = std::chrono::duration_cast<std::chrono::milliseconds>( t2 - t1 ).count();
std::string type = boost::core::type_name<T>();
#if defined( _MSC_VER )
std::printf( "%25s : q=%20Iu, %lld ms\n", type.c_str(), q, ms1 );
#else
std::printf( "%25s : q=%20zu, %lld ms\n", type.c_str(), q, ms1 );
#endif
}
int main()
{
int const N = 1048576 * 8;
std::vector<std::string> v;
{
v.reserve( N );
boost::detail::splitmix64 rnd;
for( int i = 0; i < N; ++i )
{
char buffer[ 64 ];
unsigned long long k = rnd();
if( k & 1 )
{
sprintf( buffer, "prefix_%llu_suffix", k );
}
else
{
sprintf( buffer, "{%u}", static_cast<unsigned>( k ) );
}
v.push_back( buffer );
}
}
std::puts( "Char sequence hashing test:\n" );
test_hash_speed< std::string >( N, v );
test_hash_speed< std::vector<char> >( N, v );
test_hash_speed< std::deque<char> >( N, v );
test_hash_speed< std::list<char> >( N, v );
std::puts( "" );
}

389
benchmark/unordered.cpp Normal file
View File

@@ -0,0 +1,389 @@
// Copyright 2022 Peter Dimov.
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#define _CRT_SECURE_NO_WARNINGS
#include <boost/container_hash/hash.hpp>
#include <boost/unordered_set.hpp>
#include <boost/core/detail/splitmix64.hpp>
#include <boost/core/type_name.hpp>
#include <boost/config.hpp>
#include <cstddef>
#include <cstdio>
#include <cstdint>
#include <string>
#include <vector>
#include <chrono>
#include <functional>
// mul31_hash
class mul31_hash
{
public:
std::size_t operator()( std::string const& st ) const BOOST_NOEXCEPT
{
char const * p = st.data();
std::size_t n = st.size();
#if SIZE_MAX > UINT32_MAX
std::size_t h = 0xCBF29CE484222325ull;
#else
std::size_t h = 0x811C9DC5u;
#endif
for( std::size_t i = 0; i < n; ++i )
{
h = h * 31 + static_cast<unsigned char>( p[i] );
}
return h;
}
};
// mul31_unrolled_hash
template<int Bits> struct mul31_unrolled_hash_impl;
template<> struct mul31_unrolled_hash_impl<32>
{
std::size_t operator()( std::string const& st ) const BOOST_NOEXCEPT
{
char const * p = st.data();
std::size_t n = st.size();
std::size_t h = 0x811C9DC5u;
while( n >= 4 )
{
h = h * (31u * 31u * 31u * 31u)
+ static_cast<unsigned char>( p[0] ) * (31u * 31u * 31u)
+ static_cast<unsigned char>( p[1] ) * (31u * 31u)
+ static_cast<unsigned char>( p[2] ) * 31u
+ static_cast<unsigned char>( p[3] );
p += 4;
n -= 4;
}
while( n > 0 )
{
h = h * 31u + static_cast<unsigned char>( *p );
++p;
--n;
}
return h;
}
};
template<> struct mul31_unrolled_hash_impl<64>
{
std::size_t operator()( std::string const& st ) const BOOST_NOEXCEPT
{
char const * p = st.data();
std::size_t n = st.size();
std::size_t h = 0xCBF29CE484222325ull;
while( n >= 8 )
{
h = h * (31ull * 31ull * 31ull * 31ull * 31ull * 31ull * 31ull * 31ull)
+ static_cast<unsigned char>( p[0] ) * (31ull * 31ull * 31ull * 31ull * 31ull * 31ull * 31ull)
+ static_cast<unsigned char>( p[1] ) * (31ull * 31ull * 31ull * 31ull * 31ull * 31ull)
+ static_cast<unsigned char>( p[2] ) * (31ull * 31ull * 31ull * 31ull * 31ull)
+ static_cast<unsigned char>( p[3] ) * (31ull * 31ull * 31ull * 31ull)
+ static_cast<unsigned char>( p[4] ) * (31ull * 31ull * 31ull)
+ static_cast<unsigned char>( p[5] ) * (31ull * 31ull)
+ static_cast<unsigned char>( p[6] ) * 31ull
+ static_cast<unsigned char>( p[7] );
p += 8;
n -= 8;
}
while( n > 0 )
{
h = h * 31u + static_cast<unsigned char>( *p );
++p;
--n;
}
return h;
}
};
struct mul31_unrolled_hash: mul31_unrolled_hash_impl< std::numeric_limits<std::size_t>::digits > {};
// fnv1a_hash
template<int Bits> struct fnv1a_hash_impl;
template<> struct fnv1a_hash_impl<32>
{
std::size_t operator()( std::string const& s ) const
{
std::size_t h = 0x811C9DC5u;
char const * first = s.data();
char const * last = first + s.size();
for( ; first != last; ++first )
{
h ^= static_cast<unsigned char>( *first );
h *= 0x01000193ul;
}
return h;
}
};
template<> struct fnv1a_hash_impl<64>
{
std::size_t operator()( std::string const& s ) const
{
std::size_t h = 0xCBF29CE484222325ull;
char const * first = s.data();
char const * last = first + s.size();
for( ; first != last; ++first )
{
h ^= static_cast<unsigned char>( *first );
h *= 0x00000100000001B3ull;
}
return h;
}
};
struct fnv1a_hash: fnv1a_hash_impl< std::numeric_limits<std::size_t>::digits > {};
// old_boost_hash
class old_boost_hash
{
public:
std::size_t operator()( std::string const& st ) const BOOST_NOEXCEPT
{
char const * p = st.data();
std::size_t n = st.size();
std::size_t h = 0;
for( std::size_t i = 0; i < n; ++i )
{
h ^= static_cast<unsigned char>( p[i] ) + 0x9e3779b9 + ( h << 6 ) + ( h >> 2 );
}
return h;
}
};
// test_hash_speed
template<class H, class V> void test_hash_speed( int N, V const& v )
{
typedef std::chrono::steady_clock clock_type;
clock_type::time_point t1 = clock_type::now();
std::size_t q = 0;
H const h;
for( int i = 0; i < N; ++i )
{
q += h( v[i] );
}
clock_type::time_point t2 = clock_type::now();
long long ms1 = std::chrono::duration_cast<std::chrono::milliseconds>( t2 - t1 ).count();
std::string hash = boost::core::type_name<H>();
#if defined( _MSC_VER )
std::printf( "%25s : q=%20Iu, %lld ms\n", hash.c_str(), q, ms1 );
#else
std::printf( "%25s : q=%20zu, %lld ms\n", hash.c_str(), q, ms1 );
#endif
}
// test_hash_collision
template<class H, class V> void test_hash_collision( int N, V const& v, std::size_t n )
{
boost::unordered_set<std::size_t> s;
H const h;
for( int i = 0; i < N; ++i )
{
s.insert( h( v[i] ) );
}
std::string hash = boost::core::type_name<H>();
#if defined( _MSC_VER )
std::printf( "%25s : c=%Iu\n", hash.c_str(), n - s.size() );
#else
std::printf( "%25s : c=%zu\n", hash.c_str(), n - s.size() );
#endif
}
// test_container_speed
template<class V, class S> void test4( int N, V const& v, char const * hash, S s )
{
typedef std::chrono::steady_clock clock_type;
clock_type::time_point t1 = clock_type::now();
for( int i = 0; i < N; ++i )
{
s.insert( v[ i * 16 ] );
}
clock_type::time_point t2 = clock_type::now();
std::size_t q = 0;
for( int i = 0; i < 16 * N; ++i )
{
q += s.count( v[ i ] );
}
clock_type::time_point t3 = clock_type::now();
long long ms1 = std::chrono::duration_cast<std::chrono::milliseconds>( t2 - t1 ).count();
long long ms2 = std::chrono::duration_cast<std::chrono::milliseconds>( t3 - t2 ).count();
std::size_t n = s.bucket_count();
std::size_t m = 0;
std::size_t c = 0;
for( std::size_t i = 0; i < n; ++i )
{
std::size_t k = s.bucket_size( i );
if( k > 1 )
{
c += k - 1;
}
if( k > m )
{
m = k;
}
}
#if defined( _MSC_VER )
std::printf( "%25s : n=%Iu, m=%Iu, c=%Iu, q=%Iu, %lld + %lld ms\n", hash, n, m, c, q, ms1, ms2 );
#else
std::printf( "%25s : n=%zu, m=%zu, c=%zu, q=%zu, %lld + %lld ms\n", hash, n, m, c, q, ms1, ms2 );
#endif
}
template<class K, class H, class V> void test_container_speed( int N, V const& v )
{
boost::unordered_set<K, H> s( 0 );
test4( N, v, boost::core::type_name<H>().c_str(), s );
}
int main()
{
int const N = 1048576 / 2; // 1048576 is too much for 32 bit
std::vector<std::string> v;
{
v.reserve( N * 16 );
boost::detail::splitmix64 rnd;
for( int i = 0; i < 16 * N; ++i )
{
char buffer[ 64 ];
unsigned long long k = rnd();
if( k & 1 )
{
sprintf( buffer, "prefix_%llu_suffix", k );
}
else
{
sprintf( buffer, "{%u}", static_cast<unsigned>( k ) );
}
v.push_back( buffer );
}
}
std::puts( "Hash speed test:\n" );
test_hash_speed<mul31_hash>( N * 16, v );
test_hash_speed<mul31_unrolled_hash>( N * 16, v );
test_hash_speed<fnv1a_hash>( N * 16, v );
test_hash_speed<old_boost_hash>( N * 16, v );
test_hash_speed<boost::hash<std::string> >( N * 16, v );
test_hash_speed<std::hash<std::string> >( N * 16, v );
std::puts( "" );
std::puts( "Hash collision test:\n" );
{
std::size_t n = 0;
{
boost::unordered_set<std::string> s;
for( int i = 0; i < N * 16; ++i )
{
s.insert( v[i] );
}
n = s.size();
}
test_hash_collision<mul31_hash>( N * 16, v, n );
test_hash_collision<mul31_unrolled_hash>( N * 16, v, n );
test_hash_collision<fnv1a_hash>( N * 16, v, n );
test_hash_collision<old_boost_hash>( N * 16, v, n );
test_hash_collision<boost::hash<std::string> >( N * 16, v, n );
test_hash_collision<std::hash<std::string> >( N * 16, v, n );
}
std::puts( "" );
typedef std::string K;
std::puts( "Container speed test:\n" );
test_container_speed<K, mul31_hash>( N, v );
test_container_speed<K, mul31_unrolled_hash>( N, v );
test_container_speed<K, fnv1a_hash>( N, v );
test_container_speed<K, old_boost_hash>( N, v );
test_container_speed<K, boost::hash<std::string> >( N, v );
test_container_speed<K, std::hash<std::string> >( N, v );
std::puts( "" );
}

2
doc/.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
/html/
/pdf/

View File

@@ -3,23 +3,20 @@
# 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)
using boostbook ;
using quickbook ;
import asciidoctor ;
xml hash : hash.qbk ;
boostbook standalone : hash :
<xsl:param>boost.root=../../../..
html hash.html : hash.adoc ;
<xsl:param>chunk.first.sections=1
<xsl:param>chunk.section.depth=2
<xsl:param>generate.section.toc.level=2
<xsl:param>toc.section.depth=1
<xsl:param>toc.max.depth=1
<format>pdf:<xsl:param>boost.url.prefix=http://www.boost.org/doc/libs/release/libs/container_hash/doc/html
;
install html_ : hash.html : <location>html ;
pdf hash.pdf : hash.adoc ;
explicit hash.pdf ;
install pdf_ : hash.pdf : <location>pdf ;
explicit pdf_ ;
###############################################################################
alias boostdoc : hash ;
explicit boostdoc ;
alias boostrelease ;
explicit boostrelease ;
alias boostdoc ;
explicit boostdoc ;
alias boostrelease : html_ ;
explicit boostrelease ;

View File

@@ -1,222 +0,0 @@
[/ Copyright 2005-2008 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) ]
[template ticket[number]'''<ulink url="https://svn.boost.org/trac/boost/ticket/'''[number]'''">'''#[number]'''</ulink>''']
[section:changes Change Log]
[h2 Boost 1.33.0]
* Initial Release
[h2 Boost 1.33.1]
* Fixed the points example, as pointed out by 沈慧峰.
[h2 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.
* Update the portable example to hopefully be more generally portable.
[h2 Boost 1.34.1]
* [@http://svn.boost.org/trac/boost/ticket/952 Ticket 952]:
Suppress incorrect 64-bit warning on Visual C++.
[h2 Boost 1.35.0]
* Support for `long long`, `std::complex`.
* Improved algorithm for hashing floating point numbers:
* Improved portablity, as described by Daniel Krügler in
[@http://lists.boost.org/boost-users/2005/08/13418.php
a post to the boost users list].
* Fits more information into each combine loop, which can reduce the
the number of times combine is called and hopefully give a better
quality hash function.
* Improved the algorithm for hashing floating point numbers.
* On Cygwin use a binary hash function for floating point numbers, as
Cygwin doesn't have decent floating point functions for `long double`.
* Never uses `fpclass` which doesn't support `long double`.
* [@http://svn.boost.org/trac/boost/ticket/1064 Ticket 1064]:
Removed unnecessary use of `errno`.
* Explicitly overload for more built in types.
* Minor improvements to the documentation.
* A few bug and warning fixes:
* [@http://svn.boost.org/trac/boost/ticket/1509 Ticket 1509]:
Suppress another Visual C++ warning.
* Some workarounds for the Sun compilers.
[h2 Boost 1.36.0]
* Stop using OpenBSD's dodgy `std::numeric_limits`.
* Using the boost typedefs for `long long` and `unsigned long long`.
* Move the extensions into their own header.
[h2 Boost 1.37.0]
* [@http://svn.boost.org/trac/boost/ticket/2264 Ticket 2264]:
In Visual C++, always use C99 float functions for `long double` and `float` as
the C++ overloads aren't always availables.
[h2 Boost 1.38.0]
* Changed the warnings in the deprecated headers from 1.34.0 to errors. These
will be removed in a future version of Boost.
* Moved detail headers out of `boost/container_hash/detail`, since they are part of
functional/hash, not container_hash. `boost/container_hash/detail/container_fwd.hpp`
has been moved to `boost/detail/container_fwd.hpp` as it's used outside of
this library, the others have been moved to `boost/functional/hash/detail`.
[h2 Boost 1.39.0]
* Move the hash_fwd.hpp implementation into the hash subdirectory, leaving a
forwarding header in the old location. You should still use the old location,
the new location is mainly for implementation and possible modularization.
* [@https://svn.boost.org/trac/boost/ticket/2412 Ticket 2412]: Removed deprecated
headers.
* [@https://svn.boost.org/trac/boost/ticket/2957 Ticket 2957]: Fix configuration
for vxworks.
[h2 Boost 1.40.0]
* Automatically configure the float functions using template metaprogramming
instead of trying to configure every possibility manually.
* Workaround for when STLport doesn't support long double.
[h2 Boost 1.42.0]
* Reduce the number of warnings for Visual C++ warning level 4.
* Some code formatting changes to fit lines into 80 characters.
* Rename an internal namespace.
[h2 Boost 1.43.0]
* [@https://svn.boost.org/trac/boost/ticket/3866 Ticket 3866]:
Don't foward declare containers when using gcc's parallel library,
allow user to stop forward declaration by defining the
`BOOST_DETAIL_NO_CONTAINER_FWD` macro.
* [@https://svn.boost.org/trac/boost/ticket/4038 Ticket 4038]:
Avoid hashing 0.5 and 0 to the same number.
* Stop using deprecated `BOOST_HAS_*` macros.
[h2 Boost 1.44.0]
* Add option to prevent implicit conversions when calling `hash_value` by
defining `BOOST_HASH_NO_IMPLICIT_CASTS`. When using `boost::hash`
for a type that does not have `hash_value` declared but does have
an implicit conversion to a type that does, it would use that
implicit conversion to hash it. Which can sometimes go very wrong,
e.g. using a conversion to bool and only hashing to 2 possible
values. Since fixing this is a breaking change and was only
approached quite late in the release cycle with little discussion
it's opt-in for now. This, or something like it, will become the
default in a future version.
[h2 Boost 1.46.0]
* Avoid warning due with gcc's `-Wconversion` flag.
[h2 Boost 1.50.0]
* [@http://svn.boost.org/trac/boost/ticket/6771 Ticket 6771]:
Avoid gcc's `-Wfloat-equal` warning.
* [@http://svn.boost.org/trac/boost/ticket/6806 Ticket 6806]:
Support `std::array` and `std::tuple` when available.
* Add deprecation warning to the long deprecated
`boost/container_hash/detail/container_fwd.hpp`.
[h2 Boost 1.51.0]
* Support the standard smart pointers.
* `hash_value` now implemented using SFINAE to avoid implicit casts to built
in types when calling it.
* Updated to use the new config macros.
[h2 Boost 1.52.0]
* Restore `enum` support, which was accidentally removed in the last version.
* New floating point hasher - will hash the binary representation on more
platforms, which should be faster.
[h2 Boost 1.53.0]
* Add support for `boost::int128_type` and `boost::uint128_type` where
available - currently only `__int128` and `unsigned __int128` on some
versions of gcc.
* On platforms that are known to have the standard floating point functions,
don't use automatic detection - which can break if there are ambiguous
overloads.
* Fix undefined behaviour when using the binary float hash (Thomas Heller).
[h2 Boost 1.54.0]
* [@https://svn.boost.org/trac/boost/ticket/7957 Ticket 7957]:
Fixed a typo.
[h2 Boost 1.55.0]
* Simplify a SFINAE check so that it will hopefully work on Sun 5.9
([ticket 8822]).
* Suppress Visual C++ infinite loop warning ([ticket 8568]).
[h2 Boost 1.56.0]
* Removed some Visual C++ 6 workarounds.
* Ongoing work on improving `hash_combine`. This changes the combine function
which was previously defined in the reference documentation.
[h2 Boost 1.58.0]
* Fixed strict aliasing violation
([@https://github.com/boostorg/container_hash/pull/3 GitHub #3]).
[h2 Boost 1.63.0]
* Fixed some warnings.
* Only define hash for `std::wstring` when we know we have a `wchar_t`.
Otherwise there's a compile error as there's no overload for hashing
the characters in wide strings ([ticket 8552]).
[h2 Boost 1.64.0]
* Fix for recent versions of Visual C++ which have removed `std::unary_function`
and `std::binary_function` ([ticket 12353]).
[h2 Boost 1.65.0]
* Support for `char16_t`, `char32_t`, `u16string`, `u32string`
[h2 Boost 1.66.0]
* Avoid float comparison warning when using Clang - this workaround was
already in place for GCC, and was used when Clang pretends to be GCC,
but the warning was appearing when running Clang in other contexts.
[h2 Boost 1.67.0]
* Moved library into its own module, `container_hash`.
* Moved headers for new module name, now at:
`<boost/container_hash/hash.hpp>`,
`<boost/container_hash/hash_fwd.hpp>`,
`<boost/container_hash/extensions.hpp>`.
* Added forwarding headers to support the old headers locations.
* Support `std::string_view`, `std::error_code`, `std::error_condition`
`std::optional`, `std::variant`, `std::monostate` where available.
* Update include paths from other Boost libraries.
* Manually write out tuple overloads, rather than using the
preprocessor to generate them. Should improve usability, due
to better error messages, and easier debugging.
* Fix tutorial example ([ticket 11017]).
* Quick fix for hashing `vector<bool>` when using libc++. Will try to introduce
a more general fix in the next release.
[endsect]

View File

@@ -1,29 +0,0 @@
[/ Copyright 2005-2008 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/container_hash/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.adoc Normal file
View File

@@ -0,0 +1,24 @@
= Boost.ContainerHash
:toc: left
:toclevels: 2
:idprefix:
:docinfo: private-footer
:source-highlighter: rouge
:nofooter:
:sectlinks:
:source-language: c++
:leveloffset: +1
include::hash/intro.adoc[]
include::hash/tutorial.adoc[]
include::hash/custom.adoc[]
include::hash/combine.adoc[]
include::hash/portability.adoc[]
include::hash/disable.adoc[]
include::hash/changes.adoc[]
include::hash/rationale.adoc[]
include::hash/ref.adoc[]
include::hash/links.adoc[]
include::hash/thanks.adoc[]
include::hash/copyright.adoc[]

View File

@@ -1,29 +0,0 @@
[library Boost.ContainerHash
[quickbook 1.5]
[authors [James, Daniel]]
[copyright 2005 2006 2007 2008 Daniel James]
[purpose A TR1 hash function object that can be extended to hash user
defined types]
[category higher-order]
[id hash]
[dirname container_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])
]
]
[def __issues__
[@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1837.pdf
Library Extension Technical Report Issues List]]
[include:hash intro.qbk]
[include:hash tutorial.qbk]
[include:hash portability.qbk]
[include:hash disable.qbk]
[include:hash changes.qbk]
[include:hash rationale.qbk]
[xinclude ref.xml]
[include:hash links.qbk]
[include:hash thanks.qbk]

132
doc/hash/changes.adoc Normal file
View File

@@ -0,0 +1,132 @@
[#changes]
= Change Log
:cpp: C++
:int128: __int128
:idprefix: changes_
== Boost 1.67.0
* Moved library into its own module, `container_hash`.
* Moved headers for new module name, now at: `<boost/container_hash/hash.hpp>`, `<boost/container_hash/hash_fwd.hpp>`, `<boost/container_hash/extensions.hpp>`.
* Added forwarding headers to support the old headers locations.
* Support `std::string_view`, `std::error_code`, `std::error_condition`, `std::optional`, `std::variant`, `std::monostate` where available.
* Update include paths from other Boost libraries.
* Manually write out tuple overloads, rather than using the preprocessor to generate them. Should improve usability, due to better error messages, and easier debugging.
* Fix tutorial example (https://svn.boost.org/trac/boost/ticket/11017[#11017]).
* Quick fix for hashing `vector<bool>` when using lib{cpp}. Will try to introduce a more general fix in the next release.
== Boost 1.66.0
* Avoid float comparison warning when using Clang - this workaround was already in place for GCC, and was used when Clang pretends to be GCC, but the warning was appearing when running Clang in other contexts.
== Boost 1.65.0
* Support for `char16_t`, `char32_t`, `u16string`, `u32string`
== Boost 1.64.0
* Fix for recent versions of Visual {cpp} which have removed `std::unary_function` and `std::binary_function` (https://svn.boost.org/trac/boost/ticket/12353[#12353]).
== Boost 1.63.0
* Fixed some warnings.
* Only define hash for `std::wstring` when we know we have a `wchar_t`. Otherwise there's a compile error as there's no overload for hashing the characters in wide strings (https://svn.boost.org/trac/boost/ticket/8552[#8552]).
== Boost 1.58.0
* Fixed strict aliasing violation (https://github.com/boostorg/container_hash/issues/3[GitHub #3]).
== Boost 1.56.0
* Removed some Visual {cpp} 6 workarounds.
* Ongoing work on improving `hash_combine`. This changes the combine function which was previously defined in the reference documentation.
== Boost 1.55.0
* Simplify a SFINAE check so that it will hopefully work on Sun 5.9 (https://svn.boost.org/trac10/ticket/8822[#8822]).
* Suppress Visual {cpp} infinite loop warning (https://svn.boost.org/trac10/ticket/8568[#8568]).
== Boost 1.54.0
* https://svn.boost.org/trac/boost/ticket/7957[Ticket 7957]: Fixed a typo.
== Boost 1.53.0
* Add support for `boost::int128_type` and `boost::uint128_type` where available - currently only `{int128}` and `unsigned {int128}` on some versions of gcc.
* On platforms that are known to have the standard floating point functions, don't use automatic detection - which can break if there are ambiguous overloads.
* Fix undefined behaviour when using the binary `float` hash (Thomas Heller).
== Boost 1.52.0
* Restore `enum` support, which was accidentally removed in the last version.
* New floating point hasher - will hash the binary representation on more platforms, which should be faster.
== Boost 1.51.0
* Support the standard smart pointers.
* `hash_value` now implemented using SFINAE to avoid implicit casts to built in types when calling it.
* Updated to use the new config macros.
== Boost 1.50.0
* https://svn.boost.org/trac/boost/ticket/6771[Ticket 6771]: Avoid gcc's `-Wfloat-equal` warning.
* https://svn.boost.org/trac/boost/ticket/6806[Ticket 6806]: Support `std::array` and `std::tuple` when available.
* Add deprecation warning to the long deprecated `boost/container_hash/detail/container_fwd.hpp`.
== Boost 1.46.0
* Avoid warning due with gcc's `-Wconversion` flag.
== Boost 1.44.0
* Add option to prevent implicit conversions when calling `hash_value` by defining `BOOST_HASH_NO_IMPLICIT_CASTS`. When using `boost::hash` for a type that does not have `hash_value` declared but does have an implicit conversion to a type that does, it would use that implicit conversion to hash it. Which can sometimes go very wrong, e.g. using a conversion to `bool` and only hashing to 2 possible values. Since fixing this is a breaking change and was only approached quite late in the release cycle with little discussion it's opt-in for now. This, or something like it, will become the default in a future version.
== Boost 1.43.0
* https://svn.boost.org/trac/boost/ticket/3866[Ticket 3866]: Don't foward declare containers when using gcc's parallel library, allow user to stop forward declaration by defining the `BOOST_DETAIL_NO_CONTAINER_FWD` macro.
* https://svn.boost.org/trac/boost/ticket/4038[Ticket 4038]: Avoid hashing `0.5` and `0` to the same number.
* Stop using deprecated `BOOST_HAS_*` macros.
== Boost 1.42.0
* Reduce the number of warnings for Visual {cpp} warning level 4.
* Some code formatting changes to fit lines into 80 characters.
* Rename an internal namespace.
== Boost 1.40.0
* Automatically configure the `float` functions using template metaprogramming instead of trying to configure every possibility manually.
* Workaround for when STLport doesn't support long double.
== Boost 1.39.0
* Move the `hash_fwd.hpp` implementation into the hash subdirectory, leaving a forwarding header in the old location. You should still use the old location, the new location is mainly for implementation and possible modularization.
* https://svn.boost.org/trac/boost/ticket/2412[Ticket 2412]: Removed deprecated headers.
* https://svn.boost.org/trac/boost/ticket/2957[Ticket 2957]: Fix configuration for vxworks.
== Boost 1.38.0
* Changed the warnings in the deprecated headers from 1.34.0 to errors. These will be removed in a future version of Boost.
* Moved detail headers out of `boost/container_hash/detail`, since they are part of `functional/hash`, not `container_hash`. `boost/container_hash/detail/container_fwd.hpp` has been moved to `boost/detail/container_fwd.hpp` as it's used outside of this library, the others have been moved to `boost/functional/hash/detail`.
== Boost 1.37.0
* http://svn.boost.org/trac/boost/ticket/2264[Ticket 2264]: In Visual {cpp}, always use C99 float functions for long double and float as the {cpp} overloads aren't always availables.
== Boost 1.36.0
* Stop using OpenBSD's dodgy `std::numeric_limits`.
* Using the boost typedefs for `long long` and `unsigned long long`.
* Move the extensions into their own header.
== Boost 1.35.0
* Support for `long long`, `std::complex`.
* Improved algorithm for hashing floating point numbers:
** Improved portablity, as described by Daniel Krügler in http://lists.boost.org/boost-users/2005/08/13418.php[a post to the boost users list].
** Fits more information into each combine loop, which can reduce the the number of times combine is called and hopefully give a better quality hash function.
** Improved the algorithm for hashing floating point numbers.
** On Cygwin use a binary hash function for floating point numbers, as Cygwin doesn't have decent floating point functions for `long double`.
** Never uses `fpclass` which doesn't support `long double`.
** http://svn.boost.org/trac/boost/ticket/1064[Ticket 1064]: Removed unnecessary use of errno.
* Explicitly overload for more built in types.
* Minor improvements to the documentation.
* A few bug and warning fixes:
** http://svn.boost.org/trac/boost/ticket/1509[Ticket 1509]: Suppress another Visual {cpp} warning.
** Some workarounds for the Sun compilers.
== Boost 1.34.1
* https://svn.boost.org/trac10/ticket/952[Ticket 952]: Suppress incorrect 64-bit warning on Visual {cpp}.
== 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, `<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.
* Update the portable example to hopefully be more generally portable.
== Boost 1.33.1
* Fixed the points example, as pointed out by 沈慧峰.
== Boost 1.33.0
* Initial Release

80
doc/hash/combine.adoc Normal file
View File

@@ -0,0 +1,80 @@
[#combine]
= Combining hash values
:idprefix: combine_
Say you have a point class, representing a two dimensional location:
[source]
----
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 `boost::hash_combine` is supplied for this purpose:
[source]
----
class point
{
...
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;
}
...
};
----
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 `hash_value` on the supplied element, and combines it with the seed.
Full code for this example is at link:../../examples/point.cpp[/libs/container_hash/examples/point.cpp].
[NOTE]
====
When using `boost::hash_combine` the order of the calls matters.
[source]
----
std::size_t seed = 0;
boost::hash_combine(seed, 1);
boost::hash_combine(seed, 2);
----
results in a different seed to:
[source]
----
std::size_t seed = 0;
boost::hash_combine(seed, 2);
boost::hash_combine(seed, 1);
----
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 `boost::hash_range`:
[source]
----
std::vector<std::string> some_strings;
std::size_t hash = boost::hash_range(some_strings.begin(), some_strings.end());
----
Note that when writing template classes, you might not want to include the main hash header as it's quite an expensive include that brings in a lot of other headers, so instead you can include the `<boost/container_hash/hash_fwd.hpp>` header which forward declares `boost::hash`, `boost::hash_range` and `boost::hash_combine`. You'll need to include the main header before instantiating `boost::hash`. When using a container that uses `boost::hash` it should do that for you, so your type will work fine with the boost hash containers. There's an example of this in link:../../examples/template.hpp[template.hpp] and link:../../examples/template.cpp[template.cpp].

10
doc/hash/copyright.adoc Normal file
View File

@@ -0,0 +1,10 @@
[#copyright]
= Copyright and License
:idprefix: copyright_
*Daniel James*
Copyright (C) 2005-2008 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)

68
doc/hash/custom.adoc Normal file
View File

@@ -0,0 +1,68 @@
[#custom]
= Extending boost::hash for a custom data type
:idprefix: custom_
`boost::hash` is implemented by calling the function `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 its member `id`:
[source]
----
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`:
[source]
----
namespace library
{
std::size_t hash_value(book const& b)
{
boost::hash<int> hasher;
return hasher(b.id);
}
}
----
And you can now use `boost::hash` with book:
[source]
----
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 is 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());
----
The full example can be found in: link:../../examples/books.hpp[/libs/container_hash/examples/books.hpp] and link:../../examples/books.cpp[/libs/container_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 hashes the id. If it was based on the object's name and author then the hash function should take them into account (how to do this is discussed in the next section).

12
doc/hash/disable.adoc Normal file
View File

@@ -0,0 +1,12 @@
[#disable]
= Disabling The Extensions
:idprefix: disable_
While ``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 `<boost/container_hash/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.

22
doc/hash/intro.adoc Normal file
View File

@@ -0,0 +1,22 @@
[#intro]
= Introduction
:idprefix: intro_
`boost::hash` is an implementation of the https://en.wikipedia.org/wiki/Hash_function[hash function] object specified by the http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1836.pdf[Draft Technical Report on C++ Library Extensions] (TR1). It is the default hash function for link:../../../unordered/index.html[Boost.Unordered], link:../../../intrusive/index.html[Boost.Intrusive]'s unordered associative containers, and link:../../../multi_index/index.html[Boost.MultiIndex]'s hash indicies and link:../../../bimap/index.html[Boost.Bimap]'s `unordered_set_of`.
As it is compliant with http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1836.pdf[TR1], it will work with:
* integers
* floats
* pointers
* strings
It also implements the extension proposed by Peter Dimov in issue 6.18 of the http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1837.pdf[Library Extension Technical Report Issues List] (page 63), this adds support for:
* arrays
* `std::pair`
* the standard containers.
* extending `boost::hash` for custom types.
NOTE: This hash function is designed to be used in containers based on the STL and is not suitable as a general purpose hash function. For more details see the <<rationale,rationale>>.

12
doc/hash/links.adoc Normal file
View File

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

82
doc/hash/portability.adoc Normal file
View File

@@ -0,0 +1,82 @@
[#portability]
= Portability
:idprefix: portability_
`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` needs 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:
[source]
----
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:
[source]
----
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:
[source]
----
#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 link:../../examples/portable.cpp[/libs/container_hash/examples/portable.cpp].

16
doc/hash/rationale.adoc Normal file
View File

@@ -0,0 +1,16 @@
[#rationale]
= Rationale
:idprefix: rationale_
The rationale can be found in the original designfootnote:[issue 6.18 of the http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1837.pdf[Library Extension Technical Report Issues List] (page 63)].
== Quality of the hash function
Many hash functions strive to have little correlation between the input and output values. They attempt to uniformally distribute the output values for very similar inputs. This hash function makes no such attempt. In fact, for integers, the result of the hash function is often just the input value. So similar but different input values will often result in similar but different output values. This means that it is not appropriate as a general hash function. For example, a hash table may discard bits from the hash function resulting in likely collisions, or might have poor collision resolution when hash values are clustered together. In such cases this hash function will preform poorly.
But the standard has no such requirement for the hash function, it just requires that the hashes of two different values are unlikely to collide. Containers or algorithms designed to work with the standard hash function will have to be implemented to work well when the hash function's output is correlated to its input. Since they are paying that cost a higher quality hash function would be wasteful.
For other use cases, if you do need a higher quality hash function, then neither the standard hash function or `boost::hash` are appropriate. There are several options available. One is to use a second hash on the output of this hash function, such as http://web.archive.org/web/20121102023700/http://www.concentric.net/~Ttwang/tech/inthash.htm[Thomas Wang's hash function]. This this may not work as well as a hash algorithm tailored for the input.
For strings there are several fast, high quality hash functions available (for example http://code.google.com/p/smhasher/[MurmurHash3] and http://code.google.com/p/cityhash/[Google's CityHash]), although they tend to be more machine specific. These may also be appropriate for hashing a binary representation of your data - providing that all equal values have an equal representation, which is not always the case (e.g. for floating point values).

386
doc/hash/ref.adoc Normal file
View File

@@ -0,0 +1,386 @@
[#ref]
= Reference
:idprefix: ref_
For the full specification, see section 6.3 of the http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1836.pdf[C++ Standard Library Technical Report] and issue 6.18 of the http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1837.pdf[Library Extension Technical Report Issues List] (page 63).
== Header <boost/container_hash/hash.hpp>
Defines `boost::hash`, and helper functions.
[source]
----
namespace boost {
template<typename T> struct hash;
template<> struct hash<bool>;
template<> struct hash<char>;
template<> struct hash<signed char>;
template<> struct hash<unsigned char>;
template<> struct hash<wchar_t>;
template<> struct hash<char16_t>;
template<> struct hash<char32_t>;
template<> struct hash<short>;
template<> struct hash<unsigned short>;
template<> struct hash<int>;
template<> struct hash<unsigned int>;
template<> struct hash<long>;
template<> struct hash<unsigned long>;
template<> struct hash<long long>;
template<> struct hash<unsigned long long>;
template<> struct hash<float>;
template<> struct hash<double>;
template<> struct hash<long double>;
template<> struct hash<std::string>;
template<> struct hash<std::wstring>;
template<> struct hash<std::u16string>;
template<> struct hash<std::u32string>;
template<> struct hash<std::type_index>;
template<typename T> struct hash<T*>;
// Support functions (Boost extension).
template<typename T>
void hash_combine(size_t &, T const&);
template<typename It>
std::size_t hash_range(It, It);
template<typename It>
void hash_range(std::size_t&, It, It);
// Overloadable hash implementation (Boost extension).
std::size_t hash_value(bool);
std::size_t hash_value(char);
std::size_t hash_value(signed char);
std::size_t hash_value(unsigned char);
std::size_t hash_value(wchar_t);
std::size_t hash_value(char16_t);
std::size_t hash_value(char32_t);
std::size_t hash_value(short);
std::size_t hash_value(unsigned short);
std::size_t hash_value(int);
std::size_t hash_value(unsigned int);
std::size_t hash_value(long);
std::size_t hash_value(unsigned long);
std::size_t hash_value(long long);
std::size_t hash_value(unsigned long long);
std::size_t hash_value(float);
std::size_t hash_value(double);
std::size_t hash_value(long double);
template<typename T>
std::size_t hash_value(T* const&);
template<typename T, unsigned N>
std::size_t hash_value(T (&val)[N]);
template<typename T, unsigned N>
std::size_t hash_value(const T (&val)[N]);
template<typename Ch, typename A>
std::size_t hash_value(std::basic_string<Ch, std::char_traits<Ch>, A> const&);
template<typename A, typename B>
std::size_t hash_value(std::pair<A, B> const&);
template<typename T, typename A>
std::size_t hash_value(std::vector<T, A> const&);
template<typename T, typename A>
std::size_t hash_value(std::list<T, A> const&);
template<typename T, typename A>
std::size_t hash_value(std::deque<T, A> const&);
template<typename K, typename C, typename A>
std::size_t hash_value(std::set<K, C, A> const&);
template<typename K, typename C, typename A>
std::size_t hash_value(std::multiset<K, C, A> const&);
template<typename K, typename T, typename C, typename A>
std::size_t hash_value(std::map<K, T, C, A> const&);
template<typename K, typename T, typename C, typename A>
std::size_t hash_value(std::multimap<K, T, C, A> const&);
template<typename T> std::size_t hash_value(std::complex<T> const&);
std::size_t hash_value(std::type_index);
template<typename T, std::size_t N>
std::size_t hash_value(std::array<T, N> const&);
template<typename... T>
std::size_t hash_value(std::tuple<T...>);
}
----
== Struct template hash
=== hash
`boost::hash` — A http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1836.pdf[TR1] compliant hash function object.
==== Synopsis
[source]
----
// #include <boost/container_hash/hash.hpp>
template<typename T>
struct hash : public std::unary_function<T, std::size_t> {
std::size_t operator()(T const&) const;
};
----
==== Description
[source]
----
std::size_t operator()(T const& val) const;
----
[horizontal]
Returns:: `hash_value(val)`
Notes:: The call to `hash_value` is unqualified, so that custom overloads can be found via argument dependent lookup.
+
This is not defined when the macro `BOOST_HASH_NO_EXTENSIONS` is defined. The specializations are still defined, so only the specializations required by TR1 are defined.
+
Forward declared in `<boost/container_hash/hash_fwd.hpp>`
+
This hash function is not intended for general use, and isn't guaranteed to be equal during separate runs of a program - so please don't use it for any persistent storage or communication.
Throws:: Only throws if `hash_value(T)` throws.
== Specializations
`boost::hash<T>`
=== Synopsis
[source]
----
// #include <boost/container_hash/hash.hpp>
struct hash<T> {
std::size_t operator()(T const&) const;
};
----
=== Description
[source]
----
std::size_t operator()(T const val) const;
----
[horizontal]
Returns:: Unspecified in TR1, except that equal arguments yield the same result.
+
`hash_value(val)` in Boost.
[horizontal]
Throws:: Doesn't throw
== Support functions (Boost extension).
=== hash_combine
[source]
----
template<typename T>
void hash_combine(size_t &, T const&);
----
Called repeatedly to incrementally create a hash value from several variables.
[horizontal]
Effects:: Updates seed with a new hash value generated by combining it with the result of `hash_value(v)`. Will always produce the same result for the same combination of seed and `hash_value(v)` during the single run of a program.
[horizontal]
Notes:: `hash_value` is called without qualification, so that overloads can be found via ADL. +
+
This is an extension to TR1 +
+
Forward declared in `<boost/container_hash/hash_fwd.hpp>` +
+
This hash function is not intended for general use, and isn't guaranteed to be equal during separate runs of a program - so please don't use it for any persistent storage or communication.
[horizontal]
Throws:: Only throws if `hash_value(T)` throws. Strong exception safety, as long as `hash_value(T)` also has strong exception safety.
=== hash_range
[source]
----
template<typename It>
std::size_t hash_range(It, It);
template<typename It>
void hash_range(std::size_t&, It, It);
----
Calculate the combined hash value of the elements of an iterator range.
[horizontal]
Effects:: For the two argument overload:
+
[source]
----
size_t seed = 0;
for(; first != last; ++first)
{
hash_combine(seed, *first);
}
return seed;
----
+
For the three arguments overload:
+
[source]
----
for(; first != last; ++first)
{
hash_combine(seed, *first);
}
----
[horizontal]
Notes:: `hash_range` is sensitive to the order of the elements so it wouldn't be appropriate to use this with an unordered container.
+
This is an extension to TR1
+
Forward declared in `<boost/container_hash/hash_fwd.hpp>`
+
This hash function is not intended for general use, and isn't guaranteed to be equal during separate runs of a program - so please don't use it for any persistent storage or communication.
[horizontal]
Throws:: Only throws if `hash_value(std::iterator_traits<It>::value_type)` throws. `hash_range(std::size_t&, It, It)` has basic exception safety as long as `hash_value(std::iterator_traits<It>::value_type)` has basic exception safety.
== Overloadable hash implementation (Boost extension).
=== hash_value
[source]
----
std::size_t hash_value(bool val);
std::size_t hash_value(char val);
std::size_t hash_value(signed char val);
std::size_t hash_value(unsigned char val);
std::size_t hash_value(wchar_t val);
std::size_t hash_value(char16_t val);
std::size_t hash_value(char32_t val);
std::size_t hash_value(short val);
std::size_t hash_value(unsigned short val);
std::size_t hash_value(int val);
std::size_t hash_value(unsigned int val);
std::size_t hash_value(long val);
std::size_t hash_value(unsigned long val);
std::size_t hash_value(long long val);
std::size_t hash_value(unsigned long long val);
std::size_t hash_value(float val);
std::size_t hash_value(double val);
std::size_t hash_value(long double val);
template<typename T> std::size_t hash_value(T* const& val);
template<typename T, unsigned N> std::size_t hash_value(T (&val)[N]);
template<typename T, unsigned N> std::size_t hash_value(const T (&val)[N]);
template<typename Ch, typename A>
std::size_t hash_value(std::basic_string<Ch, std::char_traits<Ch>, A> const& val);
template<typename A, typename B>
std::size_t hash_value(std::pair<A, B> const& val);
template<typename T, typename A>
std::size_t hash_value(std::vector<T, A> const& val);
template<typename T, typename A>
std::size_t hash_value(std::list<T, A> const& val);
template<typename T, typename A>
std::size_t hash_value(std::deque<T, A> const& val);
template<typename K, typename C, typename A>
std::size_t hash_value(std::set<K, C, A> const& val);
template<typename K, typename C, typename A>
std::size_t hash_value(std::multiset<K, C, A> const& val);
template<typename K, typename T, typename C, typename A>
std::size_t hash_value(std::map<K, T, C, A> const& val);
template<typename K, typename T, typename C, typename A>
std::size_t hash_value(std::multimap<K, T, C, A> const& val);
template<typename T> std::size_t hash_value(std::complex<T> const& val);
std::size_t hash_value(std::type_index val);
template<typename T, std::size_t N>
std::size_t hash_value(std::array<T, N> const& val);
template<typename... T>
std::size_t hash_value(std::tuple<T...> val);
----
Implementation of the hash function.
Generally shouldn't be called directly by users, instead they should use `boost::hash`, `boost::hash_range` or `boost::hash_combine` which call `hash_value` without namespace qualification so that overloads for custom types are found via ADL.
[horizontal]
Notes:: This is an extension to TR1
+
This hash function is not intended for general use, and isn't guaranteed to be equal during separate runs of a program - so please don't use it for any persistent storage or communication.
[horizontal]
Throws:: Only throws if a user supplied version of `hash_value` throws for an element of a container, or one of the types stored in a pair.
[vertical]
Returns::
+
[cols="1,1", frame=all, grid=rows]
|===
|Types |Returns
|`bool`, `char`, `signed char`, `unsigned char`, `wchar_t`, `char16_t`, `char32_t`, `short`, `unsigned short`, `int`, `unsigned int`, `long`, `unsigned long`
|val
|`long long`, `unsigned long long`
|val when `abs(val) \<= std::numeric_limits<std::size_t>::max()`.
|`float`, `double`, `long double`
|An unspecified value, except that equal arguments shall yield the same result.
|`T*`
|An unspecified value, except that equal arguments shall yield the same result.
|`T val[N]`, `const T val[N]`
|`hash_range(val, val+N)`
|`std:basic_string<Ch, std::char_traits<Ch>, A>`, `std::vector<T, A>`, `std::list<T, A>`, `std::deque<T, A>`, `std::set<K, C, A>`, `std::multiset<K, C, A>`, `std::map<K, T, C, A>`, `std::multimap<K, T, C, A>`, `std::array<T, N>`
|`hash_range(val.begin(), val.end())`
|`std::pair<A, B>`
a|
[source]
----
size_t seed = 0;
hash_combine(seed, val.first);
hash_combine(seed, val.second);
return seed;
----
|`std::tuple<T...>`
a|
[source]
----
size_t seed = 0;
hash_combine(seed, get<0>(val));
hash_combine(seed, get<1>(val));
// ....
return seed;
----
|`std::complex<T>`
|When T is a built in type and `val.imag() == 0`, the result is equal to `hash_value(val.real())`. Otherwise an unspecified value, except that equal arguments shall yield the same result.
|`std::type_index`
|`val.hash_code()`
|===

14
doc/hash/thanks.adoc Normal file
View File

@@ -0,0 +1,14 @@
[#thanks]
= Acknowledgements
:idprefix: thanks_
This library is based on the design by Peter Dimov. During the initial development Joaquín M López Muñoz made many useful suggestions and 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, further constructive criticism has been made by Daniel Krügler, Alexander Nasonov and 沈慧峰.
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 `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.

48
doc/hash/tutorial.adoc Normal file
View File

@@ -0,0 +1,48 @@
[#tutorial]
= Tutorial
:idprefix: tutorial_
When using a hash index with link:../../../multi_index/index.html[Boost.MultiIndex], you don't need to do anything to use `boost::hash` as it uses it by default. To find out how to use a user-defined type, read the <<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 `boost::hash`, just use an extra template parameter:
[source]
----
std::unordered_multiset<int, boost::hash<int> >
set_of_ints;
std::unordered_set<std::pair<int, int>, boost::hash<std::pair<int, int> > >
set_of_pairs;
std::unordered_map<int, std::string, boost::hash<int> > map_int_to_string;
----
To use `boost::hash` directly, create an instance and call it as a function:
[source]
----
#include <boost/container_hash/hash.hpp>
int main()
{
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:
[source]
----
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::back_inserter(hashes),
boost::hash<typename Container::value_type>());
return hashes;
}
----

View File

@@ -1,52 +0,0 @@
[/ Copyright 2005-2008 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 __unordered__ [link unordered Boost.Unordered]]
[def __intrusive__ [link intrusive.unordered_set_unordered_multiset Boost.Intrusive]]
[def __multi-index__ [@boost:/libs/multi_index/doc/index.html
Boost Multi-Index Containers Library]]
[def __multi-index-short__ [@boost:/libs/multi_index/doc/index.html
Boost.MultiIndex]]
[def __bimap__ [@boost:/libs/bimap/index.html Boost.Bimap]]
[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 the default hash function for
__unordered__, __intrusive__'s unordered associative containers, and
__multi-index-short__'s hash indicies and __bimap__'s `unordered_set_of`.
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.
[note
This hash function is designed to be used in containers based on
the STL and is not suitable as a general purpose hash function.
For more details see the [link hash.rationale rationale].
]
[endsect]

View File

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

View File

@@ -1,93 +0,0 @@
[/ Copyright 2005-2008 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`
needs 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
[@boost:/libs/container_hash/examples/portable.cpp /libs/container_hash/examples/portable.cpp].
[endsect]

View File

@@ -1,50 +0,0 @@
[/ Copyright 2011 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:rationale Rationale]
The rationale can be found in the original design
[footnote issue 6.18 of the __issues__ (page 63)].
[heading Quality of the hash function]
Many hash functions strive to have little correlation between the input
and output values. They attempt to uniformally distribute the output
values for very similar inputs. This hash function makes no such
attempt. In fact, for integers, the result of the hash function is often
just the input value. So similar but different input values will often
result in similar but different output values.
This means that it is not appropriate as a general hash function. For
example, a hash table may discard bits from the hash function resulting
in likely collisions, or might have poor collision resolution when hash
values are clustered together. In such cases this hash function will
preform poorly.
But the standard has no such requirement for the hash function,
it just requires that the hashes of two different values are unlikely
to collide. Containers or algorithms
designed to work with the standard hash function will have to be
implemented to work well when the hash function's output is correlated
to its input. Since they are paying that cost a higher quality hash function
would be wasteful.
For other use cases, if you do need a higher quality hash function,
then neither the standard hash function or `boost::hash` are appropriate.
There are several options
available. One is to use a second hash on the output of this hash
function, such as [@http://web.archive.org/web/20121102023700/http://www.concentric.net/~Ttwang/tech/inthash.htm
Thomas Wang's hash function]. This this may not work as
well as a hash algorithm tailored for the input.
For strings there are several fast, high quality hash functions
available (for example [@http://code.google.com/p/smhasher/ MurmurHash3]
and [@http://code.google.com/p/cityhash/ Google's CityHash]),
although they tend to be more machine specific.
These may also be appropriate for hashing a binary representation of
your data - providing that all equal values have an equal
representation, which is not always the case (e.g. for floating point
values).
[endsect]

View File

@@ -1,994 +0,0 @@
<!--
Copyright Daniel James 2005-2009
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/container_hash/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><simpara>A <ulink url="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1836.pdf">TR1</ulink> compliant hash function object.</simpara></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>
<para>
Forward declared in
<code>&lt;boost/container_hash/hash_fwd.hpp&gt;</code>
</para>
<para>
This hash function is not intended for general use, and isn't
guaranteed to be equal during separate runs of a program - so
please don't use it for any persistent storage or communication.
</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>char16_t</template-arg>
</specialization>
<method name="operator()" cv="const">
<type>std::size_t</type>
<parameter name="val">
<paramtype>char16_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>char32_t</template-arg>
</specialization>
<method name="operator()" cv="const">
<type>std::size_t</type>
<parameter name="val">
<paramtype>char32_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>long long</template-arg>
</specialization>
<method name="operator()" cv="const">
<type>std::size_t</type>
<parameter name="val">
<paramtype>long 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 long</template-arg>
</specialization>
<method name="operator()" cv="const">
<type>std::size_t</type>
<parameter name="val">
<paramtype>unsigned long 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>
<specialization>
<template-arg>std::u16string</template-arg>
</specialization>
<method name="operator()" cv="const">
<type>std::size_t</type>
<parameter name="val">
<paramtype>std::u16string 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::u32string</template-arg>
</specialization>
<method name="operator()" cv="const">
<type>std::size_t</type>
<parameter name="val">
<paramtype>std::u32string 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>
<struct-specialization name="hash">
<template></template>
<specialization>
<template-arg>std::type_index</template-arg>
</specialization>
<method name="operator()" cv="const">
<type>std::size_t</type>
<parameter name="val">
<paramtype>std::type_index</paramtype>
</parameter>
<returns>
<para><code>val.hash_code()</code></para>
</returns>
<throws><para>Doesn't throw</para></throws>
</method>
<notes>
<para>
Only available if it's in your standard library and Boost.Config
is aware of it.
</para>
</notes>
</struct-specialization>
<free-function-group name="Support functions (Boost extension).">
<!--
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><simpara>
Called repeatedly to incrementally create a hash value from
several variables.
</simpara></purpose>
<effects>
Updates <code>seed</code> with a new hash value generated by
combining it with the result of
<code><functionname>hash_value</functionname>(v)</code>. Will
always produce the same result for the same combination of
<code>seed</code> and
<code><functionname>hash_value</functionname>(v)</code> during
the single run of a program.
</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>
<para>
Forward declared in
<code>&lt;boost/container_hash/hash_fwd.hpp&gt;</code>
</para>
<para>
This hash function is not intended for general use, and isn't
guaranteed to be equal during separate runs of a program - so
please don't use it for any persistent storage or communication.
</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><simpara>
Calculate the combined hash value of the elements of an iterator
range.
</simpara></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>
<para>For the three arguments overload:</para>
<programlisting>
for(; first != last; ++first)
{
<functionname>hash_combine</functionname>(seed, *first);
}
</programlisting>
</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>
<para>
Forward declared in
<code>&lt;boost/container_hash/hash_fwd.hpp&gt;</code>
</para>
<para>
This hash function is not intended for general use, and isn't
guaranteed to be equal during separate runs of a program - so
please don't use it for any persistent storage or communication.
</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>
</free-function-group>
<free-function-group name="Overloadable hash implementation (Boost extension).">
<!--
boost::hash_value - integers
-->
<overloaded-function name="hash_value">
<purpose><simpara>
Implementation of the hash function.
</simpara></purpose>
<signature>
<type>std::size_t</type>
<parameter name="val"><paramtype>bool</paramtype></parameter>
</signature>
<signature>
<type>std::size_t</type>
<parameter name="val"><paramtype>char</paramtype></parameter>
</signature>
<signature>
<type>std::size_t</type>
<parameter name="val"><paramtype>signed char</paramtype></parameter>
</signature>
<signature>
<type>std::size_t</type>
<parameter name="val"><paramtype>unsigned char</paramtype></parameter>
</signature>
<signature>
<type>std::size_t</type>
<parameter name="val"><paramtype>wchar_t</paramtype></parameter>
</signature>
<signature>
<type>std::size_t</type>
<parameter name="val"><paramtype>char16_t</paramtype></parameter>
</signature>
<signature>
<type>std::size_t</type>
<parameter name="val"><paramtype>char32_t</paramtype></parameter>
</signature>
<signature>
<type>std::size_t</type>
<parameter name="val"><paramtype>short</paramtype></parameter>
</signature>
<signature>
<type>std::size_t</type>
<parameter name="val"><paramtype>unsigned short</paramtype></parameter>
</signature>
<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>long long</paramtype></parameter>
</signature>
<signature>
<type>std::size_t</type>
<parameter name="val"><paramtype>unsigned long 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>
<signature>
<template>
<template-type-parameter name="T"/>
</template>
<type>std::size_t</type>
<parameter name="val"><paramtype>std::complex&lt;T&gt; const&amp;</paramtype></parameter>
</signature>
<signature>
<type>std::size_t</type>
<parameter name="val"><paramtype>std::type_index</paramtype></parameter>
</signature>
<signature>
<template>
<template-type-parameter name="T"/>
<template-nontype-parameter name="N">
<type>std::size_t</type>
</template-nontype-parameter>
</template>
<type>std::size_t</type>
<parameter name="val"><paramtype>std::array&lt;T, N&gt; const&amp;</paramtype></parameter>
</signature>
<signature>
<template>
<template-type-parameter name="T" pack="1"/>
</template>
<type>std::size_t</type>
<parameter name="val"><paramtype>std::tuple&lt;T...&gt;</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>
<para>
This hash function is not intended for general use, and isn't
guaranteed to be equal during separate runs of a program - so
please don't use it for any persistent storage or communication.
</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>bool</code>,
<code>char</code>, <code>signed char</code>, <code>unsigned char</code>,
<code>wchar_t</code>, <code>char16_t</code>, <code>char32_t</code>,
<code>short</code>, <code>unsigned short</code>,
<code>int</code>, <code>unsigned int</code>, <code>long</code>, <code>unsigned long</code>
</entry>
<entry><code>val</code></entry>
</row>
<row>
<entry><code>long long</code>, <code>unsigned long long</code></entry>
<entry><code>val</code> when <code>abs(val) &lt;= std::numeric_limits&lt;std::size_t&gt;::max()</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>,
<code>std::array&lt;T,&#160;N&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>
<row>
<entry><code>std::tuple&lt;T...&gt;</code></entry>
<entry><programlisting>size_t seed = 0;
<functionname>hash_combine</functionname>(seed, get&lt;0&gt;(val));
<functionname>hash_combine</functionname>(seed, get&lt;1&gt;(val));
// ....
return seed;</programlisting></entry>
</row>
<row>
<entry>
<code>std::complex&lt;T&gt;</code>
</entry>
<entry>When <code>T</code> is a built in type and <code>val.imag() == 0</code>, the result is equal to <code>hash_value(val.real())</code>. Otherwise an unspecified value, except that equal arguments shall yield the same result.</entry>
</row>
<row>
<entry>
<code>std::type_index</code>
</entry>
<entry><code>val.hash_code()</code></entry>
</row>
</tbody>
</tgroup>
</informaltable>
</returns>
</overloaded-function>
</free-function-group>
</namespace>
</header>
</library-reference>

View File

@@ -1,27 +0,0 @@
#include <boost/container_hash/hash.hpp>
#include <vector>
#include <algorithm>
#include <iterator>
#include <cassert>
//[ get_hashes
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::back_inserter(hashes),
boost::hash<typename Container::value_type>());
return hashes;
}
//]
int main() {
std::vector<int> values;
values.push_back(10);
values.push_back(20);
std::vector<std::size_t> hashes = get_hashes(values);
assert(hashes[0] = boost::hash<int>()(values[0]));
assert(hashes[1] = boost::hash<int>()(values[1]));
}

View File

@@ -1,28 +0,0 @@
[/ Copyright 2005-2008 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. During the initial
development
Joaquín M López Muñoz made many useful suggestions and 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, further constructive criticism has
been made by Daniel Krügler, Alexander Nasonov and 沈慧峰.
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]

View File

@@ -1,207 +0,0 @@
[/ Copyright 2005-2008 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) ]
[quickbook 1.7]
[import samples/tutorial.cpp]
[def __multi-index-short__ [@boost:/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/container_hash/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:
[get_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:
[@boost:/libs/container_hash/examples/books.hpp /libs/container_hash/examples/books.hpp]
and
[@boost:/libs/container_hash/examples/books.cpp /libs/container_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 hashes the id. If it was based on the object's 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
[@boost:/libs/container_hash/examples/point.cpp /libs/container_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());
Note that when writing template classes, you might not want to include the main
hash header as it's quite an expensive include that brings in a lot of other
headers, so instead you can include the `<boost/container_hash/hash_fwd.hpp>`
header which forward declares [classref boost::hash],
[funcref boost::hash_range] and [funcref boost::hash_combine]. You'll need to
include the main header before instantiating [classref boost::hash]. When using
a container that uses [classref boost::hash] it should do that for you, so your
type will work fine with the boost hash containers. There's an example of this
in [@boost:/libs/container_hash/examples/template.hpp template.hpp] and
[@boost:/libs/container_hash/examples/template.cpp template.cpp].
[endsect]

View File

@@ -1,336 +0,0 @@
// Copyright 2005-2009 Daniel James.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#if !defined(BOOST_FUNCTIONAL_HASH_DETAIL_FLOAT_FUNCTIONS_HPP)
#define BOOST_FUNCTIONAL_HASH_DETAIL_FLOAT_FUNCTIONS_HPP
#include <boost/config.hpp>
#if defined(BOOST_HAS_PRAGMA_ONCE)
#pragma once
#endif
#include <boost/config/no_tr1/cmath.hpp>
// Set BOOST_HASH_CONFORMANT_FLOATS to 1 for libraries known to have
// sufficiently good floating point support to not require any
// workarounds.
//
// When set to 0, the library tries to automatically
// use the best available implementation. This normally works well, but
// breaks when ambiguities are created by odd namespacing of the functions.
//
// Note that if this is set to 0, the library should still take full
// advantage of the platform's floating point support.
#if defined(__SGI_STL_PORT) || defined(_STLPORT_VERSION)
# define BOOST_HASH_CONFORMANT_FLOATS 0
#elif defined(__LIBCOMO__)
# define BOOST_HASH_CONFORMANT_FLOATS 0
#elif defined(__STD_RWCOMPILER_H__) || defined(_RWSTD_VER)
// Rogue Wave library:
# define BOOST_HASH_CONFORMANT_FLOATS 0
#elif defined(_LIBCPP_VERSION)
// libc++
# define BOOST_HASH_CONFORMANT_FLOATS 1
#elif defined(__GLIBCPP__) || defined(__GLIBCXX__)
// GNU libstdc++ 3
# if defined(__GNUC__) && __GNUC__ >= 4
# define BOOST_HASH_CONFORMANT_FLOATS 1
# else
# define BOOST_HASH_CONFORMANT_FLOATS 0
# endif
#elif defined(__STL_CONFIG_H)
// generic SGI STL
# define BOOST_HASH_CONFORMANT_FLOATS 0
#elif defined(__MSL_CPP__)
// MSL standard lib:
# define BOOST_HASH_CONFORMANT_FLOATS 0
#elif defined(__IBMCPP__)
// VACPP std lib (probably conformant for much earlier version).
# if __IBMCPP__ >= 1210
# define BOOST_HASH_CONFORMANT_FLOATS 1
# else
# define BOOST_HASH_CONFORMANT_FLOATS 0
# endif
#elif defined(MSIPL_COMPILE_H)
// Modena C++ standard library
# define BOOST_HASH_CONFORMANT_FLOATS 0
#elif (defined(_YVALS) && !defined(__IBMCPP__)) || defined(_CPPLIB_VER)
// Dinkumware Library (this has to appear after any possible replacement libraries):
# if _CPPLIB_VER >= 405
# define BOOST_HASH_CONFORMANT_FLOATS 1
# else
# define BOOST_HASH_CONFORMANT_FLOATS 0
# endif
#else
# define BOOST_HASH_CONFORMANT_FLOATS 0
#endif
#if BOOST_HASH_CONFORMANT_FLOATS
// The standard library is known to be compliant, so don't use the
// configuration mechanism.
namespace boost {
namespace hash_detail {
template <typename Float>
struct call_ldexp {
typedef Float float_type;
inline Float operator()(Float x, int y) const {
return std::ldexp(x, y);
}
};
template <typename Float>
struct call_frexp {
typedef Float float_type;
inline Float operator()(Float x, int* y) const {
return std::frexp(x, y);
}
};
template <typename Float>
struct select_hash_type
{
typedef Float type;
};
}
}
#else // BOOST_HASH_CONFORMANT_FLOATS == 0
// 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.
//
// The following tries to automatically detect which are available.
namespace boost {
namespace hash_detail {
// Returned by dummy versions of the float functions.
struct not_found {
// Implicitly convertible to float and long double in order to avoid
// a compile error when the dummy float functions are used.
inline operator float() const { return 0; }
inline operator long double() const { return 0; }
};
// A type for detecting the return type of functions.
template <typename T> struct is;
template <> struct is<float> { char x[10]; };
template <> struct is<double> { char x[20]; };
template <> struct is<long double> { char x[30]; };
template <> struct is<boost::hash_detail::not_found> { char x[40]; };
// Used to convert the return type of a function to a type for sizeof.
template <typename T> is<T> float_type(T);
// call_ldexp
//
// This will get specialized for float and long double
template <typename Float> struct call_ldexp
{
typedef double float_type;
inline double operator()(double a, int b) const
{
using namespace std;
return ldexp(a, b);
}
};
// call_frexp
//
// This will get specialized for float and long double
template <typename Float> struct call_frexp
{
typedef double float_type;
inline double operator()(double a, int* b) const
{
using namespace std;
return frexp(a, b);
}
};
}
}
// A namespace for dummy functions to detect when the actual function we want
// isn't available. ldexpl, ldexpf etc. might be added tby the macros below.
//
// AFAICT these have to be outside of the boost namespace, as if they're in
// the boost namespace they'll always be preferable to any other function
// (since the arguments are built in types, ADL can't be used).
namespace boost_hash_detect_float_functions {
template <class Float> boost::hash_detail::not_found ldexp(Float, int);
template <class Float> boost::hash_detail::not_found frexp(Float, int*);
}
// Macros for generating specializations of call_ldexp and call_frexp.
//
// check_cpp and check_c99 check if the C++ or C99 functions are available.
//
// Then the call_* functions select an appropriate implementation.
//
// I used c99_func in a few places just to get a unique name.
//
// Important: when using 'using namespace' at namespace level, include as
// little as possible in that namespace, as Visual C++ has an odd bug which
// can cause the namespace to be imported at the global level. This seems to
// happen mainly when there's a template in the same namesapce.
#define BOOST_HASH_CALL_FLOAT_FUNC(cpp_func, c99_func, type1, type2) \
namespace boost_hash_detect_float_functions { \
template <class Float> \
boost::hash_detail::not_found c99_func(Float, type2); \
} \
\
namespace boost { \
namespace hash_detail { \
namespace c99_func##_detect { \
using namespace std; \
using namespace boost_hash_detect_float_functions; \
\
struct check { \
static type1 x; \
static type2 y; \
BOOST_STATIC_CONSTANT(bool, cpp = \
sizeof(float_type(cpp_func(x,y))) \
== sizeof(is<type1>)); \
BOOST_STATIC_CONSTANT(bool, c99 = \
sizeof(float_type(c99_func(x,y))) \
== sizeof(is<type1>)); \
}; \
} \
\
template <bool x> \
struct call_c99_##c99_func : \
boost::hash_detail::call_##cpp_func<double> {}; \
\
template <> \
struct call_c99_##c99_func<true> { \
typedef type1 float_type; \
\
template <typename T> \
inline type1 operator()(type1 a, T b) const \
{ \
using namespace std; \
return c99_func(a, b); \
} \
}; \
\
template <bool x> \
struct call_cpp_##c99_func : \
call_c99_##c99_func< \
::boost::hash_detail::c99_func##_detect::check::c99 \
> {}; \
\
template <> \
struct call_cpp_##c99_func<true> { \
typedef type1 float_type; \
\
template <typename T> \
inline type1 operator()(type1 a, T b) const \
{ \
using namespace std; \
return cpp_func(a, b); \
} \
}; \
\
template <> \
struct call_##cpp_func<type1> : \
call_cpp_##c99_func< \
::boost::hash_detail::c99_func##_detect::check::cpp \
> {}; \
} \
}
#define BOOST_HASH_CALL_FLOAT_MACRO(cpp_func, c99_func, type1, type2) \
namespace boost { \
namespace hash_detail { \
\
template <> \
struct call_##cpp_func<type1> { \
typedef type1 float_type; \
inline type1 operator()(type1 x, type2 y) const { \
return c99_func(x, y); \
} \
}; \
} \
}
#if defined(ldexpf)
BOOST_HASH_CALL_FLOAT_MACRO(ldexp, ldexpf, float, int)
#else
BOOST_HASH_CALL_FLOAT_FUNC(ldexp, ldexpf, float, int)
#endif
#if defined(ldexpl)
BOOST_HASH_CALL_FLOAT_MACRO(ldexp, ldexpl, long double, int)
#else
BOOST_HASH_CALL_FLOAT_FUNC(ldexp, ldexpl, long double, int)
#endif
#if defined(frexpf)
BOOST_HASH_CALL_FLOAT_MACRO(frexp, frexpf, float, int*)
#else
BOOST_HASH_CALL_FLOAT_FUNC(frexp, frexpf, float, int*)
#endif
#if defined(frexpl)
BOOST_HASH_CALL_FLOAT_MACRO(frexp, frexpl, long double, int*)
#else
BOOST_HASH_CALL_FLOAT_FUNC(frexp, frexpl, long double, int*)
#endif
#undef BOOST_HASH_CALL_FLOAT_MACRO
#undef BOOST_HASH_CALL_FLOAT_FUNC
namespace boost
{
namespace hash_detail
{
template <typename Float1, typename Float2>
struct select_hash_type_impl {
typedef double type;
};
template <>
struct select_hash_type_impl<float, float> {
typedef float type;
};
template <>
struct select_hash_type_impl<long double, long double> {
typedef long double type;
};
// select_hash_type
//
// If there is support for a particular floating point type, use that
// otherwise use double (there's always support for double).
template <typename Float>
struct select_hash_type : select_hash_type_impl<
BOOST_DEDUCED_TYPENAME call_ldexp<Float>::float_type,
BOOST_DEDUCED_TYPENAME call_frexp<Float>::float_type
> {};
}
}
#endif // BOOST_HASH_CONFORMANT_FLOATS
#endif

View File

@@ -1,271 +0,0 @@
// Copyright 2005-2012 Daniel James.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#if !defined(BOOST_FUNCTIONAL_HASH_DETAIL_HASH_FLOAT_HEADER)
#define BOOST_FUNCTIONAL_HASH_DETAIL_HASH_FLOAT_HEADER
#include <boost/config.hpp>
#if defined(BOOST_HAS_PRAGMA_ONCE)
#pragma once
#endif
#include <boost/container_hash/detail/float_functions.hpp>
#include <boost/container_hash/detail/limits.hpp>
#include <boost/core/enable_if.hpp>
#include <boost/integer/static_log2.hpp>
#include <boost/cstdint.hpp>
#include <boost/assert.hpp>
#include <boost/limits.hpp>
#include <cstring>
#if defined(BOOST_MSVC)
#pragma warning(push)
#if BOOST_MSVC >= 1400
#pragma warning(disable:6294) // Ill-defined for-loop: initial condition does
// not satisfy test. Loop body not executed
#endif
#endif
// Can we use fpclassify?
// STLport
#if defined(__SGI_STL_PORT) || defined(_STLPORT_VERSION)
#define BOOST_HASH_USE_FPCLASSIFY 0
// GNU libstdc++ 3
#elif defined(__GLIBCPP__) || defined(__GLIBCXX__)
# if (defined(__USE_ISOC99) || defined(_GLIBCXX_USE_C99_MATH)) && \
!(defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__))
# define BOOST_HASH_USE_FPCLASSIFY 1
# else
# define BOOST_HASH_USE_FPCLASSIFY 0
# endif
// Everything else
#else
# define BOOST_HASH_USE_FPCLASSIFY 0
#endif
namespace boost
{
namespace hash_detail
{
inline void hash_float_combine(std::size_t& seed, std::size_t value)
{
seed ^= value + (seed<<6) + (seed>>2);
}
////////////////////////////////////////////////////////////////////////
// Binary hash function
//
// Only used for floats with known iec559 floats, and certain values in
// numeric_limits
inline std::size_t hash_binary(char* ptr, std::size_t length)
{
std::size_t seed = 0;
if (length >= sizeof(std::size_t)) {
std::memcpy(&seed, ptr, sizeof(std::size_t));
length -= sizeof(std::size_t);
ptr += sizeof(std::size_t);
while(length >= sizeof(std::size_t)) {
std::size_t buffer = 0;
std::memcpy(&buffer, ptr, sizeof(std::size_t));
hash_float_combine(seed, buffer);
length -= sizeof(std::size_t);
ptr += sizeof(std::size_t);
}
}
if (length > 0) {
std::size_t buffer = 0;
std::memcpy(&buffer, ptr, length);
hash_float_combine(seed, buffer);
}
return seed;
}
template <typename Float, unsigned digits, unsigned max_exponent>
struct enable_binary_hash
{
BOOST_STATIC_CONSTANT(bool, value =
std::numeric_limits<Float>::is_iec559 &&
std::numeric_limits<Float>::digits == digits &&
std::numeric_limits<Float>::radix == 2 &&
std::numeric_limits<Float>::max_exponent == max_exponent);
};
template <typename Float>
inline std::size_t float_hash_impl(Float v,
BOOST_DEDUCED_TYPENAME boost::enable_if_c<
enable_binary_hash<Float, 24, 128>::value,
std::size_t>::type)
{
return hash_binary((char*) &v, 4);
}
template <typename Float>
inline std::size_t float_hash_impl(Float v,
BOOST_DEDUCED_TYPENAME boost::enable_if_c<
enable_binary_hash<Float, 53, 1024>::value,
std::size_t>::type)
{
return hash_binary((char*) &v, 8);
}
template <typename Float>
inline std::size_t float_hash_impl(Float v,
BOOST_DEDUCED_TYPENAME boost::enable_if_c<
enable_binary_hash<Float, 64, 16384>::value,
std::size_t>::type)
{
return hash_binary((char*) &v, 10);
}
template <typename Float>
inline std::size_t float_hash_impl(Float v,
BOOST_DEDUCED_TYPENAME boost::enable_if_c<
enable_binary_hash<Float, 113, 16384>::value,
std::size_t>::type)
{
return hash_binary((char*) &v, 16);
}
////////////////////////////////////////////////////////////////////////
// Portable hash function
//
// Used as a fallback when the binary hash function isn't supported.
template <class T>
inline std::size_t float_hash_impl2(T v)
{
boost::hash_detail::call_frexp<T> frexp;
boost::hash_detail::call_ldexp<T> ldexp;
int exp = 0;
v = frexp(v, &exp);
// A postive value is easier to hash, so combine the
// sign with the exponent and use the absolute value.
if(v < 0) {
v = -v;
exp += limits<T>::max_exponent -
limits<T>::min_exponent;
}
v = ldexp(v, limits<std::size_t>::digits);
std::size_t seed = static_cast<std::size_t>(v);
v -= static_cast<T>(seed);
// ceiling(digits(T) * log2(radix(T))/ digits(size_t)) - 1;
std::size_t const length
= (limits<T>::digits *
boost::static_log2<limits<T>::radix>::value
+ limits<std::size_t>::digits - 1)
/ limits<std::size_t>::digits;
for(std::size_t i = 0; i != length; ++i)
{
v = ldexp(v, limits<std::size_t>::digits);
std::size_t part = static_cast<std::size_t>(v);
v -= static_cast<T>(part);
hash_float_combine(seed, part);
}
hash_float_combine(seed, static_cast<std::size_t>(exp));
return seed;
}
#if !defined(BOOST_HASH_DETAIL_TEST_WITHOUT_GENERIC)
template <class T>
inline std::size_t float_hash_impl(T v, ...)
{
typedef BOOST_DEDUCED_TYPENAME select_hash_type<T>::type type;
return float_hash_impl2(static_cast<type>(v));
}
#endif
}
}
#if BOOST_HASH_USE_FPCLASSIFY
#include <boost/config/no_tr1/cmath.hpp>
namespace boost
{
namespace hash_detail
{
template <class T>
inline std::size_t float_hash_value(T v)
{
#if defined(fpclassify)
switch (fpclassify(v))
#elif BOOST_HASH_CONFORMANT_FLOATS
switch (std::fpclassify(v))
#else
using namespace std;
switch (fpclassify(v))
#endif
{
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, 0);
default:
BOOST_ASSERT(0);
return 0;
}
}
}
}
#else // !BOOST_HASH_USE_FPCLASSIFY
namespace boost
{
namespace hash_detail
{
template <class T>
inline bool is_zero(T v)
{
#if !defined(__GNUC__) && !defined(__clang__)
return v == 0;
#else
// GCC's '-Wfloat-equal' will complain about comparing
// v to 0, but because it disables warnings for system
// headers it won't complain if you use std::equal_to to
// compare with 0. Resulting in this silliness:
return std::equal_to<T>()(v, 0);
#endif
}
template <class T>
inline std::size_t float_hash_value(T v)
{
return boost::hash_detail::is_zero(v) ? 0 : float_hash_impl(v, 0);
}
}
}
#endif // BOOST_HASH_USE_FPCLASSIFY
#undef BOOST_HASH_USE_FPCLASSIFY
#if defined(BOOST_MSVC)
#pragma warning(pop)
#endif
#endif

View File

@@ -0,0 +1,133 @@
// Copyright 2005-2009 Daniel James.
// Copyright 2021 Peter Dimov.
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#ifndef BOOST_HASH_DETAIL_HASH_TUPLE_LIKE_HPP
#define BOOST_HASH_DETAIL_HASH_TUPLE_LIKE_HPP
#include <boost/container_hash/hash_fwd.hpp>
#include <boost/type_traits/enable_if.hpp>
#include <boost/config.hpp>
#if defined(BOOST_NO_CXX11_HDR_TUPLE)
// no support
#else
#include <tuple>
namespace boost
{
namespace hash_detail
{
template <std::size_t I, typename T>
inline typename boost::enable_if_<(I == std::tuple_size<T>::value),
void>::type
hash_combine_tuple(std::size_t&, T const&)
{
}
template <std::size_t I, typename T>
inline typename boost::enable_if_<(I < std::tuple_size<T>::value),
void>::type
hash_combine_tuple(std::size_t& seed, T const& v)
{
boost::hash_combine(seed, std::get<I>(v));
boost::hash_detail::hash_combine_tuple<I + 1>(seed, v);
}
template <typename T>
inline std::size_t hash_tuple(T const& v)
{
std::size_t seed = 0;
boost::hash_detail::hash_combine_tuple<0>(seed, v);
return seed;
}
} // namespace hash_detail
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template <typename... T>
inline std::size_t hash_value(std::tuple<T...> const& v)
{
return boost::hash_detail::hash_tuple(v);
}
#else
inline std::size_t hash_value(std::tuple<> const& v)
{
return boost::hash_detail::hash_tuple(v);
}
template<typename A0>
inline std::size_t hash_value(std::tuple<A0> const& v)
{
return boost::hash_detail::hash_tuple(v);
}
template<typename A0, typename A1>
inline std::size_t hash_value(std::tuple<A0, A1> const& v)
{
return boost::hash_detail::hash_tuple(v);
}
template<typename A0, typename A1, typename A2>
inline std::size_t hash_value(std::tuple<A0, A1, A2> const& v)
{
return boost::hash_detail::hash_tuple(v);
}
template<typename A0, typename A1, typename A2, typename A3>
inline std::size_t hash_value(std::tuple<A0, A1, A2, A3> const& v)
{
return boost::hash_detail::hash_tuple(v);
}
template<typename A0, typename A1, typename A2, typename A3, typename A4>
inline std::size_t hash_value(std::tuple<A0, A1, A2, A3, A4> const& v)
{
return boost::hash_detail::hash_tuple(v);
}
template<typename A0, typename A1, typename A2, typename A3, typename A4, typename A5>
inline std::size_t hash_value(std::tuple<A0, A1, A2, A3, A4, A5> const& v)
{
return boost::hash_detail::hash_tuple(v);
}
template<typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6>
inline std::size_t hash_value(std::tuple<A0, A1, A2, A3, A4, A5, A6> const& v)
{
return boost::hash_detail::hash_tuple(v);
}
template<typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7>
inline std::size_t hash_value(std::tuple<A0, A1, A2, A3, A4, A5, A6, A7> const& v)
{
return boost::hash_detail::hash_tuple(v);
}
template<typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8>
inline std::size_t hash_value(std::tuple<A0, A1, A2, A3, A4, A5, A6, A7, A8> const& v)
{
return boost::hash_detail::hash_tuple(v);
}
template<typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9>
inline std::size_t hash_value(std::tuple<A0, A1, A2, A3, A4, A5, A6, A7, A8, A9> const& v)
{
return boost::hash_detail::hash_tuple(v);
}
#endif // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
} // namespace boost
#endif // #if defined(BOOST_NO_CXX11_HDR_TUPLE)
#endif // #ifndef BOOST_HASH_DETAIL_HASH_TUPLE_LIKE_HPP

View File

@@ -0,0 +1,81 @@
// Copyright 2017, 2018 Peter Dimov.
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#ifndef BOOST_HASH_DETAIL_IS_CONTIGUOUS_RANGE_HPP_INCLUDED
#define BOOST_HASH_DETAIL_IS_CONTIGUOUS_RANGE_HPP_INCLUDED
#include <boost/type_traits/integral_constant.hpp>
#include <boost/config.hpp>
#include <boost/config/workaround.hpp>
#if !defined(BOOST_NO_CXX11_DECLTYPE) && !defined(BOOST_NO_SFINAE_EXPR) && !BOOST_WORKAROUND(BOOST_GCC, < 40700)
#include <boost/type_traits/is_integral.hpp>
#include <boost/type_traits/declval.hpp>
#include <boost/type_traits/is_same.hpp>
#include <iterator>
namespace boost
{
namespace hash_detail
{
template<class It, class T, class S>
integral_constant< bool, is_same<typename std::iterator_traits<It>::value_type, T>::value && is_integral<S>::value >
is_contiguous_range_check( It first, It last, T const*, T const*, S );
template<class T> decltype( is_contiguous_range_check( declval<T const&>().begin(), declval<T const&>().end(), declval<T const&>().data(), declval<T const&>().data() + declval<T const&>().size(), declval<T const&>().size() ) ) is_contiguous_range_( int );
template<class T> false_type is_contiguous_range_( ... );
template<class T> struct is_contiguous_range: decltype( hash_detail::is_contiguous_range_<T>( 0 ) )
{
};
} // namespace hash_detail
} // namespace boost
#else // !defined(BOOST_NO_CXX11_DECLTYPE) && !defined(BOOST_NO_SFINAE_EXPR)
#include <cstddef>
#include <vector>
#include <string>
#if !defined(BOOST_NO_CXX11_HDR_ARRAY)
#include <array>
#endif
namespace boost
{
namespace hash_detail
{
template<class T> struct is_contiguous_range: false_type
{
};
template<class E, class T, class A> struct is_contiguous_range< std::basic_string<E, T, A> >: true_type
{
};
template<class E, class T, class A> struct is_contiguous_range< std::basic_string<E, T, A> const >: true_type
{
};
#if !defined(BOOST_NO_CXX11_HDR_ARRAY)
template<class T, std::size_t N> struct is_contiguous_range< std::array<T, N> >: true_type
{
};
template<class T, std::size_t N> struct is_contiguous_range< std::array<T, N> const >: true_type
{
};
#endif
} // namespace hash_detail
} // namespace boost
#endif // !defined(BOOST_NO_CXX11_DECLTYPE) && !defined(BOOST_NO_SFINAE_EXPR)
#endif // #ifndef BOOST_HASH_DETAIL_IS_CONTIGUOUS_RANGE_HPP_INCLUDED

View File

@@ -0,0 +1,57 @@
// Copyright 2017 Peter Dimov.
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#ifndef BOOST_HASH_DETAIL_IS_RANGE_HPP_INCLUDED
#define BOOST_HASH_DETAIL_IS_RANGE_HPP_INCLUDED
#include <boost/type_traits/integral_constant.hpp>
#include <boost/type_traits/is_integral.hpp>
#include <boost/type_traits/declval.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/type_traits/remove_cv.hpp>
#include <boost/config.hpp>
#include <boost/config/workaround.hpp>
#include <iterator>
namespace boost
{
namespace hash_detail
{
#if !defined(BOOST_NO_CXX11_DECLTYPE) && !defined(BOOST_NO_SFINAE_EXPR) && !BOOST_WORKAROUND(BOOST_GCC, < 40700)
template<class T, class It>
integral_constant< bool, !is_same<typename remove_cv<T>::type, typename std::iterator_traits<It>::value_type>::value >
is_range_check( It first, It last );
template<class T> decltype( is_range_check<T>( declval<T const&>().begin(), declval<T const&>().end() ) ) is_range_( int );
template<class T> false_type is_range_( ... );
template<class T> struct is_range: decltype( is_range_<T>( 0 ) )
{
};
#else
template<class T, class E = true_type> struct is_range_: false_type
{
};
template<class T> struct is_range_< T, integral_constant< bool,
is_same<typename T::value_type, typename std::iterator_traits<typename T::const_iterator>::value_type>::value &&
is_integral<typename T::size_type>::value
> >: true_type
{
};
template<class T> struct is_range: is_range_<T>
{
};
#endif // !defined(BOOST_NO_CXX11_DECLTYPE) && !defined(BOOST_NO_SFINAE_EXPR)
} // namespace hash_detail
} // namespace boost
#endif // #ifndef BOOST_HASH_DETAIL_IS_RANGE_HPP_INCLUDED

View File

@@ -0,0 +1,34 @@
// Copyright 2017 Peter Dimov.
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#ifndef BOOST_HASH_DETAIL_IS_UNORDERED_RANGE_HPP_INCLUDED
#define BOOST_HASH_DETAIL_IS_UNORDERED_RANGE_HPP_INCLUDED
#include <boost/container_hash/detail/is_range.hpp>
#include <boost/type_traits/integral_constant.hpp>
#include <boost/type_traits/is_same.hpp>
namespace boost
{
namespace hash_detail
{
template<class T, class E = true_type> struct has_hasher_: false_type
{
};
template<class T> struct has_hasher_< T, integral_constant< bool,
is_same<typename T::hasher, typename T::hasher>::value
> >: true_type
{
};
template<class T> struct is_unordered_range: integral_constant< bool, is_range<T>::value && has_hasher_<T>::value >
{
};
} // namespace hash_detail
} // namespace boost
#endif // #ifndef BOOST_HASH_DETAIL_IS_UNORDERED_RANGE_HPP_INCLUDED

View File

@@ -1,28 +1,11 @@
// Copyright 2005-2009 Daniel James.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// On some platforms std::limits gives incorrect values for long double.
// This tries to work around them.
#if !defined(BOOST_FUNCTIONAL_HASH_DETAIL_LIMITS_HEADER)
#ifndef BOOST_FUNCTIONAL_HASH_DETAIL_LIMITS_HEADER
#define BOOST_FUNCTIONAL_HASH_DETAIL_LIMITS_HEADER
#include <boost/config.hpp>
#if defined(BOOST_HAS_PRAGMA_ONCE)
#pragma once
#endif
#include <boost/limits.hpp>
// On OpenBSD, numeric_limits is not reliable for long doubles, but
// the macros defined in <float.h> are and support long double when STLport
// doesn't.
#if defined(__OpenBSD__) || defined(_STLP_NO_LONG_DOUBLE)
#include <float.h>
#endif
#include <limits>
namespace boost
{
@@ -30,33 +13,7 @@ namespace boost
{
template <class T>
struct limits : std::numeric_limits<T> {};
#if defined(__OpenBSD__) || defined(_STLP_NO_LONG_DOUBLE)
template <>
struct limits<long double>
: std::numeric_limits<long double>
{
static long double epsilon() {
return LDBL_EPSILON;
}
static long double (max)() {
return LDBL_MAX;
}
static long double (min)() {
return LDBL_MIN;
}
BOOST_STATIC_CONSTANT(int, digits = LDBL_MANT_DIG);
BOOST_STATIC_CONSTANT(int, max_exponent = LDBL_MAX_EXP);
BOOST_STATIC_CONSTANT(int, min_exponent = LDBL_MIN_EXP);
#if defined(_STLP_NO_LONG_DOUBLE)
BOOST_STATIC_CONSTANT(int, radix = FLT_RADIX);
#endif
};
#endif // __OpenBSD__
}
}
#endif
#endif // #ifndef BOOST_FUNCTIONAL_HASH_DETAIL_LIMITS_HEADER

View File

@@ -1,414 +1,10 @@
// Copyright 2005-2009 Daniel James.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// Based on Peter Dimov's proposal
// http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2005/n1756.pdf
// issue 6.18.
// This implements the extensions to the standard.
// It's undocumented, so you shouldn't use it....
#if !defined(BOOST_FUNCTIONAL_HASH_EXTENSIONS_HPP)
#ifndef BOOST_FUNCTIONAL_HASH_EXTENSIONS_HPP
#define BOOST_FUNCTIONAL_HASH_EXTENSIONS_HPP
#include <boost/config.hpp>
#if defined(BOOST_HAS_PRAGMA_ONCE)
#pragma once
#endif
#include <boost/container_hash/hash.hpp>
#include <boost/detail/container_fwd.hpp>
#include <boost/core/enable_if.hpp>
#include <boost/static_assert.hpp>
#include <vector>
#if !defined(BOOST_NO_CXX11_HDR_ARRAY)
# include <array>
#endif
#if !defined(BOOST_NO_CXX11_HDR_TUPLE)
# include <tuple>
#endif
#if !defined(BOOST_NO_CXX11_HDR_MEMORY)
# include <memory>
#endif
#if defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
#include <boost/type_traits/is_array.hpp>
#endif
namespace boost
{
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);
template <class T>
std::size_t hash_value(std::complex<T> const&);
template <class A, class B>
std::size_t hash_value(std::pair<A, B> const& v)
{
std::size_t seed = 0;
boost::hash_combine(seed, v.first);
boost::hash_combine(seed, v.second);
return seed;
}
inline std::size_t hash_range(
std::vector<bool>::iterator first,
std::vector<bool>::iterator last)
{
std::size_t seed = 0;
for(; first != last; ++first)
{
hash_combine<bool>(seed, *first);
}
return seed;
}
inline std::size_t hash_range(
std::vector<bool>::const_iterator first,
std::vector<bool>::const_iterator last)
{
std::size_t seed = 0;
for(; first != last; ++first)
{
hash_combine<bool>(seed, *first);
}
return seed;
}
inline void hash_range(
std::size_t& seed,
std::vector<bool>::iterator first,
std::vector<bool>::iterator last)
{
for(; first != last; ++first)
{
hash_combine<bool>(seed, *first);
}
}
inline void hash_range(
std::size_t& seed,
std::vector<bool>::const_iterator first,
std::vector<bool>::const_iterator last)
{
for(; first != last; ++first)
{
hash_combine<bool>(seed, *first);
}
}
template <class T, class A>
std::size_t hash_value(std::vector<T, A> const& v)
{
return boost::hash_range(v.begin(), v.end());
}
template <class T, class A>
std::size_t hash_value(std::list<T, A> const& v)
{
return boost::hash_range(v.begin(), v.end());
}
template <class T, class A>
std::size_t hash_value(std::deque<T, A> const& v)
{
return boost::hash_range(v.begin(), v.end());
}
template <class K, class C, class A>
std::size_t hash_value(std::set<K, C, A> const& v)
{
return boost::hash_range(v.begin(), v.end());
}
template <class K, class C, class A>
std::size_t hash_value(std::multiset<K, C, A> const& v)
{
return boost::hash_range(v.begin(), v.end());
}
template <class K, class T, class C, class A>
std::size_t hash_value(std::map<K, T, C, A> const& v)
{
return boost::hash_range(v.begin(), v.end());
}
template <class K, class T, class C, class A>
std::size_t hash_value(std::multimap<K, T, C, A> const& v)
{
return boost::hash_range(v.begin(), v.end());
}
template <class T>
std::size_t hash_value(std::complex<T> const& v)
{
boost::hash<T> hasher;
std::size_t seed = hasher(v.imag());
seed ^= hasher(v.real()) + (seed<<6) + (seed>>2);
return seed;
}
#if !defined(BOOST_NO_CXX11_HDR_ARRAY)
template <class T, std::size_t N>
std::size_t hash_value(std::array<T, N> const& v)
{
return boost::hash_range(v.begin(), v.end());
}
#endif
#if !defined(BOOST_NO_CXX11_HDR_TUPLE)
namespace hash_detail {
template <std::size_t I, typename T>
inline typename boost::enable_if_c<(I == std::tuple_size<T>::value),
void>::type
hash_combine_tuple(std::size_t&, T const&)
{
}
template <std::size_t I, typename T>
inline typename boost::enable_if_c<(I < std::tuple_size<T>::value),
void>::type
hash_combine_tuple(std::size_t& seed, T const& v)
{
boost::hash_combine(seed, std::get<I>(v));
boost::hash_detail::hash_combine_tuple<I + 1>(seed, v);
}
template <typename T>
inline std::size_t hash_tuple(T const& v)
{
std::size_t seed = 0;
boost::hash_detail::hash_combine_tuple<0>(seed, v);
return seed;
}
}
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template <typename... T>
inline std::size_t hash_value(std::tuple<T...> const& v)
{
return boost::hash_detail::hash_tuple(v);
}
#else
inline std::size_t hash_value(std::tuple<> const& v)
{
return boost::hash_detail::hash_tuple(v);
}
template<typename A0>
inline std::size_t hash_value(std::tuple<A0> const& v)
{
return boost::hash_detail::hash_tuple(v);
}
template<typename A0, typename A1>
inline std::size_t hash_value(std::tuple<A0, A1> const& v)
{
return boost::hash_detail::hash_tuple(v);
}
template<typename A0, typename A1, typename A2>
inline std::size_t hash_value(std::tuple<A0, A1, A2> const& v)
{
return boost::hash_detail::hash_tuple(v);
}
template<typename A0, typename A1, typename A2, typename A3>
inline std::size_t hash_value(std::tuple<A0, A1, A2, A3> const& v)
{
return boost::hash_detail::hash_tuple(v);
}
template<typename A0, typename A1, typename A2, typename A3, typename A4>
inline std::size_t hash_value(std::tuple<A0, A1, A2, A3, A4> const& v)
{
return boost::hash_detail::hash_tuple(v);
}
template<typename A0, typename A1, typename A2, typename A3, typename A4, typename A5>
inline std::size_t hash_value(std::tuple<A0, A1, A2, A3, A4, A5> const& v)
{
return boost::hash_detail::hash_tuple(v);
}
template<typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6>
inline std::size_t hash_value(std::tuple<A0, A1, A2, A3, A4, A5, A6> const& v)
{
return boost::hash_detail::hash_tuple(v);
}
template<typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7>
inline std::size_t hash_value(std::tuple<A0, A1, A2, A3, A4, A5, A6, A7> const& v)
{
return boost::hash_detail::hash_tuple(v);
}
template<typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8>
inline std::size_t hash_value(std::tuple<A0, A1, A2, A3, A4, A5, A6, A7, A8> const& v)
{
return boost::hash_detail::hash_tuple(v);
}
template<typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9>
inline std::size_t hash_value(std::tuple<A0, A1, A2, A3, A4, A5, A6, A7, A8, A9> const& v)
{
return boost::hash_detail::hash_tuple(v);
}
#endif
#endif
#if !defined(BOOST_NO_CXX11_SMART_PTR)
template <typename T>
inline std::size_t hash_value(std::shared_ptr<T> const& x) {
return boost::hash_value(x.get());
}
template <typename T, typename Deleter>
inline std::size_t hash_value(std::unique_ptr<T, Deleter> const& x) {
return boost::hash_value(x.get());
}
#endif
//
// call_hash_impl
//
// On compilers without function template ordering, this deals with arrays.
#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
{
static std::size_t call(Array const& v)
{
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
//
// boost::hash
//
#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
template <class T> struct hash
: boost::hash_detail::hash_base<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]>
: boost::hash_detail::hash_base<T[n]>
{
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 of hash_impl.
namespace hash_detail
{
template <bool IsPointer>
struct hash_impl;
template <>
struct hash_impl<false>
{
template <class T>
struct inner
: boost::hash_detail::hash_base<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
};
};
}
#endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
}
#endif
#endif // #ifndef BOOST_FUNCTIONAL_HASH_EXTENSIONS_HPP

File diff suppressed because it is too large Load Diff

View File

@@ -1,23 +1,13 @@
// Copyright 2005-2009 Daniel James.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// Copyright 2021 Peter Dimov.
// Distributed under the Boost Software License, Version 1.0.
// https://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)
#ifndef BOOST_FUNCTIONAL_HASH_FWD_HPP
#define BOOST_FUNCTIONAL_HASH_FWD_HPP
#include <boost/config/workaround.hpp>
#include <cstddef>
#if defined(BOOST_HAS_PRAGMA_ONCE)
#pragma once
#endif
namespace boost
{
template <class T> struct hash;
@@ -27,10 +17,8 @@ namespace boost
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
template <class It> std::size_t hash_unordered_range(It, It);
template <class It> void hash_unordered_range(std::size_t&, It, It);
}
#endif
#endif // #ifndef BOOST_FUNCTIONAL_HASH_FWD_HPP

View File

@@ -7,10 +7,10 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
<html>
<head>
<meta http-equiv="refresh" content="0; URL=../../doc/html/hash.html">
<meta http-equiv="refresh" content="0; URL=doc/html/hash.html">
</head>
<body>
Automatic redirection failed, please go to
<a href="../../doc/html/hash.html">../../doc/html/hash.html</a>
<a href="doc/html/hash.html">doc/html/hash.html</a>
</body>
</html>

View File

@@ -1,6 +1,6 @@
[
{
"key": "functional/hash",
"key": "container_hash",
"boost-version": "1.33.0",
"name": "Container Hash",
"authors": [
@@ -15,6 +15,7 @@
],
"category": [
"Function-objects"
]
],
"cxxstd": "03"
}
]

11
test/CMakeLists.txt Normal file
View File

@@ -0,0 +1,11 @@
# Copyright 2018, 2019, 2021 Peter Dimov
# 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(BoostTestJamfile OPTIONAL RESULT_VARIABLE HAVE_BOOST_TEST)
if(HAVE_BOOST_TEST)
boost_test_jamfile(FILE Jamfile.v2 LINK_LIBRARIES Boost::container_hash Boost::core Boost::utility)
endif()

View File

@@ -1,87 +1,81 @@
# Copyright 2005-2012 Daniel James.
# Distributed under the Boost Software License, Version 1.0. (See accompanying
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
# Copyright 2022 Peter Dimov
# Distributed under the Boost Software License, Version 1.0.
# https://www.boost.org/LICENSE_1_0.txt
import testing ;
local gcc-flags = -Wunused-parameter -Wconversion -Wsign-conversion -Wfloat-equal -Wshadow -Wno-variadic-macros ;
local clang-flags = $(gcc-flags) -Wno-c99-extensions ;
project hash-tests
: requirements
<warnings>all
<warnings>pedantic
<toolset>intel:<warnings>on
#<toolset>intel:<cxxflags>-strict-ansi
<toolset>gcc:<cxxflags>"-pedantic -Wstrict-aliasing -fstrict-aliasing -Wextra -Wsign-promo -Wunused-parameter -Wconversion -Wfloat-equal -Wshadow"
<toolset>darwin:<cxxflags>"-pedantic -Wstrict-aliasing -fstrict-aliasing -Wextra -Wsign-promo -Wunused-parameter -Wconversion -Wfloat-equal -Wshadow"
<toolset>clang:<cxxflags>"-pedantic -Wstrict-aliasing -fstrict-aliasing -Wextra -Wsign-promo -Wunused-parameter -Wsign-conversion -Wconversion -Wfloat-equal -Wshadow"
#<toolset>msvc:<warnings-as-errors>on
#<toolset>gcc:<warnings-as-errors>on
#<toolset>darwin:<warnings-as-errors>on
<toolset>gcc:<cxxflags>$(gcc-flags)
<toolset>darwin:<cxxflags>$(gcc-flags)
<toolset>clang:<cxxflags>$(clang-flags)
<toolset>msvc:<warnings-as-errors>on
<toolset>gcc:<warnings-as-errors>on
<toolset>clang:<warnings-as-errors>on
;
test-suite container_hash/hash
:
[ run hash_info.cpp : : : <test-info>always_show_run_output ]
[ compile check_float_funcs.cpp ]
[ run hash_fwd_test_1.cpp ]
[ run hash_fwd_test_2.cpp ]
[ run hash_number_test.cpp ]
[ run hash_enum_test.cpp ]
[ run hash_pointer_test.cpp ]
[ run hash_function_pointer_test.cpp ]
[ run hash_float_test.cpp ]
[ run hash_long_double_test.cpp ]
[ run hash_string_test.cpp ]
[ run hash_range_test.cpp ]
[ run hash_custom_test.cpp ]
[ run hash_global_namespace_test.cpp ]
[ run hash_friend_test.cpp ]
[ run hash_built_in_array_test.cpp ]
[ run hash_value_array_test.cpp ]
[ run hash_vector_test.cpp ]
[ run hash_list_test.cpp ]
[ run hash_deque_test.cpp ]
[ run hash_set_test.cpp ]
[ run hash_map_test.cpp ]
[ run hash_complex_test.cpp ]
[ run hash_optional_test.cpp ]
[ run hash_variant_test.cpp ]
[ run hash_type_index_test.cpp ]
[ run hash_system_error_test.cpp ]
[ run hash_std_array_test.cpp ]
[ run hash_std_tuple_test.cpp ]
[ run hash_std_smart_ptr_test.cpp ]
[ run link_test.cpp link_test_2.cpp ]
[ run link_ext_test.cpp link_no_ext_test.cpp ]
[ run extensions_hpp_test.cpp ]
[ compile-fail hash_no_ext_fail_test.cpp ]
[ compile-fail namespace_fail_test.cpp ]
[ run implicit_test.cpp ]
[ run hash_no_ext_macro_1.cpp ]
[ run hash_no_ext_macro_2.cpp ]
;
test-suite container_hash/hash_no_ext
:
[ run hash_number_test.cpp : : : <define>BOOST_HASH_NO_EXTENSIONS : no_ext_number_test ]
[ run hash_pointer_test.cpp : : : <define>BOOST_HASH_NO_EXTENSIONS : no_ext_pointer_test ]
[ run hash_function_pointer_test.cpp : : : <define>BOOST_HASH_NO_EXTENSIONS : no_ext_function_pointer_test ]
[ run hash_float_test.cpp : : : <define>BOOST_HASH_NO_EXTENSIONS : no_ext_float_test ]
[ run hash_long_double_test.cpp : : : <define>BOOST_HASH_NO_EXTENSIONS : no_ext_long_double_test ]
[ run hash_string_test.cpp : : : <define>BOOST_HASH_NO_EXTENSIONS : no_ext_string_test ]
[ run link_test.cpp link_test_2.cpp : : : <define>BOOST_HASH_NO_EXTENSIONS : no_ext_link_test ]
;
# Tests to see if the floating point hash is using the binary hash.
# Not run normally because on some platforms these should fail.
test-suite container_hash/hash_no_generic_float
:
[ run hash_float_test.cpp
: : : <define>BOOST_HASH_DETAIL_TEST_WITHOUT_GENERIC
: hash_float_test_no_generic ]
[ run hash_long_double_test.cpp
: : : <define>BOOST_HASH_DETAIL_TEST_WITHOUT_GENERIC
: hash_long_double_test_no_generic ]
;
explicit container_hash/hash_no_generic_float ;
run hash_info.cpp : : : <test-info>always_show_run_output ;
compile check_float_funcs.cpp ;
run hash_fwd_test_1.cpp ;
run hash_fwd_test_2.cpp ;
run hash_number_test.cpp ;
run hash_enum_test.cpp ;
run hash_pointer_test.cpp ;
run hash_function_pointer_test.cpp ;
run hash_float_test.cpp ;
run hash_long_double_test.cpp ;
run hash_string_test.cpp ;
run hash_range_test.cpp ;
run hash_custom_test.cpp ;
run hash_global_namespace_test.cpp ;
run hash_friend_test.cpp ;
run hash_built_in_array_test.cpp ;
run hash_value_array_test.cpp ;
run hash_vector_test.cpp ;
run hash_list_test.cpp ;
run hash_deque_test.cpp ;
run hash_set_test.cpp ;
run hash_map_test.cpp ;
run hash_complex_test.cpp ;
run hash_optional_test.cpp ;
run hash_variant_test.cpp ;
run hash_type_index_test.cpp ;
run hash_system_error_test.cpp ;
run hash_std_array_test.cpp ;
run hash_std_tuple_test.cpp ;
run hash_std_smart_ptr_test.cpp ;
run link_test.cpp link_test_2.cpp ;
run link_ext_test.cpp link_no_ext_test.cpp ;
run extensions_hpp_test.cpp ;
compile-fail namespace_fail_test.cpp ;
run implicit_test.cpp ;
run hash_no_ext_macro_1.cpp ;
run hash_no_ext_macro_2.cpp ;
build-project ../examples ;
run hash_reference_values.cpp ;
run detail_is_range_test.cpp ;
run detail_is_contiguous_range_test.cpp ;
run detail_is_unordered_range_test.cpp ;
run hash_forward_list_test.cpp ;
run quick.cpp ;
run hash_number_test2.cpp ;
run hash_integral_test.cpp ;
run hash_string_test2.cpp ;
# for gcc-4.8
local fs-path-req = "-<toolset>gcc:<cxxflags>-Wshadow" "-<toolset>gcc:<cxxflags>-Wconversion" ;
run hash_fs_path_test.cpp /boost//filesystem/<warnings>off : : : $(fs-path-req) <toolset>msvc-14.0,<cxxstd>latest:<build>no ;
run detail_is_range_test2.cpp : : : $(fs-path-req) ;

View File

@@ -3,6 +3,11 @@
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#if defined(__GNUC__)
// in type_traits/is_complete.hpp:47
#pragma GCC diagnostic ignored "-Wconversion"
#endif
#include <boost/static_assert.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/type_traits/is_convertible.hpp>

View File

@@ -0,0 +1,17 @@
# Copyright 2018, 2019, 2021 Peter Dimov
# 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
cmake_minimum_required(VERSION 3.5...3.20)
project(cmake_install_test LANGUAGES CXX)
find_package(boost_container_hash REQUIRED)
add_executable(quick ../quick.cpp)
target_link_libraries(quick Boost::container_hash)
enable_testing()
add_test(quick quick)
add_custom_target(check COMMAND ${CMAKE_CTEST_COMMAND} --output-on-failure -C $<CONFIG>)

View File

@@ -0,0 +1,21 @@
# Copyright 2018, 2019, 2021 Peter Dimov
# 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
cmake_minimum_required(VERSION 3.5...3.20)
project(cmake_subdir_test LANGUAGES CXX)
add_subdirectory(../.. boostorg/container_hash)
add_subdirectory(../../../config boostorg/config)
add_subdirectory(../../../type_traits boostorg/type_traits)
add_subdirectory(../../../static_assert boostorg/static_assert)
add_executable(quick ../quick.cpp)
target_link_libraries(quick Boost::container_hash)
enable_testing()
add_test(quick quick)
add_custom_target(check COMMAND ${CMAKE_CTEST_COMMAND} --output-on-failure -C $<CONFIG>)

View File

@@ -0,0 +1,101 @@
// Copyright 2017, 2018 Peter Dimov.
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/container_hash/detail/is_contiguous_range.hpp>
#include <boost/core/lightweight_test_trait.hpp>
#include <boost/config.hpp>
#include <string>
#include <vector>
#include <list>
#include <deque>
#include <set>
#include <map>
#if !defined(BOOST_NO_CXX11_HDR_ARRAY)
# include <array>
#endif
#if !defined(BOOST_NO_CXX11_HDR_FORWARD_LIST)
# include <forward_list>
#endif
#if !defined(BOOST_NO_CXX11_HDR_UNORDERED_SET)
# include <unordered_set>
#endif
#if !defined(BOOST_NO_CXX11_HDR_UNORDERED_MAP)
# include <unordered_map>
#endif
struct X
{
};
int main()
{
using boost::hash_detail::is_contiguous_range;
BOOST_TEST_TRAIT_FALSE((is_contiguous_range<void>));
BOOST_TEST_TRAIT_FALSE((is_contiguous_range<void const>));
BOOST_TEST_TRAIT_FALSE((is_contiguous_range<int>));
BOOST_TEST_TRAIT_FALSE((is_contiguous_range<int const>));
BOOST_TEST_TRAIT_FALSE((is_contiguous_range<X>));
BOOST_TEST_TRAIT_FALSE((is_contiguous_range<X const>));
BOOST_TEST_TRAIT_FALSE((is_contiguous_range<int[2]>));
BOOST_TEST_TRAIT_FALSE((is_contiguous_range<int const[2]>));
BOOST_TEST_TRAIT_TRUE((is_contiguous_range<std::string>));
BOOST_TEST_TRAIT_TRUE((is_contiguous_range<std::string const>));
BOOST_TEST_TRAIT_TRUE((is_contiguous_range<std::wstring>));
BOOST_TEST_TRAIT_TRUE((is_contiguous_range<std::wstring const>));
// std::vector doesn't have data() in C++03
#if !defined(BOOST_NO_CXX11_DECLTYPE) && !defined(BOOST_NO_SFINAE_EXPR) && !BOOST_WORKAROUND(BOOST_GCC, < 40700)
BOOST_TEST_TRAIT_TRUE((is_contiguous_range< std::vector<X> >));
BOOST_TEST_TRAIT_TRUE((is_contiguous_range< std::vector<X> const >));
#endif
BOOST_TEST_TRAIT_FALSE((is_contiguous_range< std::deque<X> >));
BOOST_TEST_TRAIT_FALSE((is_contiguous_range< std::deque<X> const >));
BOOST_TEST_TRAIT_FALSE((is_contiguous_range< std::set<int> >));
BOOST_TEST_TRAIT_FALSE((is_contiguous_range< std::set<int> const >));
BOOST_TEST_TRAIT_FALSE((is_contiguous_range< std::multiset<int> >));
BOOST_TEST_TRAIT_FALSE((is_contiguous_range< std::multiset<int> const >));
BOOST_TEST_TRAIT_FALSE((is_contiguous_range< std::map<int, X> >));
BOOST_TEST_TRAIT_FALSE((is_contiguous_range< std::map<int, X> const >));
BOOST_TEST_TRAIT_FALSE((is_contiguous_range< std::multimap<int, X> >));
BOOST_TEST_TRAIT_FALSE((is_contiguous_range< std::multimap<int, X> const >));
#if !defined(BOOST_NO_CXX11_HDR_ARRAY)
BOOST_TEST_TRAIT_TRUE((is_contiguous_range< std::array<X, 2> >));
BOOST_TEST_TRAIT_TRUE((is_contiguous_range< std::array<X, 2> const >));
#endif
#if !defined(BOOST_NO_CXX11_HDR_FORWARD_LIST)
BOOST_TEST_TRAIT_FALSE((is_contiguous_range< std::forward_list<X> >));
BOOST_TEST_TRAIT_FALSE((is_contiguous_range< std::forward_list<X> const >));
#endif
#if !defined(BOOST_NO_CXX11_HDR_UNORDERED_SET)
BOOST_TEST_TRAIT_FALSE((is_contiguous_range< std::unordered_set<int> >));
BOOST_TEST_TRAIT_FALSE((is_contiguous_range< std::unordered_set<int> const >));
BOOST_TEST_TRAIT_FALSE((is_contiguous_range< std::unordered_multiset<int> >));
BOOST_TEST_TRAIT_FALSE((is_contiguous_range< std::unordered_multiset<int> const >));
#endif
#if !defined(BOOST_NO_CXX11_HDR_UNORDERED_MAP)
BOOST_TEST_TRAIT_FALSE((is_contiguous_range< std::unordered_map<int, X> >));
BOOST_TEST_TRAIT_FALSE((is_contiguous_range< std::unordered_map<int, X> const >));
BOOST_TEST_TRAIT_FALSE((is_contiguous_range< std::unordered_multimap<int, X> >));
BOOST_TEST_TRAIT_FALSE((is_contiguous_range< std::unordered_multimap<int, X> const >));
#endif
return boost::report_errors();
}

View File

@@ -0,0 +1,98 @@
// Copyright 2017 Peter Dimov.
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/container_hash/detail/is_range.hpp>
#include <boost/core/lightweight_test_trait.hpp>
#include <boost/config.hpp>
#include <string>
#include <vector>
#include <list>
#include <deque>
#include <set>
#include <map>
#if !defined(BOOST_NO_CXX11_HDR_ARRAY)
# include <array>
#endif
#if !defined(BOOST_NO_CXX11_HDR_FORWARD_LIST)
# include <forward_list>
#endif
#if !defined(BOOST_NO_CXX11_HDR_UNORDERED_SET)
# include <unordered_set>
#endif
#if !defined(BOOST_NO_CXX11_HDR_UNORDERED_MAP)
# include <unordered_map>
#endif
struct X
{
};
int main()
{
using boost::hash_detail::is_range;
BOOST_TEST_TRAIT_FALSE((is_range<void>));
BOOST_TEST_TRAIT_FALSE((is_range<void const>));
BOOST_TEST_TRAIT_FALSE((is_range<int>));
BOOST_TEST_TRAIT_FALSE((is_range<int const>));
BOOST_TEST_TRAIT_FALSE((is_range<X>));
BOOST_TEST_TRAIT_FALSE((is_range<X const>));
BOOST_TEST_TRAIT_FALSE((is_range<int[2]>));
BOOST_TEST_TRAIT_FALSE((is_range<int const[2]>));
BOOST_TEST_TRAIT_TRUE((is_range<std::string>));
BOOST_TEST_TRAIT_TRUE((is_range<std::string const>));
BOOST_TEST_TRAIT_TRUE((is_range<std::wstring>));
BOOST_TEST_TRAIT_TRUE((is_range<std::wstring const>));
BOOST_TEST_TRAIT_TRUE((is_range< std::vector<X> >));
BOOST_TEST_TRAIT_TRUE((is_range< std::vector<X> const >));
BOOST_TEST_TRAIT_TRUE((is_range< std::deque<X> >));
BOOST_TEST_TRAIT_TRUE((is_range< std::deque<X> const >));
BOOST_TEST_TRAIT_TRUE((is_range< std::set<int> >));
BOOST_TEST_TRAIT_TRUE((is_range< std::set<int> const >));
BOOST_TEST_TRAIT_TRUE((is_range< std::multiset<int> >));
BOOST_TEST_TRAIT_TRUE((is_range< std::multiset<int> const >));
BOOST_TEST_TRAIT_TRUE((is_range< std::map<int, X> >));
BOOST_TEST_TRAIT_TRUE((is_range< std::map<int, X> const >));
BOOST_TEST_TRAIT_TRUE((is_range< std::multimap<int, X> >));
BOOST_TEST_TRAIT_TRUE((is_range< std::multimap<int, X> const >));
#if !defined(BOOST_NO_CXX11_HDR_ARRAY)
BOOST_TEST_TRAIT_TRUE((is_range< std::array<X, 2> >));
BOOST_TEST_TRAIT_TRUE((is_range< std::array<X, 2> const >));
#endif
#if !defined(BOOST_NO_CXX11_HDR_FORWARD_LIST)
BOOST_TEST_TRAIT_TRUE((is_range< std::forward_list<X> >));
BOOST_TEST_TRAIT_TRUE((is_range< std::forward_list<X> const >));
#endif
#if !defined(BOOST_NO_CXX11_HDR_UNORDERED_SET)
BOOST_TEST_TRAIT_TRUE((is_range< std::unordered_set<int> >));
BOOST_TEST_TRAIT_TRUE((is_range< std::unordered_set<int> const >));
BOOST_TEST_TRAIT_TRUE((is_range< std::unordered_multiset<int> >));
BOOST_TEST_TRAIT_TRUE((is_range< std::unordered_multiset<int> const >));
#endif
#if !defined(BOOST_NO_CXX11_HDR_UNORDERED_MAP)
BOOST_TEST_TRAIT_TRUE((is_range< std::unordered_map<int, X> >));
BOOST_TEST_TRAIT_TRUE((is_range< std::unordered_map<int, X> const >));
BOOST_TEST_TRAIT_TRUE((is_range< std::unordered_multimap<int, X> >));
BOOST_TEST_TRAIT_TRUE((is_range< std::unordered_multimap<int, X> const >));
#endif
return boost::report_errors();
}

View File

@@ -0,0 +1,37 @@
// Copyright 2022 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#if defined(_MSC_VER)
# pragma warning(disable: 4714) // forceinline not inlined
#endif
#if defined(__GNUC__) || defined(__clang__)
# pragma GCC diagnostic ignored "-Wsign-conversion"
#endif
#include <boost/container_hash/detail/is_range.hpp>
#include <boost/core/lightweight_test_trait.hpp>
#include <boost/config.hpp>
#include <boost/filesystem/path.hpp>
#if !defined(BOOST_NO_CXX17_HDR_FILESYSTEM) && !defined(__MINGW32__)
# include <filesystem>
#endif
int main()
{
using boost::hash_detail::is_range;
BOOST_TEST_TRAIT_FALSE((is_range< boost::filesystem::path >));
BOOST_TEST_TRAIT_FALSE((is_range< boost::filesystem::path const >));
#if !defined(BOOST_NO_CXX17_HDR_FILESYSTEM) && !defined(__MINGW32__)
BOOST_TEST_TRAIT_FALSE((is_range< std::filesystem::path >));
BOOST_TEST_TRAIT_FALSE((is_range< std::filesystem::path const >));
#endif
return boost::report_errors();
}

View File

@@ -0,0 +1,98 @@
// Copyright 2017 Peter Dimov.
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/container_hash/detail/is_unordered_range.hpp>
#include <boost/core/lightweight_test_trait.hpp>
#include <boost/config.hpp>
#include <string>
#include <vector>
#include <list>
#include <deque>
#include <set>
#include <map>
#if !defined(BOOST_NO_CXX11_HDR_ARRAY)
# include <array>
#endif
#if !defined(BOOST_NO_CXX11_HDR_FORWARD_LIST)
# include <forward_list>
#endif
#if !defined(BOOST_NO_CXX11_HDR_UNORDERED_SET)
# include <unordered_set>
#endif
#if !defined(BOOST_NO_CXX11_HDR_UNORDERED_MAP)
# include <unordered_map>
#endif
struct X
{
};
int main()
{
using boost::hash_detail::is_unordered_range;
BOOST_TEST_TRAIT_FALSE((is_unordered_range<void>));
BOOST_TEST_TRAIT_FALSE((is_unordered_range<void const>));
BOOST_TEST_TRAIT_FALSE((is_unordered_range<int>));
BOOST_TEST_TRAIT_FALSE((is_unordered_range<int const>));
BOOST_TEST_TRAIT_FALSE((is_unordered_range<X>));
BOOST_TEST_TRAIT_FALSE((is_unordered_range<X const>));
BOOST_TEST_TRAIT_FALSE((is_unordered_range<int[2]>));
BOOST_TEST_TRAIT_FALSE((is_unordered_range<int const[2]>));
BOOST_TEST_TRAIT_FALSE((is_unordered_range<std::string>));
BOOST_TEST_TRAIT_FALSE((is_unordered_range<std::string const>));
BOOST_TEST_TRAIT_FALSE((is_unordered_range<std::wstring>));
BOOST_TEST_TRAIT_FALSE((is_unordered_range<std::wstring const>));
BOOST_TEST_TRAIT_FALSE((is_unordered_range< std::vector<X> >));
BOOST_TEST_TRAIT_FALSE((is_unordered_range< std::vector<X> const >));
BOOST_TEST_TRAIT_FALSE((is_unordered_range< std::deque<X> >));
BOOST_TEST_TRAIT_FALSE((is_unordered_range< std::deque<X> const >));
BOOST_TEST_TRAIT_FALSE((is_unordered_range< std::set<int> >));
BOOST_TEST_TRAIT_FALSE((is_unordered_range< std::set<int> const >));
BOOST_TEST_TRAIT_FALSE((is_unordered_range< std::multiset<int> >));
BOOST_TEST_TRAIT_FALSE((is_unordered_range< std::multiset<int> const >));
BOOST_TEST_TRAIT_FALSE((is_unordered_range< std::map<int, X> >));
BOOST_TEST_TRAIT_FALSE((is_unordered_range< std::map<int, X> const >));
BOOST_TEST_TRAIT_FALSE((is_unordered_range< std::multimap<int, X> >));
BOOST_TEST_TRAIT_FALSE((is_unordered_range< std::multimap<int, X> const >));
#if !defined(BOOST_NO_CXX11_HDR_ARRAY)
BOOST_TEST_TRAIT_FALSE((is_unordered_range< std::array<X, 2> >));
BOOST_TEST_TRAIT_FALSE((is_unordered_range< std::array<X, 2> const >));
#endif
#if !defined(BOOST_NO_CXX11_HDR_FORWARD_LIST)
BOOST_TEST_TRAIT_FALSE((is_unordered_range< std::forward_list<X> >));
BOOST_TEST_TRAIT_FALSE((is_unordered_range< std::forward_list<X> const >));
#endif
#if !defined(BOOST_NO_CXX11_HDR_UNORDERED_SET)
BOOST_TEST_TRAIT_TRUE((is_unordered_range< std::unordered_set<int> >));
BOOST_TEST_TRAIT_TRUE((is_unordered_range< std::unordered_set<int> const >));
BOOST_TEST_TRAIT_TRUE((is_unordered_range< std::unordered_multiset<int> >));
BOOST_TEST_TRAIT_TRUE((is_unordered_range< std::unordered_multiset<int> const >));
#endif
#if !defined(BOOST_NO_CXX11_HDR_UNORDERED_MAP)
BOOST_TEST_TRAIT_TRUE((is_unordered_range< std::unordered_map<int, X> >));
BOOST_TEST_TRAIT_TRUE((is_unordered_range< std::unordered_map<int, X> const >));
BOOST_TEST_TRAIT_TRUE((is_unordered_range< std::unordered_multimap<int, X> >));
BOOST_TEST_TRAIT_TRUE((is_unordered_range< std::unordered_multimap<int, X> const >));
#endif
return boost::report_errors();
}

View File

@@ -35,13 +35,14 @@ int main() {}
#endif
#endif
#if defined(__GNUC__) && !defined(BOOST_INTEL_CXX_VERSION)
#if ( defined(__GNUC__) || defined(__clang__) ) && !defined(BOOST_INTEL_CXX_VERSION)
#pragma GCC diagnostic ignored "-Wfloat-equal"
#endif
#include <boost/limits.hpp>
#include <complex>
#include <sstream>
#include <boost/limits.hpp>
#include <set>
template <class T>
void generic_complex_tests(std::complex<T> v)
@@ -88,6 +89,21 @@ void complex_integral_tests(Integer*)
generic_complex_tests(complex(Integer(-543),Integer(763)));
}
template<class T> void complex_grid_test( short N )
{
std::set<std::size_t> hashes;
for( short i = 0; i < N; ++i )
{
for( short j = 0; j < N; ++j )
{
hashes.insert( boost::hash< std::complex<T> >()( std::complex<T>( i, j ) ) );
}
}
BOOST_TEST_EQ( hashes.size(), static_cast<std::size_t>( N * N ) );
}
int main()
{
// I've comments out the short and unsigned short tests
@@ -104,6 +120,11 @@ int main()
complex_integral_tests((unsigned int*) 0);
complex_integral_tests((unsigned long*) 0);
complex_grid_test<int>( 16 );
complex_grid_test<float>( 7 );
complex_grid_test<double>( 16 );
complex_grid_test<long double>( 15 );
return boost::report_errors();
}

View File

@@ -15,7 +15,6 @@
#include <cmath>
#include <boost/container_hash/detail/limits.hpp>
#include <boost/container_hash/detail/float_functions.hpp>
#include <boost/config/workaround.hpp>
#include <iostream>
@@ -30,7 +29,7 @@
#endif
#endif
#if defined(__GNUC__) && !defined(BOOST_INTEL_CXX_VERSION)
#if ( defined(__GNUC__) || defined(__clang__) ) && !defined(BOOST_INTEL_CXX_VERSION)
#pragma GCC diagnostic ignored "-Wfloat-equal"
#endif
@@ -55,19 +54,6 @@ void float_tests(char const* name, T* = 0)
<< boost::hash_detail::limits<std::size_t>::digits
<< "\n"
<< "\n"
<< "boost::hash_detail::call_ldexp<T>::float_type = "
<< float_type(static_cast<BOOST_DEDUCED_TYPENAME
boost::hash_detail::call_ldexp<T>::float_type*>(0))
<< "\n"
<< "boost::hash_detail::call_frexp<T>::float_type = "
<< float_type(static_cast<BOOST_DEDUCED_TYPENAME
boost::hash_detail::call_frexp<T>::float_type*>(0))
<< "\n"
<< "boost::hash_detail::select_hash_type<T>::type = "
<< float_type(static_cast<BOOST_DEDUCED_TYPENAME
boost::hash_detail::select_hash_type<T>::type*>(0))
<< "\n"
<< "\n"
;
BOOST_HASH_TEST_NAMESPACE::hash<T> x1;
@@ -91,7 +77,7 @@ void float_tests(char const* name, T* = 0)
using namespace std;
// Doing anything with infinity causes borland to crash.
#if defined(__BORLANDC__)
#if defined(BOOST_BORLANDC)
std::cerr
<< "Not running infinity checks on Borland, as it causes it to crash."
"\n";
@@ -292,7 +278,7 @@ void float_tests(char const* name, T* = 0)
}
// NaN also causes borland to crash.
#if !defined(__BORLANDC__) && defined(BOOST_HASH_TEST_EXTENSIONS)
#if !defined(BOOST_BORLANDC) && defined(BOOST_HASH_TEST_EXTENSIONS)
if(boost::hash_detail::limits<T>::has_quiet_NaN) {
if(x1(boost::hash_detail::limits<T>::quiet_NaN()) == x1(1.0)) {
std::cerr<<"x1(quiet_NaN) == x1(1.0) == "<<x1(1.0)<<"\n";

View File

@@ -0,0 +1,59 @@
// Copyright 2021 Peter Dimov.
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#if defined(__GNUC__) && __GNUC__ == 8
# pragma GCC diagnostic ignored "-Wsign-conversion"
#endif
#include <boost/container_hash/hash.hpp>
#include <boost/core/lightweight_test.hpp>
#include <boost/config.hpp>
#include <boost/config/pragma_message.hpp>
#if defined(BOOST_NO_CXX11_HDR_FORWARD_LIST)
BOOST_PRAGMA_MESSAGE( "Test skipped, BOOST_NO_CXX11_HDR_FORWARD_LIST is defined" )
int main() {}
#else
#include <forward_list>
template<class T> void test()
{
typedef std::forward_list<T> list;
typedef boost::hash<list> hash;
int const N = 32;
std::size_t h[ N ];
list v;
for( int i = 0; i < N; ++i )
{
h[ i ] = hash()( v );
BOOST_TEST_EQ( h[ i ], hash()( v ) );
for( int j = 0; j < i; ++j )
{
BOOST_TEST_NE( h[ j ], h[ i ] );
}
v.push_front( T() );
}
}
int main()
{
test<int>();
test<float>();
test<double>();
test< std::forward_list<int> >();
return boost::report_errors();
}
#endif

View File

@@ -0,0 +1,30 @@
// Copyright 2022 Peter Dimov.
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#if defined(_MSC_VER)
# pragma warning(disable: 4714) // forceinline not inlined
#endif
#if defined(__GNUC__) || defined(__clang__)
# pragma GCC diagnostic ignored "-Wsign-conversion"
#endif
#include <boost/filesystem/path.hpp>
#include <boost/container_hash/hash.hpp>
#include <boost/core/lightweight_test.hpp>
template<class T> std::size_t hv( T const& t )
{
return boost::hash<T>()( t );
}
int main()
{
boost::filesystem::path p1( "/foo/bar" );
boost::filesystem::path p2( "/foo/baz" );
BOOST_TEST_NE( hv( p1 ), hv( p2 ) );
return boost::report_errors();
}

View File

@@ -8,6 +8,8 @@
#include <boost/container_hash/hash.hpp>
#include <iostream>
#include <algorithm>
#include <limits>
#include <climits>
#if defined(BOOST_MSVC)
@@ -37,10 +39,9 @@ void write_compiler_info() {
{1700, "Visual C++ 11.0, VS2012"},
{1800, "Visual C++ 12.0, VS2013"},
{1900, "Visual C++ 14.00, VS2015"},
{1910, "Visual C++ 14.10, VS2017 15.1/2"},
{1911, "Visual C++ 14.11, VS2017 15.3/4"},
{1912, "Visual C++ 14.12, VS2017 15.5"},
{1913, "Visual C++ 14.13, VS2017 15.6"}
{1910, "Visual C++ 14.1x, VS2017"},
{1920, "Visual C++ 14.2x, VS2019"},
{1930, "Visual C++ 14.3x, VS2022"},
};
msvc_version msvc = { BOOST_MSVC, "" };
@@ -62,41 +63,62 @@ void write_compiler_info() {
#endif
#define PRINT(x) std::cout << #x ": " << x << std::endl
int main() {
write_compiler_info();
std::cout << std::endl;
#if defined(__cplusplus)
std::cout << "__cplusplus: "
<< __cplusplus
<< std::endl;
PRINT(__cplusplus);
PRINT(BOOST_CXX_VERSION);
std::cout << std::endl;
#if defined(BOOST_NO_CXX17_HDR_STRING_VIEW)
std::cout << "No <string_view>" << std::endl;
#else
std::cout << "Has <string_view>" << std::endl;
#endif
std::cout << "BOOST_HASH_CXX17: "
<< BOOST_HASH_CXX17
<< std::endl;
#if defined(BOOST_NO_CXX17_HDR_OPTIONAL)
std::cout << "No <optional>" << std::endl;
#else
std::cout << "Has <optional>" << std::endl;
#endif
std::cout << "BOOST_HASH_HAS_STRING_VIEW: "
<< BOOST_HASH_HAS_STRING_VIEW
<< std::endl;
std::cout << "BOOST_HASH_HAS_OPTIONAL: "
<< BOOST_HASH_HAS_OPTIONAL
<< std::endl;
std::cout << "BOOST_HASH_HAS_VARIANT: "
<< BOOST_HASH_HAS_VARIANT
<< std::endl;
#if defined(BOOST_NO_CXX17_HDR_VARIANT)
std::cout << "No <variant>" << std::endl;
#else
std::cout << "Has <variant>" << std::endl;
#endif
#if defined(BOOST_NO_CXX11_HDR_TYPEINDEX)
std::cout << "No <typeindex>" << std::endl;
#else
std::cout << "<typeindex>" << std::endl;
std::cout << "Has <typeindex>" << std::endl;
#endif
#if defined(BOOST_NO_CXX11_HDR_SYSTEM_ERROR)
std::cout << "No <system_error>" << std::endl;
#else
std::cout << "<system_error>" << std::endl;
std::cout << "Has <system_error>" << std::endl;
#endif
std::cout << std::endl;
PRINT(CHAR_BIT);
std::cout << std::endl;
PRINT(sizeof(std::size_t)*CHAR_BIT);
std::cout << std::endl;
PRINT(sizeof(float)*CHAR_BIT);
PRINT(std::numeric_limits<float>::digits);
std::cout << std::endl;
PRINT(sizeof(double)*CHAR_BIT);
PRINT(std::numeric_limits<double>::digits);
std::cout << std::endl;
PRINT(sizeof(long double)*CHAR_BIT);
PRINT(std::numeric_limits<long double>::digits);
}

View File

@@ -0,0 +1,75 @@
// Copyright 2005-2009 Daniel James.
// Copyright 2021 Peter Dimov.
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/container_hash/hash.hpp>
#include <boost/core/lightweight_test.hpp>
#include <boost/core/type_name.hpp>
#include <boost/type_traits/is_signed.hpp>
#include <set>
#if defined(BOOST_MSVC)
#pragma warning(disable: 4127) // conditional expression is constant
#endif
// This test checks that small numbers hash to themselves even if
// their type is wider than size_t
template<class T>
void identity_test()
{
if( boost::is_signed<T>::value )
{
for( int i = -128; i <= 127; ++i )
{
BOOST_TEST_EQ( boost::hash<T>()( static_cast<T>( i ) ), static_cast<std::size_t>( i ) );
}
}
else
{
for( int i = 0; i <= 255; ++i )
{
BOOST_TEST_EQ( boost::hash<T>()( static_cast<T>( i ) ), static_cast<std::size_t>( i ) );
}
}
}
#define TEST(type) std::cerr << "Testing: " #type " (" << boost::core::type_name<type>() << ")\n"; identity_test<type>();
int main()
{
TEST(char)
TEST(signed char)
TEST(unsigned char)
#ifndef BOOST_NO_INTRINSIC_WCHAR_T
TEST(wchar_t)
#endif
#ifndef BOOST_NO_CXX11_CHAR16_T
TEST(char16_t)
#endif
#ifndef BOOST_NO_CXX11_CHAR32_T
TEST(char32_t)
#endif
TEST(short)
TEST(unsigned short)
TEST(int)
TEST(unsigned int)
TEST(long)
TEST(unsigned long)
#if !defined(BOOST_NO_LONG_LONG)
TEST(boost::long_long_type)
TEST(boost::ulong_long_type)
#endif
#if defined(BOOST_HAS_INT128)
TEST(boost::int128_type)
TEST(boost::uint128_type)
#endif
TEST(std::size_t)
TEST(std::ptrdiff_t)
return boost::report_errors();
}

View File

@@ -13,6 +13,11 @@
#pragma warning(disable:4245) // signed/unsigned mismatch
#endif
#if defined(__GNUC__) && __GNUC__ == 8
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wsign-conversion"
#endif
namespace HASH_TEST_CAT(CONTAINER_TYPE, _tests)
{
template <class T>
@@ -66,6 +71,10 @@ namespace HASH_TEST_CAT(CONTAINER_TYPE, _tests)
}
}
#if defined(__GNUC__) && __GNUC__ == 8
# pragma GCC diagnostic pop
#endif
#if defined(BOOST_MSVC)
#pragma warning(pop)
#endif

View File

@@ -1,28 +0,0 @@
// Copyright 2006-2009 Daniel James.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include "./config.hpp"
// Simple test to make sure BOOST_HASH_NO_EXTENSIONS does disable extensions
// (or at least one of them).
#if !defined(BOOST_HASH_NO_EXTENSIONS)
# define BOOST_HASH_NO_EXTENSIONS
#endif
#ifdef BOOST_HASH_TEST_STD_INCLUDES
# include <functional>
#else
# include <boost/container_hash/hash.hpp>
#endif
template <class T> void ignore(T const&) {}
int main()
{
BOOST_HASH_TEST_NAMESPACE::hash< int[10] > hasher;
ignore(hasher);
return 0;
}

View File

@@ -26,7 +26,7 @@
#pragma warning(disable:4310) // cast truncates constant value
#endif
#if defined(__GNUC__) && !defined(BOOST_INTEL_CXX_VERSION)
#if ( defined(__GNUC__) || defined(__clang__) ) && !defined(BOOST_INTEL_CXX_VERSION)
#pragma GCC diagnostic ignored "-Wfloat-equal"
#endif
@@ -103,10 +103,8 @@ void limits_test(T*)
if (limits::is_integer)
{
BOOST_TEST(BOOST_HASH_TEST_NAMESPACE::hash_value(min_value)
== std::size_t(min_value));
BOOST_TEST(BOOST_HASH_TEST_NAMESPACE::hash_value(max_value)
== std::size_t(max_value));
BOOST_TEST_EQ(BOOST_HASH_TEST_NAMESPACE::hash_value(min_value), std::size_t(min_value));
BOOST_TEST_EQ(BOOST_HASH_TEST_NAMESPACE::hash_value(max_value), std::size_t(max_value));
}
#endif
}

View File

@@ -0,0 +1,90 @@
// Copyright 2005-2009 Daniel James.
// Copyright 2021 Peter Dimov.
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/container_hash/hash.hpp>
#include <boost/core/lightweight_test.hpp>
#include <boost/core/type_name.hpp>
#include <set>
#if defined(BOOST_MSVC)
# pragma warning(disable: 4244) // conversion from int to float
#endif
#if defined(__GNUC__) || defined(__clang__)
# pragma GCC diagnostic ignored "-Wconversion"
# pragma GCC diagnostic ignored "-Wsign-conversion"
#endif
// This test checks for collisions in a small range of numbers
template<class T, int M>
void collision_test_()
{
std::set<std::size_t> hashes;
for( int i = -128; i <= 127; ++i )
{
hashes.insert( boost::hash<T>()( i * M ) );
}
BOOST_TEST_EQ( hashes.size(), 256u );
}
template <class T>
void collision_test()
{
collision_test_<T, 1>();
collision_test_<T, 2>();
collision_test_<T, 3>();
collision_test_<T, 4>();
collision_test_<T, 5>();
collision_test_<T, 8>();
collision_test_<T, 10>();
collision_test_<T, 16>();
collision_test_<T, 32>();
collision_test_<T, 64>();
collision_test_<T, 100>();
collision_test_<T, 128>();
}
#define TEST(type) std::cerr << "Testing: " #type " (" << boost::core::type_name<type>() << ")\n"; collision_test<type>();
int main()
{
#ifndef BOOST_NO_INTRINSIC_WCHAR_T
TEST(wchar_t)
#endif
#ifndef BOOST_NO_CXX11_CHAR16_T
TEST(char16_t)
#endif
#ifndef BOOST_NO_CXX11_CHAR32_T
TEST(char32_t)
#endif
TEST(short)
TEST(unsigned short)
TEST(int)
TEST(unsigned int)
TEST(long)
TEST(unsigned long)
#if !defined(BOOST_NO_LONG_LONG)
TEST(boost::long_long_type)
TEST(boost::ulong_long_type)
#endif
#if defined(BOOST_HAS_INT128)
TEST(boost::int128_type)
TEST(boost::uint128_type)
#endif
TEST(float)
TEST(double)
TEST(long double)
TEST(std::size_t)
TEST(std::ptrdiff_t)
return boost::report_errors();
}

View File

@@ -11,7 +11,7 @@
#include <boost/config.hpp>
#include <boost/core/lightweight_test.hpp>
#if BOOST_HASH_HAS_OPTIONAL
#if !defined(BOOST_NO_CXX17_HDR_OPTIONAL)
#include <optional>
#include <string>
@@ -60,7 +60,7 @@ void test_optional_string()
int main()
{
#if BOOST_HASH_HAS_OPTIONAL
#if !defined(BOOST_NO_CXX17_HDR_OPTIONAL)
test_optional_int();
test_optional_string();
#else

View File

@@ -0,0 +1,444 @@
// Copyright 2021 Peter Dimov.
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/config/pragma_message.hpp>
#if defined(__GNUC__) && !defined(__clang__) && __cplusplus < 201100L
BOOST_PRAGMA_MESSAGE("Skipping test under GCC in C++98 mode")
int main() {}
#else
#if defined(__clang__)
# pragma clang diagnostic ignored "-Wlong-long"
#endif
#if defined(__GNUC__)
# pragma GCC diagnostic ignored "-Wsign-conversion"
#endif
#include <boost/container_hash/hash.hpp>
#include <boost/core/lightweight_test.hpp>
#include <string>
#include <vector>
#include <list>
#include <utility>
#include <complex>
#include <limits>
#include <climits>
#include <cfloat>
#include <cstddef>
// This test checks whether hash values have changed
template<class T> std::size_t hv( T const& t )
{
return boost::hash<T>()( t );
}
int main()
{
// char
BOOST_TEST_EQ( hv('\x00'), 0 );
BOOST_TEST_EQ( hv('A'), 'A' );
BOOST_TEST_EQ( hv('\x7F'), 0x7F );
// signed char
BOOST_TEST_EQ( hv((signed char)0), 0 );
BOOST_TEST_EQ( hv((signed char)+1), +1 );
BOOST_TEST_EQ( hv((signed char)-1), (std::size_t)-1 );
BOOST_TEST_EQ( hv((signed char)+127), 127 );
BOOST_TEST_EQ( hv((signed char)-128), (std::size_t)-128 );
// unsigned char
BOOST_TEST_EQ( hv((unsigned char)0), 0 );
BOOST_TEST_EQ( hv((unsigned char)1), 1 );
BOOST_TEST_EQ( hv((unsigned char)255), 255 );
// short
BOOST_TEST_EQ( hv((short)0), 0 );
BOOST_TEST_EQ( hv((short)+1), 1 );
BOOST_TEST_EQ( hv((short)-1), (std::size_t)-1 );
BOOST_TEST_EQ( hv((short)+32767), 32767 );
BOOST_TEST_EQ( hv((short)-32768), (std::size_t)-32768 );
// unsigned short
BOOST_TEST_EQ( hv((unsigned short)0), 0 );
BOOST_TEST_EQ( hv((unsigned short)1), 1 );
BOOST_TEST_EQ( hv((unsigned short)65535), 65535 );
// int
BOOST_TEST_EQ( hv(0), 0 );
BOOST_TEST_EQ( hv(+1), 1 );
BOOST_TEST_EQ( hv(-1), (std::size_t)-1 );
BOOST_TEST_EQ( hv(+32767), 32767 );
BOOST_TEST_EQ( hv(-32768), (std::size_t)-32768 );
// unsigned int
BOOST_TEST_EQ( hv((unsigned)0), 0 );
BOOST_TEST_EQ( hv((unsigned)1), 1 );
BOOST_TEST_EQ( hv((unsigned)65535), 65535 );
BOOST_TEST_EQ( hv((unsigned)-1), (std::size_t)(unsigned)-1 );
// long
BOOST_TEST_EQ( hv(0L), 0 );
BOOST_TEST_EQ( hv(+1L), 1 );
BOOST_TEST_EQ( hv(-1L), (std::size_t)-1 );
BOOST_TEST_EQ( hv(+32767L), 32767 );
BOOST_TEST_EQ( hv(-32768L), (std::size_t)-32768 );
// unsigned long
BOOST_TEST_EQ( hv(0UL), 0 );
BOOST_TEST_EQ( hv(1UL), 1 );
BOOST_TEST_EQ( hv(65535UL), 65535 );
BOOST_TEST_EQ( hv((unsigned long)-1), (std::size_t)(unsigned long)-1 );
// long long
BOOST_TEST_EQ( hv(0LL), 0 );
BOOST_TEST_EQ( hv(+1LL), 1 );
BOOST_TEST_EQ( hv(-1LL), (std::size_t)-1 );
BOOST_TEST_EQ( hv(+32767LL), 32767 );
BOOST_TEST_EQ( hv(-32768LL), (std::size_t)-32768 );
// unsigned long long
BOOST_TEST_EQ( hv(0ULL), 0 );
BOOST_TEST_EQ( hv(1ULL), 1 );
BOOST_TEST_EQ( hv(65535ULL), 65535 );
#if SIZE_MAX == 4294967295U
BOOST_TEST_EQ( hv((unsigned long long)-1), 3221225537U );
#else
BOOST_TEST_EQ( hv((unsigned long long)-1), (std::size_t)-1 );
#endif
#if defined(BOOST_HAS_INT128)
typedef boost::int128_type int128;
BOOST_TEST_EQ( hv((int128)0), 0 );
BOOST_TEST_EQ( hv((int128)1), 1 );
BOOST_TEST_EQ( hv((int128)-1), (std::size_t)-1 );
BOOST_TEST_EQ( hv((int128)+32767), 32767 );
BOOST_TEST_EQ( hv((int128)-32768), (std::size_t)-32768 );
typedef boost::uint128_type uint128;
BOOST_TEST_EQ( hv((uint128)0), 0 );
BOOST_TEST_EQ( hv((uint128)1), 1 );
BOOST_TEST_EQ( hv((uint128)65535), 65535 );
#if defined(BOOST_GCC) && BOOST_GCC < 100000
// This looks like some sort of miscompilation.
// Under CI, both GHA and Appveyor GCCs produce this value.
// But the exact same test on godbolt.org produces the correct
// value, below.
// BOOST_TEST_EQ( hv((uint128)-1), 18446744073709551615ULL );
#else
BOOST_TEST_EQ( hv((uint128)-1), 13835058055282163777ULL );
#endif
#endif
// float
BOOST_TEST_EQ( hv(0.0f), 0 );
BOOST_TEST_EQ( hv(-0.0f), 0 );
BOOST_TEST_EQ( hv(1.0f), 1065353216U );
BOOST_TEST_EQ( hv(-1.0f), 3212836864U );
BOOST_TEST_EQ( hv(3.14f), 1078523331U );
BOOST_TEST_EQ( hv(-3.14f), 3226006979U );
BOOST_TEST_EQ( hv(1e-38f), 7136238U );
BOOST_TEST_EQ( hv(-1e-38f), 2154619886U );
BOOST_TEST_EQ( hv(1e+38f), 2123789977U );
BOOST_TEST_EQ( hv(-1e+38f), 4271273625U );
BOOST_TEST_EQ( hv(std::numeric_limits<float>::infinity()), 2139095040U );
BOOST_TEST_EQ( hv(-std::numeric_limits<float>::infinity()), 4286578688U );
// double
BOOST_TEST_EQ( hv(0.0), 0 );
BOOST_TEST_EQ( hv(-0.0), 0 );
#if SIZE_MAX == 4294967295U
BOOST_TEST_EQ( hv(1.0), 1072693248U );
BOOST_TEST_EQ( hv(-1.0), 3220176896U );
BOOST_TEST_EQ( hv(3.14), 2660156064U );
BOOST_TEST_EQ( hv(-3.14), 512672416U );
BOOST_TEST_EQ( hv(1e-308), 1553872728U );
BOOST_TEST_EQ( hv(-1e-308), 3701356376U );
BOOST_TEST_EQ( hv(1e+308), 2577739707U );
BOOST_TEST_EQ( hv(-1e+308), 430256059U );
BOOST_TEST_EQ( hv(std::numeric_limits<double>::infinity()), 2146435072U );
BOOST_TEST_EQ( hv(-std::numeric_limits<double>::infinity()), 4293918720U );
#else
BOOST_TEST_EQ( hv(1.0), 4607182418800017408ULL );
BOOST_TEST_EQ( hv(-1.0), 13830554455654793216ULL );
BOOST_TEST_EQ( hv(3.14), 4614253070214989087ULL );
BOOST_TEST_EQ( hv(-3.14), 13837625107069764895ULL );
BOOST_TEST_EQ( hv(1e-308), 2024022533073106ULL );
BOOST_TEST_EQ( hv(-1e-308), 9225396059387848914ULL );
BOOST_TEST_EQ( hv(1e+308), 9214871658872686752ULL );
BOOST_TEST_EQ( hv(-1e+308), 18438243695727462560ULL );
BOOST_TEST_EQ( hv(std::numeric_limits<double>::infinity()), 9218868437227405312ULL );
BOOST_TEST_EQ( hv(-std::numeric_limits<double>::infinity()), 18442240474082181120ULL );
#endif
// long double
BOOST_TEST_EQ( hv(0.0L), 0 );
BOOST_TEST_EQ( hv(-0.0L), 0 );
#if defined(_WIN32) && !defined(__GNUC__) // Under MS ABI, long double == double
#if SIZE_MAX == 4294967295U
BOOST_TEST_EQ( hv(1.0L), 1072693248U );
BOOST_TEST_EQ( hv(-1.0L), 3220176896U );
BOOST_TEST_EQ( hv(3.14L), 2660156064U );
BOOST_TEST_EQ( hv(-3.14L), 512672416U );
BOOST_TEST_EQ( hv(std::numeric_limits<long double>::infinity()), 2146435072U );
BOOST_TEST_EQ( hv(-std::numeric_limits<long double>::infinity()), 4293918720U );
#else
BOOST_TEST_EQ( hv(1.0L), 4607182418800017408ULL );
BOOST_TEST_EQ( hv(-1.0L), 13830554455654793216ULL );
BOOST_TEST_EQ( hv(3.14L), 4614253070214989087ULL );
BOOST_TEST_EQ( hv(-3.14L), 13837625107069764895ULL );
BOOST_TEST_EQ( hv(std::numeric_limits<long double>::infinity()), 9218868437227405312ULL );
BOOST_TEST_EQ( hv(-std::numeric_limits<long double>::infinity()), 18442240474082181120ULL );
#endif
#else
#if SIZE_MAX == 4294967295U
BOOST_TEST_EQ( hv(1.0L), 2684370943U );
BOOST_TEST_EQ( hv(-1.0L), 2684403711U );
BOOST_TEST_EQ( hv(3.14L), 83002659U );
BOOST_TEST_EQ( hv(-3.14L), 82969891U );
BOOST_TEST_EQ( hv(std::numeric_limits<long double>::infinity()), 0xA0007FFFu );
BOOST_TEST_EQ( hv(-std::numeric_limits<long double>::infinity()), 0xA000FFFFu );
#else
BOOST_TEST_EQ( hv(1.0L), 11529215046068486143ULL );
BOOST_TEST_EQ( hv(-1.0L), 11529215046068518911ULL );
BOOST_TEST_EQ( hv(3.14L), 12059468778148142067ULL );
BOOST_TEST_EQ( hv(-3.14L), 12059468778147191795ULL );
BOOST_TEST_EQ( hv(std::numeric_limits<long double>::infinity()), 11529215046068502527ULL );
BOOST_TEST_EQ( hv(-std::numeric_limits<long double>::infinity()), 11529215046068535295ULL );
#endif
#endif
// C array
{
int a1[] = { 0 };
int a2[] = { 0, 0 };
int a3[] = { 0, 0, 0 };
#if SIZE_MAX == 4294967295U
BOOST_TEST_EQ( hv(a1), 3864292196U );
BOOST_TEST_EQ( hv(a2), 2842917718U );
BOOST_TEST_EQ( hv(a3), 325752138U );
#else
BOOST_TEST_EQ( hv(a1), 3864292196ULL );
BOOST_TEST_EQ( hv(a2), 14642545639667855512ULL );
BOOST_TEST_EQ( hv(a3), 17867750819888810972ULL );
#endif
}
// string
#if SIZE_MAX == 4294967295U
BOOST_TEST_EQ( hv(std::string()), 0 );
BOOST_TEST_EQ( hv(std::string("abc")), 1849538372U );
BOOST_TEST_EQ( hv(std::string("\0", 1)), 3864292196U );
BOOST_TEST_EQ( hv(std::string("\0\0", 2)), 2842917718U );
BOOST_TEST_EQ( hv(std::string("\0\0\0", 3)), 325752138U );
#else
BOOST_TEST_EQ( hv(std::string()), 0 );
BOOST_TEST_EQ( hv(std::string("abc")), 6420922261882292859ULL );
BOOST_TEST_EQ( hv(std::string("\0", 1)), 3864292196ULL );
BOOST_TEST_EQ( hv(std::string("\0\0", 2)), 14642545639667855512ULL );
BOOST_TEST_EQ( hv(std::string("\0\0\0", 3)), 17867750819888810972ULL );
#endif
// pointer
BOOST_TEST_EQ( hv((void*)0), 0 );
BOOST_TEST_EQ( hv((void*)0x200014A0), 603985716U );
// complex<int>
BOOST_TEST_EQ( hv(std::complex<int>(0, 0)), 0U );
BOOST_TEST_EQ( hv(std::complex<int>(+1, 0)), 1U );
BOOST_TEST_EQ( hv(std::complex<int>(0, +1)), 65U );
#if SIZE_MAX == 4294967295U
BOOST_TEST_EQ( hv(std::complex<int>(-1, 0)), 4294967295U );
BOOST_TEST_EQ( hv(std::complex<int>(0, -1)), 3221225536U );
#else
BOOST_TEST_EQ( hv(std::complex<int>(-1, 0)), 18446744073709551615ULL );
BOOST_TEST_EQ( hv(std::complex<int>(0, -1)), 13835058055282163776ULL );
#endif
// complex<float>
BOOST_TEST_EQ( hv(std::complex<float>(0.0f, 0.0f)), 0U );
BOOST_TEST_EQ( hv(std::complex<float>(+1.0f, 0.0f)), 1065353216U );
BOOST_TEST_EQ( hv(std::complex<float>(-1.0f, 0.0f)), 3212836864U );
#if SIZE_MAX == 4294967295U
BOOST_TEST_EQ( hv(std::complex<float>(0.0f, +1.0f)), 3495952384U );
BOOST_TEST_EQ( hv(std::complex<float>(0.0f, -1.0f)), 2959081472U );
#else
BOOST_TEST_EQ( hv(std::complex<float>(0.0f, +1.0f)), 67920461824ULL );
BOOST_TEST_EQ( hv(std::complex<float>(0.0f, -1.0f)), 209117511680ULL );
#endif
// complex<double>
BOOST_TEST_EQ( hv(std::complex<double>(0.0, 0.0)), 0U );
#if SIZE_MAX == 4294967295U
BOOST_TEST_EQ( hv(std::complex<double>(+1.0, 0.0)), 1072693248U );
BOOST_TEST_EQ( hv(std::complex<double>(-1.0, 0.0)), 3220176896U );
BOOST_TEST_EQ( hv(std::complex<double>(0.0, +1.0)), 873201664U );
BOOST_TEST_EQ( hv(std::complex<double>(0.0, -1.0)), 2483814400U );
#else
BOOST_TEST_EQ( hv(std::complex<double>(+1.0, 0.0)), 4607182418800017408ULL );
BOOST_TEST_EQ( hv(std::complex<double>(-1.0, 0.0)), 13830554455654793216ULL );
BOOST_TEST_EQ( hv(std::complex<double>(0.0, +1.0)), 3750372589692780544ULL );
BOOST_TEST_EQ( hv(std::complex<double>(0.0, -1.0)), 10667901617333862400ULL );
#endif
// pair
#if SIZE_MAX == 4294967295U
BOOST_TEST_EQ( hv(std::make_pair(0, 0)), 2842917718U );
BOOST_TEST_EQ( hv(std::make_pair(1, 2)), 2507434894U );
BOOST_TEST_EQ( hv(std::make_pair(-1, -2)), 1874100199 );
#else
BOOST_TEST_EQ( hv(std::make_pair(0, 0)), 14642545639667855512ULL );
BOOST_TEST_EQ( hv(std::make_pair(1, 2)), 3370697991563800380ULL );
BOOST_TEST_EQ( hv(std::make_pair(-1, -2)), 4139767141999124554ULL );
#endif
// vector<char>
#if SIZE_MAX == 4294967295U
BOOST_TEST_EQ( hv(std::vector<char>(0)), 0 );
BOOST_TEST_EQ( hv(std::vector<char>(1)), 3864292196U );
BOOST_TEST_EQ( hv(std::vector<char>(2)), 2842917718U );
BOOST_TEST_EQ( hv(std::vector<char>(3)), 325752138U );
#else
BOOST_TEST_EQ( hv(std::vector<char>(0)), 0 );
BOOST_TEST_EQ( hv(std::vector<char>(1)), 3864292196ULL );
BOOST_TEST_EQ( hv(std::vector<char>(2)), 14642545639667855512ULL );
BOOST_TEST_EQ( hv(std::vector<char>(3)), 17867750819888810972ULL );
#endif
// vector<int>
#if SIZE_MAX == 4294967295U
BOOST_TEST_EQ( hv(std::vector<int>(0)), 0 );
BOOST_TEST_EQ( hv(std::vector<int>(1)), 3864292196U );
BOOST_TEST_EQ( hv(std::vector<int>(2)), 2842917718U );
BOOST_TEST_EQ( hv(std::vector<int>(3)), 325752138U );
#else
BOOST_TEST_EQ( hv(std::vector<int>(0)), 0 );
BOOST_TEST_EQ( hv(std::vector<int>(1)), 3864292196ULL );
BOOST_TEST_EQ( hv(std::vector<int>(2)), 14642545639667855512ULL );
BOOST_TEST_EQ( hv(std::vector<int>(3)), 17867750819888810972ULL );
#endif
// vector<vector<int>>
#if SIZE_MAX == 4294967295U
BOOST_TEST_EQ( hv(std::vector<std::vector<int> >(0)), 0 );
BOOST_TEST_EQ( hv(std::vector<std::vector<int> >(1)), 3864292196U );
BOOST_TEST_EQ( hv(std::vector<std::vector<int> >(2)), 2842917718U );
BOOST_TEST_EQ( hv(std::vector<std::vector<int> >(3)), 325752138U );
#else
BOOST_TEST_EQ( hv(std::vector<std::vector<int> >(0)), 0 );
BOOST_TEST_EQ( hv(std::vector<std::vector<int> >(1)), 3864292196ULL );
BOOST_TEST_EQ( hv(std::vector<std::vector<int> >(2)), 14642545639667855512ULL );
BOOST_TEST_EQ( hv(std::vector<std::vector<int> >(3)), 17867750819888810972ULL );
#endif
// list<char>
#if SIZE_MAX == 4294967295U
BOOST_TEST_EQ( hv(std::list<char>(0)), 0 );
BOOST_TEST_EQ( hv(std::list<char>(1)), 3864292196U );
BOOST_TEST_EQ( hv(std::list<char>(2)), 2842917718U );
BOOST_TEST_EQ( hv(std::list<char>(3)), 325752138U );
#else
BOOST_TEST_EQ( hv(std::list<char>(0)), 0 );
BOOST_TEST_EQ( hv(std::list<char>(1)), 3864292196ULL );
BOOST_TEST_EQ( hv(std::list<char>(2)), 14642545639667855512ULL );
BOOST_TEST_EQ( hv(std::list<char>(3)), 17867750819888810972ULL );
#endif
// list<int>
#if SIZE_MAX == 4294967295U
BOOST_TEST_EQ( hv(std::list<int>(0)), 0 );
BOOST_TEST_EQ( hv(std::list<int>(1)), 3864292196U );
BOOST_TEST_EQ( hv(std::list<int>(2)), 2842917718U );
BOOST_TEST_EQ( hv(std::list<int>(3)), 325752138U );
#else
BOOST_TEST_EQ( hv(std::list<int>(0)), 0 );
BOOST_TEST_EQ( hv(std::list<int>(1)), 3864292196ULL );
BOOST_TEST_EQ( hv(std::list<int>(2)), 14642545639667855512ULL );
BOOST_TEST_EQ( hv(std::list<int>(3)), 17867750819888810972ULL );
#endif
return boost::report_errors();
}
#endif

View File

@@ -12,6 +12,11 @@
#pragma warning(disable:4245) // signed/unsigned mismatch
#endif
#if defined(__GNUC__) && __GNUC__ == 8
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wsign-conversion"
#endif
namespace HASH_TEST_CAT(CONTAINER_TYPE, _tests)
{
template <class T>
@@ -68,6 +73,10 @@ namespace HASH_TEST_CAT(CONTAINER_TYPE, _tests)
}
}
#if defined(__GNUC__) && __GNUC__ == 8
# pragma GCC diagnostic pop
#endif
#if defined(BOOST_MSVC)
#pragma warning(pop)
#endif

View File

@@ -12,6 +12,11 @@
#pragma warning(disable:4245) // signed/unsigned mismatch
#endif
#if defined(__GNUC__) && __GNUC__ == 8
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wsign-conversion"
#endif
namespace HASH_TEST_CAT(CONTAINER_TYPE, _tests)
{
template <class T>
@@ -71,6 +76,10 @@ namespace HASH_TEST_CAT(CONTAINER_TYPE, _tests)
}
}
#if defined(__GNUC__) && __GNUC__ == 8
# pragma GCC diagnostic pop
#endif
#if defined(BOOST_MSVC)
#pragma warning(pop)
#endif

View File

@@ -176,7 +176,7 @@ int main()
#endif
generic_string_tests((std::string*) 0);
#if BOOST_HASH_HAS_STRING_VIEW
#if !defined(BOOST_NO_CXX17_HDR_STRING_VIEW)
generic_string_tests((std::string_view*) 0);
#endif

View File

@@ -0,0 +1,36 @@
// Copyright 2022 Peter Dimov.
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/utility/string_view.hpp>
#include <boost/core/detail/string_view.hpp>
#include <boost/container_hash/hash.hpp>
#include <boost/core/lightweight_test.hpp>
#include <boost/config.hpp>
#include <string>
#if !defined(BOOST_NO_CXX17_HDR_STRING_VIEW)
#include <string_view>
#endif
// Test whether the hash values of a string and a
// string_view that refers to it match. This is
// important for unordered heterogeneous lookups.
template<class T> std::size_t hv( T const& t )
{
return boost::hash<T>()( t );
}
int main()
{
std::string s( "Test." );
BOOST_TEST_EQ( hv( s ), hv( boost::string_view( s ) ) );
BOOST_TEST_EQ( hv( s ), hv( boost::core::string_view( s ) ) );
#if !defined(BOOST_NO_CXX17_HDR_STRING_VIEW)
BOOST_TEST_EQ( hv( s ), hv( std::string_view( s ) ) );
#endif
return boost::report_errors();
}

View File

@@ -11,7 +11,7 @@
#include <boost/config.hpp>
#include <boost/core/lightweight_test.hpp>
#if BOOST_HASH_HAS_VARIANT
#if !defined(BOOST_NO_CXX17_HDR_VARIANT)
#include <variant>
#include <string>
@@ -90,7 +90,7 @@ void test_variant_unique_types()
int main()
{
#if BOOST_HASH_HAS_VARIANT
#if !defined(BOOST_NO_CXX17_HDR_VARIANT)
test_variant_int();
test_variant_unique_types();
#else

17
test/quick.cpp Normal file
View File

@@ -0,0 +1,17 @@
// Copyright 2006-2009 Daniel James.
// Copyright 2021 Peter Dimov.
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt)
#include <boost/container_hash/hash.hpp>
#include <deque>
int main()
{
std::deque<int> x;
x.push_back( 1 );
x.push_back( 2 );
return boost::hash< std::deque<int> >()( x ) == boost::hash_value( x )? 0: 1;
}