Compare commits

...

68 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
Peter Dimov
226eb066e9 Update .drone.jsonnet 2023-06-29 14:38:53 +03:00
Peter Dimov
d9cb23d96a Update ci.yml 2023-06-29 11:50:12 +03:00
Peter Dimov
bd8a5cb867 Merge pull request #34 from ecatmur/libcxx-16
Fix libc++16 failures
2023-06-29 11:22:13 +03:00
Ed Catmur
b43ce472fa Fix libc++16 failures
Similar to de8fe4fad7
2023-06-28 11:12:42 -05:00
Peter Dimov
e798972130 Update C++03 deprecation message 2023-06-03 02:27:41 +03:00
Peter Dimov
ebb49fa459 Update ci.yml 2023-05-21 15:28:59 +03:00
Peter Dimov
1e1c0ea38c Update ci.yml 2023-05-21 04:08:58 +03:00
Peter Dimov
e62a268566 Update documentation 2023-04-05 17:34:08 +03:00
41 changed files with 1157 additions and 636 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,228 +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 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 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,144 +18,225 @@ 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"
os: ubuntu-20.04
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"
os: ubuntu-20.04
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: "11,14,17,20,2b"
container: ubuntu:24.04
os: ubuntu-latest
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
cxxstd: "03,11,14,17,2a"
os: macos-11
compiler: clang++-16
cxxstd: "11,14,17,20,2b"
container: ubuntu:24.04
os: ubuntu-latest
install: clang-16
- toolset: clang
cxxstd: "03,11,14,17,20,2b"
os: macos-12
compiler: clang++-17
cxxstd: "11,14,17,20,2b"
container: ubuntu:24.04
os: ubuntu-latest
install: clang-17
- toolset: clang
compiler: clang++-18
cxxstd: "11,14,17,20,2b"
container: ubuntu:24.04
os: ubuntu-latest
install: clang-18
- toolset: clang
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 python 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
run: sudo apt-get -y install ${{matrix.install}}
run: |
sudo apt-get update
sudo apt-get -y install ${{matrix.install}}
- name: Setup Boost
run: |
@@ -175,7 +256,7 @@ jobs:
cd boost-root
cp -r $GITHUB_WORKSPACE/* libs/$LIBRARY
git submodule update --init tools/boostdep
python tools/boostdep/depinst/depinst.py -I examples --git_args "--jobs 3" $LIBRARY
python3 tools/boostdep/depinst/depinst.py -I examples --git_args "--jobs 3" $LIBRARY
./bootstrap.sh
./b2 -d0 headers
@@ -196,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
@@ -213,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
@@ -256,15 +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
@@ -303,15 +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
@@ -360,15 +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
@@ -409,3 +485,183 @@ jobs:
run: |
cd ../boost-root/__build__
ctest --output-on-failure --no-tests=error
windows-cmake-subdir:
strategy:
fail-fast: false
matrix:
include:
- os: windows-2022
- os: windows-2025
runs-on: ${{matrix.os}}
steps:
- uses: actions/checkout@v4
- name: Setup Boost
shell: cmd
run: |
echo GITHUB_REPOSITORY: %GITHUB_REPOSITORY%
for /f %%i in ("%GITHUB_REPOSITORY%") do set LIBRARY=%%~nxi
echo LIBRARY: %LIBRARY%
echo LIBRARY=%LIBRARY%>>%GITHUB_ENV%
echo GITHUB_BASE_REF: %GITHUB_BASE_REF%
echo GITHUB_REF: %GITHUB_REF%
if "%GITHUB_BASE_REF%" == "" set GITHUB_BASE_REF=%GITHUB_REF%
set BOOST_BRANCH=develop
for /f %%i in ("%GITHUB_BASE_REF%") do if "%%~nxi" == "master" set BOOST_BRANCH=master
echo BOOST_BRANCH: %BOOST_BRANCH%
cd ..
git clone -b %BOOST_BRANCH% --depth 1 https://github.com/boostorg/boost.git boost-root
cd boost-root
xcopy /s /e /q %GITHUB_WORKSPACE% libs\%LIBRARY%\
git submodule update --init tools/boostdep
python tools/boostdep/depinst/depinst.py --git_args "--jobs 3" %LIBRARY%
- name: Use library with add_subdirectory (Debug)
shell: cmd
run: |
cd ../boost-root/libs/%LIBRARY%/test/cmake_subdir_test
mkdir __build__ && cd __build__
cmake ..
cmake --build . --config Debug
ctest --output-on-failure --no-tests=error -C Debug
- name: Use library with add_subdirectory (Release)
shell: cmd
run: |
cd ../boost-root/libs/%LIBRARY%/test/cmake_subdir_test/__build__
cmake --build . --config Release
ctest --output-on-failure --no-tests=error -C Release
windows-cmake-install:
strategy:
fail-fast: false
matrix:
include:
- os: windows-2022
- os: windows-2025
runs-on: ${{matrix.os}}
steps:
- uses: actions/checkout@v4
- name: Setup Boost
shell: cmd
run: |
echo GITHUB_REPOSITORY: %GITHUB_REPOSITORY%
for /f %%i in ("%GITHUB_REPOSITORY%") do set LIBRARY=%%~nxi
echo LIBRARY: %LIBRARY%
echo LIBRARY=%LIBRARY%>>%GITHUB_ENV%
echo GITHUB_BASE_REF: %GITHUB_BASE_REF%
echo GITHUB_REF: %GITHUB_REF%
if "%GITHUB_BASE_REF%" == "" set GITHUB_BASE_REF=%GITHUB_REF%
set BOOST_BRANCH=develop
for /f %%i in ("%GITHUB_BASE_REF%") do if "%%~nxi" == "master" set BOOST_BRANCH=master
echo BOOST_BRANCH: %BOOST_BRANCH%
cd ..
git clone -b %BOOST_BRANCH% --depth 1 https://github.com/boostorg/boost.git boost-root
cd boost-root
xcopy /s /e /q %GITHUB_WORKSPACE% libs\%LIBRARY%\
git submodule update --init tools/boostdep
python tools/boostdep/depinst/depinst.py --git_args "--jobs 3" %LIBRARY%
- name: Configure
shell: cmd
run: |
cd ../boost-root
mkdir __build__ && cd __build__
cmake -DBOOST_INCLUDE_LIBRARIES=%LIBRARY% -DCMAKE_INSTALL_PREFIX=C:/cmake-prefix ..
- name: Install (Debug)
shell: cmd
run: |
cd ../boost-root/__build__
cmake --build . --target install --config Debug
- name: Install (Release)
shell: cmd
run: |
cd ../boost-root/__build__
cmake --build . --target install --config Release
- name: Use the installed library (Debug)
shell: cmd
run: |
cd ../boost-root/libs/%LIBRARY%/test/cmake_install_test && mkdir __build__ && cd __build__
cmake -DCMAKE_INSTALL_PREFIX=C:/cmake-prefix ..
cmake --build . --config Debug
ctest --output-on-failure --no-tests=error -C Debug
- name: Use the installed library (Release)
shell: cmd
run: |
cd ../boost-root/libs/%LIBRARY%/test/cmake_install_test/__build__
cmake --build . --config Release
ctest --output-on-failure --no-tests=error -C Release
windows-cmake-test:
strategy:
fail-fast: false
matrix:
include:
- os: windows-2022
- os: windows-2025
runs-on: ${{matrix.os}}
steps:
- uses: actions/checkout@v4
- name: Setup Boost
shell: cmd
run: |
echo GITHUB_REPOSITORY: %GITHUB_REPOSITORY%
for /f %%i in ("%GITHUB_REPOSITORY%") do set LIBRARY=%%~nxi
echo LIBRARY: %LIBRARY%
echo LIBRARY=%LIBRARY%>>%GITHUB_ENV%
echo GITHUB_BASE_REF: %GITHUB_BASE_REF%
echo GITHUB_REF: %GITHUB_REF%
if "%GITHUB_BASE_REF%" == "" set GITHUB_BASE_REF=%GITHUB_REF%
set BOOST_BRANCH=develop
for /f %%i in ("%GITHUB_BASE_REF%") do if "%%~nxi" == "master" set BOOST_BRANCH=master
echo BOOST_BRANCH: %BOOST_BRANCH%
cd ..
git clone -b %BOOST_BRANCH% --depth 1 https://github.com/boostorg/boost.git boost-root
cd boost-root
xcopy /s /e /q %GITHUB_WORKSPACE% libs\%LIBRARY%\
git submodule update --init tools/boostdep
python tools/boostdep/depinst/depinst.py --git_args "--jobs 3" %LIBRARY%
- name: Configure
shell: cmd
run: |
cd ../boost-root
mkdir __build__ && cd __build__
cmake -DBOOST_INCLUDE_LIBRARIES=%LIBRARY% -DBUILD_TESTING=ON ..
- name: Build tests (Debug)
shell: cmd
run: |
cd ../boost-root/__build__
cmake --build . --target tests --config Debug
- name: Run tests (Debug)
shell: cmd
run: |
cd ../boost-root/__build__
ctest --output-on-failure --no-tests=error -C Debug
- name: Build tests (Release)
shell: cmd
run: |
cd ../boost-root/__build__
cmake --build . --target tests --config Release
- name: Run tests (Release)
shell: cmd
run: |
cd ../boost-root/__build__
ctest --output-on-failure --no-tests=error -C Release

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

@@ -55,6 +55,22 @@ to be templates constrained on e.g. `std::is_integral` or its moral
equivalent. This causes types convertible to an integral to no longer
match, avoiding the problem.
== Hash Value Stability
In general, the library does not promise that the hash values will stay
the same from release to release (otherwise improvements would be
impossible). However, historically values have been quite stable. Before
release 1.81, the previous changes have been in 1.56 (a better
`hash_combine`) and 1.78 (macOS-specific change to `hash_combine`.)
Code should generally not depend on specific hash values, but for those
willing to take the risk of occasional breaks due to hash value changes,
the library now has a test that checks hash values for a number of types
against reference values (`test/hash_reference_values.cpp`),
whose https://github.com/boostorg/container_hash/commits/develop/test/hash_reference_values.cpp[version history]
can be used as a rough guide to when hash values have changed, and for what
types.
== hash_combine
The initial implementation of the library was based on Issue 6.18 of the

View File

@@ -8,14 +8,24 @@ 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`.
* Added `is_tuple_like` and an overload of `hash_value` for
tuple-like types.
* Changed string hashing to use
https://github.com/pdimov/mulxp_hash[`mulxp1_hash`]. This
improves both quality and speed.
https://github.com/pdimov/mulxp_hash[`mulxp1_hash`],
improving both quality and speed. This changes the hash values
for string-like types (ranges of `char`, `signed char`,
`unsigned char`, `std::byte`, `char8_t`).
== Boost 1.81.0
@@ -33,9 +43,18 @@ Major update.
* Described structs and classes (those annotated with
`BOOST_DESCRIBE_STRUCT` or `BOOST_DESCRIBE_CLASS`) are now
supported out of the box.
* `hash_combine` has been improved.
* `hash_combine` has been improved. This changes the hash values
of composite (container and tuple) types and of scalar types
bigger than `size_t`.
* The performance (and quality, as a result of the above change)
of string hashing has been improved. `boost::hash` for strings
now passes SMHasher in 64 bit mode.
* The documentation has been substantially revised to reflect
the changes.
== Boost 1.78.0
* Fixed `hash_combine` so that its behavior no longer depends
on whether `size_t` is the exact same type as `boost::uint64_t`
(which wasn't the case on macOS). This changes the hash values
of composite (container and tuple) types on macOS.

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 is deprecated in Boost.ContainerHash 1.82 and will be removed in Boost.ContainerHash 1.84.")
#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> > ));
@@ -35,7 +35,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<my_char> > > ));
#endif
return boost::report_errors();
}

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