mirror of
https://github.com/boostorg/container_hash.git
synced 2026-03-07 14:34:11 +01:00
Compare commits
74 Commits
feature/nu
...
boost-1.85
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6d214eb776 | ||
|
|
b0d3107b99 | ||
|
|
e2446b187e | ||
|
|
1dd2f73866 | ||
|
|
1278f1c2b5 | ||
|
|
067f636d6c | ||
|
|
338c053889 | ||
|
|
94d4f7cb88 | ||
|
|
6957a20ab1 | ||
|
|
28cc18a4bc | ||
|
|
7288df8bee | ||
|
|
5c2d5e5b36 | ||
|
|
db8743e1c3 | ||
|
|
48a306dcf2 | ||
|
|
f6279a0615 | ||
|
|
41746c0bdb | ||
|
|
07a0910640 | ||
|
|
4c32071739 | ||
|
|
30c05c93b1 | ||
|
|
197f75845c | ||
|
|
bf8ad2c0ee | ||
|
|
fef60938e5 | ||
|
|
f04d866fa7 | ||
|
|
17201433f8 | ||
|
|
9d09674f08 | ||
|
|
f8ecd66820 | ||
|
|
565bac8d31 | ||
|
|
b8496de2f2 | ||
|
|
641a59342e | ||
|
|
226eb066e9 | ||
|
|
d9cb23d96a | ||
|
|
bd8a5cb867 | ||
|
|
b43ce472fa | ||
|
|
e798972130 | ||
|
|
ebb49fa459 | ||
|
|
1e1c0ea38c | ||
|
|
e62a268566 | ||
|
|
ad89c02360 | ||
|
|
64948e5f57 | ||
|
|
1958e96561 | ||
|
|
4a7287d371 | ||
|
|
5638134081 | ||
|
|
7c49f0bfb1 | ||
|
|
9ae5790657 | ||
|
|
8ce81c361d | ||
|
|
4315faf470 | ||
|
|
eb049e0cae | ||
|
|
6373656710 | ||
|
|
ec1503bbc8 | ||
|
|
ee064dc7f8 | ||
|
|
b505e06b3c | ||
|
|
6075f3e1f5 | ||
|
|
0bfeabfd63 | ||
|
|
758596533d | ||
|
|
640bd48f51 | ||
|
|
b25fd745ca | ||
|
|
6fe3469a8b | ||
|
|
c07630ac60 | ||
|
|
45270ae11e | ||
|
|
5bef4901b9 | ||
|
|
d724bcd0ef | ||
|
|
ceb8303601 | ||
|
|
cf87e304f6 | ||
|
|
4d9f7b8931 | ||
|
|
2f4efbced4 | ||
|
|
bf7a78594e | ||
|
|
c0c70e5b3e | ||
|
|
891a64d45d | ||
|
|
08d69c31b1 | ||
|
|
6526b24900 | ||
|
|
1a8dca4f2c | ||
|
|
8761157a19 | ||
|
|
30560ada18 | ||
|
|
c61a4f691e |
@@ -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
|
||||
|
||||
145
.drone.jsonnet
145
.drone.jsonnet
@@ -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,217 +123,256 @@ 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",
|
||||
"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' } + asan,
|
||||
"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,
|
||||
{ TOOLSET: 'gcc', COMPILER: 'g++-12', CXXSTD: '11,14,17,20,2b', ADDRMD: '64' } + asan,
|
||||
"g++-12-multilib",
|
||||
),
|
||||
|
||||
linux_pipeline(
|
||||
"Linux 23.04 GCC 13 32 UBSAN",
|
||||
"cppalliance/droneubuntu2304:1",
|
||||
{ TOOLSET: 'gcc', COMPILER: 'g++-13', CXXSTD: '11,14,17,20,2b', ADDRMD: '32' } + ubsan,
|
||||
"g++-13-multilib",
|
||||
),
|
||||
|
||||
linux_pipeline(
|
||||
"Linux 23.04 GCC 13 64 UBSAN",
|
||||
"cppalliance/droneubuntu2304:1",
|
||||
{ TOOLSET: 'gcc', COMPILER: 'g++-13', CXXSTD: '11,14,17,20,2b', ADDRMD: '64' } + ubsan,
|
||||
"g++-13-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' },
|
||||
{ TOOLSET: 'clang', COMPILER: 'clang++-13', CXXSTD: '11,14,17,20,2b' },
|
||||
"clang-13",
|
||||
),
|
||||
|
||||
linux_pipeline(
|
||||
"Linux 22.04 Clang 14 UBSAN",
|
||||
"Linux 22.04 Clang 14",
|
||||
"cppalliance/droneubuntu2204:1",
|
||||
{ TOOLSET: 'clang', COMPILER: 'clang++-14', CXXSTD: '03,11,14,17,20,2b' } + ubsan,
|
||||
"clang-14",
|
||||
),
|
||||
|
||||
linux_pipeline(
|
||||
"Linux 22.04 Clang 14 ASAN",
|
||||
"cppalliance/droneubuntu2204:1",
|
||||
{ TOOLSET: 'clang', COMPILER: 'clang++-14', CXXSTD: '03,11,14,17,20,2b' } + asan,
|
||||
{ TOOLSET: 'clang', COMPILER: 'clang++-14', CXXSTD: '11,14,17,20,2b' },
|
||||
"clang-14",
|
||||
),
|
||||
|
||||
linux_pipeline(
|
||||
"Linux 22.04 Clang 15",
|
||||
"cppalliance/droneubuntu2204:1",
|
||||
{ TOOLSET: 'clang', COMPILER: 'clang++-15', CXXSTD: '03,11,14,17,20,2b' },
|
||||
{ TOOLSET: 'clang', COMPILER: 'clang++-15', CXXSTD: '11,14,17,20,2b' },
|
||||
"clang-15",
|
||||
["deb http://apt.llvm.org/jammy/ llvm-toolchain-jammy-15 main"],
|
||||
),
|
||||
|
||||
linux_pipeline(
|
||||
"Linux 23.04 Clang 16",
|
||||
"cppalliance/droneubuntu2304:1",
|
||||
{ TOOLSET: 'clang', COMPILER: 'clang++-16', CXXSTD: '11,14,17,20,2b' },
|
||||
"clang-16",
|
||||
),
|
||||
|
||||
linux_pipeline(
|
||||
"Linux 23.10 Clang 17 UBSAN",
|
||||
"cppalliance/droneubuntu2310:1",
|
||||
{ TOOLSET: 'clang', COMPILER: 'clang++-17', CXXSTD: '11,14,17,20,2b' } + ubsan,
|
||||
"clang-17",
|
||||
),
|
||||
|
||||
linux_pipeline(
|
||||
"Linux 23.10 Clang 17 ASAN",
|
||||
"cppalliance/droneubuntu2310:1",
|
||||
{ TOOLSET: 'clang', COMPILER: 'clang++-17', CXXSTD: '11,14,17,20,2b' } + asan,
|
||||
"clang-17",
|
||||
),
|
||||
|
||||
macos_pipeline(
|
||||
"MacOS 10.15 Xcode 12.2 UBSAN",
|
||||
{ TOOLSET: 'clang', COMPILER: 'clang++', CXXSTD: '03,11,14,1z' } + 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,1z' } + 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: '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: '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(
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
# https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
set -ex
|
||||
export PATH=~/.local/bin:/usr/local/bin:$PATH
|
||||
|
||||
DRONE_BUILD_DIR=$(pwd)
|
||||
|
||||
|
||||
324
.github/workflows/ci.yml
vendored
324
.github/workflows/ci.yml
vendored
@@ -18,119 +18,170 @@ jobs:
|
||||
matrix:
|
||||
include:
|
||||
- toolset: gcc-4.8
|
||||
cxxstd: "03,11"
|
||||
os: ubuntu-18.04
|
||||
cxxstd: "11"
|
||||
os: ubuntu-latest
|
||||
container: ubuntu:18.04
|
||||
install: g++-4.8-multilib
|
||||
address-model: 32,64
|
||||
- toolset: gcc-5
|
||||
cxxstd: "03,11,14,1z"
|
||||
os: ubuntu-18.04
|
||||
cxxstd: "11,14,1z"
|
||||
os: ubuntu-latest
|
||||
container: ubuntu:18.04
|
||||
install: g++-5-multilib
|
||||
address-model: 32,64
|
||||
- toolset: gcc-6
|
||||
cxxstd: "03,11,14,1z"
|
||||
os: ubuntu-18.04
|
||||
cxxstd: "11,14,1z"
|
||||
os: ubuntu-latest
|
||||
container: ubuntu:18.04
|
||||
install: g++-6-multilib
|
||||
address-model: 32,64
|
||||
- toolset: gcc-7
|
||||
cxxstd: "03,11,14,17"
|
||||
os: ubuntu-18.04
|
||||
cxxstd: "11,14,17"
|
||||
os: ubuntu-20.04
|
||||
install: g++-7-multilib
|
||||
address-model: 32,64
|
||||
- toolset: gcc-8
|
||||
cxxstd: "03,11,14,17,2a"
|
||||
os: ubuntu-18.04
|
||||
cxxstd: "11,14,17,2a"
|
||||
os: ubuntu-20.04
|
||||
install: g++-8-multilib
|
||||
address-model: 32,64
|
||||
- toolset: gcc-9
|
||||
cxxstd: "03,11,14,17,2a"
|
||||
cxxstd: "11,14,17,2a"
|
||||
os: ubuntu-20.04
|
||||
install: g++-9-multilib
|
||||
address-model: 32,64
|
||||
- toolset: gcc-10
|
||||
cxxstd: "03,11,14,17,2a"
|
||||
os: ubuntu-20.04
|
||||
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"
|
||||
os: ubuntu-latest
|
||||
container: ubuntu:23.04
|
||||
install: g++-13-multilib
|
||||
address-model: 32,64
|
||||
- toolset: clang
|
||||
compiler: clang++-3.9
|
||||
cxxstd: "03,11,14"
|
||||
os: ubuntu-18.04
|
||||
cxxstd: "11,14"
|
||||
os: ubuntu-latest
|
||||
container: ubuntu:18.04
|
||||
install: clang-3.9
|
||||
- toolset: clang
|
||||
compiler: clang++-4.0
|
||||
cxxstd: "03,11,14"
|
||||
os: ubuntu-18.04
|
||||
cxxstd: "11,14"
|
||||
os: ubuntu-latest
|
||||
container: ubuntu:18.04
|
||||
install: clang-4.0
|
||||
- toolset: clang
|
||||
compiler: clang++-5.0
|
||||
cxxstd: "03,11,14,1z"
|
||||
os: ubuntu-18.04
|
||||
cxxstd: "11,14,1z"
|
||||
os: ubuntu-latest
|
||||
container: ubuntu:18.04
|
||||
install: clang-5.0
|
||||
- toolset: clang
|
||||
compiler: clang++-6.0
|
||||
cxxstd: "03,11,14,17"
|
||||
os: ubuntu-18.04
|
||||
cxxstd: "11,14,17"
|
||||
os: ubuntu-20.04
|
||||
install: clang-6.0
|
||||
- toolset: clang
|
||||
compiler: clang++-7
|
||||
cxxstd: "03,11,14,17"
|
||||
os: ubuntu-18.04
|
||||
cxxstd: "11,14,17"
|
||||
os: ubuntu-20.04
|
||||
install: clang-7
|
||||
- toolset: clang
|
||||
compiler: clang++-8
|
||||
cxxstd: "03,11,14,17"
|
||||
cxxstd: "11,14,17"
|
||||
os: ubuntu-20.04
|
||||
install: clang-8
|
||||
- toolset: clang
|
||||
compiler: clang++-9
|
||||
cxxstd: "03,11,14,17,2a"
|
||||
cxxstd: "11,14,17,2a"
|
||||
os: ubuntu-20.04
|
||||
install: clang-9
|
||||
- toolset: clang
|
||||
compiler: clang++-10
|
||||
cxxstd: "03,11,14,17,2a"
|
||||
cxxstd: "11,14,17,2a"
|
||||
os: ubuntu-20.04
|
||||
- toolset: clang
|
||||
compiler: clang++-11
|
||||
cxxstd: "03,11,14,17,2a"
|
||||
cxxstd: "11,14,17,2a"
|
||||
os: ubuntu-20.04
|
||||
- toolset: clang
|
||||
compiler: clang++-12
|
||||
cxxstd: "03,11,14,17,20"
|
||||
cxxstd: "11,14,17,20"
|
||||
os: ubuntu-20.04
|
||||
- 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
|
||||
cxxstd: "03,11,14,17,2a"
|
||||
compiler: clang++-15
|
||||
cxxstd: "11,14,17,20,2b"
|
||||
container: ubuntu:22.04
|
||||
os: ubuntu-latest
|
||||
install: clang-15
|
||||
- toolset: clang
|
||||
compiler: clang++-16
|
||||
cxxstd: "11,14,17,20,2b"
|
||||
container: ubuntu:23.04
|
||||
os: ubuntu-latest
|
||||
install: clang-16
|
||||
- toolset: clang
|
||||
compiler: clang++-17
|
||||
cxxstd: "11,14,17,20,2b"
|
||||
container: ubuntu:23.10
|
||||
os: ubuntu-latest
|
||||
install: clang-17
|
||||
- toolset: clang
|
||||
cxxstd: "11,14,17,2a"
|
||||
os: macos-11
|
||||
- toolset: clang
|
||||
cxxstd: "11,14,17,20,2b"
|
||||
os: macos-12
|
||||
- toolset: clang
|
||||
cxxstd: "11,14,17,20,2b"
|
||||
os: macos-13
|
||||
|
||||
runs-on: ${{matrix.os}}
|
||||
container: ${{matrix.container}}
|
||||
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Setup container environment
|
||||
if: matrix.container
|
||||
run: |
|
||||
apt-get update
|
||||
apt-get -y install sudo python3 git g++
|
||||
|
||||
- name: Install packages
|
||||
if: matrix.install
|
||||
run: sudo apt install ${{matrix.install}}
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get -y install ${{matrix.install}}
|
||||
|
||||
- name: Setup Boost
|
||||
run: |
|
||||
@@ -150,7 +201,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
|
||||
|
||||
@@ -188,7 +239,7 @@ 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
|
||||
|
||||
@@ -231,10 +282,11 @@ jobs:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- os: ubuntu-18.04
|
||||
- os: ubuntu-20.04
|
||||
- os: ubuntu-22.04
|
||||
- os: macos-11
|
||||
- os: macos-12
|
||||
- os: macos-13
|
||||
|
||||
runs-on: ${{matrix.os}}
|
||||
|
||||
@@ -243,7 +295,7 @@ jobs:
|
||||
|
||||
- name: Install packages
|
||||
if: matrix.install
|
||||
run: sudo apt install ${{matrix.install}}
|
||||
run: sudo apt-get -y install ${{matrix.install}}
|
||||
|
||||
- name: Setup Boost
|
||||
run: |
|
||||
@@ -278,10 +330,11 @@ jobs:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- os: ubuntu-18.04
|
||||
- os: ubuntu-20.04
|
||||
- os: ubuntu-22.04
|
||||
- os: macos-11
|
||||
- os: macos-12
|
||||
- os: macos-13
|
||||
|
||||
runs-on: ${{matrix.os}}
|
||||
|
||||
@@ -290,7 +343,7 @@ jobs:
|
||||
|
||||
- name: Install packages
|
||||
if: matrix.install
|
||||
run: sudo apt install ${{matrix.install}}
|
||||
run: sudo apt-get -y install ${{matrix.install}}
|
||||
|
||||
- name: Setup Boost
|
||||
run: |
|
||||
@@ -335,10 +388,11 @@ jobs:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- os: ubuntu-18.04
|
||||
- os: ubuntu-20.04
|
||||
- os: ubuntu-22.04
|
||||
- os: macos-11
|
||||
- os: macos-12
|
||||
- os: macos-13
|
||||
|
||||
runs-on: ${{matrix.os}}
|
||||
|
||||
@@ -347,7 +401,7 @@ jobs:
|
||||
|
||||
- name: Install packages
|
||||
if: matrix.install
|
||||
run: sudo apt install ${{matrix.install}}
|
||||
run: sudo apt-get -y install ${{matrix.install}}
|
||||
|
||||
- name: Setup Boost
|
||||
run: |
|
||||
@@ -384,3 +438,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-2019
|
||||
- os: windows-2022
|
||||
|
||||
runs-on: ${{matrix.os}}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- 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-2019
|
||||
- os: windows-2022
|
||||
|
||||
runs-on: ${{matrix.os}}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- 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-2019
|
||||
- os: windows-2022
|
||||
|
||||
runs-on: ${{matrix.os}}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- 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
|
||||
|
||||
@@ -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)
|
||||
|
||||
1
benchmark/.gitignore
vendored
1
benchmark/.gitignore
vendored
@@ -1,3 +1,4 @@
|
||||
enwik8
|
||||
enwik9
|
||||
*.exe
|
||||
*.obj
|
||||
|
||||
@@ -13,6 +13,9 @@
|
||||
#ifdef HAVE_ABSEIL
|
||||
# include "absl/hash/hash.h"
|
||||
#endif
|
||||
#ifdef HAVE_ANKERL_UNORDERED_DENSE
|
||||
# include "ankerl/unordered_dense.h"
|
||||
#endif
|
||||
#ifdef HAVE_MULXP_HASH
|
||||
# include "mulxp_hash.hpp"
|
||||
#endif
|
||||
@@ -178,14 +181,6 @@ struct fnv1a_hash: fnv1a_hash_impl< std::numeric_limits<std::size_t>::digits > {
|
||||
|
||||
#ifdef HAVE_MULXP_HASH
|
||||
|
||||
struct mulxp0_hash_
|
||||
{
|
||||
std::size_t operator()( std::string const& st ) const BOOST_NOEXCEPT
|
||||
{
|
||||
return mulxp0_hash( (unsigned char const*)st.data(), st.size(), 0 );
|
||||
}
|
||||
};
|
||||
|
||||
struct mulxp1_hash_
|
||||
{
|
||||
std::size_t operator()( std::string const& st ) const BOOST_NOEXCEPT
|
||||
@@ -194,14 +189,6 @@ struct mulxp1_hash_
|
||||
}
|
||||
};
|
||||
|
||||
struct mulxp2_hash_
|
||||
{
|
||||
std::size_t operator()( std::string const& st ) const BOOST_NOEXCEPT
|
||||
{
|
||||
return mulxp2_hash( (unsigned char const*)st.data(), st.size(), 0 );
|
||||
}
|
||||
};
|
||||
|
||||
struct mulxp3_hash_
|
||||
{
|
||||
std::size_t operator()( std::string const& st ) const BOOST_NOEXCEPT
|
||||
@@ -210,6 +197,14 @@ struct mulxp3_hash_
|
||||
}
|
||||
};
|
||||
|
||||
struct mulxp1_hash32_
|
||||
{
|
||||
std::size_t operator()( std::string const& st ) const BOOST_NOEXCEPT
|
||||
{
|
||||
return mulxp1_hash32( (unsigned char const*)st.data(), st.size(), 0 );
|
||||
}
|
||||
};
|
||||
|
||||
struct mulxp3_hash32_
|
||||
{
|
||||
std::size_t operator()( std::string const& st ) const BOOST_NOEXCEPT
|
||||
@@ -245,11 +240,11 @@ template<class H, class V> void test_hash_speed( int N, V const& v )
|
||||
|
||||
#if defined( _MSC_VER )
|
||||
|
||||
std::printf( "%53s : q=%20Iu, %lld ms\n", hash.c_str(), q, ms1 );
|
||||
std::printf( "%57s : q=%20Iu, %lld ms\n", hash.c_str(), q, ms1 );
|
||||
|
||||
#else
|
||||
|
||||
std::printf( "%53s : q=%20zu, %lld ms\n", hash.c_str(), q, ms1 );
|
||||
std::printf( "%57s : q=%20zu, %lld ms\n", hash.c_str(), q, ms1 );
|
||||
|
||||
#endif
|
||||
}
|
||||
@@ -270,11 +265,11 @@ template<class H, class V> void test_hash_collision( int N, V const& v, std::siz
|
||||
|
||||
#if defined( _MSC_VER )
|
||||
|
||||
std::printf( "%53s : c=%Iu\n", hash.c_str(), n - s.size() );
|
||||
std::printf( "%57s : c=%Iu\n", hash.c_str(), n - s.size() );
|
||||
|
||||
#else
|
||||
|
||||
std::printf( "%53s : c=%zu\n", hash.c_str(), n - s.size() );
|
||||
std::printf( "%57s : c=%zu\n", hash.c_str(), n - s.size() );
|
||||
|
||||
#endif
|
||||
}
|
||||
@@ -327,11 +322,11 @@ template<class V, class S> void test4( int N, V const& v, char const * hash, S s
|
||||
|
||||
#if defined( _MSC_VER )
|
||||
|
||||
std::printf( "%53s : n=%Iu, m=%Iu, c=%Iu, q=%Iu, %4lld + %4lld = %4lld ms\n", hash, n, m, c, q, ms1, ms2, ms1 + ms2 );
|
||||
std::printf( "%57s : n=%Iu, m=%Iu, c=%Iu, q=%Iu, %4lld + %4lld = %4lld ms\n", hash, n, m, c, q, ms1, ms2, ms1 + ms2 );
|
||||
|
||||
#else
|
||||
|
||||
std::printf( "%53s : n=%zu, m=%zu, c=%zu, q=%zu, %4lld + %4lld = %4lld ms\n", hash, n, m, c, q, ms1, ms2, ms1 + ms2 );
|
||||
std::printf( "%57s : n=%zu, m=%zu, c=%zu, q=%zu, %4lld + %4lld = %4lld ms\n", hash, n, m, c, q, ms1, ms2, ms1 + ms2 );
|
||||
|
||||
#endif
|
||||
}
|
||||
@@ -383,11 +378,13 @@ int main()
|
||||
#ifdef HAVE_ABSEIL
|
||||
test_hash_speed<absl::Hash<std::string> >( N * 16, v );
|
||||
#endif
|
||||
#ifdef HAVE_ANKERL_UNORDERED_DENSE
|
||||
test_hash_speed<ankerl::unordered_dense::hash<std::string> >( N * 16, v );
|
||||
#endif
|
||||
#ifdef HAVE_MULXP_HASH
|
||||
test_hash_speed<mulxp0_hash_>( N * 16, v );
|
||||
test_hash_speed<mulxp1_hash_>( N * 16, v );
|
||||
test_hash_speed<mulxp2_hash_>( N * 16, v );
|
||||
test_hash_speed<mulxp3_hash_>( N * 16, v );
|
||||
test_hash_speed<mulxp1_hash32_>( N * 16, v );
|
||||
test_hash_speed<mulxp3_hash32_>( N * 16, v );
|
||||
#endif
|
||||
|
||||
@@ -418,11 +415,13 @@ int main()
|
||||
#ifdef HAVE_ABSEIL
|
||||
test_hash_collision<absl::Hash<std::string> >( N * 16, v, n );
|
||||
#endif
|
||||
#ifdef HAVE_ANKERL_UNORDERED_DENSE
|
||||
test_hash_collision<ankerl::unordered_dense::hash<std::string> >( N * 16, v, n );
|
||||
#endif
|
||||
#ifdef HAVE_MULXP_HASH
|
||||
test_hash_collision<mulxp0_hash_>( N * 16, v, n );
|
||||
test_hash_collision<mulxp1_hash_>( N * 16, v, n );
|
||||
test_hash_collision<mulxp2_hash_>( N * 16, v, n );
|
||||
test_hash_collision<mulxp3_hash_>( N * 16, v, n );
|
||||
test_hash_collision<mulxp1_hash32_>( N * 16, v, n );
|
||||
test_hash_collision<mulxp3_hash32_>( N * 16, v, n );
|
||||
#endif
|
||||
}
|
||||
@@ -431,7 +430,7 @@ int main()
|
||||
|
||||
typedef std::string K;
|
||||
|
||||
std::puts( "Container speed test:\n" );
|
||||
std::puts( "Container speed test:\n---\n" );
|
||||
|
||||
test_container_speed<K, mul31_hash>( N, v );
|
||||
test_container_speed<K, mul31_x4_hash>( N, v );
|
||||
@@ -442,11 +441,13 @@ int main()
|
||||
#ifdef HAVE_ABSEIL
|
||||
test_container_speed<K, absl::Hash<std::string> >( N, v );
|
||||
#endif
|
||||
#ifdef HAVE_ANKERL_UNORDERED_DENSE
|
||||
test_container_speed<K, ankerl::unordered_dense::hash<std::string> >( N, v );
|
||||
#endif
|
||||
#ifdef HAVE_MULXP_HASH
|
||||
test_container_speed<K, mulxp0_hash_>( N, v );
|
||||
test_container_speed<K, mulxp1_hash_>( N, v );
|
||||
test_container_speed<K, mulxp2_hash_>( N, v );
|
||||
test_container_speed<K, mulxp3_hash_>( N, v );
|
||||
test_container_speed<K, mulxp1_hash32_>( N, v );
|
||||
test_container_speed<K, mulxp3_hash32_>( N, v );
|
||||
#endif
|
||||
|
||||
|
||||
@@ -11,6 +11,9 @@
|
||||
#ifdef HAVE_ABSEIL
|
||||
# include "absl/hash/hash.h"
|
||||
#endif
|
||||
#ifdef HAVE_ANKERL_UNORDERED_DENSE
|
||||
# include "ankerl/unordered_dense.h"
|
||||
#endif
|
||||
#ifdef HAVE_MULXP_HASH
|
||||
# include "mulxp_hash.hpp"
|
||||
#endif
|
||||
@@ -210,118 +213,6 @@ template<class Hash> BOOST_NOINLINE void test( char const* label )
|
||||
times.push_back( rec );
|
||||
}
|
||||
|
||||
// mul31_hash
|
||||
|
||||
struct mul31_hash
|
||||
{
|
||||
// not avalanching
|
||||
|
||||
std::size_t operator()( std::string const& st ) const BOOST_NOEXCEPT
|
||||
{
|
||||
char const * p = st.data();
|
||||
std::size_t n = st.size();
|
||||
|
||||
#if SIZE_MAX > UINT32_MAX
|
||||
std::size_t h = 0xCBF29CE484222325ull;
|
||||
#else
|
||||
std::size_t h = 0x811C9DC5u;
|
||||
#endif
|
||||
|
||||
for( std::size_t i = 0; i < n; ++i )
|
||||
{
|
||||
h = h * 31 + static_cast<unsigned char>( p[i] );
|
||||
}
|
||||
|
||||
return h;
|
||||
}
|
||||
};
|
||||
|
||||
// mul31_x4_hash
|
||||
|
||||
struct mul31_x4_hash
|
||||
{
|
||||
// not avalanching
|
||||
|
||||
std::size_t operator()( std::string const& st ) const BOOST_NOEXCEPT
|
||||
{
|
||||
char const * p = st.data();
|
||||
std::size_t n = st.size();
|
||||
|
||||
#if SIZE_MAX > UINT32_MAX
|
||||
std::size_t h = 0xCBF29CE484222325ull;
|
||||
#else
|
||||
std::size_t h = 0x811C9DC5u;
|
||||
#endif
|
||||
|
||||
while( n >= 4 )
|
||||
{
|
||||
h = h * (31u * 31u * 31u * 31u)
|
||||
+ static_cast<unsigned char>( p[0] ) * (31u * 31u * 31u)
|
||||
+ static_cast<unsigned char>( p[1] ) * (31u * 31u)
|
||||
+ static_cast<unsigned char>( p[2] ) * 31u
|
||||
+ static_cast<unsigned char>( p[3] );
|
||||
|
||||
p += 4;
|
||||
n -= 4;
|
||||
}
|
||||
|
||||
while( n > 0 )
|
||||
{
|
||||
h = h * 31u + static_cast<unsigned char>( *p );
|
||||
|
||||
++p;
|
||||
--n;
|
||||
}
|
||||
|
||||
return h;
|
||||
}
|
||||
};
|
||||
|
||||
// mul31_x8_hash
|
||||
|
||||
struct mul31_x8_hash
|
||||
{
|
||||
// not avalanching
|
||||
|
||||
std::size_t operator()( std::string const& st ) const BOOST_NOEXCEPT
|
||||
{
|
||||
char const * p = st.data();
|
||||
std::size_t n = st.size();
|
||||
|
||||
#if SIZE_MAX > UINT32_MAX
|
||||
boost::uint64_t h = 0xCBF29CE484222325ull;
|
||||
#else
|
||||
boost::uint64_t h = 0x811C9DC5u;
|
||||
#endif
|
||||
|
||||
while( n >= 8 )
|
||||
{
|
||||
h = h * (31ull * 31ull * 31ull * 31ull * 31ull * 31ull * 31ull * 31ull)
|
||||
+ static_cast<unsigned char>( p[0] ) * (31ull * 31ull * 31ull * 31ull * 31ull * 31ull * 31ull)
|
||||
+ static_cast<unsigned char>( p[1] ) * (31ull * 31ull * 31ull * 31ull * 31ull * 31ull)
|
||||
+ static_cast<unsigned char>( p[2] ) * (31ull * 31ull * 31ull * 31ull * 31ull)
|
||||
+ static_cast<unsigned char>( p[3] ) * (31ull * 31ull * 31ull * 31ull)
|
||||
+ static_cast<unsigned char>( p[4] ) * (31ull * 31ull * 31ull)
|
||||
+ static_cast<unsigned char>( p[5] ) * (31ull * 31ull)
|
||||
+ static_cast<unsigned char>( p[6] ) * 31ull
|
||||
+ static_cast<unsigned char>( p[7] );
|
||||
|
||||
p += 8;
|
||||
n -= 8;
|
||||
}
|
||||
|
||||
while( n > 0 )
|
||||
{
|
||||
h = h * 31u + static_cast<unsigned char>( *p );
|
||||
|
||||
++p;
|
||||
--n;
|
||||
}
|
||||
|
||||
return static_cast<std::size_t>( h );
|
||||
}
|
||||
};
|
||||
|
||||
// fnv1a_hash
|
||||
|
||||
template<int Bits> struct fnv1a_hash_impl;
|
||||
@@ -391,16 +282,6 @@ struct absl_hash: absl::Hash<std::string>
|
||||
|
||||
#ifdef HAVE_MULXP_HASH
|
||||
|
||||
struct mulxp0_hash_
|
||||
{
|
||||
using is_avalanching = void;
|
||||
|
||||
std::size_t operator()( std::string const& st ) const BOOST_NOEXCEPT
|
||||
{
|
||||
return mulxp0_hash( (unsigned char const*)st.data(), st.size(), 0 );
|
||||
}
|
||||
};
|
||||
|
||||
struct mulxp1_hash_
|
||||
{
|
||||
using is_avalanching = void;
|
||||
@@ -411,16 +292,6 @@ struct mulxp1_hash_
|
||||
}
|
||||
};
|
||||
|
||||
struct mulxp2_hash_
|
||||
{
|
||||
using is_avalanching = void;
|
||||
|
||||
std::size_t operator()( std::string const& st ) const BOOST_NOEXCEPT
|
||||
{
|
||||
return mulxp2_hash( (unsigned char const*)st.data(), st.size(), 0 );
|
||||
}
|
||||
};
|
||||
|
||||
struct mulxp3_hash_
|
||||
{
|
||||
using is_avalanching = void;
|
||||
@@ -431,6 +302,24 @@ struct mulxp3_hash_
|
||||
}
|
||||
};
|
||||
|
||||
struct mulxp1_hash32_
|
||||
{
|
||||
using is_avalanching = void;
|
||||
|
||||
std::size_t operator()( std::string const& st ) const BOOST_NOEXCEPT
|
||||
{
|
||||
std::size_t r = mulxp1_hash32( (unsigned char const*)st.data(), st.size(), 0 );
|
||||
|
||||
#if SIZE_MAX > UINT32_MAX
|
||||
|
||||
r |= r << 32;
|
||||
|
||||
#endif
|
||||
|
||||
return r;
|
||||
}
|
||||
};
|
||||
|
||||
struct mulxp3_hash32_
|
||||
{
|
||||
using is_avalanching = void;
|
||||
@@ -459,9 +348,6 @@ int main()
|
||||
|
||||
test< boost::hash<std::string> >( "boost::hash" );
|
||||
test< std_hash >( "std::hash" );
|
||||
test< mul31_hash >( "mul31_hash" );
|
||||
test< mul31_x4_hash >( "mul31_x4_hash" );
|
||||
test< mul31_x8_hash >( "mul31_x8_hash" );
|
||||
test< fnv1a_hash >( "fnv1a_hash" );
|
||||
|
||||
#ifdef HAVE_ABSEIL
|
||||
@@ -470,12 +356,17 @@ int main()
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_ANKERL_UNORDERED_DENSE
|
||||
|
||||
test< ankerl::unordered_dense::hash<std::string> >( "ankerl::unordered_dense::hash" );
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_MULXP_HASH
|
||||
|
||||
test< mulxp0_hash_ >( "mulxp0_hash" );
|
||||
test< mulxp1_hash_ >( "mulxp1_hash" );
|
||||
test< mulxp2_hash_ >( "mulxp2_hash" );
|
||||
test< mulxp3_hash_ >( "mulxp3_hash" );
|
||||
test< mulxp1_hash32_ >( "mulxp1_hash32" );
|
||||
test< mulxp3_hash32_ >( "mulxp3_hash32" );
|
||||
|
||||
#endif
|
||||
@@ -484,7 +375,7 @@ int main()
|
||||
|
||||
for( auto const& x: times )
|
||||
{
|
||||
std::cout << std::setw( 22 ) << ( x.label_ + ": " ) << std::setw( 5 ) << x.time_ << " ms\n";
|
||||
std::cout << std::setw( 32 ) << ( x.label_ + ": " ) << std::setw( 5 ) << x.time_ << " ms\n";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,9 @@
|
||||
#ifdef HAVE_ABSEIL
|
||||
# include "absl/hash/hash.h"
|
||||
#endif
|
||||
#ifdef HAVE_ANKERL_UNORDERED_DENSE
|
||||
# include "ankerl/unordered_dense.h"
|
||||
#endif
|
||||
#ifdef HAVE_MULXP_HASH
|
||||
# include "mulxp_hash.hpp"
|
||||
#endif
|
||||
@@ -38,8 +41,16 @@ static std::vector<std::string> words;
|
||||
|
||||
static void init_words()
|
||||
{
|
||||
#if SIZE_MAX > UINT32_MAX
|
||||
|
||||
char const* fn = "enwik9"; // http://mattmahoney.net/dc/textdata
|
||||
|
||||
#else
|
||||
|
||||
char const* fn = "enwik8"; // ditto
|
||||
|
||||
#endif
|
||||
|
||||
auto t1 = std::chrono::steady_clock::now();
|
||||
|
||||
std::ifstream is( fn );
|
||||
@@ -137,118 +148,6 @@ template<class Hash> BOOST_NOINLINE void test( char const* label )
|
||||
times.push_back( rec );
|
||||
}
|
||||
|
||||
// mul31_hash
|
||||
|
||||
struct mul31_hash
|
||||
{
|
||||
// not avalanching
|
||||
|
||||
std::size_t operator()( std::string_view const& st ) const BOOST_NOEXCEPT
|
||||
{
|
||||
char const * p = st.data();
|
||||
std::size_t n = st.size();
|
||||
|
||||
#if SIZE_MAX > UINT32_MAX
|
||||
std::size_t h = 0xCBF29CE484222325ull;
|
||||
#else
|
||||
std::size_t h = 0x811C9DC5u;
|
||||
#endif
|
||||
|
||||
for( std::size_t i = 0; i < n; ++i )
|
||||
{
|
||||
h = h * 31 + static_cast<unsigned char>( p[i] );
|
||||
}
|
||||
|
||||
return h;
|
||||
}
|
||||
};
|
||||
|
||||
// mul31_x4_hash
|
||||
|
||||
struct mul31_x4_hash
|
||||
{
|
||||
// not avalanching
|
||||
|
||||
std::size_t operator()( std::string_view const& st ) const BOOST_NOEXCEPT
|
||||
{
|
||||
char const * p = st.data();
|
||||
std::size_t n = st.size();
|
||||
|
||||
#if SIZE_MAX > UINT32_MAX
|
||||
std::size_t h = 0xCBF29CE484222325ull;
|
||||
#else
|
||||
std::size_t h = 0x811C9DC5u;
|
||||
#endif
|
||||
|
||||
while( n >= 4 )
|
||||
{
|
||||
h = h * (31u * 31u * 31u * 31u)
|
||||
+ static_cast<unsigned char>( p[0] ) * (31u * 31u * 31u)
|
||||
+ static_cast<unsigned char>( p[1] ) * (31u * 31u)
|
||||
+ static_cast<unsigned char>( p[2] ) * 31u
|
||||
+ static_cast<unsigned char>( p[3] );
|
||||
|
||||
p += 4;
|
||||
n -= 4;
|
||||
}
|
||||
|
||||
while( n > 0 )
|
||||
{
|
||||
h = h * 31u + static_cast<unsigned char>( *p );
|
||||
|
||||
++p;
|
||||
--n;
|
||||
}
|
||||
|
||||
return h;
|
||||
}
|
||||
};
|
||||
|
||||
// mul31_x8_hash
|
||||
|
||||
struct mul31_x8_hash
|
||||
{
|
||||
// not avalanching
|
||||
|
||||
std::size_t operator()( std::string_view const& st ) const BOOST_NOEXCEPT
|
||||
{
|
||||
char const * p = st.data();
|
||||
std::size_t n = st.size();
|
||||
|
||||
#if SIZE_MAX > UINT32_MAX
|
||||
boost::uint64_t h = 0xCBF29CE484222325ull;
|
||||
#else
|
||||
boost::uint64_t h = 0x811C9DC5u;
|
||||
#endif
|
||||
|
||||
while( n >= 8 )
|
||||
{
|
||||
h = h * (31ull * 31ull * 31ull * 31ull * 31ull * 31ull * 31ull * 31ull)
|
||||
+ static_cast<unsigned char>( p[0] ) * (31ull * 31ull * 31ull * 31ull * 31ull * 31ull * 31ull)
|
||||
+ static_cast<unsigned char>( p[1] ) * (31ull * 31ull * 31ull * 31ull * 31ull * 31ull)
|
||||
+ static_cast<unsigned char>( p[2] ) * (31ull * 31ull * 31ull * 31ull * 31ull)
|
||||
+ static_cast<unsigned char>( p[3] ) * (31ull * 31ull * 31ull * 31ull)
|
||||
+ static_cast<unsigned char>( p[4] ) * (31ull * 31ull * 31ull)
|
||||
+ static_cast<unsigned char>( p[5] ) * (31ull * 31ull)
|
||||
+ static_cast<unsigned char>( p[6] ) * 31ull
|
||||
+ static_cast<unsigned char>( p[7] );
|
||||
|
||||
p += 8;
|
||||
n -= 8;
|
||||
}
|
||||
|
||||
while( n > 0 )
|
||||
{
|
||||
h = h * 31u + static_cast<unsigned char>( *p );
|
||||
|
||||
++p;
|
||||
--n;
|
||||
}
|
||||
|
||||
return static_cast<std::size_t>( h );
|
||||
}
|
||||
};
|
||||
|
||||
// fnv1a_hash
|
||||
|
||||
template<int Bits> struct fnv1a_hash_impl;
|
||||
@@ -316,16 +215,6 @@ struct absl_hash: absl::Hash<std::string_view>
|
||||
|
||||
#ifdef HAVE_MULXP_HASH
|
||||
|
||||
struct mulxp0_hash_
|
||||
{
|
||||
using is_avalanching = void;
|
||||
|
||||
std::size_t operator()( std::string_view const& st ) const BOOST_NOEXCEPT
|
||||
{
|
||||
return mulxp0_hash( (unsigned char const*)st.data(), st.size(), 0 );
|
||||
}
|
||||
};
|
||||
|
||||
struct mulxp1_hash_
|
||||
{
|
||||
using is_avalanching = void;
|
||||
@@ -336,16 +225,6 @@ struct mulxp1_hash_
|
||||
}
|
||||
};
|
||||
|
||||
struct mulxp2_hash_
|
||||
{
|
||||
using is_avalanching = void;
|
||||
|
||||
std::size_t operator()( std::string_view const& st ) const BOOST_NOEXCEPT
|
||||
{
|
||||
return mulxp2_hash( (unsigned char const*)st.data(), st.size(), 0 );
|
||||
}
|
||||
};
|
||||
|
||||
struct mulxp3_hash_
|
||||
{
|
||||
using is_avalanching = void;
|
||||
@@ -374,6 +253,24 @@ struct mulxp3_hash32_
|
||||
}
|
||||
};
|
||||
|
||||
struct mulxp1_hash32_
|
||||
{
|
||||
using is_avalanching = void;
|
||||
|
||||
std::size_t operator()( std::string_view const& st ) const BOOST_NOEXCEPT
|
||||
{
|
||||
std::size_t r = mulxp1_hash32( (unsigned char const*)st.data(), st.size(), 0 );
|
||||
|
||||
#if SIZE_MAX > UINT32_MAX
|
||||
|
||||
r |= r << 32;
|
||||
|
||||
#endif
|
||||
|
||||
return r;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
//
|
||||
@@ -384,9 +281,6 @@ int main()
|
||||
|
||||
test< boost::hash<std::string_view> >( "boost::hash" );
|
||||
test< std_hash >( "std::hash" );
|
||||
test< mul31_hash >( "mul31_hash" );
|
||||
test< mul31_x4_hash >( "mul31_x4_hash" );
|
||||
test< mul31_x8_hash >( "mul31_x8_hash" );
|
||||
test< fnv1a_hash >( "fnv1a_hash" );
|
||||
|
||||
#ifdef HAVE_ABSEIL
|
||||
@@ -395,12 +289,17 @@ int main()
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_ANKERL_UNORDERED_DENSE
|
||||
|
||||
test< ankerl::unordered_dense::hash<std::string_view> >( "ankerl::unordered_dense::hash" );
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_MULXP_HASH
|
||||
|
||||
test< mulxp0_hash_ >( "mulxp0_hash" );
|
||||
test< mulxp1_hash_ >( "mulxp1_hash" );
|
||||
test< mulxp2_hash_ >( "mulxp2_hash" );
|
||||
test< mulxp3_hash_ >( "mulxp3_hash" );
|
||||
test< mulxp1_hash32_ >( "mulxp1_hash32" );
|
||||
test< mulxp3_hash32_ >( "mulxp3_hash32" );
|
||||
|
||||
#endif
|
||||
@@ -409,7 +308,7 @@ int main()
|
||||
|
||||
for( auto const& x: times )
|
||||
{
|
||||
std::cout << std::setw( 22 ) << ( x.label_ + ": " ) << std::setw( 5 ) << x.time_ << " ms\n";
|
||||
std::cout << std::setw( 32 ) << ( x.label_ + ": " ) << std::setw( 5 ) << x.time_ << " ms\n";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -22,11 +22,13 @@ Out of the box, `boost::hash` supports
|
||||
|
||||
* standard integral types (integers, character types, and `bool`);
|
||||
* standard floating point types (`float`, `double`, `long double`);
|
||||
* pointers (to objects and to functions, but not pointers to members);
|
||||
* pointers (to objects and to functions, but not pointers to members)
|
||||
and `nullptr`;
|
||||
* enumeration types;
|
||||
* C arrays;
|
||||
* `std::complex`;
|
||||
* `std::pair`, `std::tuple`;
|
||||
* tuple-like types, such as `std::pair`, `std::tuple`, and user-defined
|
||||
types that specialize `std::tuple_size` and provide `get<I>`;
|
||||
* sequence-like types, both standard and user-defined (sequence-like types
|
||||
have `begin()` and `end()` member functions returning iterators);
|
||||
* unordered sequences, standard or user-defined (sequences for which the hash
|
||||
|
||||
@@ -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
|
||||
@@ -200,16 +216,9 @@ In Boost 1.81, `hash_range` was changed to process elements of type `char`,
|
||||
A `uint32_t` is composed from `first[0]` to `first[3]`, and that `uint32_t`
|
||||
is fed to `hash_combine`.
|
||||
|
||||
In principle, when `size_t` is 64 bit, we could have used `uint64_t` instead.
|
||||
We do not, because this allows producing an arbitrary hash value by choosing
|
||||
the input bytes appropriately (because `hash_combine` is reversible.)
|
||||
|
||||
Allowing control only over 32 bits of the full 64 bit `size_t` value makes
|
||||
these "chosen plaintext attacks" harder.
|
||||
|
||||
This is not as harmful to performance as it first appears, because the
|
||||
input to `hash<string>` (e.g. the key in an unordered container) is often
|
||||
short (9 to 13 bytes in some typical scenarios.)
|
||||
In Boost 1.82, `hash_range` for these types was changed to use
|
||||
https://github.com/pdimov/mulxp_hash[`mulxp1_hash`]. This improves both
|
||||
quality and speed of string hashing.
|
||||
|
||||
Note that `hash_range` has also traditionally guaranteed that the same element
|
||||
sequence yields the same hash value regardless of the iterator type. This
|
||||
|
||||
@@ -8,6 +8,21 @@ https://www.boost.org/LICENSE_1_0.txt
|
||||
= Recent Changes
|
||||
:idprefix: recent_
|
||||
|
||||
== 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`],
|
||||
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
|
||||
|
||||
Major update.
|
||||
@@ -24,9 +39,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.
|
||||
|
||||
@@ -30,6 +30,7 @@ template<class T> struct is_range;
|
||||
template<class T> struct is_contiguous_range;
|
||||
template<class T> struct is_unordered_range;
|
||||
template<class T> struct is_described_class;
|
||||
template<class T> struct is_tuple_like;
|
||||
|
||||
} // namespace container_hash
|
||||
|
||||
@@ -89,8 +90,9 @@ template<class T>
|
||||
template<class A, class B>
|
||||
std::size_t hash_value( std::pair<A, B> const& v );
|
||||
|
||||
template<class... T>
|
||||
std::size_t hash_value( std::tuple<T...> const& v );
|
||||
// Enabled only when container_hash::is_tuple_like<T>::value is true
|
||||
template<class T>
|
||||
std::size_t hash_value( T const& v );
|
||||
|
||||
// Enabled only when container_hash::is_range<T>::value is true
|
||||
template<class T>
|
||||
@@ -240,11 +242,16 @@ for( ; first != last; ++first )
|
||||
}
|
||||
----
|
||||
|
||||
Otherwise, bytes from `[first, last)` are coalesced in an unspecified manner
|
||||
and then passed to `hash_combine`, more than one at a time. This is done in
|
||||
order to improve performance when hashing strings.
|
||||
Otherwise, bytes from `[first, last)` are coalesced and hashed in an
|
||||
unspecified manner. This is done in order to improve performance when hashing
|
||||
strings.
|
||||
--
|
||||
|
||||
Remarks: ::
|
||||
For chars, the current implementation uses
|
||||
https://github.com/pdimov/mulxp_hash[`mulxp1_hash`] when `std::size_t` is
|
||||
64 bit, and `mulxp1_hash32` when it's 32 bit.
|
||||
|
||||
[source]
|
||||
----
|
||||
template<class It> std::size_t hash_range( It first, It last );
|
||||
@@ -385,8 +392,9 @@ return seed;
|
||||
|
||||
[source]
|
||||
----
|
||||
template<class... T>
|
||||
std::size_t hash_value( std::tuple<T...> const& v );
|
||||
// Enabled only when container_hash::is_tuple_like<T>::value is true
|
||||
template<class T>
|
||||
std::size_t hash_value( T const& v );
|
||||
----
|
||||
|
||||
Effects: ::
|
||||
@@ -395,15 +403,21 @@ Effects: ::
|
||||
----
|
||||
std::size_t seed = 0;
|
||||
|
||||
boost::hash_combine( seed, std::get<0>(v) );
|
||||
boost::hash_combine( seed, std::get<1>(v) );
|
||||
using std::get;
|
||||
|
||||
boost::hash_combine( seed, get<0>(v) );
|
||||
boost::hash_combine( seed, get<1>(v) );
|
||||
// ...
|
||||
boost::hash_combine( seed, std::get<N-1>(v) );
|
||||
boost::hash_combine( seed, get<N-1>(v) );
|
||||
|
||||
return seed;
|
||||
----
|
||||
+
|
||||
where `N` is `sizeof...(T)`.
|
||||
where `N` is `std::tuple_size<T>::value`.
|
||||
|
||||
Remarks: ::
|
||||
This overload is only enabled when
|
||||
`container_hash::is_range<T>::value` is `false`.
|
||||
|
||||
[source]
|
||||
----
|
||||
@@ -703,3 +717,38 @@ template<class T> struct is_described_class
|
||||
|
||||
Users are allowed to specialize `is_described_class` for their types
|
||||
if the default behavior does not deduce the correct value.
|
||||
|
||||
== <boost/container_hash/{zwsp}is_tuple_like.hpp>
|
||||
|
||||
Defines the trait `boost::container_hash::is_tuple_like`.
|
||||
|
||||
[source]
|
||||
----
|
||||
namespace boost
|
||||
{
|
||||
|
||||
namespace container_hash
|
||||
{
|
||||
|
||||
template<class T> struct is_tuple_like;
|
||||
|
||||
} // namespace container_hash
|
||||
|
||||
} // namespace boost
|
||||
----
|
||||
|
||||
=== is_tuple_like<T>
|
||||
|
||||
[source]
|
||||
----
|
||||
template<class T> struct is_tuple_like
|
||||
{
|
||||
static constexpr bool value = /* see below */;
|
||||
};
|
||||
----
|
||||
|
||||
`is_tuple_like<T>::value` is `true` when `std::tuple_size<T>::value`
|
||||
is valid.
|
||||
|
||||
Users are allowed to specialize `is_tuple_like` for their types
|
||||
if the default behavior does not deduce the correct value.
|
||||
|
||||
146
include/boost/container_hash/detail/hash_integral.hpp
Normal file
146
include/boost/container_hash/detail/hash_integral.hpp
Normal 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
|
||||
@@ -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;
|
||||
|
||||
@@ -6,39 +6,42 @@
|
||||
#define BOOST_HASH_DETAIL_HASH_RANGE_HPP
|
||||
|
||||
#include <boost/container_hash/hash_fwd.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 <boost/container_hash/detail/mulx.hpp>
|
||||
#include <type_traits>
|
||||
#include <cstdint>
|
||||
#include <iterator>
|
||||
#include <limits>
|
||||
#include <cstddef>
|
||||
#include <climits>
|
||||
#include <iterator>
|
||||
#include <cstring>
|
||||
|
||||
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
|
||||
|
||||
// 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 )
|
||||
@@ -51,120 +54,352 @@ std::size_t >::type
|
||||
return seed;
|
||||
}
|
||||
|
||||
template<class It>
|
||||
inline typename boost::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::size_t>::type
|
||||
hash_range( std::size_t seed, It first, It last )
|
||||
// specialized char[] version, 32 bit
|
||||
|
||||
template<class It> inline std::uint32_t read32le( It p )
|
||||
{
|
||||
std::size_t n = static_cast<std::size_t>( last - first );
|
||||
// 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
|
||||
|
||||
for( ; n >= 4; first += 4, n -= 4 )
|
||||
{
|
||||
// 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
|
||||
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;
|
||||
|
||||
boost::uint32_t w =
|
||||
static_cast<boost::uint32_t>( static_cast<unsigned char>( first[0] ) ) |
|
||||
static_cast<boost::uint32_t>( static_cast<unsigned char>( first[1] ) ) << 8 |
|
||||
static_cast<boost::uint32_t>( static_cast<unsigned char>( first[2] ) ) << 16 |
|
||||
static_cast<boost::uint32_t>( static_cast<unsigned char>( first[3] ) ) << 24;
|
||||
return w;
|
||||
}
|
||||
|
||||
hash_combine( seed, w );
|
||||
}
|
||||
#if defined(_MSC_VER) && !defined(__clang__)
|
||||
|
||||
{
|
||||
// add a trailing suffix byte of 0x01 because otherwise sequences of
|
||||
// trailing zeroes are indistinguishable from end of string
|
||||
template<class T> inline std::uint32_t read32le( T* p )
|
||||
{
|
||||
std::uint32_t w;
|
||||
|
||||
boost::uint32_t w = 0x01u;
|
||||
std::memcpy( &w, p, 4 );
|
||||
return w;
|
||||
}
|
||||
|
||||
switch( n )
|
||||
{
|
||||
case 1:
|
||||
#endif
|
||||
|
||||
w =
|
||||
static_cast<boost::uint32_t>( static_cast<unsigned char>( first[0] ) ) |
|
||||
0x0100u;
|
||||
|
||||
break;
|
||||
|
||||
case 2:
|
||||
|
||||
w =
|
||||
static_cast<boost::uint32_t>( static_cast<unsigned char>( first[0] ) ) |
|
||||
static_cast<boost::uint32_t>( static_cast<unsigned char>( first[1] ) ) << 8 |
|
||||
0x010000u;
|
||||
|
||||
break;
|
||||
|
||||
case 3:
|
||||
|
||||
w =
|
||||
static_cast<boost::uint32_t>( static_cast<unsigned char>( first[0] ) ) |
|
||||
static_cast<boost::uint32_t>( static_cast<unsigned char>( first[1] ) ) << 8 |
|
||||
static_cast<boost::uint32_t>( static_cast<unsigned char>( first[2] ) ) << 16 |
|
||||
0x01000000u;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
hash_combine( seed, w );
|
||||
}
|
||||
|
||||
return seed;
|
||||
inline std::uint64_t mul32( std::uint32_t x, std::uint32_t 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 )
|
||||
{
|
||||
It p = first;
|
||||
std::size_t n = static_cast<std::size_t>( last - first );
|
||||
|
||||
std::uint32_t const q = 0x9e3779b9U;
|
||||
std::uint32_t const k = 0xe35e67b1U; // q * q
|
||||
|
||||
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 )
|
||||
{
|
||||
std::uint32_t v1 = read32le( p );
|
||||
|
||||
w += q;
|
||||
h ^= mul32( v1 + w, k );
|
||||
|
||||
p += 4;
|
||||
n -= 4;
|
||||
}
|
||||
|
||||
{
|
||||
std::uint32_t v1 = 0;
|
||||
|
||||
if( n >= 1 )
|
||||
{
|
||||
std::size_t const x1 = ( n - 1 ) & 2; // 1: 0, 2: 0, 3: 2
|
||||
std::size_t const x2 = n >> 1; // 1: 0, 2: 1, 3: 1
|
||||
|
||||
v1 =
|
||||
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;
|
||||
h ^= mul32( v1 + w, k );
|
||||
}
|
||||
|
||||
w += q;
|
||||
h ^= mul32( static_cast<std::uint32_t>( h & 0xFFFFFFFF ) + w, static_cast<std::uint32_t>( h >> 32 ) + w + k );
|
||||
|
||||
return static_cast<std::uint32_t>( h & 0xFFFFFFFF ) ^ static_cast<std::uint32_t>( h >> 32 );
|
||||
}
|
||||
|
||||
template<class It>
|
||||
inline typename std::enable_if<
|
||||
is_char_type<typename std::iterator_traits<It>::value_type>::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;
|
||||
|
||||
std::uint32_t const q = 0x9e3779b9U;
|
||||
std::uint32_t const k = 0xe35e67b1U; // q * q
|
||||
|
||||
std::uint64_t h = mul32( static_cast<std::uint32_t>( seed ) + q, k );
|
||||
std::uint32_t w = static_cast<std::uint32_t>( h & 0xFFFFFFFF );
|
||||
|
||||
std::uint32_t v1 = 0;
|
||||
|
||||
for( ;; )
|
||||
{
|
||||
boost::uint32_t w = 0;
|
||||
v1 = 0;
|
||||
|
||||
if( first == last )
|
||||
{
|
||||
hash_combine( seed, w | 0x01u );
|
||||
return seed;
|
||||
break;
|
||||
}
|
||||
|
||||
w |= static_cast<boost::uint32_t>( static_cast<unsigned char>( *first ) );
|
||||
v1 |= static_cast<std::uint32_t>( static_cast<unsigned char>( *first ) );
|
||||
++first;
|
||||
++n;
|
||||
|
||||
if( first == last )
|
||||
{
|
||||
hash_combine( seed, w | 0x0100u );
|
||||
return seed;
|
||||
break;
|
||||
}
|
||||
|
||||
w |= 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;
|
||||
|
||||
if( first == last )
|
||||
{
|
||||
hash_combine( seed, w | 0x010000u );
|
||||
return seed;
|
||||
break;
|
||||
}
|
||||
|
||||
w |= 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;
|
||||
|
||||
if( first == last )
|
||||
{
|
||||
hash_combine( seed, w | 0x01000000u );
|
||||
return seed;
|
||||
break;
|
||||
}
|
||||
|
||||
w |= 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;
|
||||
|
||||
hash_combine( seed, w );
|
||||
w += q;
|
||||
h ^= mul32( v1 + w, k );
|
||||
}
|
||||
|
||||
h ^= n;
|
||||
|
||||
w += q;
|
||||
h ^= mul32( v1 + w, k );
|
||||
|
||||
w += q;
|
||||
h ^= mul32( static_cast<std::uint32_t>( h & 0xFFFFFFFF ) + w, static_cast<std::uint32_t>( h >> 32 ) + w + k );
|
||||
|
||||
return static_cast<std::uint32_t>( h & 0xFFFFFFFF ) ^ static_cast<std::uint32_t>( h >> 32 );
|
||||
}
|
||||
|
||||
// specialized char[] version, 64 bit
|
||||
|
||||
template<class It> inline std::uint64_t read64le( It p )
|
||||
{
|
||||
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 std::uint64_t read64le( T* p )
|
||||
{
|
||||
std::uint64_t w;
|
||||
|
||||
std::memcpy( &w, p, 8 );
|
||||
return w;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
template<class It>
|
||||
inline typename std::enable_if<
|
||||
is_char_type<typename std::iterator_traits<It>::value_type>::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 )
|
||||
{
|
||||
It p = first;
|
||||
std::size_t n = static_cast<std::size_t>( last - first );
|
||||
|
||||
std::uint64_t const q = 0x9e3779b97f4a7c15;
|
||||
std::uint64_t const k = 0xdf442d22ce4859b9; // q * q
|
||||
|
||||
std::uint64_t w = mulx( seed + q, k );
|
||||
std::uint64_t h = w ^ n;
|
||||
|
||||
while( n >= 8 )
|
||||
{
|
||||
std::uint64_t v1 = read64le( p );
|
||||
|
||||
w += q;
|
||||
h ^= mulx( v1 + w, k );
|
||||
|
||||
p += 8;
|
||||
n -= 8;
|
||||
}
|
||||
|
||||
{
|
||||
std::uint64_t v1 = 0;
|
||||
|
||||
if( n >= 4 )
|
||||
{
|
||||
v1 = static_cast<std::uint64_t>( read32le( p + static_cast<std::ptrdiff_t>( n - 4 ) ) ) << ( n - 4 ) * 8 | read32le( p );
|
||||
}
|
||||
else if( n >= 1 )
|
||||
{
|
||||
std::size_t const x1 = ( n - 1 ) & 2; // 1: 0, 2: 0, 3: 2
|
||||
std::size_t const x2 = n >> 1; // 1: 0, 2: 1, 3: 1
|
||||
|
||||
v1 =
|
||||
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;
|
||||
h ^= mulx( v1 + w, k );
|
||||
}
|
||||
|
||||
return mulx( h + w, k );
|
||||
}
|
||||
|
||||
template<class It>
|
||||
inline typename std::enable_if<
|
||||
is_char_type<typename std::iterator_traits<It>::value_type>::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;
|
||||
|
||||
std::uint64_t const q = 0x9e3779b97f4a7c15;
|
||||
std::uint64_t const k = 0xdf442d22ce4859b9; // q * q
|
||||
|
||||
std::uint64_t w = mulx( seed + q, k );
|
||||
std::uint64_t h = w;
|
||||
|
||||
std::uint64_t v1 = 0;
|
||||
|
||||
for( ;; )
|
||||
{
|
||||
v1 = 0;
|
||||
|
||||
if( first == last )
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
v1 |= static_cast<std::uint64_t>( static_cast<unsigned char>( *first ) );
|
||||
++first;
|
||||
++n;
|
||||
|
||||
if( first == last )
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
v1 |= static_cast<std::uint64_t>( static_cast<unsigned char>( *first ) ) << 8;
|
||||
++first;
|
||||
++n;
|
||||
|
||||
if( first == last )
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
v1 |= static_cast<std::uint64_t>( static_cast<unsigned char>( *first ) ) << 16;
|
||||
++first;
|
||||
++n;
|
||||
|
||||
if( first == last )
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
v1 |= static_cast<std::uint64_t>( static_cast<unsigned char>( *first ) ) << 24;
|
||||
++first;
|
||||
++n;
|
||||
|
||||
if( first == last )
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
v1 |= static_cast<std::uint64_t>( static_cast<unsigned char>( *first ) ) << 32;
|
||||
++first;
|
||||
++n;
|
||||
|
||||
if( first == last )
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
v1 |= static_cast<std::uint64_t>( static_cast<unsigned char>( *first ) ) << 40;
|
||||
++first;
|
||||
++n;
|
||||
|
||||
if( first == last )
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
v1 |= static_cast<std::uint64_t>( static_cast<unsigned char>( *first ) ) << 48;
|
||||
++first;
|
||||
++n;
|
||||
|
||||
if( first == last )
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
v1 |= static_cast<std::uint64_t>( static_cast<unsigned char>( *first ) ) << 56;
|
||||
++first;
|
||||
++n;
|
||||
|
||||
w += q;
|
||||
h ^= mulx( v1 + w, k );
|
||||
}
|
||||
|
||||
h ^= n;
|
||||
|
||||
w += q;
|
||||
h ^= mulx( v1 + w, k );
|
||||
|
||||
return mulx( h + w, k );
|
||||
}
|
||||
|
||||
} // namespace hash_detail
|
||||
|
||||
@@ -1,133 +0,0 @@
|
||||
// Copyright 2005-2009 Daniel James.
|
||||
// Copyright 2021 Peter Dimov.
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#ifndef BOOST_HASH_DETAIL_HASH_TUPLE_LIKE_HPP
|
||||
#define BOOST_HASH_DETAIL_HASH_TUPLE_LIKE_HPP
|
||||
|
||||
#include <boost/container_hash/hash_fwd.hpp>
|
||||
#include <boost/type_traits/enable_if.hpp>
|
||||
#include <boost/config.hpp>
|
||||
|
||||
#if defined(BOOST_NO_CXX11_HDR_TUPLE)
|
||||
|
||||
// no support
|
||||
|
||||
#else
|
||||
|
||||
#include <tuple>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace hash_detail
|
||||
{
|
||||
|
||||
template <std::size_t I, typename T>
|
||||
inline typename boost::enable_if_<(I == std::tuple_size<T>::value),
|
||||
void>::type
|
||||
hash_combine_tuple(std::size_t&, T const&)
|
||||
{
|
||||
}
|
||||
|
||||
template <std::size_t I, typename T>
|
||||
inline typename boost::enable_if_<(I < std::tuple_size<T>::value),
|
||||
void>::type
|
||||
hash_combine_tuple(std::size_t& seed, T const& v)
|
||||
{
|
||||
boost::hash_combine(seed, std::get<I>(v));
|
||||
boost::hash_detail::hash_combine_tuple<I + 1>(seed, v);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline std::size_t hash_tuple(T const& v)
|
||||
{
|
||||
std::size_t seed = 0;
|
||||
boost::hash_detail::hash_combine_tuple<0>(seed, v);
|
||||
return seed;
|
||||
}
|
||||
|
||||
} // namespace hash_detail
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
|
||||
template <typename... T>
|
||||
inline std::size_t hash_value(std::tuple<T...> const& v)
|
||||
{
|
||||
return boost::hash_detail::hash_tuple(v);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
inline std::size_t hash_value(std::tuple<> const& v)
|
||||
{
|
||||
return boost::hash_detail::hash_tuple(v);
|
||||
}
|
||||
|
||||
template<typename A0>
|
||||
inline std::size_t hash_value(std::tuple<A0> const& v)
|
||||
{
|
||||
return boost::hash_detail::hash_tuple(v);
|
||||
}
|
||||
|
||||
template<typename A0, typename A1>
|
||||
inline std::size_t hash_value(std::tuple<A0, A1> const& v)
|
||||
{
|
||||
return boost::hash_detail::hash_tuple(v);
|
||||
}
|
||||
|
||||
template<typename A0, typename A1, typename A2>
|
||||
inline std::size_t hash_value(std::tuple<A0, A1, A2> const& v)
|
||||
{
|
||||
return boost::hash_detail::hash_tuple(v);
|
||||
}
|
||||
|
||||
template<typename A0, typename A1, typename A2, typename A3>
|
||||
inline std::size_t hash_value(std::tuple<A0, A1, A2, A3> const& v)
|
||||
{
|
||||
return boost::hash_detail::hash_tuple(v);
|
||||
}
|
||||
|
||||
template<typename A0, typename A1, typename A2, typename A3, typename A4>
|
||||
inline std::size_t hash_value(std::tuple<A0, A1, A2, A3, A4> const& v)
|
||||
{
|
||||
return boost::hash_detail::hash_tuple(v);
|
||||
}
|
||||
|
||||
template<typename A0, typename A1, typename A2, typename A3, typename A4, typename A5>
|
||||
inline std::size_t hash_value(std::tuple<A0, A1, A2, A3, A4, A5> const& v)
|
||||
{
|
||||
return boost::hash_detail::hash_tuple(v);
|
||||
}
|
||||
|
||||
template<typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6>
|
||||
inline std::size_t hash_value(std::tuple<A0, A1, A2, A3, A4, A5, A6> const& v)
|
||||
{
|
||||
return boost::hash_detail::hash_tuple(v);
|
||||
}
|
||||
|
||||
template<typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7>
|
||||
inline std::size_t hash_value(std::tuple<A0, A1, A2, A3, A4, A5, A6, A7> const& v)
|
||||
{
|
||||
return boost::hash_detail::hash_tuple(v);
|
||||
}
|
||||
|
||||
template<typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8>
|
||||
inline std::size_t hash_value(std::tuple<A0, A1, A2, A3, A4, A5, A6, A7, A8> const& v)
|
||||
{
|
||||
return boost::hash_detail::hash_tuple(v);
|
||||
}
|
||||
|
||||
template<typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9>
|
||||
inline std::size_t hash_value(std::tuple<A0, A1, A2, A3, A4, A5, A6, A7, A8, A9> const& v)
|
||||
{
|
||||
return boost::hash_detail::hash_tuple(v);
|
||||
}
|
||||
|
||||
#endif // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // #if defined(BOOST_NO_CXX11_HDR_TUPLE)
|
||||
|
||||
#endif // #ifndef BOOST_HASH_DETAIL_HASH_TUPLE_LIKE_HPP
|
||||
62
include/boost/container_hash/detail/hash_tuple_like.hpp
Normal file
62
include/boost/container_hash/detail/hash_tuple_like.hpp
Normal file
@@ -0,0 +1,62 @@
|
||||
// Copyright 2005-2009 Daniel James.
|
||||
// Copyright 2021 Peter Dimov.
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#ifndef BOOST_HASH_DETAIL_HASH_TUPLE_LIKE_HPP
|
||||
#define BOOST_HASH_DETAIL_HASH_TUPLE_LIKE_HPP
|
||||
|
||||
#include <boost/container_hash/hash_fwd.hpp>
|
||||
#include <boost/container_hash/is_tuple_like.hpp>
|
||||
#include <boost/container_hash/is_range.hpp>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace hash_detail
|
||||
{
|
||||
|
||||
template <std::size_t I, typename T>
|
||||
inline
|
||||
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 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;
|
||||
boost::hash_combine( seed, get<I>( v ) );
|
||||
|
||||
boost::hash_detail::hash_combine_tuple_like<I + 1>( seed, v );
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline std::size_t hash_tuple_like( T const& v )
|
||||
{
|
||||
std::size_t seed = 0;
|
||||
|
||||
boost::hash_detail::hash_combine_tuple_like<0>( seed, v );
|
||||
|
||||
return seed;
|
||||
}
|
||||
|
||||
} // namespace hash_detail
|
||||
|
||||
template <class T>
|
||||
inline
|
||||
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 )
|
||||
{
|
||||
return boost::hash_detail::hash_tuple_like( v );
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // #ifndef BOOST_HASH_DETAIL_HASH_TUPLE_LIKE_HPP
|
||||
79
include/boost/container_hash/detail/mulx.hpp
Normal file
79
include/boost/container_hash/detail/mulx.hpp
Normal file
@@ -0,0 +1,79 @@
|
||||
// Copyright 2022, 2023 Peter Dimov
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#ifndef BOOST_HASH_DETAIL_MULX_HPP
|
||||
#define BOOST_HASH_DETAIL_MULX_HPP
|
||||
|
||||
#include <cstdint>
|
||||
#if defined(_MSC_VER)
|
||||
# include <intrin.h>
|
||||
#endif
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace hash_detail
|
||||
{
|
||||
|
||||
#if defined(_MSC_VER) && defined(_M_X64) && !defined(__clang__)
|
||||
|
||||
__forceinline std::uint64_t mulx( std::uint64_t x, std::uint64_t y )
|
||||
{
|
||||
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 std::uint64_t mulx( std::uint64_t x, std::uint64_t y )
|
||||
{
|
||||
std::uint64_t r = x * y;
|
||||
std::uint64_t r2 = __umulh( x, y );
|
||||
return r ^ r2;
|
||||
}
|
||||
|
||||
#elif defined(__SIZEOF_INT128__)
|
||||
|
||||
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<std::uint64_t>( r ) ^ static_cast<std::uint64_t>( r >> 64 );
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
inline std::uint64_t mulx( std::uint64_t x, std::uint64_t y )
|
||||
{
|
||||
std::uint64_t x1 = static_cast<std::uint32_t>( x );
|
||||
std::uint64_t x2 = x >> 32;
|
||||
|
||||
std::uint64_t y1 = static_cast<std::uint32_t>( y );
|
||||
std::uint64_t y2 = y >> 32;
|
||||
|
||||
std::uint64_t r3 = x2 * y2;
|
||||
|
||||
std::uint64_t r2a = x1 * y2;
|
||||
|
||||
r3 += r2a >> 32;
|
||||
|
||||
std::uint64_t r2b = x2 * y1;
|
||||
|
||||
r3 += r2b >> 32;
|
||||
|
||||
std::uint64_t r1 = x1 * y1;
|
||||
|
||||
std::uint64_t r2 = (r1 >> 32) + static_cast<std::uint32_t>( r2a ) + static_cast<std::uint32_t>( r2b );
|
||||
|
||||
r1 = (r2 << 32) + static_cast<std::uint32_t>( r1 );
|
||||
r3 += r2 >> 32;
|
||||
|
||||
return r1 ^ r3;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace hash_detail
|
||||
} // namespace boost
|
||||
|
||||
#endif // #ifndef BOOST_HASH_DETAIL_MULX_HPP
|
||||
@@ -15,22 +15,14 @@
|
||||
#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_tuple.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>
|
||||
@@ -76,95 +68,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 ) + 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
|
||||
@@ -198,7 +107,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;
|
||||
@@ -210,7 +119,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 );
|
||||
@@ -222,7 +131,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;
|
||||
@@ -239,7 +148,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;
|
||||
@@ -256,7 +165,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;
|
||||
@@ -279,7 +188,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 );
|
||||
@@ -290,7 +199,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) );
|
||||
}
|
||||
|
||||
@@ -335,7 +244,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() );
|
||||
@@ -344,7 +253,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() );
|
||||
@@ -353,7 +262,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() );
|
||||
@@ -366,7 +275,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() );
|
||||
@@ -375,14 +284,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() );
|
||||
@@ -391,7 +300,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() );
|
||||
@@ -409,10 +318,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;
|
||||
|
||||
@@ -502,7 +411,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 ) );
|
||||
@@ -519,7 +428,7 @@ namespace boost
|
||||
{
|
||||
if( !v )
|
||||
{
|
||||
// Arbitray value for empty optional.
|
||||
// Arbitrary value for empty optional.
|
||||
return 0x12345678;
|
||||
}
|
||||
else
|
||||
@@ -653,20 +562,11 @@ namespace boost
|
||||
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
|
||||
|
||||
@@ -18,6 +18,7 @@ template<class T> struct is_range;
|
||||
template<class T> struct is_contiguous_range;
|
||||
template<class T> struct is_unordered_range;
|
||||
template<class T> struct is_described_class;
|
||||
template<class T> struct is_tuple_like;
|
||||
|
||||
} // namespace container_hash
|
||||
|
||||
|
||||
@@ -6,15 +6,12 @@
|
||||
#define BOOST_HASH_IS_CONTIGUOUS_RANGE_HPP_INCLUDED
|
||||
|
||||
#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
|
||||
@@ -23,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 ) )
|
||||
{
|
||||
@@ -38,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
|
||||
|
||||
@@ -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
|
||||
{
|
||||
};
|
||||
|
||||
|
||||
@@ -5,28 +5,25 @@
|
||||
#ifndef BOOST_HASH_IS_RANGE_HPP_INCLUDED
|
||||
#define BOOST_HASH_IS_RANGE_HPP_INCLUDED
|
||||
|
||||
#include <boost/type_traits/integral_constant.hpp>
|
||||
#include <boost/type_traits/is_integral.hpp>
|
||||
#include <boost/type_traits/declval.hpp>
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
#include <boost/type_traits/remove_cv.hpp>
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/config/workaround.hpp>
|
||||
#include <iterator>
|
||||
#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
|
||||
|
||||
@@ -39,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
|
||||
|
||||
36
include/boost/container_hash/is_tuple_like.hpp
Normal file
36
include/boost/container_hash/is_tuple_like.hpp
Normal file
@@ -0,0 +1,36 @@
|
||||
#ifndef BOOST_HASH_IS_TUPLE_LIKE_HPP_INCLUDED
|
||||
#define BOOST_HASH_IS_TUPLE_LIKE_HPP_INCLUDED
|
||||
|
||||
// Copyright 2017, 2022 Peter Dimov.
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace hash_detail
|
||||
{
|
||||
|
||||
template<class T, class E = std::true_type> struct is_tuple_like_: std::false_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
|
||||
{
|
||||
};
|
||||
|
||||
} // namespace hash_detail
|
||||
|
||||
namespace container_hash
|
||||
{
|
||||
|
||||
template<class T> struct is_tuple_like: hash_detail::is_tuple_like_< typename std::remove_cv<T>::type >
|
||||
{
|
||||
};
|
||||
|
||||
} // namespace container_hash
|
||||
} // namespace boost
|
||||
|
||||
#endif // #ifndef BOOST_HASH_IS_TUPLE_LIKE_HPP_INCLUDED
|
||||
@@ -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 >
|
||||
{
|
||||
};
|
||||
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
]
|
||||
|
||||
@@ -75,10 +75,13 @@ run hash_integral_test.cpp ;
|
||||
run hash_string_test2.cpp ;
|
||||
|
||||
# for gcc-4.8
|
||||
local fs-path-req = "-<toolset>gcc:<cxxflags>-Wshadow" "-<toolset>gcc:<cxxflags>-Wconversion" ;
|
||||
local fs-path-req = "-<toolset>gcc:<cxxflags>-Wshadow" "-<toolset>gcc:<cxxflags>-Wconversion" <toolset>gcc-4.7:<build>no ;
|
||||
|
||||
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 ;
|
||||
run is_range_test2.cpp : : : $(fs-path-req) <toolset>msvc-8.0:<build>no ;
|
||||
run hash_fs_path_test.cpp /boost//filesystem/<warnings>off : : : $(fs-path-req)
|
||||
<toolset>msvc-14.0,<cxxstd>latest:<build>no
|
||||
<undefined-sanitizer>norecover:<link>static ;
|
||||
|
||||
run is_range_test2.cpp : : : $(fs-path-req) ;
|
||||
|
||||
run hash_container_test.cpp ;
|
||||
|
||||
@@ -116,4 +119,15 @@ run described_class_test.cpp
|
||||
run hash_is_avalanching_test.cpp ;
|
||||
run hash_is_avalanching_test2.cpp ;
|
||||
|
||||
run hash_integral_test2.cpp ;
|
||||
|
||||
run hash_nullptr_test.cpp ;
|
||||
|
||||
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 ;
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
39
test/hash_container_test2.cpp
Normal file
39
test/hash_container_test2.cpp
Normal 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();
|
||||
}
|
||||
@@ -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()
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
#include <boost/core/lightweight_test.hpp>
|
||||
#include <boost/core/type_name.hpp>
|
||||
#include <boost/type_traits/is_signed.hpp>
|
||||
#include <set>
|
||||
#include <boost/config.hpp>
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
#pragma warning(disable: 4127) // conditional expression is constant
|
||||
|
||||
52
test/hash_integral_test2.cpp
Normal file
52
test/hash_integral_test2.cpp
Normal file
@@ -0,0 +1,52 @@
|
||||
// Copyright 2005-2009 Daniel James.
|
||||
// Copyright 2021 Peter Dimov.
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#include <boost/container_hash/hash.hpp>
|
||||
#include <boost/core/lightweight_test.hpp>
|
||||
#include <boost/core/type_name.hpp>
|
||||
#include <boost/type_traits/is_signed.hpp>
|
||||
#include <boost/type_traits/make_unsigned.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
#include <boost/config.hpp>
|
||||
|
||||
// This test checks that values representable in a signed
|
||||
// and the corresponding unsigned type hash to the same value
|
||||
|
||||
template<class T>
|
||||
void signed_unsigned_test()
|
||||
{
|
||||
BOOST_STATIC_ASSERT( boost::is_signed<T>::value );
|
||||
|
||||
typedef typename boost::make_unsigned<T>::type U;
|
||||
|
||||
T x = std::numeric_limits<T>::max();
|
||||
|
||||
do
|
||||
{
|
||||
BOOST_TEST_EQ( boost::hash<T>()( x ), boost::hash<U>()( static_cast<U>( x ) ) );
|
||||
x /= 3;
|
||||
}
|
||||
while( x > 0 );
|
||||
}
|
||||
|
||||
#define TEST(type) std::cerr << "Testing: " #type " (" << boost::core::type_name<type>() << ")\n"; signed_unsigned_test<type>();
|
||||
|
||||
int main()
|
||||
{
|
||||
TEST(signed char)
|
||||
TEST(short)
|
||||
TEST(int)
|
||||
TEST(long)
|
||||
|
||||
#if !defined(BOOST_NO_LONG_LONG)
|
||||
TEST(boost::long_long_type)
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_HAS_INT128)
|
||||
TEST(boost::int128_type)
|
||||
#endif
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -284,19 +284,19 @@ int main()
|
||||
// string
|
||||
#if SIZE_MAX == 4294967295U
|
||||
|
||||
BOOST_TEST_EQ( hv(std::string()), 1580013426U );
|
||||
BOOST_TEST_EQ( hv(std::string("abc")), 469308065U );
|
||||
BOOST_TEST_EQ( hv(std::string("\0", 1)), 165258820U );
|
||||
BOOST_TEST_EQ( hv(std::string("\0\0", 2)), 4017288109U );
|
||||
BOOST_TEST_EQ( hv(std::string("\0\0\0", 3)), 1352445396U );
|
||||
BOOST_TEST_EQ( hv(std::string()), 1868390524U );
|
||||
BOOST_TEST_EQ( hv(std::string("abc")), 3674866719U );
|
||||
BOOST_TEST_EQ( hv(std::string("\0", 1)), 1965885047U );
|
||||
BOOST_TEST_EQ( hv(std::string("\0\0", 2)), 54340706U );
|
||||
BOOST_TEST_EQ( hv(std::string("\0\0\0", 3)), 688730713U );
|
||||
|
||||
#else
|
||||
|
||||
BOOST_TEST_EQ( hv(std::string()), 2220755840493918647ULL );
|
||||
BOOST_TEST_EQ( hv(std::string("abc")), 7565583854499162206ULL );
|
||||
BOOST_TEST_EQ( hv(std::string("\0", 1)), 1241131678047372712ULL );
|
||||
BOOST_TEST_EQ( hv(std::string("\0\0", 2)), 152341731040131640ULL );
|
||||
BOOST_TEST_EQ( hv(std::string("\0\0\0", 3)), 12957252994983528908ULL );
|
||||
BOOST_TEST_EQ( hv(std::string()), 2060355526954642342ULL );
|
||||
BOOST_TEST_EQ( hv(std::string("abc")), 2539195663733406973ULL );
|
||||
BOOST_TEST_EQ( hv(std::string("\0", 1)), 18432168439372857722ULL );
|
||||
BOOST_TEST_EQ( hv(std::string("\0\0", 2)), 6494115972580589074ULL );
|
||||
BOOST_TEST_EQ( hv(std::string("\0\0\0", 3)), 4419026507380069870ULL );
|
||||
|
||||
#endif
|
||||
|
||||
@@ -376,17 +376,17 @@ int main()
|
||||
// vector<char>
|
||||
#if SIZE_MAX == 4294967295U
|
||||
|
||||
BOOST_TEST_EQ( hv(std::vector<char>(0)), 1580013426U );
|
||||
BOOST_TEST_EQ( hv(std::vector<char>(1)), 165258820U );
|
||||
BOOST_TEST_EQ( hv(std::vector<char>(2)), 4017288109U );
|
||||
BOOST_TEST_EQ( hv(std::vector<char>(3)), 1352445396U );
|
||||
BOOST_TEST_EQ( hv(std::vector<char>(0)), 1868390524U );
|
||||
BOOST_TEST_EQ( hv(std::vector<char>(1)), 1965885047U );
|
||||
BOOST_TEST_EQ( hv(std::vector<char>(2)), 54340706U );
|
||||
BOOST_TEST_EQ( hv(std::vector<char>(3)), 688730713U );
|
||||
|
||||
#else
|
||||
|
||||
BOOST_TEST_EQ( hv(std::vector<char>(0)), 2220755840493918647ULL );
|
||||
BOOST_TEST_EQ( hv(std::vector<char>(1)), 1241131678047372712ULL );
|
||||
BOOST_TEST_EQ( hv(std::vector<char>(2)), 152341731040131640ULL );
|
||||
BOOST_TEST_EQ( hv(std::vector<char>(3)), 12957252994983528908ULL );
|
||||
BOOST_TEST_EQ( hv(std::vector<char>(0)), 2060355526954642342ULL );
|
||||
BOOST_TEST_EQ( hv(std::vector<char>(1)), 18432168439372857722ULL );
|
||||
BOOST_TEST_EQ( hv(std::vector<char>(2)), 6494115972580589074ULL );
|
||||
BOOST_TEST_EQ( hv(std::vector<char>(3)), 4419026507380069870ULL );
|
||||
|
||||
#endif
|
||||
|
||||
@@ -427,17 +427,17 @@ int main()
|
||||
// list<char>
|
||||
#if SIZE_MAX == 4294967295U
|
||||
|
||||
BOOST_TEST_EQ( hv(std::list<char>(0)), 1580013426U );
|
||||
BOOST_TEST_EQ( hv(std::list<char>(1)), 165258820U );
|
||||
BOOST_TEST_EQ( hv(std::list<char>(2)), 4017288109U );
|
||||
BOOST_TEST_EQ( hv(std::list<char>(3)), 1352445396U );
|
||||
BOOST_TEST_EQ( hv(std::list<char>(0)), 1868390524U );
|
||||
BOOST_TEST_EQ( hv(std::list<char>(1)), 1965885047U );
|
||||
BOOST_TEST_EQ( hv(std::list<char>(2)), 54340706U );
|
||||
BOOST_TEST_EQ( hv(std::list<char>(3)), 688730713U );
|
||||
|
||||
#else
|
||||
|
||||
BOOST_TEST_EQ( hv(std::list<char>(0)), 2220755840493918647ULL );
|
||||
BOOST_TEST_EQ( hv(std::list<char>(1)), 1241131678047372712ULL );
|
||||
BOOST_TEST_EQ( hv(std::list<char>(2)), 152341731040131640ULL );
|
||||
BOOST_TEST_EQ( hv(std::list<char>(3)), 12957252994983528908ULL );
|
||||
BOOST_TEST_EQ( hv(std::list<char>(0)), 2060355526954642342ULL );
|
||||
BOOST_TEST_EQ( hv(std::list<char>(1)), 18432168439372857722ULL );
|
||||
BOOST_TEST_EQ( hv(std::list<char>(2)), 6494115972580589074ULL );
|
||||
BOOST_TEST_EQ( hv(std::list<char>(3)), 4419026507380069870ULL );
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
204
test/hash_tuple_like_test.cpp
Normal file
204
test/hash_tuple_like_test.cpp
Normal file
@@ -0,0 +1,204 @@
|
||||
// Copyright 2022 Peter Dimov.
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#if defined(__clang__)
|
||||
# pragma clang diagnostic ignored "-Wmismatched-tags"
|
||||
#endif
|
||||
|
||||
#include <boost/container_hash/hash.hpp>
|
||||
#include <boost/core/lightweight_test.hpp>
|
||||
#include <boost/type_traits/enable_if.hpp>
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
#include <boost/type_traits/integral_constant.hpp>
|
||||
#include <boost/config.hpp>
|
||||
#include <utility>
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_HDR_TUPLE)
|
||||
|
||||
#include <tuple>
|
||||
|
||||
namespace user
|
||||
{
|
||||
|
||||
struct Y1
|
||||
{
|
||||
int a;
|
||||
int b;
|
||||
};
|
||||
|
||||
template<std::size_t I> int& get( Y1& v );
|
||||
template<std::size_t I> int const& get( Y1 const& v );
|
||||
|
||||
template<> int& get<0>( Y1& v )
|
||||
{
|
||||
return v.a;
|
||||
}
|
||||
|
||||
template<> int const& get<0>( Y1 const& v )
|
||||
{
|
||||
return v.a;
|
||||
}
|
||||
|
||||
template<> int& get<1>( Y1& v )
|
||||
{
|
||||
return v.b;
|
||||
}
|
||||
|
||||
template<> int const& get<1>( Y1 const& v )
|
||||
{
|
||||
return v.b;
|
||||
}
|
||||
|
||||
struct Y2
|
||||
{
|
||||
int a;
|
||||
int b;
|
||||
|
||||
template<class T> friend
|
||||
typename boost::enable_if_<boost::is_same<T, Y2>::value, std::size_t>::type
|
||||
hash_value( T const& v )
|
||||
{
|
||||
std::size_t seed = 0;
|
||||
|
||||
boost::hash_combine( seed, v.a );
|
||||
boost::hash_combine( seed, v.b );
|
||||
|
||||
return seed;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace user
|
||||
|
||||
namespace std
|
||||
{
|
||||
|
||||
template<> struct tuple_size<user::Y1>: std::integral_constant<std::size_t, 2>
|
||||
{
|
||||
};
|
||||
|
||||
template<> struct tuple_size<user::Y2>: std::integral_constant<std::size_t, 2>
|
||||
{
|
||||
};
|
||||
|
||||
} // namespace std
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace container_hash
|
||||
{
|
||||
|
||||
template<> struct is_tuple_like<user::Y2>: boost::false_type {};
|
||||
|
||||
} // namespace container_hash
|
||||
} // namespace boost
|
||||
|
||||
#endif
|
||||
|
||||
template<class T> std::size_t hv( T const& t )
|
||||
{
|
||||
return boost::hash<T>()( t );
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
{
|
||||
std::pair<int, int> tp( 1, 2 );
|
||||
int const a[] = { 1, 2 };
|
||||
|
||||
BOOST_TEST_EQ( hv(tp), hv(a) );
|
||||
}
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_HDR_TUPLE)
|
||||
|
||||
{
|
||||
std::tuple<> tp;
|
||||
|
||||
BOOST_TEST_EQ( hv(tp), 0u );
|
||||
}
|
||||
|
||||
{
|
||||
std::tuple<int> tp( 1 );
|
||||
int const a[] = { 1 };
|
||||
|
||||
BOOST_TEST_EQ( hv(tp), hv(a) );
|
||||
}
|
||||
|
||||
{
|
||||
std::tuple<int, int> tp( 1, 2 );
|
||||
int const a[] = { 1, 2 };
|
||||
|
||||
BOOST_TEST_EQ( hv(tp), hv(a) );
|
||||
}
|
||||
|
||||
{
|
||||
std::tuple<int, int, int> tp( 1, 2, 3 );
|
||||
int const a[] = { 1, 2, 3 };
|
||||
|
||||
BOOST_TEST_EQ( hv(tp), hv(a) );
|
||||
}
|
||||
|
||||
{
|
||||
std::tuple<int, int, int, int> tp( 1, 2, 3, 4 );
|
||||
int const a[] = { 1, 2, 3, 4 };
|
||||
|
||||
BOOST_TEST_EQ( hv(tp), hv(a) );
|
||||
}
|
||||
|
||||
{
|
||||
std::tuple<int, int, int, int, int> tp( 1, 2, 3, 4, 5 );
|
||||
int const a[] = { 1, 2, 3, 4, 5 };
|
||||
|
||||
BOOST_TEST_EQ( hv(tp), hv(a) );
|
||||
}
|
||||
|
||||
{
|
||||
std::tuple<int, int, int, int, int, int> tp( 1, 2, 3, 4, 5, 6 );
|
||||
int const a[] = { 1, 2, 3, 4, 5, 6 };
|
||||
|
||||
BOOST_TEST_EQ( hv(tp), hv(a) );
|
||||
}
|
||||
|
||||
{
|
||||
std::tuple<int, int, int, int, int, int, int> tp( 1, 2, 3, 4, 5, 6, 7 );
|
||||
int const a[] = { 1, 2, 3, 4, 5, 6, 7 };
|
||||
|
||||
BOOST_TEST_EQ( hv(tp), hv(a) );
|
||||
}
|
||||
|
||||
{
|
||||
std::tuple<int, int, int, int, int, int, int, int> tp( 1, 2, 3, 4, 5, 6, 7, 8 );
|
||||
int const a[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
|
||||
|
||||
BOOST_TEST_EQ( hv(tp), hv(a) );
|
||||
}
|
||||
|
||||
{
|
||||
std::tuple<int, int, int, int, int, int, int, int, int> tp( 1, 2, 3, 4, 5, 6, 7, 8, 9 );
|
||||
int const a[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
|
||||
|
||||
BOOST_TEST_EQ( hv(tp), hv(a) );
|
||||
}
|
||||
|
||||
#if !BOOST_WORKAROUND(BOOST_MSVC, <= 1800)
|
||||
|
||||
{
|
||||
user::Y1 tp = { 1, 2 };
|
||||
int const a[] = { 1, 2 };
|
||||
|
||||
BOOST_TEST_EQ( hv(tp), hv(a) );
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
{
|
||||
user::Y2 tp = { 1, 2 };
|
||||
int const a[] = { 1, 2 };
|
||||
|
||||
BOOST_TEST_EQ( hv(tp), hv(a) );
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
||||
78
test/hash_tuple_like_test2.cpp
Normal file
78
test/hash_tuple_like_test2.cpp
Normal file
@@ -0,0 +1,78 @@
|
||||
// Copyright 2022 Peter Dimov.
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#if defined(__clang__)
|
||||
# pragma clang diagnostic ignored "-Wmismatched-tags"
|
||||
#endif
|
||||
|
||||
#include <boost/container_hash/hash.hpp>
|
||||
#include <boost/core/lightweight_test.hpp>
|
||||
#include <boost/type_traits/integral_constant.hpp>
|
||||
#include <boost/describe/class.hpp>
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/config/pragma_message.hpp>
|
||||
#include <utility>
|
||||
|
||||
#if defined(BOOST_NO_CXX11_HDR_TUPLE)
|
||||
|
||||
BOOST_PRAGMA_MESSAGE( "Skipping test because BOOST_NO_CXX11_HDR_TUPLE is defined" )
|
||||
int main() {}
|
||||
|
||||
#elif !defined(BOOST_DESCRIBE_CXX14)
|
||||
|
||||
BOOST_PRAGMA_MESSAGE( "Skipping test because BOOST_DESCRIBE_CXX14 is not defined" )
|
||||
int main() {}
|
||||
|
||||
#else
|
||||
|
||||
namespace user
|
||||
{
|
||||
|
||||
struct Y3
|
||||
{
|
||||
int a;
|
||||
int b;
|
||||
};
|
||||
|
||||
BOOST_DESCRIBE_STRUCT(Y3, (), (a, b))
|
||||
|
||||
} // namespace user
|
||||
|
||||
namespace std
|
||||
{
|
||||
|
||||
template<> struct tuple_size<user::Y3>: std::integral_constant<std::size_t, 2>
|
||||
{
|
||||
};
|
||||
|
||||
} // namespace std
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace container_hash
|
||||
{
|
||||
|
||||
template<> struct is_tuple_like<user::Y3>: boost::false_type {};
|
||||
|
||||
} // namespace container_hash
|
||||
} // namespace boost
|
||||
|
||||
template<class T> std::size_t hv( T const& t )
|
||||
{
|
||||
return boost::hash<T>()( t );
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
{
|
||||
user::Y3 tp = { 1, 2 };
|
||||
int const a[] = { 1, 2 };
|
||||
|
||||
BOOST_TEST_EQ( hv(tp), hv(a) );
|
||||
}
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -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
28
test/is_range_test4.cpp
Normal 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();
|
||||
}
|
||||
107
test/is_tuple_like_test.cpp
Normal file
107
test/is_tuple_like_test.cpp
Normal file
@@ -0,0 +1,107 @@
|
||||
// Copyright 2017, 2022 Peter Dimov.
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#if defined(__clang__)
|
||||
# pragma clang diagnostic ignored "-Wmismatched-tags"
|
||||
#endif
|
||||
|
||||
#include <boost/container_hash/is_tuple_like.hpp>
|
||||
#include <boost/core/lightweight_test_trait.hpp>
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/config/workaround.hpp>
|
||||
#include <utility>
|
||||
|
||||
struct X
|
||||
{
|
||||
};
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_HDR_TUPLE)
|
||||
|
||||
#include <tuple>
|
||||
|
||||
namespace user
|
||||
{
|
||||
|
||||
struct Y
|
||||
{
|
||||
int a;
|
||||
int b;
|
||||
};
|
||||
|
||||
template<std::size_t I> int& get( Y& v );
|
||||
template<std::size_t I> int const& get( Y const& v );
|
||||
|
||||
template<> int& get<0>( Y& v )
|
||||
{
|
||||
return v.a;
|
||||
}
|
||||
|
||||
template<> int const& get<0>( Y const& v )
|
||||
{
|
||||
return v.a;
|
||||
}
|
||||
|
||||
template<> int& get<1>( Y& v )
|
||||
{
|
||||
return v.b;
|
||||
}
|
||||
|
||||
template<> int const& get<1>( Y const& v )
|
||||
{
|
||||
return v.b;
|
||||
}
|
||||
|
||||
} // namespace user
|
||||
|
||||
namespace std
|
||||
{
|
||||
|
||||
template<> struct tuple_size<user::Y>: std::integral_constant<std::size_t, 2>
|
||||
{
|
||||
};
|
||||
|
||||
} // namespace std
|
||||
|
||||
#endif // #if !defined(BOOST_NO_CXX11_HDR_TUPLE)
|
||||
|
||||
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
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
||||
Reference in New Issue
Block a user