Compare commits

...

60 Commits

Author SHA1 Message Date
Peter Dimov
060d4aea6b Change sprintf to snprintf in benchmarks. Fixes #41. 2025-08-21 19:31:51 +03:00
Peter Dimov
186c38e255 Add benchmark/Jamfile 2025-08-21 19:26:00 +03:00
Peter Dimov
c8dab7f85a Remove windows-2019 from GHA 2025-08-21 18:22:07 +03:00
Peter Dimov
5d8b8ac2b9 Add gcc-15, clang-20 to ci.yml 2025-06-09 00:05:15 +03:00
Peter Dimov
1e1cf6c46e Update ci.yml 2025-06-09 00:00:37 +03:00
Peter Dimov
88aacb6d46 Remove trailing whitespace 2025-06-08 23:23:14 +03:00
joaquintides
0a000167b7 Feature/hash_is_avalanching (#40)
* added hash_is_avalanching

* launched CI after enabling GHA

* moved 1.89 entry from Change Log to Recent Changes

* segregated some tests into hash_is_avalanching_test3.cpp and gotten rid of Unordered dependency

* removed unneeded include

* stopped using external std::hash for testing

* typo

* removed left over include

* typo

* moved hash_is_avalanching from boost::container_hash to boost

* fixed specializations of boost::hash_is_avalanching
2025-05-28 12:05:10 +03:00
Peter Dimov
d8f1075080 Update ci.yml 2025-05-27 11:55:45 +03:00
Peter Dimov
b8179488b2 Disable deprecation warning for has_denorm in hash_float_test.hpp 2024-12-13 04:30:43 +02:00
Peter Dimov
edd436231a Update .drone.jsonnet 2024-12-13 04:13:53 +02:00
Peter Dimov
d56fc37fe5 Apply Node20 workaround 2024-12-13 04:12:10 +02:00
Peter Dimov
fa6601f974 Update ci.yml 2024-12-13 03:41:48 +02:00
Peter Dimov
89e5b98f6b Fix Clang UBSAN failures 2024-08-21 16:11:17 +03:00
Peter Dimov
1193ed067c Add VERBATIM to add_custom_target 2024-08-21 01:45:25 +03:00
Peter Dimov
f85cb77bd3 Update build.jam, test/Jamfile 2024-08-20 21:50:38 +03:00
Rene Rivera
7d68e5f1d2 Sync from upstream. 2024-08-20 09:58:45 -05:00
Peter Dimov
3c9ce69f92 Update .drone.jsonnet 2024-08-18 11:36:04 +03:00
Peter Dimov
aa2e8b3674 Update ci.yml 2024-08-17 18:25:36 +03:00
Rene Rivera
c3cb5896fc Update build dependencies. 2024-07-31 23:25:37 -05:00
Rene Rivera
58cd5e35b1 Move inter-lib dependencies to a project variable and into the build targets. 2024-07-23 22:34:24 -05:00
Rene Rivera
386d007088 Update copyright dates. 2024-07-20 22:52:05 -05:00
Rene Rivera
b8090f9b87 Bump B2 require to 5.2 2024-06-14 11:33:55 -05:00
Rene Rivera
a5c2949670 Add missing test deps. 2024-05-14 07:33:03 -05:00
Rene Rivera
b16f42ef10 Update dependencies. 2024-05-13 21:44:55 -05:00
Rene Rivera
de85b0c248 Add requires-b2 check to top-level build file. 2024-05-05 09:00:01 -05:00
Rene Rivera
583e14413c Add missing b2 testing module import. 2024-04-25 08:28:42 -05:00
Rene Rivera
ef914e1b34 Sync from upstream. 2024-04-20 15:34:07 -05:00
Peter Dimov
ee5285bfa6 Revert "Update doc/Jamfile"
This reverts commit 0a9803dffe.
2024-04-16 22:36:47 +03:00
Peter Dimov
0a9803dffe Update doc/Jamfile 2024-04-16 22:16:44 +03:00
Rene Rivera
881448f75e Switch to library requirements instead of source. As source puts extra source in install targets. 2024-03-29 21:15:58 -05:00
Rene Rivera
c5b1f4894c Make the library modular usable. 2024-03-11 08:31:12 -05:00
Peter Dimov
6d214eb776 Update .appveyor.yml 2024-03-06 05:13:53 +02:00
Peter Dimov
b0d3107b99 Disable hash_fs_path_test for mingw32 2024-03-06 02:16:51 +02:00
Peter Dimov
e2446b187e Update .drone.jsonnet 2024-03-05 20:24:49 +02:00
Peter Dimov
1dd2f73866 Disable is_range_test2 for gcc-4.7 2024-03-05 19:20:47 +02:00
Peter Dimov
1278f1c2b5 Update .drone.jsonnet 2024-03-05 19:11:58 +02:00
Peter Dimov
067f636d6c Disable hash_fs_path_test for gcc-4.7 2024-03-05 19:09:43 +02:00
Peter Dimov
338c053889 Fix hash_is_avalanching_test2 for libc++ 16 and later 2024-03-05 19:07:24 +02:00
Peter Dimov
94d4f7cb88 Avoid -Wsign-conversion under GCC 6/7 2024-03-05 18:43:35 +02:00
Peter Dimov
6957a20ab1 Avoid compilation errors caused by iterator_traits<void*>. Refs #36. 2024-03-05 18:19:19 +02:00
Peter Dimov
28cc18a4bc Add test with types that return void* from begin/end. Refs #36. 2024-03-05 17:44:03 +02:00
Peter Dimov
7288df8bee Fix is_tuple_like for cv-qualified types under old compilers 2023-12-08 02:00:22 +02:00
Peter Dimov
5c2d5e5b36 Test is_tuple_like with const-qualified types 2023-12-07 22:32:10 +02:00
Peter Dimov
db8743e1c3 Update ci.yml 2023-12-07 22:21:26 +02:00
Peter Dimov
48a306dcf2 Perform apt-get update before apt-add-repository 2023-10-13 02:28:26 +03:00
Peter Dimov
f6279a0615 Add diagnostic output to .drone.jsonnet 2023-10-13 01:43:44 +03:00
Peter Dimov
41746c0bdb Cosmetic fixes 2023-10-12 20:19:57 +03:00
Peter Dimov
07a0910640 Update revision history 2023-10-12 18:14:27 +03:00
Peter Dimov
4c32071739 Remove cxxstd=latest from clang-win/VS2017 on Appveyor 2023-10-12 17:35:57 +03:00
Peter Dimov
30c05c93b1 Remove GCC 4.4, 4.6 from Drone 2023-10-12 15:10:46 +03:00
Peter Dimov
197f75845c Update dependency list in cmake_subdir_test 2023-10-12 14:53:37 +03:00
Peter Dimov
bf8ad2c0ee Regenerate CMakeLists.txt 2023-10-12 14:51:55 +03:00
Peter Dimov
fef60938e5 Update meta/libraries.json 2023-10-12 14:51:15 +03:00
Peter Dimov
f04d866fa7 Remove msvc-9.0, 10.0, 11.0, 12.0 from Appveyor 2023-10-12 14:50:14 +03:00
Peter Dimov
17201433f8 Remove unnecessary file 2023-10-12 14:41:23 +03:00
Peter Dimov
9d09674f08 Work around libstdc++ not considering __int128 integral 2023-10-12 14:24:00 +03:00
Peter Dimov
f8ecd66820 Move integrals to detail/hash_integral.hpp 2023-10-12 14:06:56 +03:00
Peter Dimov
565bac8d31 Remove C++03 workarounds 2023-10-12 13:57:41 +03:00
Peter Dimov
b8496de2f2 Silence MSSTL has_denorm deprecation warnings 2023-10-12 12:43:37 +03:00
Peter Dimov
641a59342e Remove C++03 from CI 2023-10-12 12:28:18 +03:00
40 changed files with 928 additions and 652 deletions

View File

@@ -16,10 +16,7 @@ branches:
environment:
matrix:
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
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
TOOLSET: msvc-14.0
ADDRMD: 32,64
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
TOOLSET: msvc-14.1
@@ -28,7 +25,7 @@ environment:
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
TOOLSET: clang-win
ADDRMD: 64
CXXSTD: 14,17,latest
CXXSTD: 14,17
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
TOOLSET: clang-win
CXXSTD: 14,17,latest
@@ -36,19 +33,19 @@ environment:
- 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
CXXSTD: 11,14,1z
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
ADDPATH: C:\cygwin64\bin;
TOOLSET: gcc
CXXSTD: 03,11,14,1z
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
ADDPATH: C:\mingw\bin;
CXXSTD: 11,14,17
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
ADDPATH: C:\mingw-w64\i686-8.1.0-posix-dwarf-rt_v6-rev0\mingw32\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;
CXXSTD: 11,14,17
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
ADDPATH: C:\mingw-w64\x86_64-8.1.0-posix-seh-rt_v6-rev0\mingw64\bin;
TOOLSET: gcc
CXXSTD: 03,11,14,1z
CXXSTD: 11,14,17
install:
- set BOOST_BRANCH=develop

View File

@@ -32,9 +32,11 @@ local linux_pipeline(name, image, environment, packages = "", sources = [], arch
commands:
[
'set -e',
'uname -a',
'echo $DRONE_STAGE_MACHINE',
'wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | apt-key add -',
] +
(if sources != [] then [ ('apt-add-repository "' + source + '"') for source in sources ] else []) +
(if sources != [] then [ 'apt-get update' ] + [ ('apt-add-repository "' + source + '"') for source in sources ] else []) +
(if packages != "" then [ 'apt-get update', 'apt-get -y install ' + packages ] else []) +
[
'export LIBRARY=' + library,
@@ -96,26 +98,10 @@ local windows_pipeline(name, image, environment, arch = "amd64") =
};
[
linux_pipeline(
"Linux 14.04 GCC 4.4",
"cppalliance/droneubuntu1404:1",
{ TOOLSET: 'gcc', COMPILER: 'g++-4.4', CXXSTD: '98,0x' },
"g++-4.4",
[ "ppa:ubuntu-toolchain-r/test" ],
),
linux_pipeline(
"Linux 14.04 GCC 4.6 32/64",
"cppalliance/droneubuntu1404:1",
{ TOOLSET: 'gcc', COMPILER: 'g++-4.6', CXXSTD: '98,0x', ADDRMD: '32,64' },
"g++-4.6-multilib",
[ "ppa:ubuntu-toolchain-r/test" ],
),
linux_pipeline(
"Linux 14.04 GCC 4.7 32/64",
"cppalliance/droneubuntu1404:1",
{ TOOLSET: 'gcc', COMPILER: 'g++-4.7', CXXSTD: '98,0x', ADDRMD: '32,64' },
{ TOOLSET: 'gcc', COMPILER: 'g++-4.7', CXXSTD: '0x', ADDRMD: '32,64' },
"g++-4.7-multilib",
[ "ppa:ubuntu-toolchain-r/test" ],
),
@@ -123,13 +109,13 @@ local windows_pipeline(name, image, environment, arch = "amd64") =
linux_pipeline(
"Linux 14.04 GCC 4.8* 32/64",
"cppalliance/droneubuntu1404:1",
{ TOOLSET: 'gcc', COMPILER: 'g++', CXXSTD: '03,11', ADDRMD: '32,64' },
{ TOOLSET: 'gcc', COMPILER: 'g++', CXXSTD: '11', ADDRMD: '32,64' },
),
linux_pipeline(
"Linux 14.04 GCC 4.9 32/64",
"cppalliance/droneubuntu1404:1",
{ TOOLSET: 'gcc', COMPILER: 'g++-4.9', CXXSTD: '03,11', ADDRMD: '32,64' },
{ TOOLSET: 'gcc', COMPILER: 'g++-4.9', CXXSTD: '11', ADDRMD: '32,64' },
"g++-4.9-multilib",
[ "ppa:ubuntu-toolchain-r/test" ],
),
@@ -137,242 +123,284 @@ local windows_pipeline(name, image, environment, arch = "amd64") =
linux_pipeline(
"Linux 16.04 GCC 5* 32/64",
"cppalliance/droneubuntu1604:1",
{ TOOLSET: 'gcc', COMPILER: 'g++', CXXSTD: '03,11,14', ADDRMD: '32,64' },
{ TOOLSET: 'gcc', COMPILER: 'g++', CXXSTD: '11,14', ADDRMD: '32,64' },
),
linux_pipeline(
"Linux 18.04 GCC 6 32/64",
"cppalliance/droneubuntu1804:1",
{ TOOLSET: 'gcc', COMPILER: 'g++-6', CXXSTD: '03,11,14', ADDRMD: '32,64' },
{ TOOLSET: 'gcc', COMPILER: 'g++-6', CXXSTD: '11,14', ADDRMD: '32,64' },
"g++-6-multilib",
),
linux_pipeline(
"Linux 18.04 GCC 7* 32/64",
"cppalliance/droneubuntu1804:1",
{ TOOLSET: 'gcc', COMPILER: 'g++', CXXSTD: '03,11,14,17', ADDRMD: '32,64' },
{ TOOLSET: 'gcc', COMPILER: 'g++', CXXSTD: '11,14,17', ADDRMD: '32,64' },
),
linux_pipeline(
"Linux 18.04 GCC 8 32/64",
"cppalliance/droneubuntu1804:1",
{ TOOLSET: 'gcc', COMPILER: 'g++-8', CXXSTD: '03,11,14,17', ADDRMD: '32,64' },
{ TOOLSET: 'gcc', COMPILER: 'g++-8', CXXSTD: '11,14,17', ADDRMD: '32,64' },
"g++-8-multilib",
),
linux_pipeline(
"Linux 20.04 GCC 9* 32/64",
"cppalliance/droneubuntu2004:1",
{ TOOLSET: 'gcc', COMPILER: 'g++', CXXSTD: '03,11,14,17,2a', ADDRMD: '32,64' },
{ TOOLSET: 'gcc', COMPILER: 'g++', CXXSTD: '11,14,17,2a', ADDRMD: '32,64' },
),
linux_pipeline(
"Linux 20.04 GCC 9* ARM64",
"cppalliance/droneubuntu2004:multiarch",
{ TOOLSET: 'gcc', COMPILER: 'g++', CXXSTD: '03,11,14,17,2a' },
{ TOOLSET: 'gcc', COMPILER: 'g++', CXXSTD: '11,14,17,2a' },
arch="arm64",
),
linux_pipeline(
"Linux 20.04 GCC 9* S390x",
"cppalliance/droneubuntu2004:multiarch",
{ TOOLSET: 'gcc', COMPILER: 'g++', CXXSTD: '03,11,14,17,2a' },
{ TOOLSET: 'gcc', COMPILER: 'g++', CXXSTD: '11,14,17,2a' },
arch="s390x",
),
linux_pipeline(
"Linux 20.04 GCC 10 32/64",
"cppalliance/droneubuntu2004:1",
{ TOOLSET: 'gcc', COMPILER: 'g++-10', CXXSTD: '03,11,14,17,20', ADDRMD: '32,64' },
{ TOOLSET: 'gcc', COMPILER: 'g++-10', CXXSTD: '11,14,17,20', ADDRMD: '32,64' },
"g++-10-multilib",
),
linux_pipeline(
"Linux 22.04 GCC 11* 32/64",
"cppalliance/droneubuntu2204:1",
{ TOOLSET: 'gcc', COMPILER: 'g++', CXXSTD: '03,11,14,17,2a', ADDRMD: '32,64' },
{ TOOLSET: 'gcc', COMPILER: 'g++', CXXSTD: '11,14,17,2a', ADDRMD: '32,64' },
),
linux_pipeline(
"Linux 22.04 GCC 12 32 ASAN",
"Linux 22.04 GCC 12 32/64",
"cppalliance/droneubuntu2204:1",
{ TOOLSET: 'gcc', COMPILER: 'g++-12', CXXSTD: '03,11,14,17,20,2b', ADDRMD: '32' } + asan,
{ TOOLSET: 'gcc', COMPILER: 'g++-12', CXXSTD: '11,14,17,20,2b', ADDRMD: '32,64' },
"g++-12-multilib",
),
linux_pipeline(
"Linux 22.04 GCC 12 64 ASAN",
"cppalliance/droneubuntu2204:1",
{ TOOLSET: 'gcc', COMPILER: 'g++-12', CXXSTD: '03,11,14,17,20,2b', ADDRMD: '64' } + asan,
"g++-12-multilib",
),
linux_pipeline(
"Linux 23.04 GCC 13 32/64",
"cppalliance/droneubuntu2304:1",
{ TOOLSET: 'gcc', COMPILER: 'g++-13', CXXSTD: '03,11,14,17,20,2b', ADDRMD: '32,64' },
"Linux 24.04 GCC 13 32/64 UBSAN",
"cppalliance/droneubuntu2404:1",
{ TOOLSET: 'gcc', COMPILER: 'g++-13', CXXSTD: '11,14,17,20,2b', ADDRMD: '32,64' } + ubsan,
"g++-13-multilib",
),
linux_pipeline(
"Linux 24.04 GCC 13 32 ASAN",
"cppalliance/droneubuntu2404:1",
{ TOOLSET: 'gcc', COMPILER: 'g++-13', CXXSTD: '11,14,17,20,2b', ADDRMD: '32' } + asan,
"g++-13-multilib",
),
linux_pipeline(
"Linux 24.04 GCC 14 UBSAN",
"cppalliance/droneubuntu2404:1",
{ TOOLSET: 'gcc', COMPILER: 'g++-14', CXXSTD: '11,14,17,20,2b' } + ubsan,
"g++-14-multilib",
),
linux_pipeline(
"Linux 24.04 GCC 14 ASAN",
"cppalliance/droneubuntu2404:1",
{ TOOLSET: 'gcc', COMPILER: 'g++-14', CXXSTD: '11,14,17,20,2b' } + asan,
"g++-14-multilib",
),
linux_pipeline(
"Linux 16.04 Clang 3.5",
"cppalliance/droneubuntu1604:1",
{ TOOLSET: 'clang', COMPILER: 'clang++-3.5', CXXSTD: '03,11' },
{ TOOLSET: 'clang', COMPILER: 'clang++-3.5', CXXSTD: '11' },
"clang-3.5",
),
linux_pipeline(
"Linux 16.04 Clang 3.6",
"cppalliance/droneubuntu1604:1",
{ TOOLSET: 'clang', COMPILER: 'clang++-3.6', CXXSTD: '03,11,14' },
{ TOOLSET: 'clang', COMPILER: 'clang++-3.6', CXXSTD: '11,14' },
"clang-3.6",
),
linux_pipeline(
"Linux 16.04 Clang 3.7",
"cppalliance/droneubuntu1604:1",
{ TOOLSET: 'clang', COMPILER: 'clang++-3.7', CXXSTD: '03,11,14' },
{ TOOLSET: 'clang', COMPILER: 'clang++-3.7', CXXSTD: '11,14' },
"clang-3.7",
),
linux_pipeline(
"Linux 16.04 Clang 3.8",
"cppalliance/droneubuntu1604:1",
{ TOOLSET: 'clang', COMPILER: 'clang++-3.8', CXXSTD: '03,11,14' },
{ TOOLSET: 'clang', COMPILER: 'clang++-3.8', CXXSTD: '11,14' },
"clang-3.8",
),
linux_pipeline(
"Linux 18.04 Clang 3.9",
"cppalliance/droneubuntu1804:1",
{ TOOLSET: 'clang', COMPILER: 'clang++-3.9', CXXSTD: '03,11,14' },
{ TOOLSET: 'clang', COMPILER: 'clang++-3.9', CXXSTD: '11,14' },
"clang-3.9",
),
linux_pipeline(
"Linux 18.04 Clang 4.0",
"cppalliance/droneubuntu1804:1",
{ TOOLSET: 'clang', COMPILER: 'clang++-4.0', CXXSTD: '03,11,14' },
{ TOOLSET: 'clang', COMPILER: 'clang++-4.0', CXXSTD: '11,14' },
"clang-4.0",
),
linux_pipeline(
"Linux 18.04 Clang 5.0",
"cppalliance/droneubuntu1804:1",
{ TOOLSET: 'clang', COMPILER: 'clang++-5.0', CXXSTD: '03,11,14,1z' },
{ TOOLSET: 'clang', COMPILER: 'clang++-5.0', CXXSTD: '11,14,1z' },
"clang-5.0",
),
linux_pipeline(
"Linux 18.04 Clang 6.0",
"cppalliance/droneubuntu1804:1",
{ TOOLSET: 'clang', COMPILER: 'clang++-6.0', CXXSTD: '03,11,14,17' },
{ TOOLSET: 'clang', COMPILER: 'clang++-6.0', CXXSTD: '11,14,17' },
"clang-6.0",
),
linux_pipeline(
"Linux 20.04 Clang 7",
"cppalliance/droneubuntu2004:1",
{ TOOLSET: 'clang', COMPILER: 'clang++-7', CXXSTD: '03,11,14,17' },
{ TOOLSET: 'clang', COMPILER: 'clang++-7', CXXSTD: '11,14,17' },
"clang-7",
),
linux_pipeline(
"Linux 20.04 Clang 8",
"cppalliance/droneubuntu2004:1",
{ TOOLSET: 'clang', COMPILER: 'clang++-8', CXXSTD: '03,11,14,17' },
{ TOOLSET: 'clang', COMPILER: 'clang++-8', CXXSTD: '11,14,17' },
"clang-8",
),
linux_pipeline(
"Linux 20.04 Clang 9",
"cppalliance/droneubuntu2004:1",
{ TOOLSET: 'clang', COMPILER: 'clang++-9', CXXSTD: '03,11,14,17,2a' },
{ TOOLSET: 'clang', COMPILER: 'clang++-9', CXXSTD: '11,14,17,2a' },
"clang-9",
),
linux_pipeline(
"Linux 20.04 Clang 10",
"cppalliance/droneubuntu2004:1",
{ TOOLSET: 'clang', COMPILER: 'clang++-10', CXXSTD: '03,11,14,17,2a' },
{ TOOLSET: 'clang', COMPILER: 'clang++-10', CXXSTD: '11,14,17,2a' },
"clang-10",
),
linux_pipeline(
"Linux 20.04 Clang 11",
"cppalliance/droneubuntu2004:1",
{ TOOLSET: 'clang', COMPILER: 'clang++-11', CXXSTD: '03,11,14,17,2a' },
{ TOOLSET: 'clang', COMPILER: 'clang++-11', CXXSTD: '11,14,17,2a' },
"clang-11",
),
linux_pipeline(
"Linux 20.04 Clang 12",
"cppalliance/droneubuntu2004:1",
{ TOOLSET: 'clang', COMPILER: 'clang++-12', CXXSTD: '03,11,14,17,2a' },
{ TOOLSET: 'clang', COMPILER: 'clang++-12', CXXSTD: '11,14,17,2a' },
"clang-12",
),
linux_pipeline(
"Linux 22.04 Clang 13",
"cppalliance/droneubuntu2204:1",
{ TOOLSET: 'clang', COMPILER: 'clang++-13', CXXSTD: '03,11,14,17,20,2b' },
{ TOOLSET: 'clang', COMPILER: 'clang++-13', CXXSTD: '11,14,17,20,2b' },
"clang-13",
),
linux_pipeline(
"Linux 22.04 Clang 14",
"cppalliance/droneubuntu2204:1",
{ TOOLSET: 'clang', COMPILER: 'clang++-14', CXXSTD: '03,11,14,17,20,2b' },
{ TOOLSET: 'clang', COMPILER: 'clang++-14', CXXSTD: '11,14,17,20,2b' },
"clang-14",
),
linux_pipeline(
"Linux 22.04 Clang 15 UBSAN",
"Linux 22.04 Clang 15",
"cppalliance/droneubuntu2204:1",
{ TOOLSET: 'clang', COMPILER: 'clang++-15', CXXSTD: '03,11,14,17,20,2b' } + ubsan,
{ TOOLSET: 'clang', COMPILER: 'clang++-15', CXXSTD: '11,14,17,20,2b' },
"clang-15",
),
linux_pipeline(
"Linux 22.04 Clang 15 ASAN",
"cppalliance/droneubuntu2204:1",
{ TOOLSET: 'clang', COMPILER: 'clang++-15', CXXSTD: '03,11,14,17,20,2b' } + asan,
"clang-15",
),
linux_pipeline(
"Linux 23.04 Clang 16",
"cppalliance/droneubuntu2304:1",
{ TOOLSET: 'clang', COMPILER: 'clang++-16', CXXSTD: '03,11,14,17,20,2b' },
"Linux 24.04 Clang 16",
"cppalliance/droneubuntu2404:1",
{ TOOLSET: 'clang', COMPILER: 'clang++-16', CXXSTD: '11,14,17,20,2b' },
"clang-16",
),
linux_pipeline(
"Linux 24.04 Clang 17 UBSAN",
"cppalliance/droneubuntu2404:1",
{ TOOLSET: 'clang', COMPILER: 'clang++-17', CXXSTD: '11,14,17,20,2b' } + ubsan,
"clang-17",
),
linux_pipeline(
"Linux 24.04 Clang 17 ASAN",
"cppalliance/droneubuntu2404:1",
{ TOOLSET: 'clang', COMPILER: 'clang++-17', CXXSTD: '11,14,17,20,2b' } + asan,
"clang-17",
),
linux_pipeline(
"Linux 24.04 Clang 18 UBSAN",
"cppalliance/droneubuntu2404:1",
{ TOOLSET: 'clang', COMPILER: 'clang++-18', CXXSTD: '11,14,17,20,2b' } + ubsan,
"clang-18",
),
linux_pipeline(
"Linux 24.04 Clang 18 ASAN",
"cppalliance/droneubuntu2404:1",
{ TOOLSET: 'clang', COMPILER: 'clang++-18', CXXSTD: '11,14,17,20,2b' } + asan,
"clang-18",
),
linux_pipeline(
"Linux 24.10 Clang 19",
"cppalliance/droneubuntu2410:1",
{ TOOLSET: 'clang', COMPILER: 'clang++-19', CXXSTD: '11,14,17,20,2b' },
"clang-19",
),
macos_pipeline(
"MacOS 10.15 Xcode 12.2 UBSAN",
{ TOOLSET: 'clang', COMPILER: 'clang++', CXXSTD: '03,11,14,17,2a' } + ubsan,
{ TOOLSET: 'clang', COMPILER: 'clang++', CXXSTD: '11,14,17,2a' } + ubsan,
),
macos_pipeline(
"MacOS 10.15 Xcode 12.2 ASAN",
{ TOOLSET: 'clang', COMPILER: 'clang++', CXXSTD: '03,11,14,17,2a' } + asan,
{ TOOLSET: 'clang', COMPILER: 'clang++', CXXSTD: '11,14,17,2a' } + asan,
),
macos_pipeline(
"MacOS 12.4 Xcode 13.4.1 UBSAN",
{ TOOLSET: 'clang', COMPILER: 'clang++', CXXSTD: '03,11,14,17,20,2b' } + ubsan,
{ TOOLSET: 'clang', COMPILER: 'clang++', CXXSTD: '11,14,17,20,2b' } + ubsan,
xcode_version = "13.4.1", osx_version = "monterey", arch = "arm64",
),
macos_pipeline(
"MacOS 12.4 Xcode 13.4.1 ASAN",
{ TOOLSET: 'clang', COMPILER: 'clang++', CXXSTD: '03,11,14,17,20,2b' } + asan,
{ TOOLSET: 'clang', COMPILER: 'clang++', CXXSTD: '11,14,17,20,2b' } + asan,
xcode_version = "13.4.1", osx_version = "monterey", arch = "arm64",
),
windows_pipeline(
"Windows VS2015 msvc-14.0",
"cppalliance/dronevs2015",
{ TOOLSET: 'msvc-14.0', CXXSTD: '14,latest' },
{ TOOLSET: 'msvc-14.0', CXXSTD: '14,latest', B2_DONT_EMBED_MANIFEST: '1' },
),
windows_pipeline(

View File

@@ -18,155 +18,219 @@ jobs:
matrix:
include:
- toolset: gcc-4.8
cxxstd: "03,11"
os: ubuntu-latest
cxxstd: "11"
container: ubuntu:18.04
os: ubuntu-latest
install: g++-4.8-multilib
address-model: 32,64
- toolset: gcc-5
cxxstd: "03,11,14,1z"
os: ubuntu-latest
cxxstd: "11,14,1z"
container: ubuntu:18.04
os: ubuntu-latest
install: g++-5-multilib
address-model: 32,64
- toolset: gcc-6
cxxstd: "03,11,14,1z"
os: ubuntu-latest
cxxstd: "11,14,1z"
container: ubuntu:18.04
os: ubuntu-latest
install: g++-6-multilib
address-model: 32,64
- toolset: gcc-7
cxxstd: "03,11,14,17"
os: ubuntu-20.04
cxxstd: "11,14,17"
container: ubuntu:20.04
os: ubuntu-latest
install: g++-7-multilib
address-model: 32,64
- toolset: gcc-8
cxxstd: "03,11,14,17,2a"
os: ubuntu-20.04
cxxstd: "11,14,17,2a"
container: ubuntu:20.04
os: ubuntu-latest
install: g++-8-multilib
address-model: 32,64
- toolset: gcc-9
cxxstd: "03,11,14,17,2a"
os: ubuntu-20.04
cxxstd: "11,14,17,2a"
container: ubuntu:20.04
os: ubuntu-latest
install: g++-9-multilib
address-model: 32,64
- toolset: gcc-10
cxxstd: "03,11,14,17,2a"
cxxstd: "11,14,17,2a"
os: ubuntu-22.04
install: g++-10-multilib
address-model: 32,64
- toolset: gcc-11
cxxstd: "03,11,14,17,20"
cxxstd: "11,14,17,20"
os: ubuntu-22.04
install: g++-11-multilib
address-model: 32,64
- toolset: gcc-12
cxxstd: "03,11,14,17,20,2b"
cxxstd: "11,14,17,20,2b"
os: ubuntu-22.04
install: g++-12-multilib
address-model: 32,64
- toolset: gcc-13
cxxstd: "03,11,14,17,20,2b"
cxxstd: "11,14,17,20,2b"
container: ubuntu:24.04
os: ubuntu-latest
container: ubuntu:23.04
install: g++-13-multilib
address-model: 32,64
- toolset: gcc-14
cxxstd: "11,14,17,20,2b"
container: ubuntu:24.04
os: ubuntu-latest
install: g++-14-multilib
address-model: 32,64
- toolset: gcc-15
cxxstd: "11,14,17,20,23,2c"
container: ubuntu:25.04
os: ubuntu-latest
install: g++-15-multilib
address-model: 32,64
- toolset: clang
compiler: clang++-3.9
cxxstd: "03,11,14"
os: ubuntu-latest
cxxstd: "11,14"
container: ubuntu:18.04
os: ubuntu-latest
install: clang-3.9
- toolset: clang
compiler: clang++-4.0
cxxstd: "03,11,14"
os: ubuntu-latest
cxxstd: "11,14"
container: ubuntu:18.04
os: ubuntu-latest
install: clang-4.0
- toolset: clang
compiler: clang++-5.0
cxxstd: "03,11,14,1z"
os: ubuntu-latest
cxxstd: "11,14,1z"
container: ubuntu:18.04
os: ubuntu-latest
install: clang-5.0
- toolset: clang
compiler: clang++-6.0
cxxstd: "03,11,14,17"
os: ubuntu-20.04
cxxstd: "11,14,17"
container: ubuntu:20.04
os: ubuntu-latest
install: clang-6.0
- toolset: clang
compiler: clang++-7
cxxstd: "03,11,14,17"
os: ubuntu-20.04
cxxstd: "11,14,17"
container: ubuntu:20.04
os: ubuntu-latest
install: clang-7
- toolset: clang
compiler: clang++-8
cxxstd: "03,11,14,17"
os: ubuntu-20.04
cxxstd: "11,14,17"
container: ubuntu:20.04
os: ubuntu-latest
install: clang-8
- toolset: clang
compiler: clang++-9
cxxstd: "03,11,14,17,2a"
os: ubuntu-20.04
cxxstd: "11,14,17,2a"
container: ubuntu:20.04
os: ubuntu-latest
install: clang-9
- toolset: clang
compiler: clang++-10
cxxstd: "03,11,14,17,2a"
os: ubuntu-20.04
cxxstd: "11,14,17,2a"
container: ubuntu:20.04
os: ubuntu-latest
install: clang-10
- toolset: clang
compiler: clang++-11
cxxstd: "03,11,14,17,2a"
os: ubuntu-20.04
cxxstd: "11,14,17,2a"
container: ubuntu:20.04
os: ubuntu-latest
install: clang-11
- toolset: clang
compiler: clang++-12
cxxstd: "03,11,14,17,20"
os: ubuntu-20.04
cxxstd: "11,14,17,20"
container: ubuntu:20.04
os: ubuntu-latest
install: clang-12
- toolset: clang
compiler: clang++-13
cxxstd: "03,11,14,17,20,2b"
os: ubuntu-22.04
cxxstd: "11,14,17,20,2b"
container: ubuntu:22.04
os: ubuntu-latest
install: clang-13
- toolset: clang
compiler: clang++-14
cxxstd: "03,11,14,17,20,2b"
os: ubuntu-22.04
cxxstd: "11,14,17,20,2b"
container: ubuntu:22.04
os: ubuntu-latest
install: clang-14
- toolset: clang
compiler: clang++-15
cxxstd: "03,11,14,17,20,2b"
os: ubuntu-22.04
cxxstd: "11,14,17,20,2b"
container: ubuntu:22.04
os: ubuntu-latest
install: clang-15
- toolset: clang
compiler: clang++-16
cxxstd: "03,11,14,17,20,2b"
cxxstd: "11,14,17,20,2b"
container: ubuntu:24.04
os: ubuntu-latest
container: ubuntu:23.04
install: clang-16
- toolset: clang
cxxstd: "03,11,14,17,2a"
os: macos-11
compiler: clang++-17
cxxstd: "11,14,17,20,2b"
container: ubuntu:24.04
os: ubuntu-latest
install: clang-17
- toolset: clang
cxxstd: "03,11,14,17,20,2b"
os: macos-12
compiler: clang++-18
cxxstd: "11,14,17,20,2b"
container: ubuntu:24.04
os: ubuntu-latest
install: clang-18
- toolset: clang
cxxstd: "03,11,14,17,20,2b"
compiler: clang++-19
cxxstd: "11,14,17,20,2b"
container: ubuntu:24.04
os: ubuntu-latest
install: clang-19
- toolset: clang
compiler: clang++-20
cxxstd: "11,14,17,20,23,2c"
container: ubuntu:25.04
os: ubuntu-latest
install: clang-20
- toolset: clang
cxxstd: "11,14,17,20,2b"
os: macos-13
- toolset: clang
cxxstd: "11,14,17,20,2b"
os: macos-14
- toolset: clang
cxxstd: "11,14,17,20,2b"
os: macos-15
runs-on: ${{matrix.os}}
container: ${{matrix.container}}
container:
image: ${{matrix.container}}
volumes:
- /node20217:/node20217:rw,rshared
- ${{ startsWith(matrix.container, 'ubuntu:1') && '/node20217:/__e/node20:ro,rshared' || ' ' }}
defaults:
run:
shell: bash
steps:
- uses: actions/checkout@v3
- name: Setup container environment
if: matrix.container
run: |
apt-get update
apt-get -y install sudo python3 git g++
apt-get -y install sudo python3 git g++ curl xz-utils
- name: Install nodejs20glibc2.17
if: ${{ startsWith( matrix.container, 'ubuntu:1' ) }}
run: |
curl -LO https://archives.boost.io/misc/node/node-v20.9.0-linux-x64-glibc-217.tar.xz
tar -xf node-v20.9.0-linux-x64-glibc-217.tar.xz --strip-components 1 -C /node20217
ldd /__e/node20/bin/node
- uses: actions/checkout@v4
- name: Install packages
if: matrix.install
@@ -213,14 +277,6 @@ jobs:
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
@@ -230,14 +286,14 @@ jobs:
addrmd: 32,64
os: windows-2022
- toolset: gcc
cxxstd: "03,11,14,17,2a"
cxxstd: "11,14,17,2a"
addrmd: 64
os: windows-2019
os: windows-2022
runs-on: ${{matrix.os}}
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Setup Boost
shell: cmd
@@ -273,16 +329,16 @@ jobs:
fail-fast: false
matrix:
include:
- os: ubuntu-20.04
- os: ubuntu-22.04
- os: macos-11
- os: macos-12
- os: ubuntu-24.04
- os: macos-13
- os: macos-14
- os: macos-15
runs-on: ${{matrix.os}}
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Install packages
if: matrix.install
@@ -321,16 +377,16 @@ jobs:
fail-fast: false
matrix:
include:
- os: ubuntu-20.04
- os: ubuntu-22.04
- os: macos-11
- os: macos-12
- os: ubuntu-24.04
- os: macos-13
- os: macos-14
- os: macos-15
runs-on: ${{matrix.os}}
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Install packages
if: matrix.install
@@ -379,16 +435,16 @@ jobs:
fail-fast: false
matrix:
include:
- os: ubuntu-20.04
- os: ubuntu-22.04
- os: macos-11
- os: macos-12
- os: ubuntu-24.04
- os: macos-13
- os: macos-14
- os: macos-15
runs-on: ${{matrix.os}}
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Install packages
if: matrix.install
@@ -435,13 +491,13 @@ jobs:
fail-fast: false
matrix:
include:
- os: windows-2019
- os: windows-2022
- os: windows-2025
runs-on: ${{matrix.os}}
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Setup Boost
shell: cmd
@@ -484,13 +540,13 @@ jobs:
fail-fast: false
matrix:
include:
- os: windows-2019
- os: windows-2022
- os: windows-2025
runs-on: ${{matrix.os}}
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Setup Boost
shell: cmd
@@ -551,13 +607,13 @@ jobs:
fail-fast: false
matrix:
include:
- os: windows-2019
- os: windows-2022
- os: windows-2025
runs-on: ${{matrix.os}}
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Setup Boost
shell: cmd

View File

@@ -3,7 +3,7 @@
# 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)
cmake_minimum_required(VERSION 3.8...3.20)
project(boost_container_hash VERSION "${BOOST_SUPERPROJECT_VERSION}" LANGUAGES CXX)
@@ -17,9 +17,10 @@ target_link_libraries(boost_container_hash
Boost::config
Boost::describe
Boost::mp11
Boost::type_traits
)
target_compile_features(boost_container_hash INTERFACE cxx_std_11)
if(BUILD_TESTING AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/test/CMakeLists.txt")
add_subdirectory(test)

18
benchmark/Jamfile Normal file
View File

@@ -0,0 +1,18 @@
# Copyright Daniel James 2005. Use, modification, and distribution are
# subject to the Boost Software License, Version 1.0. (See accompanying
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
import testing ;
project :
requirements
<library>/boost/container_hash//boost_container_hash
<library>/boost/core//boost_core
<library>/boost/unordered//boost_unordered
;
link char_seq.cpp ;
link unordered.cpp ;
link unordered_flat.cpp : <cxxstd>11:<build>no <cxxstd>14:<build>no ;
link word_count.cpp : <cxxstd>11:<build>no <cxxstd>14:<build>no ;

View File

@@ -79,11 +79,11 @@ int main()
if( k & 1 )
{
sprintf( buffer, "prefix_%llu_suffix", k );
std::snprintf( buffer, sizeof( buffer ), "prefix_%llu_suffix", k );
}
else
{
sprintf( buffer, "{%u}", static_cast<unsigned>( k ) );
std::snprintf( buffer, sizeof( buffer ), "{%u}", static_cast<unsigned>( k ) );
}
v.push_back( buffer );

View File

@@ -356,11 +356,11 @@ int main()
if( k & 1 )
{
sprintf( buffer, "prefix_%llu_suffix", k );
std::snprintf( buffer, sizeof( buffer ), "prefix_%llu_suffix", k );
}
else
{
sprintf( buffer, "{%u}", static_cast<unsigned>( k ) );
std::snprintf( buffer, sizeof( buffer ), "{%u}", static_cast<unsigned>( k ) );
}
v.push_back( buffer );

22
build.jam Normal file
View File

@@ -0,0 +1,22 @@
# Copyright 2023-2024 René Ferdinand Rivera Morell
# Copyright 2024 Peter Dimov
# Distributed under the Boost Software License, Version 1.0.
# https://www.boost.org/LICENSE_1_0.txt
require-b2 5.2 ;
constant boost_dependencies :
/boost/config//boost_config
/boost/describe//boost_describe
/boost/mp11//boost_mp11
;
project /boost/container_hash ;
explicit
[ alias boost_container_hash : : : : <include>include <library>$(boost_dependencies) ]
[ alias all : boost_container_hash examples test ]
;
call-if : boost-library container_hash
;

View File

@@ -8,6 +8,14 @@ https://www.boost.org/LICENSE_1_0.txt
= Recent Changes
:idprefix: recent_
== Boost 1.89.0
* Added the `hash_is_avalanching` trait class.
== Boost 1.84.0
* {cpp}03 is no longer supported.
== Boost 1.82.0
* Added an overload of `hash_value` for `std::nullptr_t`.

View File

@@ -1,7 +1,7 @@
////
Copyright 2005-2008 Daniel James
Copyright 2022 Christian Mazakas
Copyright 2022 Peter Dimov
Copyright 2022, 2025 Peter Dimov
Distributed under the Boost Software License, Version 1.0.
https://www.boost.org/LICENSE_1_0.txt
////
@@ -44,6 +44,8 @@ template<class It> std::size_t hash_range( It first, It last );
template<class It> void hash_unordered_range( std::size_t& seed, It first, It last );
template<class It> std::size_t hash_unordered_range( It first, It last );
template<class Hash> struct hash_is_avalanching;
} // namespace boost
----
@@ -572,6 +574,56 @@ where `x` is the currently contained value in `v`.
Throws: ::
`std::bad_variant_access` when `v.valueless_by_exception()` is `true`.
== <boost/container_hash/{zwsp}hash_is_avalanching.hpp>
Defines the trait `boost::hash_is_avalanching`.
[source]
----
namespace boost
{
template<class Hash> struct hash_is_avalanching;
} // namespace boost
----
=== hash_is_avalanching<Hash>
[source]
----
template<class Hash> struct hash_is_avalanching
{
static constexpr bool value = /* see below */;
};
----
`hash_is_avalanching<Hash>::value` is:
* `false` if `Hash::is_avalanching` is not present,
* `Hash::is_avalanching::value` if this is present and convertible at compile time to a `bool`,
* `true` if `Hash::is_avalanching` is `void` (this usage is deprecated),
* ill-formed otherwise.
A hash function is said to have the _avalanching property_ if small changes
in the input translate to large changes in the returned hash code
&#8212;ideally, flipping one bit in the representation of the input value results
in each bit of the hash code flipping with probability 50%. Libraries
such as link:../../../unordered/index.html[Boost.Unordered] consult this trait
to determine if the supplied hash function is of high quality.
`boost::hash` for `std::basic_string<Ch>` and `std::basic_string_view<Ch>`
has this trait set to `true` when `Ch` is an integral type (this includes
`std::string` and `std::string_view`, among others).
Users can set this trait for a particular `Hash` type by:
* Inserting the nested `is_avalanching` typedef in the class definition
if they have access to its source code.
* Writing a specialization of `boost::hash_is_avalanching`
for `Hash`.
Note that usage of this trait is not restricted to hash functions produced
with Boost.ContainerHash.
== <boost/container_hash/{zwsp}is_range.hpp>
Defines the trait `boost::container_hash::is_range`.

View File

@@ -3,8 +3,12 @@
# subject to the Boost Software License, Version 1.0. (See accompanying
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
import testing ;
project : requirements <library>/boost/container_hash//boost_container_hash ;
run books.cpp ;
run point.cpp ;
run portable.cpp ;
run template.cpp : : : <toolset>msvc-8.0:<build>no ;
run template.cpp /boost/unordered//boost_unordered : : : <toolset>msvc-8.0:<build>no ;
run point2.cpp ;

View File

@@ -0,0 +1,146 @@
// Copyright 2021-2023 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#ifndef BOOST_HASH_DETAIL_HASH_INTEGRAL_HPP
#define BOOST_HASH_DETAIL_HASH_INTEGRAL_HPP
#include <boost/container_hash/detail/hash_mix.hpp>
#include <type_traits>
#include <cstddef>
#include <climits>
namespace boost
{
namespace hash_detail
{
// libstdc++ doesn't provide support for __int128 in the standard traits
template<class T> struct is_integral: public std::is_integral<T>
{
};
template<class T> struct is_unsigned: public std::is_unsigned<T>
{
};
template<class T> struct make_unsigned: public std::make_unsigned<T>
{
};
#if defined(__SIZEOF_INT128__)
template<> struct is_integral<__int128_t>: public std::true_type
{
};
template<> struct is_integral<__uint128_t>: public std::true_type
{
};
template<> struct is_unsigned<__int128_t>: public std::false_type
{
};
template<> struct is_unsigned<__uint128_t>: public std::true_type
{
};
template<> struct make_unsigned<__int128_t>
{
typedef __uint128_t type;
};
template<> struct make_unsigned<__uint128_t>
{
typedef __uint128_t type;
};
#endif
template<class T,
bool bigger_than_size_t = (sizeof(T) > sizeof(std::size_t)),
bool is_unsigned = is_unsigned<T>::value,
std::size_t size_t_bits = sizeof(std::size_t) * CHAR_BIT,
std::size_t type_bits = sizeof(T) * CHAR_BIT>
struct hash_integral_impl;
template<class T, bool is_unsigned, std::size_t size_t_bits, std::size_t type_bits> struct hash_integral_impl<T, false, is_unsigned, size_t_bits, type_bits>
{
static std::size_t fn( T v )
{
return static_cast<std::size_t>( v );
}
};
template<class T, std::size_t size_t_bits, std::size_t type_bits> struct hash_integral_impl<T, true, false, size_t_bits, type_bits>
{
static std::size_t fn( T v )
{
typedef typename make_unsigned<T>::type U;
if( v >= 0 )
{
return hash_integral_impl<U>::fn( static_cast<U>( v ) );
}
else
{
return ~hash_integral_impl<U>::fn( static_cast<U>( ~static_cast<U>( v ) ) );
}
}
};
template<class T> struct hash_integral_impl<T, true, true, 32, 64>
{
static std::size_t fn( T v )
{
std::size_t seed = 0;
seed = static_cast<std::size_t>( v >> 32 ) + hash_detail::hash_mix( seed );
seed = static_cast<std::size_t>( v & 0xFFFFFFFF ) + hash_detail::hash_mix( seed );
return seed;
}
};
template<class T> struct hash_integral_impl<T, true, true, 32, 128>
{
static std::size_t fn( T v )
{
std::size_t seed = 0;
seed = static_cast<std::size_t>( v >> 96 ) + hash_detail::hash_mix( seed );
seed = static_cast<std::size_t>( v >> 64 ) + hash_detail::hash_mix( seed );
seed = static_cast<std::size_t>( v >> 32 ) + hash_detail::hash_mix( seed );
seed = static_cast<std::size_t>( v ) + hash_detail::hash_mix( seed );
return seed;
}
};
template<class T> struct hash_integral_impl<T, true, true, 64, 128>
{
static std::size_t fn( T v )
{
std::size_t seed = 0;
seed = static_cast<std::size_t>( v >> 64 ) + hash_detail::hash_mix( seed );
seed = static_cast<std::size_t>( v ) + hash_detail::hash_mix( seed );
return seed;
}
};
} // namespace hash_detail
template <typename T>
typename std::enable_if<hash_detail::is_integral<T>::value, std::size_t>::type
hash_value( T v )
{
return hash_detail::hash_integral_impl<T>::fn( v );
}
} // namespace boost
#endif // #ifndef BOOST_HASH_DETAIL_HASH_INTEGRAL_HPP

View File

@@ -5,7 +5,7 @@
#ifndef BOOST_HASH_DETAIL_HASH_MIX_HPP
#define BOOST_HASH_DETAIL_HASH_MIX_HPP
#include <boost/cstdint.hpp>
#include <cstdint>
#include <cstddef>
#include <climits>
@@ -66,9 +66,9 @@ template<std::size_t Bits> struct hash_mix_impl;
template<> struct hash_mix_impl<64>
{
inline static boost::uint64_t fn( boost::uint64_t x )
inline static std::uint64_t fn( std::uint64_t x )
{
boost::uint64_t const m = (boost::uint64_t(0xe9846af) << 32) + 0x9b1a615d;
std::uint64_t const m = 0xe9846af9b1a615d;
x ^= x >> 32;
x *= m;
@@ -87,10 +87,10 @@ template<> struct hash_mix_impl<64>
template<> struct hash_mix_impl<32>
{
inline static boost::uint32_t fn( boost::uint32_t x )
inline static std::uint32_t fn( std::uint32_t x )
{
boost::uint32_t const m1 = 0x21f0aaad;
boost::uint32_t const m2 = 0x735a2d97;
std::uint32_t const m1 = 0x21f0aaad;
std::uint32_t const m2 = 0x735a2d97;
x ^= x >> 16;
x *= m1;

View File

@@ -7,10 +7,8 @@
#include <boost/container_hash/hash_fwd.hpp>
#include <boost/container_hash/detail/mulx.hpp>
#include <boost/type_traits/integral_constant.hpp>
#include <boost/type_traits/enable_if.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/cstdint.hpp>
#include <type_traits>
#include <cstdint>
#include <iterator>
#include <limits>
#include <cstddef>
@@ -22,20 +20,20 @@ namespace boost
namespace hash_detail
{
template<class T> struct is_char_type: public boost::false_type {};
template<class T> struct is_char_type: public std::false_type {};
#if CHAR_BIT == 8
template<> struct is_char_type<char>: public boost::true_type {};
template<> struct is_char_type<signed char>: public boost::true_type {};
template<> struct is_char_type<unsigned char>: public boost::true_type {};
template<> struct is_char_type<char>: public std::true_type {};
template<> struct is_char_type<signed char>: public std::true_type {};
template<> struct is_char_type<unsigned char>: public std::true_type {};
#if defined(__cpp_char8_t) && __cpp_char8_t >= 201811L
template<> struct is_char_type<char8_t>: public boost::true_type {};
template<> struct is_char_type<char8_t>: public std::true_type {};
#endif
#if defined(__cpp_lib_byte) && __cpp_lib_byte >= 201603L
template<> struct is_char_type<std::byte>: public boost::true_type {};
template<> struct is_char_type<std::byte>: public std::true_type {};
#endif
#endif
@@ -43,7 +41,7 @@ template<> struct is_char_type<std::byte>: public boost::true_type {};
// generic version
template<class It>
inline typename boost::enable_if_<
inline typename std::enable_if<
!is_char_type<typename std::iterator_traits<It>::value_type>::value,
std::size_t >::type
hash_range( std::size_t seed, It first, It last )
@@ -58,25 +56,25 @@ std::size_t >::type
// specialized char[] version, 32 bit
template<class It> inline boost::uint32_t read32le( It p )
template<class It> inline std::uint32_t read32le( It p )
{
// clang 5+, gcc 5+ figure out this pattern and use a single mov on x86
// gcc on s390x and power BE even knows how to use load-reverse
boost::uint32_t w =
static_cast<boost::uint32_t>( static_cast<unsigned char>( p[0] ) ) |
static_cast<boost::uint32_t>( static_cast<unsigned char>( p[1] ) ) << 8 |
static_cast<boost::uint32_t>( static_cast<unsigned char>( p[2] ) ) << 16 |
static_cast<boost::uint32_t>( static_cast<unsigned char>( p[3] ) ) << 24;
std::uint32_t w =
static_cast<std::uint32_t>( static_cast<unsigned char>( p[0] ) ) |
static_cast<std::uint32_t>( static_cast<unsigned char>( p[1] ) ) << 8 |
static_cast<std::uint32_t>( static_cast<unsigned char>( p[2] ) ) << 16 |
static_cast<std::uint32_t>( static_cast<unsigned char>( p[3] ) ) << 24;
return w;
}
#if defined(_MSC_VER) && !defined(__clang__)
template<class T> inline boost::uint32_t read32le( T* p )
template<class T> inline std::uint32_t read32le( T* p )
{
boost::uint32_t w;
std::uint32_t w;
std::memcpy( &w, p, 4 );
return w;
@@ -84,15 +82,15 @@ template<class T> inline boost::uint32_t read32le( T* p )
#endif
inline boost::uint64_t mul32( boost::uint32_t x, boost::uint32_t y )
inline std::uint64_t mul32( std::uint32_t x, std::uint32_t y )
{
return static_cast<boost::uint64_t>( x ) * y;
return static_cast<std::uint64_t>( x ) * y;
}
template<class It>
inline typename boost::enable_if_<
inline typename std::enable_if<
is_char_type<typename std::iterator_traits<It>::value_type>::value &&
is_same<typename std::iterator_traits<It>::iterator_category, std::random_access_iterator_tag>::value &&
std::is_same<typename std::iterator_traits<It>::iterator_category, std::random_access_iterator_tag>::value &&
std::numeric_limits<std::size_t>::digits <= 32,
std::size_t>::type
hash_range( std::size_t seed, It first, It last )
@@ -100,17 +98,17 @@ std::size_t>::type
It p = first;
std::size_t n = static_cast<std::size_t>( last - first );
boost::uint32_t const q = 0x9e3779b9U;
boost::uint32_t const k = 0xe35e67b1U; // q * q
std::uint32_t const q = 0x9e3779b9U;
std::uint32_t const k = 0xe35e67b1U; // q * q
boost::uint64_t h = mul32( static_cast<boost::uint32_t>( seed ) + q, k );
boost::uint32_t w = static_cast<boost::uint32_t>( h & 0xFFFFFFFF );
std::uint64_t h = mul32( static_cast<std::uint32_t>( seed ) + q, k );
std::uint32_t w = static_cast<std::uint32_t>( h & 0xFFFFFFFF );
h ^= n;
while( n >= 4 )
{
boost::uint32_t v1 = read32le( p );
std::uint32_t v1 = read32le( p );
w += q;
h ^= mul32( v1 + w, k );
@@ -120,7 +118,7 @@ std::size_t>::type
}
{
boost::uint32_t v1 = 0;
std::uint32_t v1 = 0;
if( n >= 1 )
{
@@ -128,9 +126,9 @@ std::size_t>::type
std::size_t const x2 = n >> 1; // 1: 0, 2: 1, 3: 1
v1 =
static_cast<boost::uint32_t>( static_cast<unsigned char>( p[ static_cast<std::ptrdiff_t>( x1 ) ] ) ) << x1 * 8 |
static_cast<boost::uint32_t>( static_cast<unsigned char>( p[ static_cast<std::ptrdiff_t>( x2 ) ] ) ) << x2 * 8 |
static_cast<boost::uint32_t>( static_cast<unsigned char>( p[ 0 ] ) );
static_cast<std::uint32_t>( static_cast<unsigned char>( p[ static_cast<std::ptrdiff_t>( x1 ) ] ) ) << x1 * 8 |
static_cast<std::uint32_t>( static_cast<unsigned char>( p[ static_cast<std::ptrdiff_t>( x2 ) ] ) ) << x2 * 8 |
static_cast<std::uint32_t>( static_cast<unsigned char>( p[ 0 ] ) );
}
w += q;
@@ -138,28 +136,28 @@ std::size_t>::type
}
w += q;
h ^= mul32( static_cast<boost::uint32_t>( h & 0xFFFFFFFF ) + w, static_cast<boost::uint32_t>( h >> 32 ) + w + k );
h ^= mul32( static_cast<std::uint32_t>( h & 0xFFFFFFFF ) + w, static_cast<std::uint32_t>( h >> 32 ) + w + k );
return static_cast<boost::uint32_t>( h & 0xFFFFFFFF ) ^ static_cast<boost::uint32_t>( h >> 32 );
return static_cast<std::uint32_t>( h & 0xFFFFFFFF ) ^ static_cast<std::uint32_t>( h >> 32 );
}
template<class It>
inline typename boost::enable_if_<
inline typename std::enable_if<
is_char_type<typename std::iterator_traits<It>::value_type>::value &&
!is_same<typename std::iterator_traits<It>::iterator_category, std::random_access_iterator_tag>::value &&
!std::is_same<typename std::iterator_traits<It>::iterator_category, std::random_access_iterator_tag>::value &&
std::numeric_limits<std::size_t>::digits <= 32,
std::size_t>::type
hash_range( std::size_t seed, It first, It last )
{
std::size_t n = 0;
boost::uint32_t const q = 0x9e3779b9U;
boost::uint32_t const k = 0xe35e67b1U; // q * q
std::uint32_t const q = 0x9e3779b9U;
std::uint32_t const k = 0xe35e67b1U; // q * q
boost::uint64_t h = mul32( static_cast<boost::uint32_t>( seed ) + q, k );
boost::uint32_t w = static_cast<boost::uint32_t>( h & 0xFFFFFFFF );
std::uint64_t h = mul32( static_cast<std::uint32_t>( seed ) + q, k );
std::uint32_t w = static_cast<std::uint32_t>( h & 0xFFFFFFFF );
boost::uint32_t v1 = 0;
std::uint32_t v1 = 0;
for( ;; )
{
@@ -170,7 +168,7 @@ std::size_t>::type
break;
}
v1 |= static_cast<boost::uint32_t>( static_cast<unsigned char>( *first ) );
v1 |= static_cast<std::uint32_t>( static_cast<unsigned char>( *first ) );
++first;
++n;
@@ -179,7 +177,7 @@ std::size_t>::type
break;
}
v1 |= static_cast<boost::uint32_t>( static_cast<unsigned char>( *first ) ) << 8;
v1 |= static_cast<std::uint32_t>( static_cast<unsigned char>( *first ) ) << 8;
++first;
++n;
@@ -188,7 +186,7 @@ std::size_t>::type
break;
}
v1 |= static_cast<boost::uint32_t>( static_cast<unsigned char>( *first ) ) << 16;
v1 |= static_cast<std::uint32_t>( static_cast<unsigned char>( *first ) ) << 16;
++first;
++n;
@@ -197,7 +195,7 @@ std::size_t>::type
break;
}
v1 |= static_cast<boost::uint32_t>( static_cast<unsigned char>( *first ) ) << 24;
v1 |= static_cast<std::uint32_t>( static_cast<unsigned char>( *first ) ) << 24;
++first;
++n;
@@ -211,33 +209,33 @@ std::size_t>::type
h ^= mul32( v1 + w, k );
w += q;
h ^= mul32( static_cast<boost::uint32_t>( h & 0xFFFFFFFF ) + w, static_cast<boost::uint32_t>( h >> 32 ) + w + k );
h ^= mul32( static_cast<std::uint32_t>( h & 0xFFFFFFFF ) + w, static_cast<std::uint32_t>( h >> 32 ) + w + k );
return static_cast<boost::uint32_t>( h & 0xFFFFFFFF ) ^ static_cast<boost::uint32_t>( h >> 32 );
return static_cast<std::uint32_t>( h & 0xFFFFFFFF ) ^ static_cast<std::uint32_t>( h >> 32 );
}
// specialized char[] version, 64 bit
template<class It> inline boost::uint64_t read64le( It p )
template<class It> inline std::uint64_t read64le( It p )
{
boost::uint64_t w =
static_cast<boost::uint64_t>( static_cast<unsigned char>( p[0] ) ) |
static_cast<boost::uint64_t>( static_cast<unsigned char>( p[1] ) ) << 8 |
static_cast<boost::uint64_t>( static_cast<unsigned char>( p[2] ) ) << 16 |
static_cast<boost::uint64_t>( static_cast<unsigned char>( p[3] ) ) << 24 |
static_cast<boost::uint64_t>( static_cast<unsigned char>( p[4] ) ) << 32 |
static_cast<boost::uint64_t>( static_cast<unsigned char>( p[5] ) ) << 40 |
static_cast<boost::uint64_t>( static_cast<unsigned char>( p[6] ) ) << 48 |
static_cast<boost::uint64_t>( static_cast<unsigned char>( p[7] ) ) << 56;
std::uint64_t w =
static_cast<std::uint64_t>( static_cast<unsigned char>( p[0] ) ) |
static_cast<std::uint64_t>( static_cast<unsigned char>( p[1] ) ) << 8 |
static_cast<std::uint64_t>( static_cast<unsigned char>( p[2] ) ) << 16 |
static_cast<std::uint64_t>( static_cast<unsigned char>( p[3] ) ) << 24 |
static_cast<std::uint64_t>( static_cast<unsigned char>( p[4] ) ) << 32 |
static_cast<std::uint64_t>( static_cast<unsigned char>( p[5] ) ) << 40 |
static_cast<std::uint64_t>( static_cast<unsigned char>( p[6] ) ) << 48 |
static_cast<std::uint64_t>( static_cast<unsigned char>( p[7] ) ) << 56;
return w;
}
#if defined(_MSC_VER) && !defined(__clang__)
template<class T> inline boost::uint64_t read64le( T* p )
template<class T> inline std::uint64_t read64le( T* p )
{
boost::uint64_t w;
std::uint64_t w;
std::memcpy( &w, p, 8 );
return w;
@@ -246,9 +244,9 @@ template<class T> inline boost::uint64_t read64le( T* p )
#endif
template<class It>
inline typename boost::enable_if_<
inline typename std::enable_if<
is_char_type<typename std::iterator_traits<It>::value_type>::value &&
is_same<typename std::iterator_traits<It>::iterator_category, std::random_access_iterator_tag>::value &&
std::is_same<typename std::iterator_traits<It>::iterator_category, std::random_access_iterator_tag>::value &&
(std::numeric_limits<std::size_t>::digits > 32),
std::size_t>::type
hash_range( std::size_t seed, It first, It last )
@@ -256,15 +254,15 @@ std::size_t>::type
It p = first;
std::size_t n = static_cast<std::size_t>( last - first );
boost::uint64_t const q = static_cast<boost::uint64_t>( 0x9e3779b9 ) << 32 | 0x7f4a7c15;
boost::uint64_t const k = static_cast<boost::uint64_t>( 0xdf442d22 ) << 32 | 0xce4859b9; // q * q
std::uint64_t const q = 0x9e3779b97f4a7c15;
std::uint64_t const k = 0xdf442d22ce4859b9; // q * q
boost::uint64_t w = mulx( seed + q, k );
boost::uint64_t h = w ^ n;
std::uint64_t w = mulx( seed + q, k );
std::uint64_t h = w ^ n;
while( n >= 8 )
{
boost::uint64_t v1 = read64le( p );
std::uint64_t v1 = read64le( p );
w += q;
h ^= mulx( v1 + w, k );
@@ -274,11 +272,11 @@ std::size_t>::type
}
{
boost::uint64_t v1 = 0;
std::uint64_t v1 = 0;
if( n >= 4 )
{
v1 = static_cast<boost::uint64_t>( read32le( p + static_cast<std::ptrdiff_t>( n - 4 ) ) ) << ( n - 4 ) * 8 | read32le( p );
v1 = static_cast<std::uint64_t>( read32le( p + static_cast<std::ptrdiff_t>( n - 4 ) ) ) << ( n - 4 ) * 8 | read32le( p );
}
else if( n >= 1 )
{
@@ -286,9 +284,9 @@ std::size_t>::type
std::size_t const x2 = n >> 1; // 1: 0, 2: 1, 3: 1
v1 =
static_cast<boost::uint64_t>( static_cast<unsigned char>( p[ static_cast<std::ptrdiff_t>( x1 ) ] ) ) << x1 * 8 |
static_cast<boost::uint64_t>( static_cast<unsigned char>( p[ static_cast<std::ptrdiff_t>( x2 ) ] ) ) << x2 * 8 |
static_cast<boost::uint64_t>( static_cast<unsigned char>( p[ 0 ] ) );
static_cast<std::uint64_t>( static_cast<unsigned char>( p[ static_cast<std::ptrdiff_t>( x1 ) ] ) ) << x1 * 8 |
static_cast<std::uint64_t>( static_cast<unsigned char>( p[ static_cast<std::ptrdiff_t>( x2 ) ] ) ) << x2 * 8 |
static_cast<std::uint64_t>( static_cast<unsigned char>( p[ 0 ] ) );
}
w += q;
@@ -299,22 +297,22 @@ std::size_t>::type
}
template<class It>
inline typename boost::enable_if_<
inline typename std::enable_if<
is_char_type<typename std::iterator_traits<It>::value_type>::value &&
!is_same<typename std::iterator_traits<It>::iterator_category, std::random_access_iterator_tag>::value &&
!std::is_same<typename std::iterator_traits<It>::iterator_category, std::random_access_iterator_tag>::value &&
(std::numeric_limits<std::size_t>::digits > 32),
std::size_t>::type
hash_range( std::size_t seed, It first, It last )
{
std::size_t n = 0;
boost::uint64_t const q = static_cast<boost::uint64_t>( 0x9e3779b9 ) << 32 | 0x7f4a7c15;
boost::uint64_t const k = static_cast<boost::uint64_t>( 0xdf442d22 ) << 32 | 0xce4859b9; // q * q
std::uint64_t const q = 0x9e3779b97f4a7c15;
std::uint64_t const k = 0xdf442d22ce4859b9; // q * q
boost::uint64_t w = mulx( seed + q, k );
boost::uint64_t h = w;
std::uint64_t w = mulx( seed + q, k );
std::uint64_t h = w;
boost::uint64_t v1 = 0;
std::uint64_t v1 = 0;
for( ;; )
{
@@ -325,7 +323,7 @@ std::size_t>::type
break;
}
v1 |= static_cast<boost::uint64_t>( static_cast<unsigned char>( *first ) );
v1 |= static_cast<std::uint64_t>( static_cast<unsigned char>( *first ) );
++first;
++n;
@@ -334,7 +332,7 @@ std::size_t>::type
break;
}
v1 |= static_cast<boost::uint64_t>( static_cast<unsigned char>( *first ) ) << 8;
v1 |= static_cast<std::uint64_t>( static_cast<unsigned char>( *first ) ) << 8;
++first;
++n;
@@ -343,7 +341,7 @@ std::size_t>::type
break;
}
v1 |= static_cast<boost::uint64_t>( static_cast<unsigned char>( *first ) ) << 16;
v1 |= static_cast<std::uint64_t>( static_cast<unsigned char>( *first ) ) << 16;
++first;
++n;
@@ -352,7 +350,7 @@ std::size_t>::type
break;
}
v1 |= static_cast<boost::uint64_t>( static_cast<unsigned char>( *first ) ) << 24;
v1 |= static_cast<std::uint64_t>( static_cast<unsigned char>( *first ) ) << 24;
++first;
++n;
@@ -361,7 +359,7 @@ std::size_t>::type
break;
}
v1 |= static_cast<boost::uint64_t>( static_cast<unsigned char>( *first ) ) << 32;
v1 |= static_cast<std::uint64_t>( static_cast<unsigned char>( *first ) ) << 32;
++first;
++n;
@@ -370,7 +368,7 @@ std::size_t>::type
break;
}
v1 |= static_cast<boost::uint64_t>( static_cast<unsigned char>( *first ) ) << 40;
v1 |= static_cast<std::uint64_t>( static_cast<unsigned char>( *first ) ) << 40;
++first;
++n;
@@ -379,7 +377,7 @@ std::size_t>::type
break;
}
v1 |= static_cast<boost::uint64_t>( static_cast<unsigned char>( *first ) ) << 48;
v1 |= static_cast<std::uint64_t>( static_cast<unsigned char>( *first ) ) << 48;
++first;
++n;
@@ -388,7 +386,7 @@ std::size_t>::type
break;
}
v1 |= static_cast<boost::uint64_t>( static_cast<unsigned char>( *first ) ) << 56;
v1 |= static_cast<std::uint64_t>( static_cast<unsigned char>( *first ) ) << 56;
++first;
++n;

View File

@@ -9,17 +9,8 @@
#include <boost/container_hash/hash_fwd.hpp>
#include <boost/container_hash/is_tuple_like.hpp>
#include <boost/container_hash/is_range.hpp>
#include <boost/type_traits/enable_if.hpp>
#include <boost/config.hpp>
#include <boost/config/workaround.hpp>
#if defined(BOOST_NO_CXX11_HDR_TUPLE)
// no support for tuple-likes
#else
#include <tuple>
#include <type_traits>
#include <utility>
namespace boost
{
@@ -28,14 +19,14 @@ namespace hash_detail
template <std::size_t I, typename T>
inline
typename boost::enable_if_<(I == std::tuple_size<T>::value), void>::type
typename std::enable_if<(I == std::tuple_size<T>::value), void>::type
hash_combine_tuple_like( 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
typename std::enable_if<(I < std::tuple_size<T>::value), void>::type
hash_combine_tuple_like( std::size_t& seed, T const& v )
{
using std::get;
@@ -56,13 +47,9 @@ inline std::size_t hash_tuple_like( T const& v )
} // namespace hash_detail
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
#if !BOOST_WORKAROUND(BOOST_MSVC, <= 1800)
template <class T>
inline
typename boost::enable_if_<
typename std::enable_if<
container_hash::is_tuple_like<T>::value && !container_hash::is_range<T>::value,
std::size_t>::type
hash_value( T const& v )
@@ -70,87 +57,6 @@ std::size_t>::type
return boost::hash_detail::hash_tuple_like( v );
}
#else
template <typename... T>
inline std::size_t hash_value( std::tuple<T...> const& v )
{
return boost::hash_detail::hash_tuple_like( v );
}
#endif
#else
inline std::size_t hash_value( std::tuple<> const& v )
{
return boost::hash_detail::hash_tuple_like( v );
}
template<typename A0>
inline std::size_t hash_value( std::tuple<A0> const& v )
{
return boost::hash_detail::hash_tuple_like( v );
}
template<typename A0, typename A1>
inline std::size_t hash_value( std::tuple<A0, A1> const& v )
{
return boost::hash_detail::hash_tuple_like( 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_like( 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_like( 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_like( 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_like( 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_like( 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_like( 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_like( 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_like( 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

@@ -5,7 +5,7 @@
#ifndef BOOST_HASH_DETAIL_MULX_HPP
#define BOOST_HASH_DETAIL_MULX_HPP
#include <boost/cstdint.hpp>
#include <cstdint>
#if defined(_MSC_VER)
# include <intrin.h>
#endif
@@ -17,55 +17,55 @@ namespace hash_detail
#if defined(_MSC_VER) && defined(_M_X64) && !defined(__clang__)
__forceinline boost::uint64_t mulx( boost::uint64_t x, boost::uint64_t y )
__forceinline std::uint64_t mulx( std::uint64_t x, std::uint64_t y )
{
boost::uint64_t r2;
boost::uint64_t r = _umul128( x, y, &r2 );
std::uint64_t r2;
std::uint64_t r = _umul128( x, y, &r2 );
return r ^ r2;
}
#elif defined(_MSC_VER) && defined(_M_ARM64) && !defined(__clang__)
__forceinline boost::uint64_t mulx( boost::uint64_t x, boost::uint64_t y )
__forceinline std::uint64_t mulx( std::uint64_t x, std::uint64_t y )
{
boost::uint64_t r = x * y;
boost::uint64_t r2 = __umulh( x, y );
std::uint64_t r = x * y;
std::uint64_t r2 = __umulh( x, y );
return r ^ r2;
}
#elif defined(__SIZEOF_INT128__)
inline boost::uint64_t mulx( boost::uint64_t x, boost::uint64_t y )
inline std::uint64_t mulx( std::uint64_t x, std::uint64_t y )
{
__uint128_t r = static_cast<__uint128_t>( x ) * y;
return static_cast<boost::uint64_t>( r ) ^ static_cast<boost::uint64_t>( r >> 64 );
return static_cast<std::uint64_t>( r ) ^ static_cast<std::uint64_t>( r >> 64 );
}
#else
inline boost::uint64_t mulx( boost::uint64_t x, boost::uint64_t y )
inline std::uint64_t mulx( std::uint64_t x, std::uint64_t y )
{
boost::uint64_t x1 = static_cast<boost::uint32_t>( x );
boost::uint64_t x2 = x >> 32;
std::uint64_t x1 = static_cast<std::uint32_t>( x );
std::uint64_t x2 = x >> 32;
boost::uint64_t y1 = static_cast<boost::uint32_t>( y );
boost::uint64_t y2 = y >> 32;
std::uint64_t y1 = static_cast<std::uint32_t>( y );
std::uint64_t y2 = y >> 32;
boost::uint64_t r3 = x2 * y2;
std::uint64_t r3 = x2 * y2;
boost::uint64_t r2a = x1 * y2;
std::uint64_t r2a = x1 * y2;
r3 += r2a >> 32;
boost::uint64_t r2b = x2 * y1;
std::uint64_t r2b = x2 * y1;
r3 += r2b >> 32;
boost::uint64_t r1 = x1 * y1;
std::uint64_t r1 = x1 * y1;
boost::uint64_t r2 = (r1 >> 32) + static_cast<boost::uint32_t>( r2a ) + static_cast<boost::uint32_t>( r2b );
std::uint64_t r2 = (r1 >> 32) + static_cast<std::uint32_t>( r2a ) + static_cast<std::uint32_t>( r2b );
r1 = (r2 << 32) + static_cast<boost::uint32_t>( r1 );
r1 = (r2 << 32) + static_cast<std::uint32_t>( r1 );
r3 += r2 >> 32;
return r1 ^ r3;

View File

@@ -1,22 +0,0 @@
#ifndef BOOST_HASH_DETAIL_REQUIRES_CXX11_HPP_INCLUDED
#define BOOST_HASH_DETAIL_REQUIRES_CXX11_HPP_INCLUDED
// Copyright 2023 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/config.hpp>
#include <boost/config/pragma_message.hpp>
#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || \
defined(BOOST_NO_CXX11_RVALUE_REFERENCES) || \
defined(BOOST_NO_CXX11_DECLTYPE) || \
defined(BOOST_NO_CXX11_CONSTEXPR) || \
defined(BOOST_NO_CXX11_NOEXCEPT) || \
defined(BOOST_NO_CXX11_HDR_TUPLE)
BOOST_PRAGMA_MESSAGE("C++03 support was deprecated in Boost.ContainerHash 1.82 and will be removed in Boost.ContainerHash 1.84. Please open an issue in https://github.com/boostorg/container_hash if you want it retained.")
#endif
#endif // #ifndef BOOST_HASH_DETAIL_REQUIRES_CXX11_HPP_INCLUDED

View File

@@ -1,5 +1,5 @@
// Copyright 2005-2014 Daniel James.
// Copyright 2021, 2022 Peter Dimov.
// Copyright 2021, 2022, 2025 Peter Dimov.
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
@@ -11,27 +11,19 @@
#define BOOST_FUNCTIONAL_HASH_HASH_HPP
#include <boost/container_hash/hash_fwd.hpp>
#include <boost/container_hash/detail/requires_cxx11.hpp>
#include <boost/container_hash/hash_is_avalanching.hpp>
#include <boost/container_hash/is_range.hpp>
#include <boost/container_hash/is_contiguous_range.hpp>
#include <boost/container_hash/is_unordered_range.hpp>
#include <boost/container_hash/is_described_class.hpp>
#include <boost/container_hash/detail/hash_integral.hpp>
#include <boost/container_hash/detail/hash_tuple_like.hpp>
#include <boost/container_hash/detail/hash_mix.hpp>
#include <boost/container_hash/detail/hash_range.hpp>
#include <boost/type_traits/is_enum.hpp>
#include <boost/type_traits/is_integral.hpp>
#include <boost/type_traits/is_floating_point.hpp>
#include <boost/type_traits/is_signed.hpp>
#include <boost/type_traits/is_unsigned.hpp>
#include <boost/type_traits/make_unsigned.hpp>
#include <boost/type_traits/enable_if.hpp>
#include <boost/type_traits/conjunction.hpp>
#include <boost/type_traits/is_union.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/describe/bases.hpp>
#include <boost/describe/members.hpp>
#include <boost/cstdint.hpp>
#include <type_traits>
#include <cstdint>
#if defined(BOOST_DESCRIBE_CXX14)
# include <boost/mp11/algorithm.hpp>
@@ -77,95 +69,12 @@ namespace boost
//
// integral types
namespace hash_detail
{
template<class T,
bool bigger_than_size_t = (sizeof(T) > sizeof(std::size_t)),
bool is_unsigned = boost::is_unsigned<T>::value,
std::size_t size_t_bits = sizeof(std::size_t) * CHAR_BIT,
std::size_t type_bits = sizeof(T) * CHAR_BIT>
struct hash_integral_impl;
template<class T, bool is_unsigned, std::size_t size_t_bits, std::size_t type_bits> struct hash_integral_impl<T, false, is_unsigned, size_t_bits, type_bits>
{
static std::size_t fn( T v )
{
return static_cast<std::size_t>( v );
}
};
template<class T, std::size_t size_t_bits, std::size_t type_bits> struct hash_integral_impl<T, true, false, size_t_bits, type_bits>
{
static std::size_t fn( T v )
{
typedef typename boost::make_unsigned<T>::type U;
if( v >= 0 )
{
return hash_integral_impl<U>::fn( static_cast<U>( v ) );
}
else
{
return ~hash_integral_impl<U>::fn( static_cast<U>( ~static_cast<U>( v ) ) );
}
}
};
template<class T> struct hash_integral_impl<T, true, true, 32, 64>
{
static std::size_t fn( T v )
{
std::size_t seed = 0;
seed = static_cast<std::size_t>( v >> 32 ) + hash_detail::hash_mix( seed );
seed = static_cast<std::size_t>( v & 0xFFFFFFFF ) + hash_detail::hash_mix( seed );
return seed;
}
};
template<class T> struct hash_integral_impl<T, true, true, 32, 128>
{
static std::size_t fn( T v )
{
std::size_t seed = 0;
seed = static_cast<std::size_t>( v >> 96 ) + hash_detail::hash_mix( seed );
seed = static_cast<std::size_t>( v >> 64 ) + hash_detail::hash_mix( seed );
seed = static_cast<std::size_t>( v >> 32 ) + hash_detail::hash_mix( seed );
seed = static_cast<std::size_t>( v ) + hash_detail::hash_mix( seed );
return seed;
}
};
template<class T> struct hash_integral_impl<T, true, true, 64, 128>
{
static std::size_t fn( T v )
{
std::size_t seed = 0;
seed = static_cast<std::size_t>( v >> 64 ) + hash_detail::hash_mix( seed );
seed = static_cast<std::size_t>( v ) + hash_detail::hash_mix( seed );
return seed;
}
};
} // namespace hash_detail
template <typename T>
typename boost::enable_if_<boost::is_integral<T>::value, std::size_t>::type
hash_value( T v )
{
return hash_detail::hash_integral_impl<T>::fn( v );
}
// in detail/hash_integral.hpp
// enumeration types
template <typename T>
typename boost::enable_if_<boost::is_enum<T>::value, std::size_t>::type
typename std::enable_if<std::is_enum<T>::value, std::size_t>::type
hash_value( T v )
{
// This should in principle return the equivalent of
@@ -199,7 +108,7 @@ namespace boost
{
static std::size_t fn( T v )
{
boost::uint32_t w;
std::uint32_t w;
std::memcpy( &w, &v, sizeof( v ) );
return w;
@@ -211,7 +120,7 @@ namespace boost
{
static std::size_t fn( T v )
{
boost::uint64_t w;
std::uint64_t w;
std::memcpy( &w, &v, sizeof( v ) );
return hash_value( w );
@@ -223,7 +132,7 @@ namespace boost
{
static std::size_t fn( T v )
{
boost::uint64_t w[ 2 ] = {};
std::uint64_t w[ 2 ] = {};
std::memcpy( &w, &v, 80 / CHAR_BIT );
std::size_t seed = 0;
@@ -240,7 +149,7 @@ namespace boost
{
static std::size_t fn( T v )
{
boost::uint64_t w[ 2 ] = {};
std::uint64_t w[ 2 ] = {};
std::memcpy( &w, &v, 80 / CHAR_BIT );
std::size_t seed = 0;
@@ -257,7 +166,7 @@ namespace boost
{
static std::size_t fn( T v )
{
boost::uint64_t w[ 2 ];
std::uint64_t w[ 2 ];
std::memcpy( &w, &v, sizeof( v ) );
std::size_t seed = 0;
@@ -280,7 +189,7 @@ namespace boost
} // namespace hash_detail
template <typename T>
typename boost::enable_if_<boost::is_floating_point<T>::value, std::size_t>::type
typename std::enable_if<std::is_floating_point<T>::value, std::size_t>::type
hash_value( T v )
{
return boost::hash_detail::hash_float_impl<T>::fn( v + 0 );
@@ -291,7 +200,7 @@ namespace boost
// `x + (x >> 3)` adjustment by Alberto Barbati and Dave Harris.
template <class T> std::size_t hash_value( T* const& v )
{
boost::uintptr_t x = reinterpret_cast<boost::uintptr_t>( v );
std::uintptr_t x = reinterpret_cast<std::uintptr_t>( v );
return boost::hash_value( x + (x >> 3) );
}
@@ -336,7 +245,7 @@ namespace boost
// ranges (list, set, deque...)
template <typename T>
typename boost::enable_if_<container_hash::is_range<T>::value && !container_hash::is_contiguous_range<T>::value && !container_hash::is_unordered_range<T>::value, std::size_t>::type
typename std::enable_if<container_hash::is_range<T>::value && !container_hash::is_contiguous_range<T>::value && !container_hash::is_unordered_range<T>::value, std::size_t>::type
hash_value( T const& v )
{
return boost::hash_range( v.begin(), v.end() );
@@ -345,7 +254,7 @@ namespace boost
// contiguous ranges (string, vector, array)
template <typename T>
typename boost::enable_if_<container_hash::is_contiguous_range<T>::value, std::size_t>::type
typename std::enable_if<container_hash::is_contiguous_range<T>::value, std::size_t>::type
hash_value( T const& v )
{
return boost::hash_range( v.data(), v.data() + v.size() );
@@ -354,7 +263,7 @@ namespace boost
// unordered ranges (unordered_set, unordered_map)
template <typename T>
typename boost::enable_if_<container_hash::is_unordered_range<T>::value, std::size_t>::type
typename std::enable_if<container_hash::is_unordered_range<T>::value, std::size_t>::type
hash_value( T const& v )
{
return boost::hash_unordered_range( v.begin(), v.end() );
@@ -367,7 +276,7 @@ namespace boost
// resolve ambiguity with unconstrained stdext::hash_value in <xhash> :-/
template<template<class...> class L, class... T>
typename boost::enable_if_<container_hash::is_range<L<T...>>::value && !container_hash::is_contiguous_range<L<T...>>::value && !container_hash::is_unordered_range<L<T...>>::value, std::size_t>::type
typename std::enable_if<container_hash::is_range<L<T...>>::value && !container_hash::is_contiguous_range<L<T...>>::value && !container_hash::is_unordered_range<L<T...>>::value, std::size_t>::type
hash_value( L<T...> const& v )
{
return boost::hash_range( v.begin(), v.end() );
@@ -376,14 +285,14 @@ namespace boost
// contiguous ranges (string, vector, array)
template<template<class...> class L, class... T>
typename boost::enable_if_<container_hash::is_contiguous_range<L<T...>>::value, std::size_t>::type
typename std::enable_if<container_hash::is_contiguous_range<L<T...>>::value, std::size_t>::type
hash_value( L<T...> const& v )
{
return boost::hash_range( v.data(), v.data() + v.size() );
}
template<template<class, std::size_t> class L, class T, std::size_t N>
typename boost::enable_if_<container_hash::is_contiguous_range<L<T, N>>::value, std::size_t>::type
typename std::enable_if<container_hash::is_contiguous_range<L<T, N>>::value, std::size_t>::type
hash_value( L<T, N> const& v )
{
return boost::hash_range( v.data(), v.data() + v.size() );
@@ -392,7 +301,7 @@ namespace boost
// unordered ranges (unordered_set, unordered_map)
template<template<class...> class L, class... T>
typename boost::enable_if_<container_hash::is_unordered_range<L<T...>>::value, std::size_t>::type
typename std::enable_if<container_hash::is_unordered_range<L<T...>>::value, std::size_t>::type
hash_value( L<T...> const& v )
{
return boost::hash_unordered_range( v.begin(), v.end() );
@@ -410,10 +319,10 @@ namespace boost
#endif
template <typename T>
typename boost::enable_if_<container_hash::is_described_class<T>::value, std::size_t>::type
typename std::enable_if<container_hash::is_described_class<T>::value, std::size_t>::type
hash_value( T const& v )
{
static_assert( !boost::is_union<T>::value, "described unions are not supported" );
static_assert( !std::is_union<T>::value, "described unions are not supported" );
std::size_t r = 0;
@@ -503,7 +412,7 @@ namespace boost
#if !defined(BOOST_NO_CXX11_NULLPTR)
template <typename T>
typename boost::enable_if_<boost::is_same<T, std::nullptr_t>::value, std::size_t>::type
typename std::enable_if<std::is_same<T, std::nullptr_t>::value, std::size_t>::type
hash_value( T const& /*v*/ )
{
return boost::hash_value( static_cast<void*>( nullptr ) );
@@ -520,7 +429,7 @@ namespace boost
{
if( !v )
{
// Arbitray value for empty optional.
// Arbitrary value for empty optional.
return 0x12345678;
}
else
@@ -649,28 +558,15 @@ namespace boost
#endif
// boost::unordered::hash_is_avalanching
// hash_is_avalanching
namespace unordered
{
template<class T> struct hash_is_avalanching;
template<class Ch> struct hash_is_avalanching< boost::hash< std::basic_string<Ch> > >: boost::is_integral<Ch> {};
// boost::is_integral<char8_t> is false, but should be true (https://github.com/boostorg/type_traits/issues/175)
#if defined(__cpp_char8_t) && __cpp_char8_t >= 201811L
template<> struct hash_is_avalanching< boost::hash< std::basic_string<char8_t> > >: boost::true_type {};
#endif
template<class Ch> struct hash_is_avalanching< boost::hash< std::basic_string<Ch> > >: std::is_integral<Ch> {};
#if !defined(BOOST_NO_CXX17_HDR_STRING_VIEW)
template<class Ch> struct hash_is_avalanching< boost::hash< std::basic_string_view<Ch> > >: boost::is_integral<Ch> {};
#if defined(__cpp_char8_t) && __cpp_char8_t >= 201811L
template<> struct hash_is_avalanching< boost::hash< std::basic_string_view<char8_t> > >: boost::true_type {};
#endif
template<class Ch> struct hash_is_avalanching< boost::hash< std::basic_string_view<Ch> > >: std::is_integral<Ch> {};
#endif
} // namespace unordered
} // namespace boost

View File

@@ -1,5 +1,5 @@
// Copyright 2005-2009 Daniel James.
// Copyright 2021, 2022 Peter Dimov.
// Copyright 2021, 2022, 2025 Peter Dimov.
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
@@ -32,6 +32,8 @@ template<class It> std::size_t hash_range( It, It );
template<class It> void hash_unordered_range( std::size_t&, It, It );
template<class It> std::size_t hash_unordered_range( It, It );
template<class Hash> struct hash_is_avalanching;
} // namespace boost
#endif // #ifndef BOOST_FUNCTIONAL_HASH_FWD_HPP

View File

@@ -0,0 +1,57 @@
// Copyright 2025 Joaquin M Lopez Munoz.
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#ifndef BOOST_HASH_HASH_IS_AVALANCHING_HPP_INCLUDED
#define BOOST_HASH_HASH_IS_AVALANCHING_HPP_INCLUDED
#include <type_traits>
namespace boost
{
namespace hash_detail
{
template<class... Ts> struct make_void
{
using type = void;
};
template<class... Ts> using void_t = typename make_void<Ts...>::type;
template<class IsAvalanching> struct avalanching_value
{
static constexpr bool value = IsAvalanching::value;
};
// may be explicitly marked as BOOST_DEPRECATED in the future
template<> struct avalanching_value<void>
{
static constexpr bool value = true;
};
template<class Hash, class = void> struct hash_is_avalanching_impl: std::false_type
{
};
template<class Hash> struct hash_is_avalanching_impl<Hash, void_t<typename Hash::is_avalanching> >:
std::integral_constant<bool, avalanching_value<typename Hash::is_avalanching>::value>
{
};
template<class Hash>
struct hash_is_avalanching_impl<Hash, typename std::enable_if< ((void)Hash::is_avalanching, true) >::type>
{
// Hash::is_avalanching is not a type: we don't define value to produce
// a compile error downstream
};
} // namespace hash_detail
template<class Hash> struct hash_is_avalanching: hash_detail::hash_is_avalanching_impl<Hash>::type
{
};
} // namespace boost
#endif // #ifndef BOOST_HASH_HASH_IS_AVALANCHING_HPP_INCLUDED

View File

@@ -5,17 +5,13 @@
#ifndef BOOST_HASH_IS_CONTIGUOUS_RANGE_HPP_INCLUDED
#define BOOST_HASH_IS_CONTIGUOUS_RANGE_HPP_INCLUDED
#include <boost/container_hash/detail/requires_cxx11.hpp>
#include <boost/container_hash/is_range.hpp>
#include <boost/type_traits/integral_constant.hpp>
#include <boost/config.hpp>
#include <boost/config/workaround.hpp>
#include <type_traits>
#if !defined(BOOST_NO_CXX11_DECLTYPE) && !defined(BOOST_NO_SFINAE_EXPR) && !BOOST_WORKAROUND(BOOST_GCC, < 40700) && !BOOST_WORKAROUND(BOOST_MSVC, < 1910)
#if !BOOST_WORKAROUND(BOOST_MSVC, < 1910)
#include <boost/type_traits/is_integral.hpp>
#include <boost/type_traits/declval.hpp>
#include <boost/type_traits/is_same.hpp>
#include <iterator>
namespace boost
@@ -24,11 +20,11 @@ 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 >
std::integral_constant< bool, std::is_same<typename std::iterator_traits<It>::value_type, T>::value && std::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> decltype( is_contiguous_range_check( std::declval<T const&>().begin(), std::declval<T const&>().end(), std::declval<T const&>().data(), std::declval<T const&>().data() + std::declval<T const&>().size(), std::declval<T const&>().size() ) ) is_contiguous_range_( int );
template<class T> std::false_type is_contiguous_range_( ... );
template<class T> struct is_contiguous_range: decltype( hash_detail::is_contiguous_range_<T>( 0 ) )
{
@@ -39,54 +35,64 @@ template<class T> struct is_contiguous_range: decltype( hash_detail::is_contiguo
namespace container_hash
{
template<class T> struct is_contiguous_range: integral_constant< bool, is_range<T>::value && hash_detail::is_contiguous_range<T>::value >
template<class T> struct is_contiguous_range: std::integral_constant< bool, is_range<T>::value && hash_detail::is_contiguous_range<T>::value >
{
};
} // namespace container_hash
} // namespace boost
#else // !defined(BOOST_NO_CXX11_DECLTYPE) && !defined(BOOST_NO_SFINAE_EXPR)
#else // !BOOST_WORKAROUND(BOOST_MSVC, < 1910)
#include <cstddef>
#include <vector>
#include <string>
#if !defined(BOOST_NO_CXX11_HDR_ARRAY)
#include <array>
#endif
namespace boost
{
namespace container_hash
{
template<class T> struct is_contiguous_range: false_type
template<class T> struct is_contiguous_range: std::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> >: std::true_type
{
};
template<class E, class T, class A> struct is_contiguous_range< std::basic_string<E, T, A> const >: true_type
template<class E, class T, class A> struct is_contiguous_range< std::basic_string<E, T, A> const >: std::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, class A> struct is_contiguous_range< std::vector<T, A> >: std::true_type
{
};
template<class T, std::size_t N> struct is_contiguous_range< std::array<T, N> const >: true_type
template<class T, class A> struct is_contiguous_range< std::vector<T, A> const >: std::true_type
{
};
#endif
template<class A> struct is_contiguous_range< std::vector<bool, A> >: std::false_type
{
};
template<class A> struct is_contiguous_range< std::vector<bool, A> const >: std::false_type
{
};
template<class T, std::size_t N> struct is_contiguous_range< std::array<T, N> >: std::true_type
{
};
template<class T, std::size_t N> struct is_contiguous_range< std::array<T, N> const >: std::true_type
{
};
} // namespace container_hash
} // namespace boost
#endif // !defined(BOOST_NO_CXX11_DECLTYPE) && !defined(BOOST_NO_SFINAE_EXPR)
#endif // !BOOST_WORKAROUND(BOOST_MSVC, < 1910)
#endif // #ifndef BOOST_HASH_IS_CONTIGUOUS_RANGE_HPP_INCLUDED

View File

@@ -5,10 +5,9 @@
#ifndef BOOST_HASH_IS_DESCRIBED_CLASS_HPP_INCLUDED
#define BOOST_HASH_IS_DESCRIBED_CLASS_HPP_INCLUDED
#include <boost/type_traits/integral_constant.hpp>
#include <boost/type_traits/is_union.hpp>
#include <boost/describe/bases.hpp>
#include <boost/describe/members.hpp>
#include <type_traits>
namespace boost
{
@@ -17,16 +16,16 @@ namespace container_hash
#if defined(BOOST_DESCRIBE_CXX11)
template<class T> struct is_described_class: boost::integral_constant<bool,
template<class T> struct is_described_class: std::integral_constant<bool,
describe::has_describe_bases<T>::value &&
describe::has_describe_members<T>::value &&
!boost::is_union<T>::value>
!std::is_union<T>::value>
{
};
#else
template<class T> struct is_described_class: boost::false_type
template<class T> struct is_described_class: std::false_type
{
};

View File

@@ -5,29 +5,25 @@
#ifndef BOOST_HASH_IS_RANGE_HPP_INCLUDED
#define BOOST_HASH_IS_RANGE_HPP_INCLUDED
#include <boost/container_hash/detail/requires_cxx11.hpp>
#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>
#include <type_traits>
namespace boost
{
#if !defined(BOOST_NO_CXX11_DECLTYPE) && !defined(BOOST_NO_SFINAE_EXPR) && !BOOST_WORKAROUND(BOOST_GCC, < 40700)
namespace hash_detail
{
template<class T> struct iterator_traits: std::iterator_traits<T> {};
template<> struct iterator_traits< void* > {};
template<> struct iterator_traits< void const* > {};
template<class T, class It>
integral_constant< bool, !is_same<typename remove_cv<T>::type, typename std::iterator_traits<It>::value_type>::value >
std::integral_constant< bool, !std::is_same<typename std::remove_cv<T>::type, typename 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> decltype( is_range_check<T>( std::declval<T const&>().begin(), std::declval<T const&>().end() ) ) is_range_( int );
template<class T> std::false_type is_range_( ... );
} // namespace hash_detail
@@ -40,35 +36,6 @@ template<class T> struct is_range: decltype( hash_detail::is_range_<T>( 0 ) )
} // namespace container_hash
#else
namespace hash_detail
{
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
{
};
} // namespace hash_detail
namespace container_hash
{
template<class T> struct is_range: hash_detail::is_range_<T>
{
};
} // namespace container_hash
#endif // !defined(BOOST_NO_CXX11_DECLTYPE) && !defined(BOOST_NO_SFINAE_EXPR)
} // namespace boost
#endif // #ifndef BOOST_HASH_IS_RANGE_HPP_INCLUDED

View File

@@ -5,9 +5,7 @@
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/type_traits/integral_constant.hpp>
#include <boost/config.hpp>
#include <boost/config/workaround.hpp>
#include <type_traits>
#include <utility>
namespace boost
@@ -15,24 +13,20 @@ namespace boost
namespace hash_detail
{
template<class T, class E = true_type> struct is_tuple_like_: false_type
template<class T, class E = std::true_type> struct is_tuple_like_: std::false_type
{
};
#if !defined(BOOST_NO_CXX11_HDR_TUPLE) && !BOOST_WORKAROUND(BOOST_MSVC, <= 1800)
template<class T> struct is_tuple_like_<T, integral_constant<bool, std::tuple_size<T>::value == std::tuple_size<T>::value> >: true_type
template<class T> struct is_tuple_like_<T, std::integral_constant<bool, std::tuple_size<T>::value == std::tuple_size<T>::value> >: std::true_type
{
};
#endif
} // namespace hash_detail
namespace container_hash
{
template<class T> struct is_tuple_like: hash_detail::is_tuple_like_<T>
template<class T> struct is_tuple_like: hash_detail::is_tuple_like_< typename std::remove_cv<T>::type >
{
};

View File

@@ -6,21 +6,20 @@
#define BOOST_HASH_IS_UNORDERED_RANGE_HPP_INCLUDED
#include <boost/container_hash/is_range.hpp>
#include <boost/type_traits/integral_constant.hpp>
#include <boost/type_traits/is_same.hpp>
#include <type_traits>
namespace boost
{
namespace hash_detail
{
template<class T, class E = true_type> struct has_hasher_: false_type
template<class T, class E = std::true_type> struct has_hasher_: std::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 has_hasher_< T, std::integral_constant< bool,
std::is_same<typename T::hasher, typename T::hasher>::value
> >: std::true_type
{
};
@@ -29,7 +28,7 @@ template<class T> struct has_hasher_< T, integral_constant< bool,
namespace container_hash
{
template<class T> struct is_unordered_range: integral_constant< bool, is_range<T>::value && hash_detail::has_hasher_<T>::value >
template<class T> struct is_unordered_range: std::integral_constant< bool, is_range<T>::value && hash_detail::has_hasher_<T>::value >
{
};

View File

@@ -7,7 +7,7 @@
"Daniel James"
],
"maintainers": [
"Daniel James <dnljms -at- gmail.com>"
"Peter Dimov <pdimov -at- gmail.com>"
],
"description": "An STL-compatible hash function object that can be extended to hash user defined types.",
"std": [
@@ -16,6 +16,6 @@
"category": [
"Function-objects"
],
"cxxstd": "03"
"cxxstd": "11"
}
]

View File

@@ -1,4 +1,4 @@
# Copyright 2018, 2019, 2021, 2022 Peter Dimov
# Copyright 2018, 2019, 2021, 2022, 2025 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
@@ -7,6 +7,6 @@ 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 Boost::unordered)
LINK_LIBRARIES Boost::container_hash Boost::core Boost::utility)
endif()

View File

@@ -1,5 +1,5 @@
# Copyright 2005-2012 Daniel James.
# Copyright 2022 Peter Dimov
# Copyright 2022, 2025 Peter Dimov
# Distributed under the Boost Software License, Version 1.0.
# https://www.boost.org/LICENSE_1_0.txt
@@ -10,6 +10,10 @@ local clang-flags = $(gcc-flags) -Wno-c99-extensions ;
project hash-tests
: requirements
<library>/boost/container_hash//boost_container_hash
<library>/boost/core//boost_core
<library>/boost/type_traits//boost_type_traits
<warnings>pedantic
<toolset>intel:<warnings>on
<toolset>gcc:<cxxflags>$(gcc-flags)
@@ -72,13 +76,15 @@ run quick.cpp ;
run hash_number_test2.cpp ;
run hash_integral_test.cpp ;
run hash_string_test2.cpp ;
run hash_string_test2.cpp
/boost/utility//boost_utility ;
# for gcc-4.8
local fs-path-req = "-<toolset>gcc:<cxxflags>-Wshadow" "-<toolset>gcc:<cxxflags>-Wconversion" ;
local fs-path-req = <library>/boost/filesystem//boost_filesystem/<warnings>off "-<toolset>gcc:<cxxflags>-Wshadow" "-<toolset>gcc:<cxxflags>-Wconversion" <toolset>gcc-4.7:<build>no <undefined-sanitizer>norecover:<link>static ;
run hash_fs_path_test.cpp /boost//filesystem/<warnings>off : : : $(fs-path-req) <toolset>msvc-14.0,<cxxstd>latest:<build>no <toolset>msvc-8.0:<build>no <undefined-sanitizer>norecover:<link>static ;
run is_range_test2.cpp : : : $(fs-path-req) <toolset>msvc-8.0:<build>no ;
run hash_fs_path_test.cpp : : : $(fs-path-req) <toolset>msvc-14.0,<cxxstd>latest:<build>no ;
run is_range_test2.cpp : : : $(fs-path-req) ;
run hash_container_test.cpp ;
@@ -115,6 +121,7 @@ run described_class_test.cpp
run hash_is_avalanching_test.cpp ;
run hash_is_avalanching_test2.cpp ;
run hash_is_avalanching_test3.cpp ;
run hash_integral_test2.cpp ;
@@ -125,3 +132,6 @@ run is_tuple_like_test.cpp ;
run hash_tuple_like_test.cpp ;
run hash_tuple_like_test2.cpp
: : : <warnings>extra ;
run is_range_test4.cpp ;
run hash_container_test2.cpp ;

View File

@@ -14,4 +14,4 @@ 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>)
add_custom_target(check VERBATIM COMMAND ${CMAKE_CTEST_COMMAND} --output-on-failure -C $<CONFIG>)

View File

@@ -9,8 +9,6 @@ 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_subdirectory(../../../describe boostorg/describe)
add_subdirectory(../../../mp11 boostorg/mp11)
@@ -20,4 +18,4 @@ 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>)
add_custom_target(check VERBATIM COMMAND ${CMAKE_CTEST_COMMAND} --output-on-failure -C $<CONFIG>)

View File

@@ -0,0 +1,39 @@
// Copyright 2024 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>
struct X1
{
void* begin() const { return nullptr; }
void* end() const { return nullptr; }
};
std::size_t hash_value( X1 const& )
{
return 1;
}
struct X2
{
void const* begin() const { return nullptr; }
void const* end() const { return nullptr; }
};
std::size_t hash_value( X2 const& )
{
return 2;
}
int main()
{
X1 x1;
BOOST_TEST_EQ( boost::hash<X1>()( x1 ), 1u );
X2 x2;
BOOST_TEST_EQ( boost::hash<X2>()( x2 ), 2u );
return boost::report_errors();
}

View File

@@ -3,6 +3,8 @@
// 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)
#define _SILENCE_CXX23_DENORM_DEPRECATION_WARNING
#include "hash_float_test.hpp"
int main()

View File

@@ -33,6 +33,11 @@
#pragma GCC diagnostic ignored "-Wfloat-equal"
#endif
#if defined(__clang__)
// P2614 deprecates has_denorm in C++23
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
#endif
char const* float_type(float*) { return "float"; }
char const* float_type(double*) { return "double"; }
char const* float_type(long double*) { return "long double"; }

View File

@@ -1,10 +1,10 @@
// Copyright 2022 Peter Dimov.
// Copyright 2022, 2025 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/container_hash/hash_is_avalanching.hpp>
#include <boost/core/lightweight_test_trait.hpp>
#include <boost/unordered/hash_traits.hpp>
#include <boost/config.hpp>
#include <string>
@@ -12,7 +12,7 @@ enum my_char { min = 0, max = 255 };
int main()
{
using boost::unordered::hash_is_avalanching;
using boost::hash_is_avalanching;
BOOST_TEST_TRAIT_TRUE(( hash_is_avalanching< boost::hash<std::string> > ));
BOOST_TEST_TRAIT_TRUE(( hash_is_avalanching< boost::hash<std::wstring> > ));

View File

@@ -1,8 +1,9 @@
// Copyright 2022 Peter Dimov.
// Copyright 2022, 2025 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/container_hash/hash_is_avalanching.hpp>
#include <boost/core/lightweight_test_trait.hpp>
#include <boost/config.hpp>
#include <boost/config/pragma_message.hpp>
@@ -14,14 +15,13 @@ int main() {}
#else
#include <boost/unordered/hash_traits.hpp>
#include <string_view>
enum my_char { min = 0, max = 255 };
int main()
{
using boost::unordered::hash_is_avalanching;
using boost::hash_is_avalanching;
BOOST_TEST_TRAIT_TRUE(( hash_is_avalanching< boost::hash<std::string_view> > ));
BOOST_TEST_TRAIT_TRUE(( hash_is_avalanching< boost::hash<std::wstring_view> > ));
@@ -44,7 +44,11 @@ int main()
#endif
#if defined(_LIBCPP_VERSION) && _LIBCPP_VERSION >= 160000
// std::char_traits<Ch> is deprecated for non-char types
#else
BOOST_TEST_TRAIT_FALSE(( hash_is_avalanching< boost::hash<std::basic_string_view<my_char> > > ));
#endif
return boost::report_errors();
}

View File

@@ -0,0 +1,38 @@
// Copyright 2025 Joaquin M Lopez Munoz.
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/container_hash/hash_is_avalanching.hpp>
#include <boost/core/lightweight_test_trait.hpp>
#include <type_traits>
struct X
{
using is_avalanching = void;
};
struct Y
{
using is_avalanching = std::true_type;
};
struct Z
{
using is_avalanching = std::false_type;
};
struct W
{
};
int main()
{
using boost::hash_is_avalanching;
BOOST_TEST_TRAIT_TRUE(( hash_is_avalanching< X > ));
BOOST_TEST_TRAIT_TRUE(( hash_is_avalanching< Y > ));
BOOST_TEST_TRAIT_FALSE(( hash_is_avalanching< Z > ));
BOOST_TEST_TRAIT_FALSE(( hash_is_avalanching< W > ));
return boost::report_errors();
}

View File

@@ -3,6 +3,8 @@
// 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)
#define _SILENCE_CXX23_DENORM_DEPRECATION_WARNING
#include "hash_float_test.hpp"
int main()

View File

@@ -50,11 +50,11 @@ int main()
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_WORKAROUND(BOOST_MSVC, < 1910)
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::vector<bool> >));
BOOST_TEST_TRAIT_FALSE((is_contiguous_range< std::vector<bool> const >));
BOOST_TEST_TRAIT_FALSE((is_contiguous_range< std::deque<X> >));
BOOST_TEST_TRAIT_FALSE((is_contiguous_range< std::deque<X> const >));

28
test/is_range_test4.cpp Normal file
View File

@@ -0,0 +1,28 @@
// Copyright 2024 Peter Dimov.
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/container_hash/is_range.hpp>
#include <boost/core/lightweight_test_trait.hpp>
struct X1
{
void* begin() const;
void* end() const;
};
struct X2
{
void const* begin() const;
void const* end() const;
};
int main()
{
using boost::container_hash::is_range;
BOOST_TEST_TRAIT_FALSE((is_range<X1>));
BOOST_TEST_TRAIT_FALSE((is_range<X2>));
return boost::report_errors();
}

View File

@@ -70,20 +70,36 @@ int main()
using boost::container_hash::is_tuple_like;
BOOST_TEST_TRAIT_FALSE((is_tuple_like<void>));
BOOST_TEST_TRAIT_FALSE((is_tuple_like<void const>));
BOOST_TEST_TRAIT_FALSE((is_tuple_like<int>));
BOOST_TEST_TRAIT_FALSE((is_tuple_like<int const>));
BOOST_TEST_TRAIT_FALSE((is_tuple_like<X>));
BOOST_TEST_TRAIT_FALSE((is_tuple_like<X const>));
BOOST_TEST_TRAIT_FALSE((is_tuple_like<int[2]>));
BOOST_TEST_TRAIT_FALSE((is_tuple_like<int const [2]>));
#if !defined(BOOST_NO_CXX11_HDR_TUPLE) && !BOOST_WORKAROUND(BOOST_MSVC, <= 1800)
BOOST_TEST_TRAIT_TRUE((is_tuple_like< std::pair<int, X> >));
BOOST_TEST_TRAIT_TRUE((is_tuple_like< std::pair<int, X> const>));
BOOST_TEST_TRAIT_TRUE((is_tuple_like< std::tuple<> >));
BOOST_TEST_TRAIT_TRUE((is_tuple_like< std::tuple<> const>));
BOOST_TEST_TRAIT_TRUE((is_tuple_like< std::tuple<X> >));
BOOST_TEST_TRAIT_TRUE((is_tuple_like< std::tuple<X> const>));
BOOST_TEST_TRAIT_TRUE((is_tuple_like< std::tuple<X, X> >));
BOOST_TEST_TRAIT_TRUE((is_tuple_like< std::tuple<X, X> const>));
BOOST_TEST_TRAIT_TRUE((is_tuple_like< std::tuple<X, X, X> >));
BOOST_TEST_TRAIT_TRUE((is_tuple_like< std::tuple<X, X, X> const>));
BOOST_TEST_TRAIT_TRUE((is_tuple_like<user::Y>));
BOOST_TEST_TRAIT_TRUE((is_tuple_like<user::Y const>));
#endif