Compare commits

..
Author SHA1 Message Date
joaquintides f1d8634344 streamlined unprotected_bulk_visit 2023-10-01 18:05:24 +02:00
joaquintides 29791bbf10 micro-optimizations 2023-10-01 09:57:36 +02:00
joaquintides 35541248d4 made unprotected_bulk_visit chunk size dynamic 2023-09-30 19:31:01 +02:00
joaquintides 937081d1be iterator-based bulk visit 2023-09-30 12:40:21 +02:00
joaquintides e21e321bcf reverted "added bulk_visit2" 2023-09-30 09:43:19 +02:00
joaquintides 379b3047ee added bulk_visit2 2023-09-29 19:34:04 +02:00
joaquintides 1a2e5c8ffe adapted post-#211 2023-09-29 18:14:44 +02:00
joaquintides ddc77ebdc9 drafted bulk_visit 2023-09-29 18:10:37 +02:00
125 changed files with 4679 additions and 2507 deletions
+49
View File
@@ -31,6 +31,25 @@ environment:
B2_VARIANT: debug,release
matrix:
- FLAVOR: Visual Studio 2008
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
B2_TOOLSET: msvc-9.0
B2_ADDRESS_MODEL: 32 # No 64bit support
- FLAVOR: Visual Studio 2010
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
B2_TOOLSET: msvc-10.0
B2_ADDRESS_MODEL: 32 # No 64bit support
- FLAVOR: Visual Studio 2012
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
B2_TOOLSET: msvc-11.0
B2_ADDRESS_MODEL: 32 # No 64bit support
- FLAVOR: Visual Studio 2013
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
B2_TOOLSET: msvc-12.0
- FLAVOR: Visual Studio 2015
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
B2_TOOLSET: msvc-14.0
@@ -50,6 +69,13 @@ environment:
B2_CXXSTD: latest
B2_TOOLSET: msvc-14.1
- FLAVOR: cygwin (32-bit, C++03)
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
ADDPATH: C:\cygwin\bin;
B2_ADDRESS_MODEL: 32
B2_CXXSTD: 03
B2_TOOLSET: gcc
- FLAVOR: cygwin (32-bit, C++11)
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
ADDPATH: C:\cygwin\bin;
@@ -71,6 +97,15 @@ environment:
B2_CXXSTD: 1z
B2_TOOLSET: gcc
- FLAVOR: cygwin (64-bit, latest, C++03)
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2022
ADDPATH: C:\cygwin64\bin;
B2_ADDRESS_MODEL: 64
B2_CXXSTD: 03
B2_TOOLSET: gcc
B2_FLAGS: "include=libs/unordered/test/unordered include=libs/unordered/test/exception"
B2_VARIANT: release
- FLAVOR: cygwin (64-bit, latest, C++11)
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2022
ADDPATH: C:\cygwin64\bin;
@@ -98,6 +133,13 @@ environment:
B2_FLAGS: "include=libs/unordered/test/unordered include=libs/unordered/test/exception"
B2_VARIANT: release
- FLAVOR: mingw-w64, 32 bit, C++03
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
ADDPATH: C:\mingw-w64\i686-8.1.0-posix-dwarf-rt_v6-rev0\mingw32\bin;
B2_CXXSTD: 03
B2_TOOLSET: gcc
B2_ADDRESS_MODEL: 32
- FLAVOR: mingw-w64, 32 bit, C++11
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
ADDPATH: C:\mingw-w64\i686-8.1.0-posix-dwarf-rt_v6-rev0\mingw32\bin;
@@ -126,6 +168,13 @@ environment:
B2_TOOLSET: gcc
B2_ADDRESS_MODEL: 32
- FLAVOR: mingw-w64, 64 bit, C++03
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
ADDPATH: C:\mingw-w64\x86_64-8.1.0-posix-seh-rt_v6-rev0\mingw64\bin;
B2_CXXSTD: 03
B2_TOOLSET: gcc
B2_ADDRESS_MODEL: 64
- FLAVOR: mingw-w64, 64 bit, C++11
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
ADDPATH: C:\mingw-w64\x86_64-8.1.0-posix-seh-rt_v6-rev0\mingw64\bin;
+69 -45
View File
@@ -100,16 +100,40 @@ local windows_pipeline(name, image, environment, arch = "amd64") =
};
[
linux_pipeline(
"Linux 14.04 GCC 4.4 32/64",
"cppalliance/droneubuntu1404:1",
{ TOOLSET: 'gcc', COMPILER: 'g++-4.4', CXXSTD: '98,0x', ADDRMD: '32,64' },
"g++-4.4-multilib",
[ "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' },
"g++-4.7-multilib",
[ "ppa:ubuntu-toolchain-r/test" ],
),
linux_pipeline(
"Linux 14.04 GCC 4.8* 32/64",
"cppalliance/droneubuntu1404:1",
{ TOOLSET: 'gcc', COMPILER: 'g++', CXXSTD: '11', ADDRMD: '32,64' },
{ TOOLSET: 'gcc', COMPILER: 'g++', CXXSTD: '03,11', ADDRMD: '32,64' },
),
linux_pipeline(
"Linux 14.04 GCC 4.9 32/64",
"cppalliance/droneubuntu1404:1",
{ TOOLSET: 'gcc', COMPILER: 'g++-4.9', CXXSTD: '11', ADDRMD: '32,64' },
{ TOOLSET: 'gcc', COMPILER: 'g++-4.9', CXXSTD: '03,11', ADDRMD: '32,64' },
"g++-4.9-multilib",
[ "ppa:ubuntu-toolchain-r/test" ],
),
@@ -117,26 +141,26 @@ 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: '11,14', ADDRMD: '32,64' },
{ TOOLSET: 'gcc', COMPILER: 'g++', CXXSTD: '03,11,14', ADDRMD: '32,64' },
),
linux_pipeline(
"Linux 18.04 GCC 6 32/64",
"cppalliance/droneubuntu1804:1",
{ TOOLSET: 'gcc', COMPILER: 'g++-6', CXXSTD: '11,14', ADDRMD: '32,64' },
{ TOOLSET: 'gcc', COMPILER: 'g++-6', CXXSTD: '03,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: '11,14,17', ADDRMD: '32,64' },
{ TOOLSET: 'gcc', COMPILER: 'g++', CXXSTD: '03,11,14,17', ADDRMD: '32,64' },
),
linux_pipeline(
"Linux 18.04 GCC 8 32/64 (11)",
"Linux 18.04 GCC 8 32/64 (03,11)",
"cppalliance/droneubuntu1804:1",
{ TOOLSET: 'gcc', COMPILER: 'g++-8', CXXSTD: '11', ADDRMD: '32,64' },
{ TOOLSET: 'gcc', COMPILER: 'g++-8', CXXSTD: '03,11', ADDRMD: '32,64' },
"g++-8-multilib",
),
@@ -148,9 +172,9 @@ local windows_pipeline(name, image, environment, arch = "amd64") =
),
linux_pipeline(
"Linux 20.04 GCC 9* 32/64 (11,14)",
"Linux 20.04 GCC 9* 32/64 (03,11,14)",
"cppalliance/droneubuntu2004:1",
{ TOOLSET: 'gcc', COMPILER: 'g++', CXXSTD: '11,14', ADDRMD: '32,64' },
{ TOOLSET: 'gcc', COMPILER: 'g++', CXXSTD: '03,11,14', ADDRMD: '32,64' },
),
linux_pipeline(
@@ -162,14 +186,14 @@ local windows_pipeline(name, image, environment, arch = "amd64") =
linux_pipeline(
"Linux 20.04 GCC 9* ARM64",
"cppalliance/droneubuntu2004:multiarch",
{ TOOLSET: 'gcc', COMPILER: 'g++', CXXSTD: '11,14,17,2a' },
{ TOOLSET: 'gcc', COMPILER: 'g++', CXXSTD: '03,11,14,17,2a' },
arch="arm64",
),
linux_pipeline(
"Linux 20.04 GCC 9* S390x (11,14)",
"Linux 20.04 GCC 9* S390x (03,11,14)",
"cppalliance/droneubuntu2004:multiarch",
{ TOOLSET: 'gcc', COMPILER: 'g++', CXXSTD: '11,14' },
{ TOOLSET: 'gcc', COMPILER: 'g++', CXXSTD: '03,11,14' },
arch="s390x",
),
@@ -181,9 +205,9 @@ local windows_pipeline(name, image, environment, arch = "amd64") =
),
linux_pipeline(
"Linux 20.04 GCC 10 32/64 (11,14)",
"Linux 20.04 GCC 10 32/64 (03,11,14)",
"cppalliance/droneubuntu2004:1",
{ TOOLSET: 'gcc', COMPILER: 'g++-10', CXXSTD: '11,14', ADDRMD: '32,64' },
{ TOOLSET: 'gcc', COMPILER: 'g++-10', CXXSTD: '03,11,14', ADDRMD: '32,64' },
"g++-10-multilib",
),
@@ -195,9 +219,9 @@ local windows_pipeline(name, image, environment, arch = "amd64") =
),
linux_pipeline(
"Linux 22.04 GCC 11* 32/64 (11,14)",
"Linux 22.04 GCC 11* 32/64 (03,11,14)",
"cppalliance/droneubuntu2204:1",
{ TOOLSET: 'gcc', COMPILER: 'g++', CXXSTD: '11,14', ADDRMD: '32,64' },
{ TOOLSET: 'gcc', COMPILER: 'g++', CXXSTD: '03,11,14', ADDRMD: '32,64' },
),
linux_pipeline(
@@ -207,9 +231,9 @@ local windows_pipeline(name, image, environment, arch = "amd64") =
),
linux_pipeline(
"Linux 22.04 GCC 12 32 ASAN (11,14)",
"Linux 22.04 GCC 12 32 ASAN (03,11,14)",
"cppalliance/droneubuntu2204:1",
{ TOOLSET: 'gcc', COMPILER: 'g++-12', CXXSTD: '11', ADDRMD: '32' } + asan,
{ TOOLSET: 'gcc', COMPILER: 'g++-12', CXXSTD: '03,11', ADDRMD: '32' } + asan,
"g++-12-multilib",
),
@@ -242,9 +266,9 @@ local windows_pipeline(name, image, environment, arch = "amd64") =
),
linux_pipeline(
"Linux 22.04 GCC 12 64 ASAN (11,14)",
"Linux 22.04 GCC 12 64 ASAN (03,11,14)",
"cppalliance/droneubuntu2204:1",
{ TOOLSET: 'gcc', COMPILER: 'g++-12', CXXSTD: '11,14', ADDRMD: '64' } + asan,
{ TOOLSET: 'gcc', COMPILER: 'g++-12', CXXSTD: '03,11,14', ADDRMD: '64' } + asan,
"g++-12-multilib",
),
@@ -277,9 +301,9 @@ local windows_pipeline(name, image, environment, arch = "amd64") =
),
linux_pipeline(
"Linux 23.04 GCC 13 32/64 (11,14)",
"Linux 23.04 GCC 13 32/64 (03,11,14)",
"cppalliance/droneubuntu2304:1",
{ TOOLSET: 'gcc', COMPILER: 'g++-13', CXXSTD: '11,14', ADDRMD: '32,64' },
{ TOOLSET: 'gcc', COMPILER: 'g++-13', CXXSTD: '03,11,14', ADDRMD: '32,64' },
"g++-13 g++-13-multilib",
),
@@ -293,112 +317,112 @@ local windows_pipeline(name, image, environment, arch = "amd64") =
linux_pipeline(
"Linux 16.04 Clang 3.5",
"cppalliance/droneubuntu1604:1",
{ TOOLSET: 'clang', COMPILER: 'clang++-3.5', CXXSTD: '11' },
{ TOOLSET: 'clang', COMPILER: 'clang++-3.5', CXXSTD: '03,11' },
"clang-3.5",
),
linux_pipeline(
"Linux 16.04 Clang 3.6",
"cppalliance/droneubuntu1604:1",
{ TOOLSET: 'clang', COMPILER: 'clang++-3.6', CXXSTD: '11,14' },
{ TOOLSET: 'clang', COMPILER: 'clang++-3.6', CXXSTD: '03,11,14' },
"clang-3.6",
),
linux_pipeline(
"Linux 16.04 Clang 3.7",
"cppalliance/droneubuntu1604:1",
{ TOOLSET: 'clang', COMPILER: 'clang++-3.7', CXXSTD: '11,14' },
{ TOOLSET: 'clang', COMPILER: 'clang++-3.7', CXXSTD: '03,11,14' },
"clang-3.7",
),
linux_pipeline(
"Linux 16.04 Clang 3.8",
"cppalliance/droneubuntu1604:1",
{ TOOLSET: 'clang', COMPILER: 'clang++-3.8', CXXSTD: '11,14' },
{ TOOLSET: 'clang', COMPILER: 'clang++-3.8', CXXSTD: '03,11,14' },
"clang-3.8",
),
linux_pipeline(
"Linux 18.04 Clang 3.9",
"cppalliance/droneubuntu1804:1",
{ TOOLSET: 'clang', COMPILER: 'clang++-3.9', CXXSTD: '11,14' },
{ TOOLSET: 'clang', COMPILER: 'clang++-3.9', CXXSTD: '03,11,14' },
"clang-3.9",
),
linux_pipeline(
"Linux 18.04 Clang 4.0",
"cppalliance/droneubuntu1804:1",
{ TOOLSET: 'clang', COMPILER: 'clang++-4.0', CXXSTD: '11,14' },
{ TOOLSET: 'clang', COMPILER: 'clang++-4.0', CXXSTD: '03,11,14' },
"clang-4.0",
),
linux_pipeline(
"Linux 18.04 Clang 5.0",
"cppalliance/droneubuntu1804:1",
{ TOOLSET: 'clang', COMPILER: 'clang++-5.0', CXXSTD: '11,14,1z' },
{ TOOLSET: 'clang', COMPILER: 'clang++-5.0', CXXSTD: '03,11,14,1z' },
"clang-5.0",
),
linux_pipeline(
"Linux 18.04 Clang 6.0",
"cppalliance/droneubuntu1804:1",
{ TOOLSET: 'clang', COMPILER: 'clang++-6.0', CXXSTD: '11,14,17' },
{ TOOLSET: 'clang', COMPILER: 'clang++-6.0', CXXSTD: '03,11,14,17' },
"clang-6.0",
),
linux_pipeline(
"Linux 20.04 Clang 7",
"cppalliance/droneubuntu2004:1",
{ TOOLSET: 'clang', COMPILER: 'clang++-7', CXXSTD: '11,14,17' },
{ TOOLSET: 'clang', COMPILER: 'clang++-7', CXXSTD: '03,11,14,17' },
"clang-7",
),
linux_pipeline(
"Linux 20.04 Clang 8",
"cppalliance/droneubuntu2004:1",
{ TOOLSET: 'clang', COMPILER: 'clang++-8', CXXSTD: '11,14,17' },
{ TOOLSET: 'clang', COMPILER: 'clang++-8', CXXSTD: '03,11,14,17' },
"clang-8",
),
linux_pipeline(
"Linux 20.04 Clang 9",
"cppalliance/droneubuntu2004:1",
{ TOOLSET: 'clang', COMPILER: 'clang++-9', CXXSTD: '11,14,17,2a' },
{ TOOLSET: 'clang', COMPILER: 'clang++-9', CXXSTD: '03,11,14,17,2a' },
"clang-9",
),
linux_pipeline(
"Linux 20.04 Clang 10",
"cppalliance/droneubuntu2004:1",
{ TOOLSET: 'clang', COMPILER: 'clang++-10', CXXSTD: '11,14,17,2a' },
{ TOOLSET: 'clang', COMPILER: 'clang++-10', CXXSTD: '03,11,14,17,2a' },
"clang-10",
),
linux_pipeline(
"Linux 20.04 Clang 11",
"cppalliance/droneubuntu2004:1",
{ TOOLSET: 'clang', COMPILER: 'clang++-11', CXXSTD: '11,14,17,2a' },
{ TOOLSET: 'clang', COMPILER: 'clang++-11', CXXSTD: '03,11,14,17,2a' },
"clang-11",
),
linux_pipeline(
"Linux 20.04 Clang 12",
"cppalliance/droneubuntu2004:1",
{ TOOLSET: 'clang', COMPILER: 'clang++-12', CXXSTD: '11,14,17,2a' },
{ TOOLSET: 'clang', COMPILER: 'clang++-12', CXXSTD: '03,11,14,17,2a' },
"clang-12",
),
linux_pipeline(
"Linux 22.04 Clang 13",
"cppalliance/droneubuntu2204:1",
{ TOOLSET: 'clang', COMPILER: 'clang++-13', CXXSTD: '11,14,17,20' },
{ TOOLSET: 'clang', COMPILER: 'clang++-13', CXXSTD: '03,11,14,17,20' },
"clang-13",
),
linux_pipeline(
"Linux 22.04 Clang 14 UBSAN (11,14)",
"Linux 22.04 Clang 14 UBSAN (03,11,14)",
"cppalliance/droneubuntu2204:1",
{ TOOLSET: 'clang', COMPILER: 'clang++-14', CXXSTD: '11,14' } + ubsan,
{ TOOLSET: 'clang', COMPILER: 'clang++-14', CXXSTD: '03,11,14' } + ubsan,
"clang-14",
),
@@ -410,9 +434,9 @@ local windows_pipeline(name, image, environment, arch = "amd64") =
),
linux_pipeline(
"Linux 22.04 Clang 14 ASAN (11,14)",
"Linux 22.04 Clang 14 ASAN (03,11,14)",
"cppalliance/droneubuntu2204:1",
{ TOOLSET: 'clang', COMPILER: 'clang++-14', CXXSTD: '11,14' } + asan,
{ TOOLSET: 'clang', COMPILER: 'clang++-14', CXXSTD: '03,11,14' } + asan,
"clang-14",
),
@@ -433,14 +457,14 @@ local windows_pipeline(name, image, environment, arch = "amd64") =
linux_pipeline(
"Linux 22.04 Clang 15",
"cppalliance/droneubuntu2204:1",
{ TOOLSET: 'clang', COMPILER: 'clang++-15', CXXSTD: '11,14,17,20,2b' },
{ TOOLSET: 'clang', COMPILER: 'clang++-15', CXXSTD: '03,11,14,17,20,2b' },
"clang-15",
["deb http://apt.llvm.org/jammy/ llvm-toolchain-jammy-15 main"],
),
macos_pipeline(
"MacOS 10.15 Xcode 12.2 UBSAN (11)",
{ TOOLSET: 'clang', COMPILER: 'clang++', CXXSTD: '11' } + ubsan,
"MacOS 10.15 Xcode 12.2 UBSAN (03,11)",
{ TOOLSET: 'clang', COMPILER: 'clang++', CXXSTD: '03,11' } + ubsan,
),
macos_pipeline(
@@ -455,7 +479,7 @@ local windows_pipeline(name, image, environment, arch = "amd64") =
macos_pipeline(
"MacOS 12.4 Xcode 13.4.1 ASAN",
{ TOOLSET: 'clang', COMPILER: 'clang++', CXXSTD: '11,14,1z' } + asan,
{ TOOLSET: 'clang', COMPILER: 'clang++', CXXSTD: '03,11,14,1z' } + asan,
xcode_version = "13.4.1", osx_version = "monterey", arch = "arm64",
),
+30 -46
View File
@@ -52,65 +52,49 @@ jobs:
matrix:
include:
# Linux, gcc
- { compiler: gcc-7, cxxstd: '11,14,17', os: 'ubuntu-20.04', install: 'g++-7' }
- { compiler: gcc-8, cxxstd: '11,14,17', os: 'ubuntu-20.04', install: 'g++-8' }
- { compiler: gcc-9, cxxstd: '11,14,17', os: 'ubuntu-22.04', install: 'g++-9' }
- { compiler: gcc-10, cxxstd: '11,14,17,20', os: 'ubuntu-22.04', install: 'g++-10' }
- { compiler: gcc-11, cxxstd: '11,14,17,20', os: 'ubuntu-22.04', install: 'g++-11' }
- { name: "gcc-12 w/ sanitizers (11)", sanitize: yes,
compiler: gcc-12, cxxstd: '11', os: 'ubuntu-22.04', ccache_key: "san1" }
- { name: "gcc-12 w/ sanitizers (14)", sanitize: yes,
compiler: gcc-12, cxxstd: '14', os: 'ubuntu-22.04', ccache_key: "san1" }
- { name: "gcc-12 w/ sanitizers (17)", sanitize: yes,
compiler: gcc-12, cxxstd: '17', os: 'ubuntu-22.04', ccache_key: "san2" }
- { name: "gcc-12 w/ sanitizers (20)", sanitize: yes,
compiler: gcc-12, cxxstd: '20', os: 'ubuntu-22.04', ccache_key: "san2" }
- { name: "gcc-12 w/ sanitizers (2b)", sanitize: yes,
compiler: gcc-12, cxxstd: '2b', os: 'ubuntu-22.04', ccache_key: "san2" }
- { compiler: gcc-7, cxxstd: '03,11,14,17', os: 'ubuntu-20.04', install: 'g++-7' }
- { compiler: gcc-8, cxxstd: '03,11,14,17', os: 'ubuntu-20.04', install: 'g++-8' }
- { compiler: gcc-9, cxxstd: '03,11,14,17', os: 'ubuntu-22.04', install: 'g++-9' }
- { compiler: gcc-10, cxxstd: '03,11,14,17,20', os: 'ubuntu-22.04', install: 'g++-10' }
- { compiler: gcc-11, cxxstd: '03,11,14,17,20', os: 'ubuntu-22.04', install: 'g++-11' }
- { name: "gcc-12 w/ sanitizers (03,11,14)", sanitize: yes,
compiler: gcc-12, cxxstd: '03,11,14', os: 'ubuntu-22.04', ccache_key: "san1" }
- { name: "gcc-12 w/ sanitizers (17,20,2b)", sanitize: yes,
compiler: gcc-12, cxxstd: '17,20,2b', os: 'ubuntu-22.04', ccache_key: "san2" }
- { name: Collect coverage, coverage: yes,
compiler: gcc-12, cxxstd: '20', os: 'ubuntu-22.04', install: 'g++-12-multilib', address-model: '32,64', ccache_key: "cov" }
compiler: gcc-12, cxxstd: '03,20', os: 'ubuntu-22.04', install: 'g++-12-multilib', address-model: '32,64', ccache_key: "cov" }
- { name: "cfoa tsan (gcc-12)", cxxstd: '11,14,17,20,2b', os: 'ubuntu-22.04', compiler: gcc-12,
targets: 'libs/unordered/test//cfoa_tests', thread-sanitize: yes, ccache_key: "tsan" }
# Linux, clang, libc++
- { compiler: clang-7, cxxstd: '11,14,17', os: 'ubuntu-20.04', stdlib: libc++, install: 'clang-7 libc++-7-dev libc++abi-7-dev' }
- { compiler: clang-10, cxxstd: '11,14,17,20', os: 'ubuntu-20.04', stdlib: libc++, install: 'clang-10 libc++-10-dev libc++abi-10-dev' }
- { compiler: clang-11, cxxstd: '11,14,17,20', os: 'ubuntu-22.04', stdlib: libc++, install: 'clang-11 libc++-11-dev libc++abi-11-dev' }
- { compiler: clang-7, cxxstd: '03,11,14,17', os: 'ubuntu-20.04', stdlib: libc++, install: 'clang-7 libc++-7-dev libc++abi-7-dev' }
- { compiler: clang-10, cxxstd: '03,11,14,17,20', os: 'ubuntu-20.04', stdlib: libc++, install: 'clang-10 libc++-10-dev libc++abi-10-dev' }
- { compiler: clang-11, cxxstd: '03,11,14,17,20', os: 'ubuntu-22.04', stdlib: libc++, install: 'clang-11 libc++-11-dev libc++abi-11-dev' }
# clang-12 doesn't work on 'ubuntu-22.04', the linker can't find -lunwind for some reason
- { name: "clang-12 w/ sanitizers (11,14)", sanitize: yes,
compiler: clang-12, cxxstd: '11,14', os: 'ubuntu-20.04', stdlib: libc++, install: 'clang-12 libc++-12-dev libc++abi-12-dev', ccache_key: "san1" }
- { name: "clang-12 w/ sanitizers (17)", sanitize: yes,
compiler: clang-12, cxxstd: '17', os: 'ubuntu-20.04', stdlib: libc++, install: 'clang-12 libc++-12-dev libc++abi-12-dev', ccache_key: "san2" }
- { name: "clang-12 w/ sanitizers (20)", sanitize: yes,
compiler: clang-12, cxxstd: '20', os: 'ubuntu-20.04', stdlib: libc++, install: 'clang-12 libc++-12-dev libc++abi-12-dev', ccache_key: "san2" }
- { name: "clang-12 w/ sanitizers (2b)", sanitize: yes,
compiler: clang-12, cxxstd: '2b', os: 'ubuntu-20.04', stdlib: libc++, install: 'clang-12 libc++-12-dev libc++abi-12-dev', ccache_key: "san2" }
- { compiler: 'clang-13', cxxstd: '11,14', os: 'ubuntu-22.04', stdlib: libc++, install: 'clang-13 libc++-13-dev libc++abi-13-dev' }
- { compiler: 'clang-13', cxxstd: '17,20,2b', os: 'ubuntu-22.04', stdlib: libc++, install: 'clang-13 libc++-13-dev libc++abi-13-dev' }
- { name: "clang-12 w/ sanitizers (03,11,14)", sanitize: yes,
compiler: clang-12, cxxstd: '03,11,14', os: 'ubuntu-20.04', stdlib: libc++, install: 'clang-12 libc++-12-dev libc++abi-12-dev', ccache_key: "san1" }
- { name: "clang-12 w/ sanitizers (17,20,2b)", sanitize: yes,
compiler: clang-12, cxxstd: '17,20,2b', os: 'ubuntu-20.04', stdlib: libc++, install: 'clang-12 libc++-12-dev libc++abi-12-dev', ccache_key: "san2" }
- { compiler: clang-13, cxxstd: '03,11,14,17,20,2b', os: 'ubuntu-22.04', stdlib: libc++, install: 'clang-13 libc++-13-dev libc++abi-13-dev' }
# not using libc++ because of https://github.com/llvm/llvm-project/issues/52771
- { name: "clang-14 w/ sanitizers (11,14)", sanitize: yes,
compiler: clang-14, cxxstd: '11,14', os: 'ubuntu-22.04', ccache_key: "san1" }
- { name: "clang-14 w/ sanitizers (17)", sanitize: yes,
compiler: clang-14, cxxstd: '17', os: 'ubuntu-22.04', ccache_key: "san2" }
- { name: "clang-14 w/ sanitizers (20)", sanitize: yes,
compiler: clang-14, cxxstd: '20', os: 'ubuntu-22.04', ccache_key: "san2" }
- { name: "clang-14 w/ sanitizers (2b)", sanitize: yes,
compiler: clang-14, cxxstd: '2b', os: 'ubuntu-22.04', ccache_key: "san2" }
- { name: "clang-14 w/ sanitizers (03,11,14)", sanitize: yes,
compiler: clang-14, cxxstd: '03,11,14', os: 'ubuntu-22.04', ccache_key: "san1" }
- { name: "clang-14 w/ sanitizers (17,20,2b)", sanitize: yes,
compiler: clang-14, cxxstd: '17,20,2b', os: 'ubuntu-22.04', ccache_key: "san2" }
- { name: "cfoa tsan (clang-14)", cxxstd: '11,14,17,20,2b', os: 'ubuntu-22.04', compiler: clang-14,
targets: 'libs/unordered/test//cfoa_tests', thread-sanitize: yes,
stdlib: libc++, install: 'clang-14 libc++-14-dev libc++abi-14-dev', ccache_key: "tsan" }
- { compiler: 'clang-15', cxxstd: '11,14', os: 'ubuntu-22.04', stdlib: libc++, install: 'clang-15 libc++-15-dev libc++abi-15-dev' }
- { compiler: 'clang-15', cxxstd: '17,20,2b', os: 'ubuntu-22.04', stdlib: libc++, install: 'clang-15 libc++-15-dev libc++abi-15-dev' }
- { compiler: clang-15, cxxstd: '03,11,14,17,20,2b', os: 'ubuntu-22.04', stdlib: libc++, install: 'clang-15 libc++-15-dev libc++abi-15-dev' }
# OSX, clang
- { compiler: clang, cxxstd: '11,14,17,2a', os: 'macos-11' }
- { compiler: clang, cxxstd: '11,14,17,2a', os: 'macos-12', sanitize: yes, ccache_key: "san1" }
- { compiler: clang, cxxstd: '11,14,17,2a', os: 'macos-12', thread-sanitize: yes, targets: 'libs/unordered/test//cfoa_tests', ccache_key: "tsan" }
- { compiler: clang, cxxstd: '11,14,17,20,2b', os: 'macos-13' }
- { compiler: clang, cxxstd: '03,11,14,17,2a', os: 'macos-11' }
- { compiler: clang, cxxstd: '03,11,14,17,2a', os: 'macos-12', sanitize: yes, ccache_key: "san1" }
- { compiler: clang, cxxstd: '11,14,17,2a', os: 'macos-12', thread-sanitize: yes, targets: 'libs/unordered/test//cfoa_tests', ccache_key: "tsan" }
- { compiler: clang, cxxstd: '03,11,14,17,20,2b', os: 'macos-13' }
timeout-minutes: 360
# posix (gcc-12 w/ sanitizers is taking longer than 210 minutes
@@ -266,7 +250,7 @@ jobs:
- { toolset: msvc-14.3, cxxstd: '14', addrmd: '64', os: 'windows-2022', variant: 'debug', defines: '_ALLOW_RTCc_IN_STL', cxxflags: '/RTCc' }
- { toolset: msvc-14.3, cxxstd: '14', addrmd: '32', os: 'windows-2022', variant: 'debug', defines: '_ALLOW_RTCc_IN_STL', cxxflags: '"/RTCc /arch:IA32"' }
- { toolset: clang-win, cxxstd: '14,17,latest', addrmd: '32,64', os: 'windows-2022', variant: 'debug,release' }
- { toolset: gcc, cxxstd: '11,14,17,2a', addrmd: '64', os: 'windows-2019', variant: 'debug,release' }
- { toolset: gcc, cxxstd: '03,11,14,17,2a', addrmd: '64', os: 'windows-2019', variant: 'debug,release' }
needs: [runner-selection]
runs-on: ${{ fromJSON(needs.runner-selection.outputs.labelmatrix)[matrix.os] }}
@@ -323,8 +307,8 @@ jobs:
fail-fast: false
matrix:
include:
- { sys: MINGW32, compiler: gcc, cxxstd: '11,17,20' }
- { sys: MINGW64, compiler: gcc, cxxstd: '11,17,20' }
- { sys: MINGW32, compiler: gcc, cxxstd: '03,11,17,20' }
- { sys: MINGW64, compiler: gcc, cxxstd: '03,11,17,20' }
needs: [runner-selection]
runs-on: ${{ fromJSON(needs.runner-selection.outputs.labelmatrix)['windows-latest'] }}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 31 KiB

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 31 KiB

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 23 KiB

-4
View File
@@ -447,10 +447,6 @@ operations follow a https://en.wikipedia.org/wiki/Zipf%27s_law#Formal_definition
with different _skew_ parameters: the higher the skew, the more concentrated are the keys in the lower values
of the covered range.
`boost::concurrent_flat_map` is exercised using both regular and xref:#concurrent_bulk_visitation[bulk visitation]:
in the latter case, lookup keys are buffered in a local array and then processed at
once each time the buffer reaches xref:#concurrent_flat_map_constants[`bulk_visit_size`].
=== GCC 12, x64
-3
View File
@@ -13,14 +13,11 @@
with serial and parallel variants.
* Added efficient move construction of `boost::unordered_flat_(map|set)` from
`boost::concurrent_flat_(map|set)` and vice versa.
* Added bulk visitation to concurrent containers for increased lookup performance.
* Added debug-mode mechanisms for detecting illegal reentrancies into
a concurrent container from user code.
* Added Boost.Serialization support to all containers and their (non-local) iterator types.
* Added support for fancy pointers to open-addressing and concurrent containers.
This enables scenarios like the use of Boost.Interprocess allocators to construct containers in shared memory.
* Starting with this release, `boost::unordered_[multi]set` and `boost::unordered_[multi]map`
only work with C++11 onwards.
== Release 1.83.0 - Major update
+93 -35
View File
@@ -7,54 +7,116 @@
== Closed-addressing Containers
`boost::unordered_[multi]set` and `boost::unordered_[multi]map` provide a conformant
implementation for {cpp}11 (or later) compilers of the latest standard revision of
{cpp} unordered associative containers, with very minor deviations as noted.
The containers are fully https://en.cppreference.com/w/cpp/named_req/AllocatorAwareContainer[AllocatorAware^]
and support https://en.cppreference.com/w/cpp/named_req/Allocator#Fancy_pointers[fancy pointers^].
`unordered_[multi]set` and `unordered_[multi]map` are intended to provide a conformant
implementation of the {cpp}20 standard that will work with {cpp}98 upwards.
This wide compatibility does mean some compromises have to be made.
With a compiler and library that fully support {cpp}11, the differences should
be minor.
=== Deduction Guides
=== Move Emulation
Deduction guides for
https://en.cppreference.com/w/cpp/language/class_template_argument_deduction[class template argument deduction (CTAD)^]
are only available on {cpp}17 (or later) compilers.
Support for move semantics is implemented using Boost.Move. If rvalue
references are available it will use them, but if not it uses a close,
but imperfect emulation. On such compilers:
=== Piecewise Pair Emplacement
* Non-copyable objects can be stored in the containers.
They can be constructed in place using `emplace`, or if they support
Boost.Move, moved into place.
* The containers themselves are not movable.
* Argument forwarding is not perfect.
In accordance with the standard specification,
`boost::unordered_[multi]map::emplace` supports piecewise pair construction:
=== Use of Allocators
{cpp}11 introduced a new allocator system. It's backwards compatible due to
the lax requirements for allocators in the old standard, but might need
some changes for allocators which worked with the old versions of the
unordered containers.
It uses a traits class, `allocator_traits` to handle the allocator
adding extra functionality, and making some methods and types optional.
During development a stable release of
`allocator_traits` wasn't available so an internal partial implementation
is always used in this version. Hopefully a future version will use the
standard implementation where available.
The member functions `construct`, `destroy` and `max_size` are now
optional, if they're not available a fallback is used.
A full implementation of `allocator_traits` requires sophisticated
member function detection so that the fallback is used whenever the
member function call is not well formed.
This requires support for SFINAE expressions, which are available on
GCC from version 4.4 and Clang.
On other compilers, there's just a test to see if the allocator has
a member, but no check that it can be called. So rather than using a
fallback there will just be a compile error.
`propagate_on_container_copy_assignment`,
`propagate_on_container_move_assignment`,
`propagate_on_container_swap` and
`select_on_container_copy_construction` are also supported.
Due to imperfect move emulation, some assignments might check
`propagate_on_container_copy_assignment` on some compilers and
`propagate_on_container_move_assignment` on others.
=== Construction/Destruction Using Allocators
The following support is required for full use of {cpp}11 style
construction/destruction:
* Variadic templates.
* Piecewise construction of `std::pair`.
* Either `std::allocator_traits` or expression SFINAE.
This is detected using Boost.Config. The macro
`BOOST_UNORDERED_CXX11_CONSTRUCTION` will be set to 1 if it is found, or 0
otherwise.
When this is the case `allocator_traits::construct` and
`allocator_traits::destroy` will always be used, apart from when piecewise
constructing a `std::pair` using `boost::tuple` (see <<compliance_pairs,below>>), but that should be easily avoided.
When support is not available `allocator_traits::construct` and
`allocator_traits::destroy` are never called.
=== Pointer Traits
`pointer_traits` aren't used. Instead, pointer types are obtained from
rebound allocators, this can cause problems if the allocator can't be
used with incomplete types. If `const_pointer` is not defined in the
allocator, `boost::pointer_to_other<pointer, const value_type>::type`
is used to obtain a const pointer.
=== Pairs
Since the containers use `std::pair` they're limited to the version
from the current standard library. But since {cpp}11 ``std::pair``'s
`piecewise_construct` based constructor is very useful, `emplace`
emulates it with a `piecewise_construct` in the `boost::unordered`
namespace. So for example, the following will work:
[source,c++]
----
boost::unordered_multimap<std::string, std::complex> x;
x.emplace(
std::piecewise_construct,
std::make_tuple("key"), std::make_tuple(1, 2));
----
Additionally, the same
functionality is provided via non-standard `boost::unordered::piecewise_construct`
and Boost.Tuple:
[source,c++]
----
x.emplace(
boost::unordered::piecewise_construct,
boost::make_tuple("key"), boost::make_tuple(1, 2));
----
This feature has been retained for backwards compatibility with
previous versions of Boost.Unordered: users are encouraged to
update their code to use `std::piecewise_construct` and
``std::tuple``s instead.
Older drafts of the standard also supported variadic constructors
for `std::pair`, where the first argument would be used for the
first part of the pair, and the remaining for the second part.
=== Swap
=== Miscellaneous
When swapping, `Pred` and `Hash` are not currently swapped by calling
`swap`, their copy constructors are used. As a consequence, when swapping
`swap`, their copy constructors are used. As a consequence when swapping
an exception may be thrown from their copy constructor.
Variadic constructor arguments for `emplace` are only used when both
rvalue references and variadic template parameters are available.
Otherwise `emplace` can only take up to 10 constructors arguments.
== Open-addressing Containers
The C++ standard does not currently provide any open-addressing container
@@ -67,9 +129,7 @@ radically different from that imposed by the standard (closed addressing).
Open-addressing containers provided by Boost.Unordered only work with reasonably
compliant C++11 (or later) compilers. Language-level features such as move semantics
and variadic template parameters are then not emulated.
The containers are fully https://en.cppreference.com/w/cpp/named_req/AllocatorAwareContainer[AllocatorAware^]
and support https://en.cppreference.com/w/cpp/named_req/Allocator#Fancy_pointers[fancy pointers^].
The containers are fully https://en.cppreference.com/w/cpp/named_req/AllocatorAwareContainer[AllocatorAware^].
The main differences with C++ unordered associative containers are:
@@ -96,9 +156,7 @@ due to their inherent problems in concurrent scenarios (high contention, prone t
so, Boost.Unordered concurrent containers are technically not models of
https://en.cppreference.com/w/cpp/named_req/Container[Container^], although
they meet all the requirements of https://en.cppreference.com/w/cpp/named_req/AllocatorAwareContainer[AllocatorAware^]
containers (including
https://en.cppreference.com/w/cpp/named_req/Allocator#Fancy_pointers[fancy pointer^] support)
except those implying iterators.
containers except those implying iterators.
In a non-concurrent unordered container, iterators serve two main purposes:
-49
View File
@@ -194,55 +194,6 @@ may be inserted, modified or erased by other threads during visitation. It is
advisable not to assume too much about the exact global state of a concurrent container
at any point in your program.
== Bulk visitation
Suppose you have an `std::array` of keys you want to look up for in a concurrent map:
[source,c++]
----
std::array<int, N> keys;
...
for(const auto& key: keys) {
m.visit(key, [](auto& x) { ++x.second; });
}
----
_Bulk visitation_ allows us to pass all the keys in one operation:
[source,c++]
----
m.visit(keys.begin(), keys.end(), [](auto& x) { ++x.second; });
----
This functionality is not provided for mere syntactic convenience, though: by processing all the
keys at once, some internal optimizations can be applied that increase
performance over the regular, one-at-a-time case (consult the
xref:#benchmarks_boostconcurrent_flat_map[benchmarks]). In fact, it may be beneficial
to buffer incoming keys so that they can be bulk visited in chunks:
[source,c++]
----
static constexpr auto bulk_visit_size = boost::concurrent_flat_map<int,int>::bulk_visit_size;
std::array<int, bulk_visit_size> buffer;
std::size_t i=0;
while(...) { // processing loop
...
buffer[i++] = k;
if(i == bulk_visit_size) {
map.visit(buffer.begin(), buffer.end(), [](auto& x) { ++x.second; });
i = 0;
}
...
}
// flush remaining keys
map.visit(buffer.begin(), buffer.begin() + i, [](auto& x) { ++x.second; });
----
There's a latency/throughput tradeoff here: it will take longer for incoming keys to
be processed (since they are buffered), but the number of processed keys per second
is higher. `bulk_visit_size` is the recommended chunk size —smaller buffers
may yield worse performance.
== Blocking Operations
``boost::concurrent_flat_set``s and ``boost::concurrent_flat_map``s can be copied, assigned, cleared and merged just like any
+13 -66
View File
@@ -50,9 +50,6 @@ namespace boost {
using size_type = std::size_t;
using difference_type = std::ptrdiff_t;
// constants
static constexpr size_type xref:#concurrent_flat_map_constants[bulk_visit_size] = _implementation-defined_;
// construct/copy/destroy
xref:#concurrent_flat_map_default_constructor[concurrent_flat_map]();
explicit xref:#concurrent_flat_map_bucket_count_constructor[concurrent_flat_map](size_type n,
@@ -109,13 +106,6 @@ namespace boost {
template<class K, class F> size_t xref:#concurrent_flat_map_cvisit[visit](const K& k, F f) const;
template<class K, class F> size_t xref:#concurrent_flat_map_cvisit[cvisit](const K& k, F f) const;
template<class FwdIterator, class F>
size_t xref:concurrent_flat_map_bulk_visit[visit](FwdIterator first, FwdIterator last, F f);
template<class FwdIterator, class F>
size_t xref:concurrent_flat_map_bulk_visit[visit](FwdIterator first, FwdIterator last, F f) const;
template<class FwdIterator, class F>
size_t xref:concurrent_flat_map_bulk_visit[cvisit](FwdIterator first, FwdIterator last, F f) const;
template<class F> size_t xref:#concurrent_flat_map_cvisit_all[visit_all](F f);
template<class F> size_t xref:#concurrent_flat_map_cvisit_all[visit_all](F f) const;
template<class F> size_t xref:#concurrent_flat_map_cvisit_all[cvisit_all](F f) const;
@@ -396,13 +386,6 @@ a function visiting elements of `m`) are detected and signalled through `BOOST_A
When run-time speed is a concern, the feature can be disabled by globally defining
this macro.
=== Constants
```cpp
static constexpr size_type bulk_visit_size;
```
Chunk size internally used in xref:concurrent_flat_map_bulk_visit[bulk visit] operations.
=== Constructors
@@ -739,42 +722,6 @@ Notes:;; The `template<class K, class F>` overloads only participate in overload
---
==== Bulk visit
```c++
template<class FwdIterator, class F>
size_t visit(FwdIterator first, FwdIterator last, F f);
template<class FwdIterator, class F>
size_t visit(FwdIterator first, FwdIterator last, F f) const;
template<class FwdIterator, class F>
size_t cvisit(FwdIterator first, FwdIterator last, F f) const;
```
For each element `k` in the range [`first`, `last`),
if there is an element `x` in the container with key equivalent to `k`,
invokes `f` with a reference to `x`.
Such reference is const iff `*this` is const.
Although functionally equivalent to individually invoking
xref:concurrent_flat_map_cvisit[`[c\]visit`] for each key, bulk visitation
performs generally faster due to internal streamlining optimizations.
It is advisable that `std::distance(first,last)` be at least
xref:#concurrent_flat_map_constants[`bulk_visit_size`] to enjoy
a performance gain: beyond this size, performance is not expected
to increase further.
[horizontal]
Requires:;; `FwdIterator` is a https://en.cppreference.com/w/cpp/named_req/ForwardIterator[LegacyForwardIterator^]
({cpp}11 to {cpp}17),
or satisfies https://en.cppreference.com/w/cpp/iterator/forward_iterator[std::forward_iterator^] ({cpp}20 and later).
For `K` = `std::iterator_traits<FwdIterator>::value_type`, either `K` is `key_type` or
else `Hash::is_transparent` and `Pred::is_transparent` are valid member typedefs.
In the latter case, the library assumes that `Hash` is callable with both `K` and `Key` and that `Pred` is transparent.
This enables heterogeneous lookup which avoids the cost of instantiating an instance of the `Key` type.
Returns:;; The number of elements visited.
---
==== [c]visit_all
```c++
@@ -1098,13 +1045,13 @@ if there is an element with an equivalent key; otherwise, the construction is of
```c++
// first two overloads
value_type(std::piecewise_construct,
std::forward_as_tuple(std::forward<Key>(k)),
std::forward_as_tuple(std::forward<Args>(args)...))
std::forward_as_tuple(boost::forward<Key>(k)),
std::forward_as_tuple(boost::forward<Args>(args)...))
// third overload
value_type(std::piecewise_construct,
std::forward_as_tuple(std::forward<K>(k)),
std::forward_as_tuple(std::forward<Args>(args)...))
std::forward_as_tuple(boost::forward<K>(k)),
std::forward_as_tuple(boost::forward<Args>(args)...))
```
unlike xref:#concurrent_flat_map_emplace[emplace], which simply forwards all arguments to ``value_type``'s constructor.
@@ -1146,13 +1093,13 @@ if there is an element with an equivalent key; otherwise, the construction is of
```c++
// first four overloads
value_type(std::piecewise_construct,
std::forward_as_tuple(std::forward<Key>(k)),
std::forward_as_tuple(std::forward<Args>(args)...))
std::forward_as_tuple(boost::forward<Key>(k)),
std::forward_as_tuple(boost::forward<Args>(args)...))
// last two overloads
value_type(std::piecewise_construct,
std::forward_as_tuple(std::forward<K>(k)),
std::forward_as_tuple(std::forward<Args>(args)...))
std::forward_as_tuple(boost::forward<K>(k)),
std::forward_as_tuple(boost::forward<Args>(args)...))
```
Invalidates pointers and references to elements if a rehashing is issued.
@@ -1174,19 +1121,19 @@ template<class K, class M> bool insert_or_assign(K&& k, M&& obj);
Inserts a new element into the table or updates an existing one by assigning to the contained value.
If there is an element with key `k`, then it is updated by assigning `std::forward<M>(obj)`.
If there is an element with key `k`, then it is updated by assigning `boost::forward<M>(obj)`.
If there is no such element, it is added to the table as:
```c++
// first two overloads
value_type(std::piecewise_construct,
std::forward_as_tuple(std::forward<Key>(k)),
std::forward_as_tuple(std::forward<M>(obj)))
std::forward_as_tuple(boost::forward<Key>(k)),
std::forward_as_tuple(boost::forward<M>(obj)))
// third overload
value_type(std::piecewise_construct,
std::forward_as_tuple(std::forward<K>(k)),
std::forward_as_tuple(std::forward<M>(obj)))
std::forward_as_tuple(boost::forward<K>(k)),
std::forward_as_tuple(boost::forward<M>(obj)))
```
[horizontal]
-48
View File
@@ -45,9 +45,6 @@ namespace boost {
using size_type = std::size_t;
using difference_type = std::ptrdiff_t;
// constants
static constexpr size_type xref:#concurrent_flat_set_constants[bulk_visit_size] = _implementation-defined_;
// construct/copy/destroy
xref:#concurrent_flat_set_default_constructor[concurrent_flat_set]();
explicit xref:#concurrent_flat_set_bucket_count_constructor[concurrent_flat_set](size_type n,
@@ -101,11 +98,6 @@ namespace boost {
template<class K, class F> size_t xref:#concurrent_flat_set_cvisit[visit](const K& k, F f) const;
template<class K, class F> size_t xref:#concurrent_flat_set_cvisit[cvisit](const K& k, F f) const;
template<class FwdIterator, class F>
size_t xref:concurrent_flat_set_bulk_visit[visit](FwdIterator first, FwdIterator last, F f) const;
template<class FwdIterator, class F>
size_t xref:concurrent_flat_set_bulk_visit[cvisit](FwdIterator first, FwdIterator last, F f) const;
template<class F> size_t xref:#concurrent_flat_set_cvisit_all[visit_all](F f) const;
template<class F> size_t xref:#concurrent_flat_set_cvisit_all[cvisit_all](F f) const;
template<class ExecutionPolicy, class F>
@@ -348,13 +340,6 @@ a function visiting elements of `m`) are detected and signalled through `BOOST_A
When run-time speed is a concern, the feature can be disabled by globally defining
this macro.
=== Constants
```cpp
static constexpr size_type bulk_visit_size;
```
Chunk size internally used in xref:concurrent_flat_set_bulk_visit[bulk visit] operations.
=== Constructors
@@ -687,39 +672,6 @@ Notes:;; The `template<class K, class F>` overloads only participate in overload
---
==== Bulk visit
```c++
template<class FwdIterator, class F>
size_t visit(FwdIterator first, FwdIterator last, F f) const;
template<class FwdIterator, class F>
size_t cvisit(FwdIterator first, FwdIterator last, F f) const;
```
For each element `k` in the range [`first`, `last`),
if there is an element `x` in the container with key equivalent to `k`,
invokes `f` with a const reference to `x`.
Although functionally equivalent to individually invoking
xref:concurrent_flat_set_cvisit[`[c\]visit`] for each key, bulk visitation
performs generally faster due to internal streamlining optimizations.
It is advisable that `std::distance(first,last)` be at least
xref:#concurrent_flat_set_constants[`bulk_visit_size`] to enjoy
a performance gain: beyond this size, performance is not expected
to increase further.
[horizontal]
Requires:;; `FwdIterator` is a https://en.cppreference.com/w/cpp/named_req/ForwardIterator[LegacyForwardIterator^]
({cpp}11 to {cpp}17),
or satisfies https://en.cppreference.com/w/cpp/iterator/forward_iterator[std::forward_iterator^] ({cpp}20 and later).
For `K` = `std::iterator_traits<FwdIterator>::value_type`, either `K` is `key_type` or
else `Hash::is_transparent` and `Pred::is_transparent` are valid member typedefs.
In the latter case, the library assumes that `Hash` is callable with both `K` and `Key` and that `Pred` is transparent.
This enables heterogeneous lookup which avoids the cost of instantiating an instance of the `Key` type.
Returns:;; The number of elements visited.
---
==== [c]visit_all
```c++
+18 -18
View File
@@ -909,13 +909,13 @@ if there is an element with an equivalent key; otherwise, the construction is of
```c++
// first two overloads
value_type(std::piecewise_construct,
std::forward_as_tuple(std::forward<Key>(k)),
std::forward_as_tuple(std::forward<Args>(args)...))
std::forward_as_tuple(boost::forward<Key>(k)),
std::forward_as_tuple(boost::forward<Args>(args)...))
// third overload
value_type(std::piecewise_construct,
std::forward_as_tuple(std::forward<K>(k)),
std::forward_as_tuple(std::forward<Args>(args)...))
std::forward_as_tuple(boost::forward<K>(k)),
std::forward_as_tuple(boost::forward<Args>(args)...))
```
unlike xref:#unordered_flat_map_emplace[emplace], which simply forwards all arguments to ``value_type``'s constructor.
@@ -954,13 +954,13 @@ if there is an element with an equivalent key; otherwise, the construction is of
```c++
// first two overloads
value_type(std::piecewise_construct,
std::forward_as_tuple(std::forward<Key>(k)),
std::forward_as_tuple(std::forward<Args>(args)...))
std::forward_as_tuple(boost::forward<Key>(k)),
std::forward_as_tuple(boost::forward<Args>(args)...))
// third overload
value_type(std::piecewise_construct,
std::forward_as_tuple(std::forward<K>(k)),
std::forward_as_tuple(std::forward<Args>(args)...))
std::forward_as_tuple(boost::forward<K>(k)),
std::forward_as_tuple(boost::forward<Args>(args)...))
```
unlike xref:#unordered_flat_map_emplace_hint[emplace_hint], which simply forwards all arguments to ``value_type``'s constructor.
@@ -985,19 +985,19 @@ template<class K, class M>
Inserts a new element into the container or updates an existing one by assigning to the contained value.
If there is an element with key `k`, then it is updated by assigning `std::forward<M>(obj)`.
If there is an element with key `k`, then it is updated by assigning `boost::forward<M>(obj)`.
If there is no such element, it is added to the container as:
```c++
// first two overloads
value_type(std::piecewise_construct,
std::forward_as_tuple(std::forward<Key>(k)),
std::forward_as_tuple(std::forward<M>(obj)))
std::forward_as_tuple(boost::forward<Key>(k)),
std::forward_as_tuple(boost::forward<M>(obj)))
// third overload
value_type(std::piecewise_construct,
std::forward_as_tuple(std::forward<K>(k)),
std::forward_as_tuple(std::forward<M>(obj)))
std::forward_as_tuple(boost::forward<K>(k)),
std::forward_as_tuple(boost::forward<M>(obj)))
```
[horizontal]
@@ -1023,19 +1023,19 @@ template<class K, class M>
Inserts a new element into the container or updates an existing one by assigning to the contained value.
If there is an element with key `k`, then it is updated by assigning `std::forward<M>(obj)`.
If there is an element with key `k`, then it is updated by assigning `boost::forward<M>(obj)`.
If there is no such element, it is added to the container as:
```c++
// first two overloads
value_type(std::piecewise_construct,
std::forward_as_tuple(std::forward<Key>(k)),
std::forward_as_tuple(std::forward<M>(obj)))
std::forward_as_tuple(boost::forward<Key>(k)),
std::forward_as_tuple(boost::forward<M>(obj)))
// third overload
value_type(std::piecewise_construct,
std::forward_as_tuple(std::forward<K>(k)),
std::forward_as_tuple(std::forward<M>(obj)))
std::forward_as_tuple(boost::forward<K>(k)),
std::forward_as_tuple(boost::forward<M>(obj)))
```
`hint` is a suggestion to where the element should be inserted. This implementation ignores it.
+94 -44
View File
@@ -26,12 +26,12 @@ namespace boost {
using hasher = Hash;
using key_equal = Pred;
using allocator_type = Allocator;
using pointer = typename std::allocator_traits<Allocator>::pointer;
using const_pointer = typename std::allocator_traits<Allocator>::const_pointer;
using pointer = typename boost::allocator_traits<Allocator>::pointer;
using const_pointer = typename boost::allocator_traits<Allocator>::const_pointer;
using reference = value_type&;
using const_reference = const value_type&;
using size_type = std::size_t;
using difference_type = std::ptrdiff_t;
using size_type = _implementation-defined_;
using difference_type = _implementation-defined_;
using iterator = _implementation-defined_;
using const_iterator = _implementation-defined_;
@@ -316,7 +316,6 @@ namespace boost {
|_Allocator_
|An allocator whose value type is the same as the container's value type.
Allocators using https://en.cppreference.com/w/cpp/named_req/Allocator#Fancy_pointers[fancy pointers] are supported.
|===
@@ -333,6 +332,47 @@ a Boost.Serialization archive with a version of Boost prior to Boost 1.84.
=== Typedefs
[source,c++,subs=+quotes]
----
typedef typename allocator_type::pointer pointer;
----
`value_type*` if `allocator_type::pointer` is not defined.
---
[source,c++,subs=+quotes]
----
typedef typename allocator_type::const_pointer const_pointer;
----
`boost::pointer_to_other<pointer, value_type>::type` if `allocator_type::const_pointer` is not defined.
---
[source,c++,subs=+quotes]
----
typedef _implementation-defined_ size_type;
----
An unsigned integral type.
`size_type` can represent any non-negative value of `difference_type`.
---
[source,c++,subs=+quotes]
----
typedef _implementation-defined_ difference_type;
----
A signed integral type.
Is identical to the difference type of `iterator` and `const_iterator`.
---
[source,c++,subs=+quotes]
----
typedef _implementation-defined_ iterator;
@@ -384,8 +424,7 @@ A const_local_iterator object can be used to iterate through a single bucket.
typedef _implementation-defined_ node_type;
----
A class for holding extracted container elements, modelling
https://en.cppreference.com/w/cpp/container/node_handle[NodeHandle].
See node_handle_map for details.
---
@@ -394,20 +433,7 @@ https://en.cppreference.com/w/cpp/container/node_handle[NodeHandle].
typedef _implementation-defined_ insert_return_type;
----
A specialization of an internal class template:
[source,c++,subs=+quotes]
----
template<class Iterator, class NodeType>
struct _insert_return_type_ // name is exposition only
{
Iterator position;
bool inserted;
NodeType node;
};
----
with `Iterator` = `iterator` and `NodeType` = `node_type`.
Structure returned by inserting node_type.
---
@@ -487,7 +513,10 @@ The move constructor.
[horizontal]
Notes:;; This is implemented using Boost.Move.
Requires:;; `value_type` is move-constructible.
Requires:;; `value_type` is move-constructible. +
+
On compilers without rvalue reference support the emulation does not support moving without calling `boost::move` if `value_type` is not copyable.
So, for example, you can't return the container from a function.
---
@@ -687,6 +716,7 @@ The move assignment operator.
If `Alloc::propagate_on_container_move_assignment` exists and `Alloc::propagate_on_container_move_assignment::value` is `true`, the allocator is overwritten, if not the moved elements are created using the existing allocator.
[horizontal]
Notes:;; On compilers without rvalue references, this is emulated using Boost.Move. Note that on some compilers the copy assignment operator may be used in some circumstances.
Requires:;; `value_type` is move constructible.
---
@@ -797,7 +827,11 @@ If an insert took place, then the iterator points to the newly inserted element.
Throws:;; If an exception is thrown by an operation other than a call to `hasher` the function has no effect.
Notes:;; Can invalidate iterators, but only if the insert causes the load factor to be greater to or equal to the maximum load factor. +
+
Pointers and references to elements are never invalidated.
Pointers and references to elements are never invalidated. +
+
If the compiler doesn't support variadic template arguments or rvalue references, this is emulated for up to `10` arguments, with no support for rvalue references or move semantics. +
+
Since existing `std::pair` implementations don't support `std::piecewise_construct` this emulates it, but using `boost::unordered::piecewise_construct`.
---
@@ -818,7 +852,11 @@ Notes:;; The standard is fairly vague on the meaning of the hint. But the only p
+
Can invalidate iterators, but only if the insert causes the load factor to be greater to or equal to the maximum load factor. +
+
Pointers and references to elements are never invalidated.
Pointers and references to elements are never invalidated. +
+
If the compiler doesn't support variadic template arguments or rvalue references, this is emulated for up to 10 arguments, with no support for rvalue references or move semantics. +
+
Since existing `std::pair` implementations don't support `std::piecewise_construct` this emulates it, but using `boost::unordered::piecewise_construct`.
---
@@ -996,13 +1034,13 @@ Notes:;; This function is similiar to xref:#unordered_map_emplace[emplace] excep
```c++
// first two overloads
value_type(std::piecewise_construct,
std::forward_as_tuple(std::forward<Key>(k)),
std::forward_as_tuple(std::forward<Args>(args)...))
std::forward_as_tuple(boost::forward<Key>(k)),
std::forward_as_tuple(boost::forward<Args>(args)...))
// third overload
value_type(std::piecewise_construct,
std::forward_as_tuple(std::forward<K>(k)),
std::forward_as_tuple(std::forward<Args>(args)...))
std::forward_as_tuple(boost::forward<K>(k)),
std::forward_as_tuple(boost::forward<Args>(args)...))
```
instead of xref:#unordered_map_emplace[emplace] which simply forwards all arguments to ``value_type``'s constructor.
@@ -1012,6 +1050,10 @@ Can invalidate iterators, but only if the insert causes the load factor to be gr
Pointers and references to elements are never invalidated.
The `template<class K, class\... Args>` overload only participates in overload resolution if `Hash::is_transparent` and `Pred::is_transparent` are valid member typedefs and neither `iterator` nor `const_iterator` are implicitly convertible from `K`. The library assumes that `Hash` is callable with both `K` and `Key` and that `Pred` is transparent. This enables heterogeneous lookup which avoids the cost of instantiating an instance of the `Key` type.
If the compiler doesn't support variadic template arguments or rvalue references, this is emulated for up to `10` arguments, with no support for rvalue references or move semantics.
Since existing `std::pair` implementations don't support `std::piecewise_construct` this emulates it, but using `boost::unordered::piecewise_construct`.
--
---
@@ -1041,13 +1083,13 @@ Notes:;; This function is similiar to xref:#unordered_map_emplace_hint[emplace_h
```c++
// first two overloads
value_type(std::piecewise_construct,
std::forward_as_tuple(std::forward<Key>(k)),
std::forward_as_tuple(std::forward<Args>(args)...))
std::forward_as_tuple(boost::forward<Key>(k)),
std::forward_as_tuple(boost::forward<Args>(args)...))
// third overload
value_type(std::piecewise_construct,
std::forward_as_tuple(std::forward<K>(k)),
std::forward_as_tuple(std::forward<Args>(args)...))
std::forward_as_tuple(boost::forward<K>(k)),
std::forward_as_tuple(boost::forward<Args>(args)...))
```
instead of xref:#unordered_map_emplace_hint[emplace_hint] which simply forwards all arguments to ``value_type``'s constructor.
@@ -1059,6 +1101,10 @@ Can invalidate iterators, but only if the insert causes the load factor to be gr
Pointers and references to elements are never invalidated.
The `template<class K, class\... Args>` overload only participates in overload resolution if `Hash::is_transparent` and `Pred::is_transparent` are valid member typedefs and neither `iterator` nor `const_iterator` are implicitly convertible from `K`. The library assumes that `Hash` is callable with both `K` and `Key` and that `Pred` is transparent. This enables heterogeneous lookup which avoids the cost of instantiating an instance of the `Key` type.
If the compiler doesn't support variadic template arguments or rvalue references, this is emulated for up to `10` arguments, with no support for rvalue references or move semantics.
Since existing `std::pair` implementations don't support `std::piecewise_construct` this emulates it, but using `boost::unordered::piecewise_construct`.
--
---
@@ -1075,19 +1121,19 @@ template<class K, class M>
Inserts a new element into the container or updates an existing one by assigning to the contained value.
If there is an element with key `k`, then it is updated by assigning `std::forward<M>(obj)`.
If there is an element with key `k`, then it is updated by assigning `boost::forward<M>(obj)`.
If there is no such element, it is added to the container as:
```c++
// first two overloads
value_type(std::piecewise_construct,
std::forward_as_tuple(std::forward<Key>(k)),
std::forward_as_tuple(std::forward<M>(obj)))
std::forward_as_tuple(boost::forward<Key>(k)),
std::forward_as_tuple(boost::forward<M>(obj)))
// third overload
value_type(std::piecewise_construct,
std::forward_as_tuple(std::forward<K>(k)),
std::forward_as_tuple(std::forward<M>(obj)))
std::forward_as_tuple(boost::forward<K>(k)),
std::forward_as_tuple(boost::forward<M>(obj)))
```
[horizontal]
@@ -1115,19 +1161,19 @@ template<class K, class M>
Inserts a new element into the container or updates an existing one by assigning to the contained value.
If there is an element with key `k`, then it is updated by assigning `std::forward<M>(obj)`.
If there is an element with key `k`, then it is updated by assigning `boost::forward<M>(obj)`.
If there is no such element, it is added to the container as:
```c++
// first two overloads
value_type(std::piecewise_construct,
std::forward_as_tuple(std::forward<Key>(k)),
std::forward_as_tuple(std::forward<M>(obj)))
std::forward_as_tuple(boost::forward<Key>(k)),
std::forward_as_tuple(boost::forward<M>(obj)))
// third overload
value_type(std::piecewise_construct,
std::forward_as_tuple(std::forward<K>(k)),
std::forward_as_tuple(std::forward<M>(obj)))
std::forward_as_tuple(boost::forward<K>(k)),
std::forward_as_tuple(boost::forward<M>(obj)))
```
`hint` is a suggestion to where the element should be inserted.
@@ -1720,7 +1766,9 @@ template<class Key, class T, class Hash, class Pred, class Alloc>
Return `true` if `x.size() == y.size()` and for every element in `x`, there is an element in `y` with the same key, with an equal value (using `operator==` to compare the value types).
[horizontal]
Notes:;; Behavior is undefined if the two containers don't have equivalent equality predicates.
Notes:;; The behavior of this function was changed to match the C++11 standard in Boost 1.48. +
+
Behavior is undefined if the two containers don't have equivalent equality predicates.
---
@@ -1734,7 +1782,9 @@ template<class Key, class T, class Hash, class Pred, class Alloc>
Return `false` if `x.size() == y.size()` and for every element in `x`, there is an element in `y` with the same key, with an equal value (using `operator==` to compare the value types).
[horizontal]
Notes:;; Behavior is undefined if the two containers don't have equivalent equality predicates.
Notes:;; The behavior of this function was changed to match the C++11 standard in Boost 1.48. +
+
Behavior is undefined if the two containers don't have equivalent equality predicates.
=== Swap
```c++
+66 -10
View File
@@ -26,12 +26,12 @@ namespace boost {
using hasher = Hash;
using key_equal = Pred;
using allocator_type = Allocator;
using pointer = typename std::allocator_traits<Allocator>::pointer;
using const_pointer = typename std::allocator_traits<Allocator>::const_pointer;
using pointer = typename boost::allocator_traits<Allocator>::pointer;
using const_pointer = typename boost::allocator_traits<Allocator>::const_pointer;
using reference = value_type&;
using const_reference = const value_type&;
using size_type = std::size_t;
using difference_type = std::ptrdiff_t;
using size_type = _implementation-defined_;
using difference_type = _implementation-defined_;
using iterator = _implementation-defined_;
using const_iterator = _implementation-defined_;
@@ -283,7 +283,6 @@ namespace boost {
|_Allocator_
|An allocator whose value type is the same as the container's value type.
Allocators using https://en.cppreference.com/w/cpp/named_req/Allocator#Fancy_pointers[fancy pointers] are supported.
|===
@@ -300,6 +299,47 @@ a Boost.Serialization archive with a version of Boost prior to Boost 1.84.
=== Typedefs
[source,c++,subs=+quotes]
----
typedef typename allocator_type::pointer pointer;
----
`value_type*` if `allocator_type::pointer` is not defined.
---
[source,c++,subs=+quotes]
----
typedef typename allocator_type::const_pointer const_pointer;
----
`boost::pointer_to_other<pointer, value_type>::type` if `allocator_type::const_pointer` is not defined.
---
[source,c++,subs=+quotes]
----
typedef _implementation-defined_ size_type;
----
An unsigned integral type.
`size_type` can represent any non-negative value of `difference_type`.
---
[source,c++,subs=+quotes]
----
typedef _implementation-defined_ difference_type;
----
A signed integral type.
Is identical to the difference type of `iterator` and `const_iterator`.
---
[source,c++,subs=+quotes]
----
typedef _implementation-defined_ iterator;
@@ -431,7 +471,10 @@ The move constructor.
[horizontal]
Notes:;; This is implemented using Boost.Move.
Requires:;; `value_type` is move-constructible.
Requires:;; `value_type` is move-constructible. +
+
On compilers without rvalue reference support the emulation does not support moving without calling `boost::move` if `value_type` is not copyable.
So, for example, you can't return the container from a function.
---
@@ -630,6 +673,7 @@ The move assignment operator.
If `Alloc::propagate_on_container_move_assignment` exists and `Alloc::propagate_on_container_move_assignment::value` is `true`, the allocator is overwritten, if not the moved elements are created using the existing allocator.
[horizontal]
Notes:;; On compilers without rvalue references, this is emulated using Boost.Move. Note that on some compilers the copy assignment operator may be used in some circumstances.
Requires:;; `value_type` is move constructible.
---
@@ -738,7 +782,11 @@ Returns:;; An iterator pointing to the inserted element.
Throws:;; If an exception is thrown by an operation other than a call to `hasher` the function has no effect.
Notes:;; Can invalidate iterators, but only if the insert causes the load factor to be greater to or equal to the maximum load factor. +
+
Pointers and references to elements are never invalidated.
Pointers and references to elements are never invalidated. +
+
If the compiler doesn't support variadic template arguments or rvalue references, this is emulated for up to `10` arguments, with no support for rvalue references or move semantics. +
+
Since existing `std::pair` implementations don't support `std::piecewise_construct` this emulates it, but using `boost::unordered::piecewise_construct`.
---
@@ -759,7 +807,11 @@ Notes:;; The standard is fairly vague on the meaning of the hint. But the only p
+
Can invalidate iterators, but only if the insert causes the load factor to be greater to or equal to the maximum load factor. +
+
Pointers and references to elements are never invalidated.
Pointers and references to elements are never invalidated. +
+
If the compiler doesn't support variadic template arguments or rvalue references, this is emulated for up to 10 arguments, with no support for rvalue references or move semantics. +
+
Since existing `std::pair` implementations don't support `std::piecewise_construct` this emulates it, but using `boost::unordered::piecewise_construct`.
---
@@ -1441,7 +1493,9 @@ template<class Key, class T, class Hash, class Pred, class Alloc>
Return `true` if `x.size() == y.size()` and for every equivalent key group in `x`, there is a group in `y` for the same key, which is a permutation (using `operator==` to compare the value types).
[horizontal]
Notes:;; Behavior is undefined if the two containers don't have equivalent equality predicates.
Notes:;; The behavior of this function was changed to match the C++11 standard in Boost 1.48. +
+
Behavior is undefined if the two containers don't have equivalent equality predicates.
---
@@ -1455,7 +1509,9 @@ template<class Key, class T, class Hash, class Pred, class Alloc>
Return `false` if `x.size() == y.size()` and for every equivalent key group in `x`, there is a group in `y` for the same key, which is a permutation (using `operator==` to compare the value types).
[horizontal]
Notes:;; Behavior is undefined if the two containers don't have equivalent equality predicates.
Notes:;; The behavior of this function was changed to match the C++11 standard in Boost 1.48. +
+
Behavior is undefined if the two containers don't have equivalent equality predicates.
---
+65 -10
View File
@@ -24,12 +24,12 @@ namespace boost {
using hasher = Hash;
using key_equal = Pred;
using allocator_type = Allocator;
using pointer = typename std::allocator_traits<Allocator>::pointer;
using const_pointer = typename std::allocator_traits<Allocator>::const_pointer;
using pointer = typename boost::allocator_traits<Allocator>::pointer;
using const_pointer = typename boost::allocator_traits<Allocator>::const_pointer;
using reference = value_type&;
using const_reference = const value_type&;
using size_type = std::size_t;
using difference_type = std::ptrdiff_t;
using size_type = _implementation-defined_;
using difference_type = _implementation-defined_;
using iterator = _implementation-defined_;
using const_iterator = _implementation-defined_;
@@ -271,7 +271,6 @@ namespace boost {
|_Allocator_
|An allocator whose value type is the same as the container's value type.
Allocators using https://en.cppreference.com/w/cpp/named_req/Allocator#Fancy_pointers[fancy pointers] are supported.
|===
@@ -288,6 +287,46 @@ a Boost.Serialization archive with a version of Boost prior to Boost 1.84.
=== Typedefs
[source,c++,subs=+quotes]
----
typedef typename allocator_type::pointer pointer;
----
`value_type*` if `allocator_type::pointer` is not defined.
---
[source,c++,subs=+quotes]
----
typedef typename allocator_type::const_pointer const_pointer;
----
`boost::pointer_to_other<pointer, value_type>::type` if `allocator_type::const_pointer` is not defined.
---
[source,c++,subs=+quotes]
----
typedef _implementation-defined_ size_type;
----
An unsigned integral type.
`size_type` can represent any non-negative value of `difference_type`.
---
[source,c++,subs=+quotes]
----
typedef _implementation-defined_ difference_type;
----
A signed integral type.
Is identical to the difference type of `iterator` and `const_iterator`.
---
[source,c++,subs=+quotes]
----
typedef _implementation-defined_ iterator;
@@ -419,7 +458,10 @@ The move constructor.
[horizontal]
Notes:;; This is implemented using Boost.Move.
Requires:;; `value_type` is move-constructible.
Requires:;; `value_type` is move-constructible. +
+
On compilers without rvalue reference support the emulation does not support moving without calling `boost::move` if `value_type` is not copyable.
So, for example, you can't return the container from a function.
---
@@ -619,6 +661,7 @@ The move assignment operator.
If `Alloc::propagate_on_container_move_assignment` exists and `Alloc::propagate_on_container_move_assignment::value` is `true`, the allocator is overwritten, if not the moved elements are created using the existing allocator.
[horizontal]
Notes:;; On compilers without rvalue references, this is emulated using Boost.Move. Note that on some compilers the copy assignment operator may be used in some circumstances.
Requires:;; `value_type` is move constructible.
---
@@ -729,7 +772,11 @@ Returns:;; An iterator pointing to the inserted element.
Throws:;; If an exception is thrown by an operation other than a call to `hasher` the function has no effect.
Notes:;; Can invalidate iterators, but only if the insert causes the load factor to be greater to or equal to the maximum load factor. +
+
Pointers and references to elements are never invalidated.
Pointers and references to elements are never invalidated. +
+
If the compiler doesn't support variadic template arguments or rvalue references, this is emulated for up to `10` arguments, with no support for rvalue references or move semantics. +
+
Since existing `std::pair` implementations don't support `std::piecewise_construct` this emulates it, but using `boost::unordered::piecewise_construct`.
---
@@ -750,7 +797,11 @@ Notes:;; The standard is fairly vague on the meaning of the hint. But the only p
+
Can invalidate iterators, but only if the insert causes the load factor to be greater to or equal to the maximum load factor. +
+
Pointers and references to elements are never invalidated.
Pointers and references to elements are never invalidated. +
+
If the compiler doesn't support variadic template arguments or rvalue references, this is emulated for up to 10 arguments, with no support for rvalue references or move semantics. +
+
Since existing `std::pair` implementations don't support `std::piecewise_construct` this emulates it, but using `boost::unordered::piecewise_construct`.
---
@@ -1373,7 +1424,9 @@ template<class Key, class Hash, class Pred, class Alloc>
Return `true` if `x.size() == y.size()` and for every element in `x`, there is an element in `y` with the same key, with an equal value (using `operator==` to compare the value types).
[horizontal]
Notes:;; Behavior is undefined if the two containers don't have equivalent equality predicates.
Notes:;; The behavior of this function was changed to match the C++11 standard in Boost 1.48. +
+
Behavior is undefined if the two containers don't have equivalent equality predicates.
---
@@ -1387,7 +1440,9 @@ template<class Key, class Hash, class Pred, class Alloc>
Return `false` if `x.size() == y.size()` and for every element in `x`, there is an element in `y` with the same key, with an equal value (using `operator==` to compare the value types).
[horizontal]
Notes:;; Behavior is undefined if the two containers don't have equivalent equality predicates.
Notes:;; The behavior of this function was changed to match the C++11 standard in Boost 1.48. +
+
Behavior is undefined if the two containers don't have equivalent equality predicates.
---
+18 -18
View File
@@ -962,13 +962,13 @@ if there is an element with an equivalent key; otherwise, the construction is of
```c++
// first two overloads
value_type(std::piecewise_construct,
std::forward_as_tuple(std::forward<Key>(k)),
std::forward_as_tuple(std::forward<Args>(args)...))
std::forward_as_tuple(boost::forward<Key>(k)),
std::forward_as_tuple(boost::forward<Args>(args)...))
// third overload
value_type(std::piecewise_construct,
std::forward_as_tuple(std::forward<K>(k)),
std::forward_as_tuple(std::forward<Args>(args)...))
std::forward_as_tuple(boost::forward<K>(k)),
std::forward_as_tuple(boost::forward<Args>(args)...))
```
unlike xref:#unordered_node_map_emplace[emplace], which simply forwards all arguments to ``value_type``'s constructor.
@@ -1007,13 +1007,13 @@ if there is an element with an equivalent key; otherwise, the construction is of
```c++
// first two overloads
value_type(std::piecewise_construct,
std::forward_as_tuple(std::forward<Key>(k)),
std::forward_as_tuple(std::forward<Args>(args)...))
std::forward_as_tuple(boost::forward<Key>(k)),
std::forward_as_tuple(boost::forward<Args>(args)...))
// third overload
value_type(std::piecewise_construct,
std::forward_as_tuple(std::forward<K>(k)),
std::forward_as_tuple(std::forward<Args>(args)...))
std::forward_as_tuple(boost::forward<K>(k)),
std::forward_as_tuple(boost::forward<Args>(args)...))
```
unlike xref:#unordered_node_map_emplace_hint[emplace_hint], which simply forwards all arguments to ``value_type``'s constructor.
@@ -1038,19 +1038,19 @@ template<class K, class M>
Inserts a new element into the container or updates an existing one by assigning to the contained value.
If there is an element with key `k`, then it is updated by assigning `std::forward<M>(obj)`.
If there is an element with key `k`, then it is updated by assigning `boost::forward<M>(obj)`.
If there is no such element, it is added to the container as:
```c++
// first two overloads
value_type(std::piecewise_construct,
std::forward_as_tuple(std::forward<Key>(k)),
std::forward_as_tuple(std::forward<M>(obj)))
std::forward_as_tuple(boost::forward<Key>(k)),
std::forward_as_tuple(boost::forward<M>(obj)))
// third overload
value_type(std::piecewise_construct,
std::forward_as_tuple(std::forward<K>(k)),
std::forward_as_tuple(std::forward<M>(obj)))
std::forward_as_tuple(boost::forward<K>(k)),
std::forward_as_tuple(boost::forward<M>(obj)))
```
[horizontal]
@@ -1076,19 +1076,19 @@ template<class K, class M>
Inserts a new element into the container or updates an existing one by assigning to the contained value.
If there is an element with key `k`, then it is updated by assigning `std::forward<M>(obj)`.
If there is an element with key `k`, then it is updated by assigning `boost::forward<M>(obj)`.
If there is no such element, it is added to the container as:
```c++
// first two overloads
value_type(std::piecewise_construct,
std::forward_as_tuple(std::forward<Key>(k)),
std::forward_as_tuple(std::forward<M>(obj)))
std::forward_as_tuple(boost::forward<Key>(k)),
std::forward_as_tuple(boost::forward<M>(obj)))
// third overload
value_type(std::piecewise_construct,
std::forward_as_tuple(std::forward<K>(k)),
std::forward_as_tuple(std::forward<M>(obj)))
std::forward_as_tuple(boost::forward<K>(k)),
std::forward_as_tuple(boost::forward<M>(obj)))
```
`hint` is a suggestion to where the element should be inserted. This implementation ignores it.
+68 -26
View File
@@ -24,12 +24,12 @@ namespace boost {
using hasher = Hash;
using key_equal = Pred;
using allocator_type = Allocator;
using pointer = typename std::allocator_traits<Allocator>::pointer;
using const_pointer = typename std::allocator_traits<Allocator>::const_pointer;
using pointer = typename boost::allocator_traits<Allocator>::pointer;
using const_pointer = typename boost::allocator_traits<Allocator>::const_pointer;
using reference = value_type&;
using const_reference = const value_type&;
using size_type = std::size_t;
using difference_type = std::ptrdiff_t;
using size_type = _implementation-defined_;
using difference_type = _implementation-defined_;
using iterator = _implementation-defined_;
using const_iterator = _implementation-defined_;
@@ -272,7 +272,6 @@ namespace boost {
|_Allocator_
|An allocator whose value type is the same as the container's value type.
Allocators using https://en.cppreference.com/w/cpp/named_req/Allocator#Fancy_pointers[fancy pointers] are supported.
|===
@@ -289,6 +288,47 @@ a Boost.Serialization archive with a version of Boost prior to Boost 1.84.
=== Typedefs
[source,c++,subs=+quotes]
----
typedef typename allocator_type::pointer pointer;
----
`value_type*` if `allocator_type::pointer` is not defined.
---
[source,c++,subs=+quotes]
----
typedef typename allocator_type::const_pointer const_pointer;
----
`boost::pointer_to_other<pointer, value_type>::type` if `allocator_type::const_pointer` is not defined.
---
[source,c++,subs=+quotes]
----
typedef _implementation-defined_ size_type;
----
An unsigned integral type.
`size_type` can represent any non-negative value of `difference_type`.
---
[source,c++,subs=+quotes]
----
typedef _implementation-defined_ difference_type;
----
A signed integral type.
Is identical to the difference type of `iterator` and `const_iterator`.
---
[source,c++,subs=+quotes]
----
typedef _implementation-defined_ iterator;
@@ -340,8 +380,7 @@ A const_local_iterator object can be used to iterate through a single bucket.
typedef _implementation-defined_ node_type;
----
A class for holding extracted container elements, modelling
https://en.cppreference.com/w/cpp/container/node_handle[NodeHandle].
See node_handle_set for details.
---
@@ -350,20 +389,7 @@ https://en.cppreference.com/w/cpp/container/node_handle[NodeHandle].
typedef _implementation-defined_ insert_return_type;
----
A specialization of an internal class template:
[source,c++,subs=+quotes]
----
template<class Iterator, class NodeType>
struct _insert_return_type_ // name is exposition only
{
Iterator position;
bool inserted;
NodeType node;
};
----
with `Iterator` = `iterator` and `NodeType` = `node_type`.
Structure returned by inserting node_type.
---
@@ -443,7 +469,10 @@ The move constructor.
[horizontal]
Notes:;; This is implemented using Boost.Move.
Requires:;; `value_type` is move-constructible.
Requires:;; `value_type` is move-constructible. +
+
On compilers without rvalue reference support the emulation does not support moving without calling `boost::move` if `value_type` is not copyable.
So, for example, you can't return the container from a function.
---
@@ -643,6 +672,7 @@ The move assignment operator.
If `Alloc::propagate_on_container_move_assignment` exists and `Alloc::propagate_on_container_move_assignment::value` is `true`, the allocator is overwritten, if not the moved elements are created using the existing allocator.
[horizontal]
Notes:;; On compilers without rvalue references, this is emulated using Boost.Move. Note that on some compilers the copy assignment operator may be used in some circumstances.
Requires:;; `value_type` is move constructible.
---
@@ -755,7 +785,11 @@ If an insert took place, then the iterator points to the newly inserted element.
Throws:;; If an exception is thrown by an operation other than a call to `hasher` the function has no effect.
Notes:;; Can invalidate iterators, but only if the insert causes the load factor to be greater to or equal to the maximum load factor. +
+
Pointers and references to elements are never invalidated.
Pointers and references to elements are never invalidated. +
+
If the compiler doesn't support variadic template arguments or rvalue references, this is emulated for up to `10` arguments, with no support for rvalue references or move semantics. +
+
Since existing `std::pair` implementations don't support `std::piecewise_construct` this emulates it, but using `boost::unordered::piecewise_construct`.
---
@@ -776,7 +810,11 @@ Notes:;; The standard is fairly vague on the meaning of the hint. But the only p
+
Can invalidate iterators, but only if the insert causes the load factor to be greater to or equal to the maximum load factor. +
+
Pointers and references to elements are never invalidated.
Pointers and references to elements are never invalidated. +
+
If the compiler doesn't support variadic template arguments or rvalue references, this is emulated for up to 10 arguments, with no support for rvalue references or move semantics. +
+
Since existing `std::pair` implementations don't support `std::piecewise_construct` this emulates it, but using `boost::unordered::piecewise_construct`.
---
@@ -1451,7 +1489,9 @@ template<class Key, class Hash, class Pred, class Alloc>
Return `true` if `x.size() == y.size()` and for every element in `x`, there is an element in `y` with the same key, with an equal value (using `operator==` to compare the value types).
[horizontal]
Notes:;; Behavior is undefined if the two containers don't have equivalent equality predicates.
Notes:;; The behavior of this function was changed to match the C++11 standard in Boost 1.48. +
+
Behavior is undefined if the two containers don't have equivalent equality predicates.
---
@@ -1465,7 +1505,9 @@ template<class Key, class Hash, class Pred, class Alloc>
Return `false` if `x.size() == y.size()` and for every element in `x`, there is an element in `y` with the same key, with an equal value (using `operator==` to compare the value types).
[horizontal]
Notes:;; Behavior is undefined if the two containers don't have equivalent equality predicates.
Notes:;; The behavior of this function was changed to match the C++11 standard in Boost 1.48. +
+
Behavior is undefined if the two containers don't have equivalent equality predicates.
---
+1 -1
View File
@@ -14,7 +14,7 @@
#define BOOST_HASH_EXAMPLES_CASE_INSENSITIVE_HEADER
#include <boost/algorithm/string/predicate.hpp>
#include <boost/container_hash/hash.hpp>
#include <boost/functional/hash.hpp>
namespace hash_examples
{
+41 -61
View File
@@ -1,7 +1,6 @@
/* Fast open-addressing concurrent hashmap.
*
* Copyright 2023 Christian Mazakas.
* Copyright 2023 Joaquin M Lopez Munoz.
* 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)
@@ -22,6 +21,7 @@
#include <boost/container_hash/hash.hpp>
#include <boost/core/allocator_access.hpp>
#include <boost/core/serialization.hpp>
#include <boost/type_traits/type_identity.hpp>
#include <type_traits>
@@ -65,15 +65,14 @@ namespace boost {
using init_type = typename type_policy::init_type;
using size_type = std::size_t;
using difference_type = std::ptrdiff_t;
using hasher = typename boost::unordered::detail::type_identity<Hash>::type;
using key_equal = typename boost::unordered::detail::type_identity<Pred>::type;
using allocator_type = typename boost::unordered::detail::type_identity<Allocator>::type;
using hasher = typename boost::type_identity<Hash>::type;
using key_equal = typename boost::type_identity<Pred>::type;
using allocator_type = typename boost::type_identity<Allocator>::type;
using reference = value_type&;
using const_reference = value_type const&;
using pointer = typename boost::allocator_pointer<allocator_type>::type;
using const_pointer =
typename boost::allocator_const_pointer<allocator_type>::type;
static constexpr size_type bulk_visit_size = table_type::bulk_visit_size;
concurrent_flat_map()
: concurrent_flat_map(detail::foa::default_bucket_count)
@@ -245,6 +244,14 @@ namespace boost {
return table_.visit(k, f);
}
template<typename FwdIterator,typename F>
BOOST_FORCEINLINE
std::size_t visit(FwdIterator first,FwdIterator last,F f)const
{
BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F)
return table_.visit(first, last, f);
}
template <class K, class F>
BOOST_FORCEINLINE typename std::enable_if<
detail::are_transparent<K, hasher, key_equal>::value, size_type>::type
@@ -272,33 +279,6 @@ namespace boost {
return table_.visit(std::forward<K>(k), f);
}
template<class FwdIterator, class F>
BOOST_FORCEINLINE
size_t visit(FwdIterator first, FwdIterator last, F f)
{
BOOST_UNORDERED_STATIC_ASSERT_BULK_VISIT_ITERATOR(FwdIterator)
BOOST_UNORDERED_STATIC_ASSERT_INVOCABLE(F)
return table_.visit(first, last, f);
}
template<class FwdIterator, class F>
BOOST_FORCEINLINE
size_t visit(FwdIterator first, FwdIterator last, F f) const
{
BOOST_UNORDERED_STATIC_ASSERT_BULK_VISIT_ITERATOR(FwdIterator)
BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F)
return table_.visit(first, last, f);
}
template<class FwdIterator, class F>
BOOST_FORCEINLINE
size_t cvisit(FwdIterator first, FwdIterator last, F f) const
{
BOOST_UNORDERED_STATIC_ASSERT_BULK_VISIT_ITERATOR(FwdIterator)
BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F)
return table_.visit(first, last, f);
}
template <class F> size_type visit_all(F f)
{
BOOST_UNORDERED_STATIC_ASSERT_INVOCABLE(F)
@@ -772,10 +752,10 @@ namespace boost {
std::equal_to<boost::unordered::detail::iter_key_t<InputIterator> >,
class Allocator = std::allocator<
boost::unordered::detail::iter_to_alloc_t<InputIterator> >,
class = std::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
class = std::enable_if_t<detail::is_hash_v<Hash> >,
class = std::enable_if_t<detail::is_pred_v<Pred> >,
class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
class = boost::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
class = boost::enable_if_t<detail::is_hash_v<Hash> >,
class = boost::enable_if_t<detail::is_pred_v<Pred> >,
class = boost::enable_if_t<detail::is_allocator_v<Allocator> > >
concurrent_flat_map(InputIterator, InputIterator,
std::size_t = boost::unordered::detail::foa::default_bucket_count,
Hash = Hash(), Pred = Pred(), Allocator = Allocator())
@@ -785,21 +765,21 @@ namespace boost {
Allocator>;
template <class Key, class T,
class Hash = boost::hash<std::remove_const_t<Key> >,
class Pred = std::equal_to<std::remove_const_t<Key> >,
class Hash = boost::hash<boost::remove_const_t<Key> >,
class Pred = std::equal_to<boost::remove_const_t<Key> >,
class Allocator = std::allocator<std::pair<const Key, T> >,
class = std::enable_if_t<detail::is_hash_v<Hash> >,
class = std::enable_if_t<detail::is_pred_v<Pred> >,
class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
class = boost::enable_if_t<detail::is_hash_v<Hash> >,
class = boost::enable_if_t<detail::is_pred_v<Pred> >,
class = boost::enable_if_t<detail::is_allocator_v<Allocator> > >
concurrent_flat_map(std::initializer_list<std::pair<Key, T> >,
std::size_t = boost::unordered::detail::foa::default_bucket_count,
Hash = Hash(), Pred = Pred(), Allocator = Allocator())
-> concurrent_flat_map<std::remove_const_t<Key>, T, Hash, Pred,
-> concurrent_flat_map<boost::remove_const_t<Key>, T, Hash, Pred,
Allocator>;
template <class InputIterator, class Allocator,
class = std::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
class = boost::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
class = boost::enable_if_t<detail::is_allocator_v<Allocator> > >
concurrent_flat_map(InputIterator, InputIterator, std::size_t, Allocator)
-> concurrent_flat_map<
boost::unordered::detail::iter_key_t<InputIterator>,
@@ -809,8 +789,8 @@ namespace boost {
Allocator>;
template <class InputIterator, class Allocator,
class = std::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
class = boost::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
class = boost::enable_if_t<detail::is_allocator_v<Allocator> > >
concurrent_flat_map(InputIterator, InputIterator, Allocator)
-> concurrent_flat_map<
boost::unordered::detail::iter_key_t<InputIterator>,
@@ -820,9 +800,9 @@ namespace boost {
Allocator>;
template <class InputIterator, class Hash, class Allocator,
class = std::enable_if_t<detail::is_hash_v<Hash> >,
class = std::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
class = boost::enable_if_t<detail::is_hash_v<Hash> >,
class = boost::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
class = boost::enable_if_t<detail::is_allocator_v<Allocator> > >
concurrent_flat_map(
InputIterator, InputIterator, std::size_t, Hash, Allocator)
-> concurrent_flat_map<
@@ -832,25 +812,25 @@ namespace boost {
Allocator>;
template <class Key, class T, class Allocator,
class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
class = boost::enable_if_t<detail::is_allocator_v<Allocator> > >
concurrent_flat_map(std::initializer_list<std::pair<Key, T> >, std::size_t,
Allocator) -> concurrent_flat_map<std::remove_const_t<Key>, T,
boost::hash<std::remove_const_t<Key> >,
std::equal_to<std::remove_const_t<Key> >, Allocator>;
Allocator) -> concurrent_flat_map<boost::remove_const_t<Key>, T,
boost::hash<boost::remove_const_t<Key> >,
std::equal_to<boost::remove_const_t<Key> >, Allocator>;
template <class Key, class T, class Allocator,
class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
class = boost::enable_if_t<detail::is_allocator_v<Allocator> > >
concurrent_flat_map(std::initializer_list<std::pair<Key, T> >, Allocator)
-> concurrent_flat_map<std::remove_const_t<Key>, T,
boost::hash<std::remove_const_t<Key> >,
std::equal_to<std::remove_const_t<Key> >, Allocator>;
-> concurrent_flat_map<boost::remove_const_t<Key>, T,
boost::hash<boost::remove_const_t<Key> >,
std::equal_to<boost::remove_const_t<Key> >, Allocator>;
template <class Key, class T, class Hash, class Allocator,
class = std::enable_if_t<detail::is_hash_v<Hash> >,
class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
class = boost::enable_if_t<detail::is_hash_v<Hash> >,
class = boost::enable_if_t<detail::is_allocator_v<Allocator> > >
concurrent_flat_map(std::initializer_list<std::pair<Key, T> >, std::size_t,
Hash, Allocator) -> concurrent_flat_map<std::remove_const_t<Key>, T,
Hash, std::equal_to<std::remove_const_t<Key> >, Allocator>;
Hash, Allocator) -> concurrent_flat_map<boost::remove_const_t<Key>, T,
Hash, std::equal_to<boost::remove_const_t<Key> >, Allocator>;
#endif
+23 -44
View File
@@ -22,6 +22,7 @@
#include <boost/container_hash/hash.hpp>
#include <boost/core/allocator_access.hpp>
#include <boost/core/serialization.hpp>
#include <boost/type_traits/type_identity.hpp>
#include <utility>
@@ -38,10 +39,7 @@ namespace boost {
using type_policy = detail::foa::flat_set_types<Key>;
using table_type =
detail::foa::concurrent_table<type_policy, Hash, Pred, Allocator>;
table_type table_;
detail::foa::concurrent_table<type_policy, Hash, Pred, Allocator> table_;
template <class K, class H, class KE, class A>
bool friend operator==(concurrent_flat_set<K, H, KE, A> const& lhs,
@@ -62,15 +60,14 @@ namespace boost {
using init_type = typename type_policy::init_type;
using size_type = std::size_t;
using difference_type = std::ptrdiff_t;
using hasher = typename boost::unordered::detail::type_identity<Hash>::type;
using key_equal = typename boost::unordered::detail::type_identity<Pred>::type;
using allocator_type = typename boost::unordered::detail::type_identity<Allocator>::type;
using hasher = typename boost::type_identity<Hash>::type;
using key_equal = typename boost::type_identity<Pred>::type;
using allocator_type = typename boost::type_identity<Allocator>::type;
using reference = value_type&;
using const_reference = value_type const&;
using pointer = typename boost::allocator_pointer<allocator_type>::type;
using const_pointer =
typename boost::allocator_const_pointer<allocator_type>::type;
static constexpr size_type bulk_visit_size = table_type::bulk_visit_size;
concurrent_flat_set()
: concurrent_flat_set(detail::foa::default_bucket_count)
@@ -255,24 +252,6 @@ namespace boost {
return table_.visit(std::forward<K>(k), f);
}
template<class FwdIterator, class F>
BOOST_FORCEINLINE
size_t visit(FwdIterator first, FwdIterator last, F f) const
{
BOOST_UNORDERED_STATIC_ASSERT_BULK_VISIT_ITERATOR(FwdIterator)
BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F)
return table_.visit(first, last, f);
}
template<class FwdIterator, class F>
BOOST_FORCEINLINE
size_t cvisit(FwdIterator first, FwdIterator last, F f) const
{
BOOST_UNORDERED_STATIC_ASSERT_BULK_VISIT_ITERATOR(FwdIterator)
BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F)
return table_.visit(first, last, f);
}
template <class F> size_type visit_all(F f) const
{
BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F)
@@ -640,10 +619,10 @@ namespace boost {
std::equal_to<typename std::iterator_traits<InputIterator>::value_type>,
class Allocator = std::allocator<
typename std::iterator_traits<InputIterator>::value_type>,
class = std::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
class = std::enable_if_t<detail::is_hash_v<Hash> >,
class = std::enable_if_t<detail::is_pred_v<Pred> >,
class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
class = boost::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
class = boost::enable_if_t<detail::is_hash_v<Hash> >,
class = boost::enable_if_t<detail::is_pred_v<Pred> >,
class = boost::enable_if_t<detail::is_allocator_v<Allocator> > >
concurrent_flat_set(InputIterator, InputIterator,
std::size_t = boost::unordered::detail::foa::default_bucket_count,
Hash = Hash(), Pred = Pred(), Allocator = Allocator())
@@ -653,17 +632,17 @@ namespace boost {
template <class T, class Hash = boost::hash<T>,
class Pred = std::equal_to<T>, class Allocator = std::allocator<T>,
class = std::enable_if_t<detail::is_hash_v<Hash> >,
class = std::enable_if_t<detail::is_pred_v<Pred> >,
class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
class = boost::enable_if_t<detail::is_hash_v<Hash> >,
class = boost::enable_if_t<detail::is_pred_v<Pred> >,
class = boost::enable_if_t<detail::is_allocator_v<Allocator> > >
concurrent_flat_set(std::initializer_list<T>,
std::size_t = boost::unordered::detail::foa::default_bucket_count,
Hash = Hash(), Pred = Pred(), Allocator = Allocator())
-> concurrent_flat_set< T, Hash, Pred, Allocator>;
template <class InputIterator, class Allocator,
class = std::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
class = boost::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
class = boost::enable_if_t<detail::is_allocator_v<Allocator> > >
concurrent_flat_set(InputIterator, InputIterator, std::size_t, Allocator)
-> concurrent_flat_set<
typename std::iterator_traits<InputIterator>::value_type,
@@ -672,8 +651,8 @@ namespace boost {
Allocator>;
template <class InputIterator, class Allocator,
class = std::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
class = boost::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
class = boost::enable_if_t<detail::is_allocator_v<Allocator> > >
concurrent_flat_set(InputIterator, InputIterator, Allocator)
-> concurrent_flat_set<
typename std::iterator_traits<InputIterator>::value_type,
@@ -682,9 +661,9 @@ namespace boost {
Allocator>;
template <class InputIterator, class Hash, class Allocator,
class = std::enable_if_t<detail::is_hash_v<Hash> >,
class = std::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
class = boost::enable_if_t<detail::is_hash_v<Hash> >,
class = boost::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
class = boost::enable_if_t<detail::is_allocator_v<Allocator> > >
concurrent_flat_set(
InputIterator, InputIterator, std::size_t, Hash, Allocator)
-> concurrent_flat_set<
@@ -693,18 +672,18 @@ namespace boost {
Allocator>;
template <class T, class Allocator,
class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
class = boost::enable_if_t<detail::is_allocator_v<Allocator> > >
concurrent_flat_set(std::initializer_list<T>, std::size_t, Allocator)
-> concurrent_flat_set<T, boost::hash<T>,std::equal_to<T>, Allocator>;
template <class T, class Allocator,
class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
class = boost::enable_if_t<detail::is_allocator_v<Allocator> > >
concurrent_flat_set(std::initializer_list<T >, Allocator)
-> concurrent_flat_set<T, boost::hash<T>, std::equal_to<T>, Allocator>;
template <class T, class Hash, class Allocator,
class = std::enable_if_t<detail::is_hash_v<Hash> >,
class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
class = boost::enable_if_t<detail::is_hash_v<Hash> >,
class = boost::enable_if_t<detail::is_allocator_v<Allocator> > >
concurrent_flat_set(std::initializer_list<T >, std::size_t,Hash, Allocator)
-> concurrent_flat_set<T, Hash, std::equal_to<T>, Allocator>;
@@ -9,12 +9,13 @@
#ifndef BOOST_UNORDERED_DETAIL_ARCHIVE_CONSTRUCTED_HPP
#define BOOST_UNORDERED_DETAIL_ARCHIVE_CONSTRUCTED_HPP
#include <boost/unordered/detail/opt_storage.hpp>
#include <boost/config.hpp>
#include <boost/core/addressof.hpp>
#include <boost/core/no_exceptions_support.hpp>
#include <boost/core/noncopyable.hpp>
#include <boost/core/serialization.hpp>
#include <boost/type_traits/aligned_storage.hpp>
#include <boost/type_traits/alignment_of.hpp>
namespace boost{
namespace unordered{
@@ -28,7 +29,7 @@ struct archive_constructed:private noncopyable
template<class Archive>
archive_constructed(const char* name,Archive& ar,unsigned int version)
{
core::load_construct_data_adl(ar,std::addressof(get()),version);
core::load_construct_data_adl(ar,boost::addressof(get()),version);
BOOST_TRY{
ar>>core::make_nvp(name,get());
}
@@ -53,7 +54,7 @@ struct archive_constructed:private noncopyable
#pragma GCC diagnostic ignored "-Wstrict-aliasing"
#endif
T& get(){return *space.address();}
T& get(){return *reinterpret_cast<T*>(&space);}
#if defined(BOOST_UNORDERED_IGNORE_WSTRICT_ALIASING)
#pragma GCC diagnostic pop
@@ -61,7 +62,7 @@ struct archive_constructed:private noncopyable
#endif
private:
opt_storage<T> space;
typename aligned_storage<sizeof(T),alignment_of<T>::value>::type space;
};
} /* namespace detail */
@@ -10,12 +10,10 @@
#ifndef BOOST_UNORDERED_DETAIL_CONCURRENT_STATIC_ASSERTS_HPP
#define BOOST_UNORDERED_DETAIL_CONCURRENT_STATIC_ASSERTS_HPP
#include <boost/config.hpp>
#include <boost/mp11/algorithm.hpp>
#include <boost/mp11/list.hpp>
#include <functional>
#include <iterator>
#include <type_traits>
#define BOOST_UNORDERED_STATIC_ASSERT_INVOCABLE(F) \
@@ -74,32 +72,4 @@ namespace boost {
} // namespace boost
#if defined(BOOST_NO_CXX20_HDR_CONCEPTS)
#define BOOST_UNORDERED_STATIC_ASSERT_FWD_ITERATOR(Iterator) \
static_assert( \
std::is_base_of< \
std::forward_iterator_tag, \
typename std::iterator_traits<Iterator>::iterator_category>::value, \
"The provided iterator must be at least forward");
#else
#define BOOST_UNORDERED_STATIC_ASSERT_FWD_ITERATOR(Iterator) \
static_assert(std::forward_iterator<Iterator>, \
"The provided iterator must be at least forward");
#endif
#define BOOST_UNORDERED_STATIC_ASSERT_KEY_COMPATIBLE_ITERATOR(Iterator) \
static_assert( \
std::is_same< \
typename std::iterator_traits<Iterator>::value_type, \
key_type>::value || \
detail::are_transparent< \
typename std::iterator_traits<Iterator>::value_type, \
hasher, key_equal>::value, \
"The provided iterator must dereference to a compatible key value");
#define BOOST_UNORDERED_STATIC_ASSERT_BULK_VISIT_ITERATOR(Iterator) \
BOOST_UNORDERED_STATIC_ASSERT_FWD_ITERATOR(Iterator) \
BOOST_UNORDERED_STATIC_ASSERT_KEY_COMPATIBLE_ITERATOR(Iterator)
#endif // BOOST_UNORDERED_DETAIL_CONCURRENT_STATIC_ASSERTS_HPP
+88 -90
View File
@@ -115,9 +115,8 @@ to normal separate chaining implementations.
#include <boost/unordered/detail/prime_fmod.hpp>
#include <boost/unordered/detail/serialize_tracked_address.hpp>
#include <boost/unordered/detail/opt_storage.hpp>
#include <boost/assert.hpp>
#include <boost/core/addressof.hpp>
#include <boost/core/allocator_access.hpp>
#include <boost/core/bit.hpp>
#include <boost/core/empty_value.hpp>
@@ -125,6 +124,10 @@ to normal separate chaining implementations.
#include <boost/core/no_exceptions_support.hpp>
#include <boost/core/serialization.hpp>
#include <boost/cstdint.hpp>
#include <boost/move/core.hpp>
#include <boost/move/utility_core.hpp>
#include <boost/type_traits/aligned_storage.hpp>
#include <boost/type_traits/alignment_of.hpp>
#include <boost/config.hpp>
@@ -141,18 +144,19 @@ namespace boost {
node>::type node_pointer;
node_pointer next;
opt_storage<value_type> buf;
typename boost::aligned_storage<sizeof(value_type),
boost::alignment_of<value_type>::value>::type buf;
node() noexcept : next(), buf() {}
node() BOOST_NOEXCEPT : next(), buf() {}
value_type* value_ptr() noexcept
value_type* value_ptr() BOOST_NOEXCEPT
{
return buf.address();
return reinterpret_cast<value_type*>(buf.address());
}
value_type& value() noexcept
value_type& value() BOOST_NOEXCEPT
{
return *buf.address();
return *reinterpret_cast<value_type*>(buf.address());
}
};
@@ -166,7 +170,7 @@ namespace boost {
node_pointer next;
bucket() noexcept : next() {}
bucket() BOOST_NOEXCEPT : next() {}
};
template <class Bucket> struct bucket_group
@@ -182,7 +186,7 @@ namespace boost {
std::size_t bitmask;
bucket_group_pointer next, prev;
bucket_group() noexcept : buckets(), bitmask(0), next(), prev() {}
bucket_group() BOOST_NOEXCEPT : buckets(), bitmask(0), next(), prev() {}
~bucket_group() {}
};
@@ -220,28 +224,33 @@ namespace boost {
public:
grouped_bucket_iterator() : p(), pbg() {}
reference operator*() const noexcept { return dereference(); }
pointer operator->() const noexcept { return boost::to_address(p); }
reference operator*() const BOOST_NOEXCEPT { return dereference(); }
pointer operator->() const BOOST_NOEXCEPT
{
return boost::to_address(p);
}
grouped_bucket_iterator& operator++() noexcept
grouped_bucket_iterator& operator++() BOOST_NOEXCEPT
{
increment();
return *this;
}
grouped_bucket_iterator operator++(int) noexcept
grouped_bucket_iterator operator++(int) BOOST_NOEXCEPT
{
grouped_bucket_iterator old = *this;
increment();
return old;
}
bool operator==(grouped_bucket_iterator const& other) const noexcept
bool operator==(
grouped_bucket_iterator const& other) const BOOST_NOEXCEPT
{
return equal(other);
}
bool operator!=(grouped_bucket_iterator const& other) const noexcept
bool operator!=(
grouped_bucket_iterator const& other) const BOOST_NOEXCEPT
{
return !equal(other);
}
@@ -257,14 +266,14 @@ namespace boost {
{
}
Bucket& dereference() const noexcept { return *p; }
Bucket& dereference() const BOOST_NOEXCEPT { return *p; }
bool equal(const grouped_bucket_iterator& x) const noexcept
bool equal(const grouped_bucket_iterator& x) const BOOST_NOEXCEPT
{
return p == x.p;
}
void increment() noexcept
void increment() BOOST_NOEXCEPT
{
std::size_t const offset = static_cast<std::size_t>(p - pbg->buckets);
@@ -281,7 +290,7 @@ namespace boost {
}
}
template <typename Archive>
template<typename Archive>
friend void serialization_track(
Archive& ar, grouped_bucket_iterator const& x)
{
@@ -292,7 +301,8 @@ namespace boost {
friend class boost::serialization::access;
template <typename Archive> void serialize(Archive& ar, unsigned int)
template<typename Archive>
void serialize(Archive& ar,unsigned int)
{
// requires: not at end() position
serialize_tracked_address(ar, p);
@@ -316,17 +326,20 @@ namespace boost {
grouped_local_bucket_iterator() : p() {}
reference operator*() const noexcept { return dereference(); }
reference operator*() const BOOST_NOEXCEPT { return dereference(); }
pointer operator->() const noexcept { return boost::to_address(p); }
pointer operator->() const BOOST_NOEXCEPT
{
return boost::to_address(p);
}
grouped_local_bucket_iterator& operator++() noexcept
grouped_local_bucket_iterator& operator++() BOOST_NOEXCEPT
{
increment();
return *this;
}
grouped_local_bucket_iterator operator++(int) noexcept
grouped_local_bucket_iterator operator++(int) BOOST_NOEXCEPT
{
grouped_local_bucket_iterator old = *this;
increment();
@@ -334,13 +347,13 @@ namespace boost {
}
bool operator==(
grouped_local_bucket_iterator const& other) const noexcept
grouped_local_bucket_iterator const& other) const BOOST_NOEXCEPT
{
return equal(other);
}
bool operator!=(
grouped_local_bucket_iterator const& other) const noexcept
grouped_local_bucket_iterator const& other) const BOOST_NOEXCEPT
{
return !equal(other);
}
@@ -353,14 +366,14 @@ namespace boost {
grouped_local_bucket_iterator(node_pointer p_) : p(p_) {}
value_type& dereference() const noexcept { return p->value(); }
value_type& dereference() const BOOST_NOEXCEPT { return p->value(); }
bool equal(const grouped_local_bucket_iterator& x) const noexcept
bool equal(const grouped_local_bucket_iterator& x) const BOOST_NOEXCEPT
{
return p == x.p;
}
void increment() noexcept { p = p->next; }
void increment() BOOST_NOEXCEPT { p = p->next; }
node_pointer p;
};
@@ -384,17 +397,20 @@ namespace boost {
{
}
reference operator*() const noexcept { return dereference(); }
reference operator*() const BOOST_NOEXCEPT { return dereference(); }
pointer operator->() const noexcept { return boost::to_address(p); }
pointer operator->() const BOOST_NOEXCEPT
{
return boost::to_address(p);
}
const_grouped_local_bucket_iterator& operator++() noexcept
const_grouped_local_bucket_iterator& operator++() BOOST_NOEXCEPT
{
increment();
return *this;
}
const_grouped_local_bucket_iterator operator++(int) noexcept
const_grouped_local_bucket_iterator operator++(int) BOOST_NOEXCEPT
{
const_grouped_local_bucket_iterator old = *this;
increment();
@@ -402,13 +418,13 @@ namespace boost {
}
bool operator==(
const_grouped_local_bucket_iterator const& other) const noexcept
const_grouped_local_bucket_iterator const& other) const BOOST_NOEXCEPT
{
return equal(other);
}
bool operator!=(
const_grouped_local_bucket_iterator const& other) const noexcept
const_grouped_local_bucket_iterator const& other) const BOOST_NOEXCEPT
{
return !equal(other);
}
@@ -419,22 +435,23 @@ namespace boost {
const_grouped_local_bucket_iterator(node_pointer p_) : p(p_) {}
value_type& dereference() const noexcept { return p->value(); }
value_type& dereference() const BOOST_NOEXCEPT { return p->value(); }
bool equal(const const_grouped_local_bucket_iterator& x) const noexcept
bool equal(
const const_grouped_local_bucket_iterator& x) const BOOST_NOEXCEPT
{
return p == x.p;
}
void increment() noexcept { p = p->next; }
void increment() BOOST_NOEXCEPT { p = p->next; }
node_pointer p;
};
template <class T> struct span
{
T* begin() const noexcept { return data; }
T* end() const noexcept { return data + size; }
T* begin() const BOOST_NOEXCEPT { return data; }
T* end() const BOOST_NOEXCEPT { return data + size; }
T* data;
std::size_t size;
@@ -449,6 +466,8 @@ namespace boost {
typename boost::allocator_void_pointer<Allocator>::type> >::
type>
{
BOOST_MOVABLE_BUT_NOT_COPYABLE(grouped_bucket_array)
typedef typename boost::allocator_value_type<Allocator>::type
allocator_value_type;
typedef
@@ -513,7 +532,8 @@ namespace boost {
grouped_bucket_array(size_type n, const Allocator& al)
: empty_value<node_allocator_type>(empty_init_t(), al),
size_index_(0), size_(0), buckets(), groups()
size_index_(0),
size_(0), buckets(), groups()
{
if (n == 0) {
return;
@@ -562,10 +582,8 @@ namespace boost {
~grouped_bucket_array() { this->deallocate(); }
grouped_bucket_array(grouped_bucket_array const&) = delete;
grouped_bucket_array& operator=(grouped_bucket_array const&) = delete;
grouped_bucket_array(grouped_bucket_array&& other) noexcept
grouped_bucket_array(
BOOST_RV_REF(grouped_bucket_array) other) BOOST_NOEXCEPT
: empty_value<node_allocator_type>(
empty_init_t(), other.get_node_allocator()),
size_index_(other.size_index_),
@@ -579,12 +597,13 @@ namespace boost {
other.groups = group_pointer();
}
grouped_bucket_array& operator=(grouped_bucket_array&& other) noexcept
grouped_bucket_array& operator=(
BOOST_RV_REF(grouped_bucket_array) other) BOOST_NOEXCEPT
{
BOOST_ASSERT(
this->get_node_allocator() == other.get_node_allocator());
if (this == std::addressof(other)) {
if (this == boost::addressof(other)) {
return *this;
}
@@ -603,48 +622,25 @@ namespace boost {
return *this;
}
#if defined(BOOST_MSVC)
#pragma warning(push)
#pragma warning(disable : 4100) // unreferenced formal parameter (dtor calls)
#endif
void deallocate() noexcept
void deallocate() BOOST_NOEXCEPT
{
if (buckets) {
size_type const num_buckets = buckets_len();
bucket_type* pb = boost::to_address(buckets);
(void)pb; // VS complains when dtor is trivial
for (size_type i = 0; i < num_buckets; ++i) {
(pb + i)->~bucket_type();
}
bucket_allocator_type bucket_alloc = this->get_bucket_allocator();
boost::allocator_deallocate(bucket_alloc, buckets, num_buckets);
boost::allocator_deallocate(
bucket_alloc, buckets, this->buckets_len());
buckets = bucket_pointer();
}
if (groups) {
size_type const num_groups = groups_len();
group* pg = boost::to_address(groups);
(void)pg; // VS complains when dtor is trivial
for (size_type i = 0; i < num_groups; ++i) {
(pg + i)->~group();
}
group_allocator_type group_alloc = this->get_group_allocator();
boost::allocator_deallocate(group_alloc, groups, num_groups);
boost::allocator_deallocate(
group_alloc, groups, this->groups_len());
groups = group_pointer();
}
}
#if defined(BOOST_MSVC)
#pragma warning(pop)
#endif
void swap(grouped_bucket_array& other)
{
std::swap(size_index_, other.size_index_);
@@ -655,8 +651,7 @@ namespace boost {
bool b = boost::allocator_propagate_on_container_swap<
allocator_type>::type::value;
if (b) {
boost::core::invoke_swap(
get_node_allocator(), other.get_node_allocator());
boost::core::invoke_swap(get_node_allocator(), other.get_node_allocator());
}
}
@@ -680,9 +675,12 @@ namespace boost {
return this->get_node_allocator();
}
size_type buckets_len() const noexcept { return size_ + 1; }
size_type buckets_len() const BOOST_NOEXCEPT { return size_ + 1; }
size_type groups_len() const noexcept { return size_ / group::N + 1; }
size_type groups_len() const BOOST_NOEXCEPT
{
return size_ / group::N + 1;
}
void reset_allocator(Allocator const& allocator_)
{
@@ -715,7 +713,7 @@ namespace boost {
local_iterator end(size_type) const { return local_iterator(); }
size_type capacity() const noexcept { return size_; }
size_type capacity() const BOOST_NOEXCEPT { return size_; }
iterator at(size_type n) const
{
@@ -749,7 +747,7 @@ namespace boost {
size_ = 0;
}
void append_bucket_group(iterator itb) noexcept
void append_bucket_group(iterator itb) BOOST_NOEXCEPT
{
std::size_t const N = group::N;
@@ -779,7 +777,7 @@ namespace boost {
}
}
void insert_node(iterator itb, node_pointer p) noexcept
void insert_node(iterator itb, node_pointer p) BOOST_NOEXCEPT
{
this->append_bucket_group(itb);
@@ -788,7 +786,7 @@ namespace boost {
}
void insert_node_hint(
iterator itb, node_pointer p, node_pointer hint) noexcept
iterator itb, node_pointer p, node_pointer hint) BOOST_NOEXCEPT
{
this->append_bucket_group(itb);
@@ -801,24 +799,24 @@ namespace boost {
}
}
void extract_node(iterator itb, node_pointer p) noexcept
void extract_node(iterator itb, node_pointer p) BOOST_NOEXCEPT
{
node_pointer* pp = std::addressof(itb->next);
node_pointer* pp = boost::addressof(itb->next);
while ((*pp) != p)
pp = std::addressof((*pp)->next);
pp = boost::addressof((*pp)->next);
*pp = p->next;
if (!itb->next)
unlink_bucket(itb);
}
void extract_node_after(iterator itb, node_pointer* pp) noexcept
void extract_node_after(iterator itb, node_pointer* pp) BOOST_NOEXCEPT
{
*pp = (*pp)->next;
if (!itb->next)
unlink_bucket(itb);
}
void unlink_empty_buckets() noexcept
void unlink_empty_buckets() BOOST_NOEXCEPT
{
std::size_t const N = group::N;
@@ -866,7 +864,7 @@ namespace boost {
}
};
} // namespace detail
} // namespace unordered
} // namespace unordered
} // namespace boost
#endif // BOOST_UNORDERED_DETAIL_FCA_HPP
@@ -19,6 +19,7 @@
#include <boost/core/serialization.hpp>
#include <boost/cstdint.hpp>
#include <boost/mp11/tuple.hpp>
#include <boost/static_assert.hpp>
#include <boost/throw_exception.hpp>
#include <boost/unordered/detail/archive_constructed.hpp>
#include <boost/unordered/detail/bad_archive_exception.hpp>
@@ -27,7 +28,6 @@
#include <boost/unordered/detail/foa/rw_spinlock.hpp>
#include <boost/unordered/detail/foa/tuple_rotate_right.hpp>
#include <boost/unordered/detail/serialization_version.hpp>
#include <boost/unordered/detail/static_assert.hpp>
#include <cstddef>
#include <functional>
#include <initializer_list>
@@ -89,7 +89,7 @@ private:
static constexpr std::size_t element_offset=
(sizeof(T)+cacheline_size-1)/cacheline_size*cacheline_size;
BOOST_UNORDERED_STATIC_ASSERT(alignof(T)<=cacheline_size);
BOOST_STATIC_ASSERT(alignof(T)<=cacheline_size);
T* data(std::size_t pos)noexcept
{
@@ -127,7 +127,7 @@ template<typename Mutex>
class shared_lock
{
public:
shared_lock(Mutex& m_)noexcept:m(m_){m.lock_shared();}
shared_lock(Mutex& m_)noexcept:m{m_}{m.lock_shared();}
~shared_lock()noexcept{if(owns)m.unlock_shared();}
/* not used but VS in pre-C++17 mode needs to see it for RVO */
@@ -149,7 +149,7 @@ template<typename Mutex>
class lock_guard
{
public:
lock_guard(Mutex& m_)noexcept:m(m_){m.lock();}
lock_guard(Mutex& m_)noexcept:m{m_}{m.lock();}
~lock_guard()noexcept{m.unlock();}
/* not used but VS in pre-C++17 mode needs to see it for RVO */
@@ -342,7 +342,7 @@ struct concurrent_table_arrays:table_arrays<Value,Group,SizePolicy,Allocator>
struct atomic_size_control
{
static constexpr auto atomic_size_t_size=sizeof(std::atomic<std::size_t>);
BOOST_UNORDERED_STATIC_ASSERT(atomic_size_t_size<cacheline_size);
BOOST_STATIC_ASSERT(atomic_size_t_size<cacheline_size);
atomic_size_control(std::size_t ml_,std::size_t size_):
pad0_{},ml{ml_},pad1_{},size{size_}{}
@@ -466,7 +466,6 @@ public:
using key_equal=typename super::key_equal;
using allocator_type=typename super::allocator_type;
using size_type=typename super::size_type;
static constexpr std::size_t bulk_visit_size=16;
private:
template<typename Value,typename T>
@@ -566,26 +565,96 @@ public:
return visit(x,std::forward<F>(f));
}
static constexpr std::size_t bulk_visit_size=16;
#if 0
#define BOOST_UNORDERED_BULK_VISIT_CASE(r,b) \
case r: \
res+=unprotected_bulk_visit<b>( \
group_shared{},first,std::forward<F>(f)); \
break;
template<typename FwdIterator,typename F>
BOOST_FORCEINLINE
std::size_t visit(FwdIterator first,FwdIterator last,F&& f)
std::size_t visit(FwdIterator first,FwdIterator last,F&& f)const
{
return bulk_visit_impl(group_exclusive{},first,last,std::forward<F>(f));
BOOST_STATIC_ASSERT(bulk_visit_size==16);
std::size_t res=0;
auto n=static_cast<std::size_t>(std::distance(first,last));
auto m=n/bulk_visit_size;
auto lck=shared_access();
if(m){
for(std::size_t i=m-1;i--;){
res+=unprotected_bulk_visit<bulk_visit_size>(
group_shared{},first,std::forward<F>(f));
std::advance(first,bulk_visit_size);
}
switch(n-m*bulk_visit_size){
BOOST_UNORDERED_BULK_VISIT_CASE(0,bulk_visit_size)
BOOST_UNORDERED_BULK_VISIT_CASE(1,bulk_visit_size+1)
BOOST_UNORDERED_BULK_VISIT_CASE(2,bulk_visit_size+2)
BOOST_UNORDERED_BULK_VISIT_CASE(3,bulk_visit_size+3)
BOOST_UNORDERED_BULK_VISIT_CASE(4,bulk_visit_size+4)
BOOST_UNORDERED_BULK_VISIT_CASE(5,bulk_visit_size+5)
BOOST_UNORDERED_BULK_VISIT_CASE(6,bulk_visit_size+6)
BOOST_UNORDERED_BULK_VISIT_CASE(7,bulk_visit_size+7)
BOOST_UNORDERED_BULK_VISIT_CASE(8,bulk_visit_size+8)
BOOST_UNORDERED_BULK_VISIT_CASE(9,bulk_visit_size+9)
BOOST_UNORDERED_BULK_VISIT_CASE(10,bulk_visit_size+10)
BOOST_UNORDERED_BULK_VISIT_CASE(11,bulk_visit_size+11)
BOOST_UNORDERED_BULK_VISIT_CASE(12,bulk_visit_size+12)
BOOST_UNORDERED_BULK_VISIT_CASE(13,bulk_visit_size+13)
BOOST_UNORDERED_BULK_VISIT_CASE(14,bulk_visit_size+14)
BOOST_UNORDERED_BULK_VISIT_CASE(15,bulk_visit_size+15)
default:break;
}
}
else{
switch(n){
case 0:break;
BOOST_UNORDERED_BULK_VISIT_CASE(1,1)
BOOST_UNORDERED_BULK_VISIT_CASE(2,2)
BOOST_UNORDERED_BULK_VISIT_CASE(3,3)
BOOST_UNORDERED_BULK_VISIT_CASE(4,4)
BOOST_UNORDERED_BULK_VISIT_CASE(5,5)
BOOST_UNORDERED_BULK_VISIT_CASE(6,6)
BOOST_UNORDERED_BULK_VISIT_CASE(7,7)
BOOST_UNORDERED_BULK_VISIT_CASE(8,8)
BOOST_UNORDERED_BULK_VISIT_CASE(9,9)
BOOST_UNORDERED_BULK_VISIT_CASE(10,10)
BOOST_UNORDERED_BULK_VISIT_CASE(11,11)
BOOST_UNORDERED_BULK_VISIT_CASE(12,12)
BOOST_UNORDERED_BULK_VISIT_CASE(13,13)
BOOST_UNORDERED_BULK_VISIT_CASE(14,14)
BOOST_UNORDERED_BULK_VISIT_CASE(15,15)
default:break;
}
}
return res;
}
#undef BOOST_UNORDERED_BULK_VISIT_CASE
#else
template<typename FwdIterator,typename F>
BOOST_FORCEINLINE
std::size_t visit(FwdIterator first,FwdIterator last,F&& f)const
{
return bulk_visit_impl(group_shared{},first,last,std::forward<F>(f));
}
std::size_t res=0;
auto n=static_cast<std::size_t>(std::distance(first,last));
auto lck=shared_access();
template<typename FwdIterator,typename F>
BOOST_FORCEINLINE
std::size_t cvisit(FwdIterator first,FwdIterator last,F&& f)const
{
return visit(first,last,std::forward<F>(f));
while(n){
auto m=n<2*bulk_visit_size?n:bulk_visit_size;
res+=unprotected_bulk_visit(group_shared{},first,m,std::forward<F>(f));
n-=m;
std::advance(first,m);
}
return res;
}
#endif
template<typename F> std::size_t visit_all(F&& f)
{
@@ -1052,7 +1121,7 @@ private:
erase_on_exit(
concurrent_table& x_,
group_type* pg_,unsigned int pos_,element_type* p_):
x(x_),pg(pg_),pos(pos_),p(p_){}
x{x_},pg{pg_},pos{pos_},p{p_}{}
~erase_on_exit(){if(!rollback_)x.super::erase(pg,pos,p);}
void rollback(){rollback_=true;}
@@ -1074,26 +1143,6 @@ private:
access_mode,x,this->position_for(hash),hash,std::forward<F>(f));
}
template<typename GroupAccessMode,typename FwdIterator,typename F>
BOOST_FORCEINLINE
std::size_t bulk_visit_impl(
GroupAccessMode access_mode,FwdIterator first,FwdIterator last,F&& f)const
{
auto lck=shared_access();
std::size_t res=0;
auto n=static_cast<std::size_t>(std::distance(first,last));
while(n){
auto m=n<2*bulk_visit_size?n:bulk_visit_size;
res+=unprotected_bulk_visit(access_mode,first,m,std::forward<F>(f));
n-=m;
std::advance(
first,
static_cast<
typename std::iterator_traits<FwdIterator>::difference_type>(m));
}
return res;
}
template<typename GroupAccessMode,typename F>
std::size_t visit_all_impl(GroupAccessMode access_mode,F&& f)const
{
@@ -1192,11 +1241,88 @@ private:
return 0;
}
template<typename GroupAccessMode,typename FwdIterator,typename F>
#if 0
template<
std::size_t M,typename GroupAccessMode,
typename FwdIterator,typename F
>
BOOST_FORCEINLINE
std::size_t unprotected_bulk_visit(
GroupAccessMode access_mode,FwdIterator first,F&& f)const
{
std::size_t res=0,
hashes[M],
positions[M];
int masks[M];
auto it=first;
for(std::size_t i=0;i<M;++i,++it){
hashes[i]=this->hash_for(*it);
auto pos=positions[i]=this->position_for(hashes[i]);
BOOST_UNORDERED_PREFETCH(this->arrays.groups()+pos);
}
for(std::size_t i=0;i<M;++i){
auto hash=hashes[i];
auto pos=positions[i];
masks[i]=(this->arrays.groups()+pos)->match(hash);
if(masks[i]){
BOOST_UNORDERED_PREFETCH(this->arrays.group_accesses()+pos);
BOOST_UNORDERED_PREFETCH_ELEMENTS(this->arrays.elements()+pos*N,N);
}
}
it=first;
for(std::size_t i=0;i<M;++i,++it){
auto pos=positions[i];
prober pb(pos);
auto pg=this->arrays.groups()+pos;
auto mask=masks[i];
element_type *p;
if(mask){
p=this->arrays.elements()+pos*N;
goto post_prefetch;
}
else{
goto post_mask;
}
do{
pos=pb.get();
pg=this->arrays.groups()+pos;
mask=pg->match(hashes[i]);
if(BOOST_UNLIKELY(mask!=0)){ /* unlikely bc we're past the 1st probe */
p=this->arrays.elements()+pos*N;
BOOST_UNORDERED_PREFETCH_ELEMENTS(p,N);
post_prefetch:
auto lck=access(access_mode,pos);
do{
auto n=unchecked_countr_zero(mask);
if(BOOST_LIKELY(
pg->is_occupied(n)&&
bool(this->pred()(*it,this->key_from(p[n]))))){
f(cast_for(access_mode,type_policy::value_from(p[n])));
++res;
goto next_key;
}
mask&=mask-1;
}while(mask);
}
post_mask:
if(BOOST_LIKELY(pg->is_not_overflowed(hashes[i]))){
goto next_key;
}
}
while(BOOST_LIKELY(pb.next(this->arrays.groups_size_mask)));
next_key:;
}
return res;
}
#else
template<typename GroupAccessMode,typename FwdIterator,typename F>
BOOST_FORCEINLINE std::size_t unprotected_bulk_visit(
GroupAccessMode access_mode,FwdIterator first,std::size_t m,F&& f)const
{
BOOST_ASSERT(m<2*bulk_visit_size);
BOOST_ASSERT(s<2*bulk_visit_size);
std::size_t res=0,
hashes[2*bulk_visit_size-1],
@@ -1216,8 +1342,7 @@ private:
auto mask=masks[i]=(this->arrays.groups()+pos)->match(hash);
if(mask){
BOOST_UNORDERED_PREFETCH(this->arrays.group_accesses()+pos);
//BOOST_UNORDERED_PREFETCH_ELEMENTS(this->arrays.elements()+pos*N,N);
BOOST_UNORDERED_PREFETCH(this->arrays.elements()+pos*N+unchecked_countr_zero(mask));
BOOST_UNORDERED_PREFETCH_ELEMENTS(this->arrays.elements()+pos*N,N);
}
}
@@ -1246,15 +1371,14 @@ private:
}while(mask);
}
post_mask:
do{
if(BOOST_LIKELY(pg->is_not_overflowed(hashes[i]))||
BOOST_UNLIKELY(!pb.next(this->arrays.groups_size_mask))){
goto next_key;
}
pos=pb.get();
pg=this->arrays.groups()+pos;
mask=pg->match(hashes[i]);
}while(!mask);
if(BOOST_LIKELY(pg->is_not_overflowed(hashes[i]))||
BOOST_UNLIKELY(!pb.next(this->arrays.groups_size_mask))){
goto next_key;
}
pos=pb.get();
pg=this->arrays.groups()+pos;
mask=pg->match(hashes[i]);
if(BOOST_LIKELY(mask==0))goto next_key;
p=this->arrays.elements()+pos*N;
BOOST_UNORDERED_PREFETCH_ELEMENTS(p,N);
}
@@ -1262,6 +1386,7 @@ private:
}
return res;
}
#endif
#if defined(BOOST_MSVC)
#pragma warning(pop) /* C4800 */
@@ -1397,7 +1522,7 @@ private:
struct reserve_size
{
reserve_size(concurrent_table& x_):x(x_)
reserve_size(concurrent_table& x_):x{x_}
{
size_=++x.size_ctrl.size;
}
+38 -13
View File
@@ -22,10 +22,13 @@
#include <boost/core/pointer_traits.hpp>
#include <boost/cstdint.hpp>
#include <boost/predef.h>
#include <boost/static_assert.hpp>
#include <boost/type_traits/has_trivial_constructor.hpp>
#include <boost/type_traits/has_trivial_copy.hpp>
#include <boost/type_traits/has_trivial_assign.hpp>
#include <boost/type_traits/is_nothrow_swappable.hpp>
#include <boost/unordered/detail/narrow_cast.hpp>
#include <boost/unordered/detail/mulx.hpp>
#include <boost/unordered/detail/static_assert.hpp>
#include <boost/unordered/detail/type_traits.hpp>
#include <boost/unordered/hash_traits.hpp>
#include <climits>
#include <cmath>
@@ -92,7 +95,7 @@
#elif defined(BOOST_UNORDERED_SSE2)
#define BOOST_UNORDERED_PREFETCH(p) _mm_prefetch((const char*)(p),_MM_HINT_T0)
#else
#define BOOST_UNORDERED_PREFETCH(p) ((void)(p))
#define BOOST_UNORDERED_PREFETCH(p) ((void)0)
#endif
/* We have experimentally confirmed that ARM architectures get a higher
@@ -130,10 +133,10 @@
#define BOOST_UNORDERED_THREAD_SANITIZER
#endif
#define BOOST_UNORDERED_STATIC_ASSERT_HASH_PRED(Hash, Pred) \
static_assert(boost::unordered::detail::is_nothrow_swappable<Hash>::value, \
"Template parameter Hash is required to be nothrow Swappable."); \
static_assert(boost::unordered::detail::is_nothrow_swappable<Pred>::value, \
#define BOOST_UNORDERED_STATIC_ASSERT_HASH_PRED(Hash, Pred) \
static_assert(boost::is_nothrow_swappable<Hash>::value, \
"Template parameter Hash is required to be nothrow Swappable."); \
static_assert(boost::is_nothrow_swappable<Pred>::value, \
"Template parameter Pred is required to be nothrow Swappable");
namespace boost{
@@ -308,7 +311,7 @@ struct group15
private:
using slot_type=IntegralWrapper<unsigned char>;
BOOST_UNORDERED_STATIC_ASSERT(sizeof(slot_type)==1);
BOOST_STATIC_ASSERT(sizeof(slot_type)==1);
static constexpr unsigned char available_=0,
sentinel_=1;
@@ -511,7 +514,7 @@ struct group15
private:
using slot_type=IntegralWrapper<unsigned char>;
BOOST_UNORDERED_STATIC_ASSERT(sizeof(slot_type)==1);
BOOST_STATIC_ASSERT(sizeof(slot_type)==1);
static constexpr unsigned char available_=0,
sentinel_=1;
@@ -704,7 +707,7 @@ struct group15
private:
using word_type=IntegralWrapper<uint64_t>;
BOOST_UNORDERED_STATIC_ASSERT(sizeof(word_type)==8);
BOOST_STATIC_ASSERT(sizeof(word_type)==8);
static constexpr unsigned char available_=0,
sentinel_=1;
@@ -1042,7 +1045,15 @@ struct table_arrays
initialize_groups(
arrays.groups(),groups_size,
is_trivially_default_constructible<group_type>{});
std::integral_constant<
bool,
#if BOOST_WORKAROUND(BOOST_LIBSTDCXX_VERSION,<50000)
/* std::is_trivially_constructible not provided */
boost::has_trivial_constructor<group_type>::value
#else
std::is_trivially_constructible<group_type>::value
#endif
>{});
arrays.groups()[groups_size-1].set_sentinel();
}
@@ -2015,7 +2026,13 @@ private:
x,
std::integral_constant<
bool,
is_trivially_copy_constructible<element_type>::value&&(
#if BOOST_WORKAROUND(BOOST_LIBSTDCXX_VERSION,<50000)
/* std::is_trivially_copy_constructible not provided */
boost::has_trivial_copy<element_type>::value
#else
std::is_trivially_copy_constructible<element_type>::value
#endif
&&(
is_std_allocator<Allocator>::value||
!alloc_has_construct<Allocator,value_type*,const value_type&>::value)
>{}
@@ -2057,7 +2074,15 @@ private:
}
void copy_groups_array_from(const table_core& x) {
copy_groups_array_from(x,is_trivially_copy_assignable<group_type>{});
copy_groups_array_from(x, std::integral_constant<bool,
#if BOOST_WORKAROUND(BOOST_LIBSTDCXX_VERSION,<50000)
/* std::is_trivially_copy_assignable not provided */
boost::has_trivial_assign<group_type>::value
#else
std::is_trivially_copy_assignable<group_type>::value
#endif
>{}
);
}
void copy_groups_array_from(
@@ -9,8 +9,6 @@
#ifndef BOOST_UNORDERED_DETAIL_FOA_NODE_HANDLE_HPP
#define BOOST_UNORDERED_DETAIL_FOA_NODE_HANDLE_HPP
#include <boost/unordered/detail/opt_storage.hpp>
#include <boost/config.hpp>
#include <boost/core/allocator_access.hpp>
@@ -27,6 +25,14 @@ struct insert_return_type
NodeType node;
};
template <class T>
union opt_storage {
BOOST_ATTRIBUTE_NO_UNIQUE_ADDRESS T t_;
opt_storage(){}
~opt_storage(){}
};
template <class TypePolicy,class Allocator>
struct node_handle_base
{
+4 -4
View File
@@ -106,7 +106,7 @@ public:
using element_type=
typename std::conditional<Const,value_type const,value_type>::type;
table_iterator():pc_{nullptr},p_{nullptr}{};
table_iterator()=default;
template<bool Const2,typename std::enable_if<!Const2>::type* =nullptr>
table_iterator(const table_iterator<TypePolicy,GroupPtr,Const2>& x):
pc_{x.pc_},p_{x.p_}{}
@@ -133,10 +133,10 @@ private:
template<typename> friend class table_erase_return_type;
template<typename,typename,typename,typename> friend class table;
table_iterator(group_type* pg,std::size_t n,const table_element_type* ptet):
table_iterator(group_type* pg,std::size_t n,const table_element_type* p):
pc_{to_pointer<char_pointer>(
reinterpret_cast<unsigned char*>(const_cast<group_type*>(pg))+n)},
p_{to_pointer<table_element_pointer>(const_cast<table_element_type*>(ptet))}
p_{to_pointer<table_element_pointer>(const_cast<table_element_type*>(p))}
{}
unsigned char* pc()const noexcept{return boost::to_address(pc_);}
@@ -568,7 +568,7 @@ private:
struct erase_on_exit
{
erase_on_exit(table& x_,const_iterator it_):x(x_),it(it_){}
erase_on_exit(table& x_,const_iterator it_):x{x_},it{it_}{}
~erase_on_exit(){if(!rollback_)x.erase(it);}
void rollback(){rollback_=true;}
+150
View File
@@ -0,0 +1,150 @@
// Copyright (C) 2008-2016 Daniel James.
// Copyright (C) 2022 Christian Mazakas
// 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)
#ifndef BOOST_UNORDERED_FWD_HPP_INCLUDED
#define BOOST_UNORDERED_FWD_HPP_INCLUDED
#include <boost/config.hpp>
#if defined(BOOST_HAS_PRAGMA_ONCE)
#pragma once
#endif
#include <boost/predef.h>
#if defined(BOOST_UNORDERED_HAVE_PIECEWISE_CONSTRUCT)
// Already defined.
#elif defined(BOOST_LIBSTDCXX11)
// https://github.com/gcc-mirror/gcc/blob/gcc-4_6-branch/libstdc++-v3/include/bits/stl_pair.h#L70
#if BOOST_LIBSTDCXX_VERSION > 40600
#define BOOST_UNORDERED_HAVE_PIECEWISE_CONSTRUCT 1
#endif
#elif BOOST_LIB_STD_CXX
// https://github.com/llvm-mirror/libcxx/blob/release_30/include/utility#L206
#if BOOST_LIB_STD_CXX >= BOOST_VERSION_NUMBER(3, 0, 0)
#define BOOST_UNORDERED_HAVE_PIECEWISE_CONSTRUCT 1
#endif
#elif defined(BOOST_LIB_STD_DINKUMWARE)
// Apparently C++11 standard supported in Visual Studio 2012
// https://msdn.microsoft.com/en-us/library/hh567368.aspx#stl
// 2012 = VC+11 = BOOST_MSVC 1700 Hopefully!
// I have no idea when Dinkumware added it, probably a lot
// earlier than this check.
#if BOOST_LIB_STD_DINKUMWARE >= BOOST_VERSION_NUMBER(6, 10, 0) || \
BOOST_COMP_MSVC >= BOOST_VERSION_NUMBER(17, 0, 0)
#define BOOST_UNORDERED_HAVE_PIECEWISE_CONSTRUCT 1
#endif
#endif
// Assume that an unknown library does not support piecewise construction.
#if !defined(BOOST_UNORDERED_HAVE_PIECEWISE_CONSTRUCT)
#define BOOST_UNORDERED_HAVE_PIECEWISE_CONSTRUCT 0
#endif
#if BOOST_UNORDERED_HAVE_PIECEWISE_CONSTRUCT
#include <utility>
#endif
namespace boost {
namespace unordered {
#if BOOST_UNORDERED_HAVE_PIECEWISE_CONSTRUCT
using std::piecewise_construct_t;
using std::piecewise_construct;
#else
struct piecewise_construct_t
{
};
const piecewise_construct_t piecewise_construct = piecewise_construct_t();
#endif
}
}
// BOOST_UNORDERED_EMPLACE_LIMIT = The maximum number of parameters in
// emplace (not including things like hints). Don't set it to a lower value, as
// that might break something.
#if !defined BOOST_UNORDERED_EMPLACE_LIMIT
#define BOOST_UNORDERED_EMPLACE_LIMIT 10
#endif
////////////////////////////////////////////////////////////////////////////////
// Configuration
//
// Unless documented elsewhere these configuration macros should be considered
// an implementation detail, I'll try not to break them, but you never know.
// Use Sun C++ workarounds
// I'm not sure which versions of the compiler require these workarounds, so
// I'm just using them of everything older than the current test compilers
// (as of May 2017).
#if !defined(BOOST_UNORDERED_SUN_WORKAROUNDS1)
#if BOOST_COMP_SUNPRO && BOOST_COMP_SUNPRO < BOOST_VERSION_NUMBER(5, 20, 0)
#define BOOST_UNORDERED_SUN_WORKAROUNDS1 1
#else
#define BOOST_UNORDERED_SUN_WORKAROUNDS1 0
#endif
#endif
// BOOST_UNORDERED_TUPLE_ARGS
//
// Maximum number of std::tuple members to support, or 0 if std::tuple
// isn't avaiable. More are supported when full C++11 is used.
// Already defined, so do nothing
#if defined(BOOST_UNORDERED_TUPLE_ARGS)
// Assume if we have C++11 tuple it's properly variadic,
// and just use a max number of 10 arguments.
#elif !defined(BOOST_NO_CXX11_HDR_TUPLE)
#define BOOST_UNORDERED_TUPLE_ARGS 10
// Visual C++ has a decent enough tuple for piecewise construction,
// so use that if available, using _VARIADIC_MAX for the maximum
// number of parameters. Note that this comes after the check
// for a full C++11 tuple.
#elif defined(BOOST_MSVC)
#if !BOOST_UNORDERED_HAVE_PIECEWISE_CONSTRUCT
#define BOOST_UNORDERED_TUPLE_ARGS 0
#elif defined(_VARIADIC_MAX)
#define BOOST_UNORDERED_TUPLE_ARGS _VARIADIC_MAX
#else
#define BOOST_UNORDERED_TUPLE_ARGS 5
#endif
// Assume that we don't have std::tuple
#else
#define BOOST_UNORDERED_TUPLE_ARGS 0
#endif
#if BOOST_UNORDERED_TUPLE_ARGS
#include <tuple>
#endif
// BOOST_UNORDERED_CXX11_CONSTRUCTION
//
// Use C++11 construction, requires variadic arguments, good construct support
// in allocator_traits and piecewise construction of std::pair
// Otherwise allocators aren't used for construction/destruction
#if BOOST_UNORDERED_HAVE_PIECEWISE_CONSTRUCT && \
!defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && BOOST_UNORDERED_TUPLE_ARGS
#if BOOST_COMP_SUNPRO && BOOST_LIB_STD_GNU
// Sun C++ std::pair piecewise construction doesn't seem to be exception safe.
// (At least for Sun C++ 12.5 using libstdc++).
#define BOOST_UNORDERED_CXX11_CONSTRUCTION 0
#elif BOOST_COMP_GNUC && BOOST_COMP_GNUC < BOOST_VERSION_NUMBER(4, 7, 0)
// Piecewise construction in GCC 4.6 doesn't work for uncopyable types.
#define BOOST_UNORDERED_CXX11_CONSTRUCTION 0
#elif !defined(BOOST_NO_CXX11_ALLOCATOR)
#define BOOST_UNORDERED_CXX11_CONSTRUCTION 1
#endif
#endif
#if !defined(BOOST_UNORDERED_CXX11_CONSTRUCTION)
#define BOOST_UNORDERED_CXX11_CONSTRUCTION 0
#endif
#endif
File diff suppressed because it is too large Load Diff
@@ -9,21 +9,21 @@
#ifndef BOOST_UNORDERED_DETAIL_NARROW_CAST_HPP
#define BOOST_UNORDERED_DETAIL_NARROW_CAST_HPP
#include <boost/unordered/detail/static_assert.hpp>
#include <boost/config.hpp>
#include <type_traits>
#include <boost/static_assert.hpp>
#include <boost/type_traits/is_integral.hpp>
#include <boost/type_traits/make_unsigned.hpp>
namespace boost{
namespace unordered{
namespace detail{
template<typename To,typename From>
constexpr To narrow_cast(From x) noexcept
BOOST_CONSTEXPR To narrow_cast(From x) BOOST_NOEXCEPT
{
BOOST_UNORDERED_STATIC_ASSERT(std::is_integral<From>::value);
BOOST_UNORDERED_STATIC_ASSERT(std::is_integral<To>::value);
BOOST_UNORDERED_STATIC_ASSERT(sizeof(From)>=sizeof(To));
BOOST_STATIC_ASSERT(boost::is_integral<From>::value);
BOOST_STATIC_ASSERT(boost::is_integral<To>::value);
BOOST_STATIC_ASSERT(sizeof(From)>=sizeof(To));
return static_cast<To>(
x
@@ -32,7 +32,7 @@ constexpr To narrow_cast(From x) noexcept
/* Avoids VS's "Run-Time Check Failure #1 - A cast to a smaller data type
* has caused a loss of data."
*/
&static_cast<typename std::make_unsigned<To>::type>(~static_cast<To>(0))
&static_cast<typename boost::make_unsigned<To>::type>(~static_cast<To>(0))
#endif
);
}
@@ -1,30 +0,0 @@
// Copyright (C) 2023 Christian Mazakas
//
// 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)
#ifndef BOOST_UNORDERED_DETAIL_OPT_STORAGE_HPP
#define BOOST_UNORDERED_DETAIL_OPT_STORAGE_HPP
#include <boost/config.hpp>
#include <memory>
namespace boost {
namespace unordered {
namespace detail {
template <class T> union opt_storage
{
BOOST_ATTRIBUTE_NO_UNIQUE_ADDRESS T t_;
opt_storage() {}
~opt_storage() {}
T* address() noexcept { return std::addressof(t_); }
T const* address() const noexcept { return std::addressof(t_); }
};
} // namespace detail
} // namespace unordered
} // namespace boost
#endif // BOOST_UNORDERED_DETAIL_OPT_STORAGE_HPP
+145 -96
View File
@@ -1,5 +1,5 @@
// Copyright (C) 2022 Joaquin M Lopez Munoz.
// Copyright (C) 2022-2023 Christian Mazakas
// Copyright (C) 2022 Christian Mazakas
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -7,10 +7,13 @@
#ifndef BOOST_UNORDERED_DETAIL_PRIME_FMOD_HPP
#define BOOST_UNORDERED_DETAIL_PRIME_FMOD_HPP
#include <boost/cstdint.hpp>
#include <boost/preprocessor/seq/enum.hpp>
#include <boost/preprocessor/seq/for_each.hpp>
#include <boost/preprocessor/seq/size.hpp>
#include <boost/unordered/detail/narrow_cast.hpp>
#include <boost/config.hpp>
#include <boost/cstdint.hpp>
#include <climits>
#include <cstddef>
@@ -34,90 +37,21 @@ namespace boost {
namespace detail {
template <class = void> struct prime_fmod_size
{
constexpr static std::size_t const sizes[] = {13ul, 29ul, 53ul, 97ul,
193ul, 389ul, 769ul, 1543ul, 3079ul, 6151ul, 12289ul, 24593ul,
49157ul, 98317ul, 196613ul, 393241ul, 786433ul, 1572869ul, 3145739ul,
6291469ul, 12582917ul, 25165843ul, 50331653ul, 100663319ul,
201326611ul, 402653189ul, 805306457ul, 1610612741ul, 3221225473ul,
#if !defined(BOOST_UNORDERED_FCA_HAS_64B_SIZE_T)
4294967291ul
#else
6442450939ull, 12884901893ull, 25769803751ull, 51539607551ull,
103079215111ull, 206158430209ull, 412316860441ull, 824633720831ull,
1649267441651ull
#endif
};
constexpr static std::size_t const sizes_len =
sizeof(sizes) / sizeof(sizes[0]);
// Because we compile for C++03, we don't have access to any inline
// initialization for array data members so the definitions must exist
// out-of-line. To keep the library header-only, we introduce a dummy
// template parameter which permits the definition to be included in
// multiple TUs without conflict.
//
static std::size_t sizes[];
static std::size_t const sizes_len;
static std::size_t (*positions[])(std::size_t);
#if defined(BOOST_UNORDERED_FCA_HAS_64B_SIZE_T)
constexpr static boost::uint64_t const inv_sizes32[] = {
1418980313362273202ull, 636094623231363849ull, 348051774975651918ull,
190172619316593316ull, 95578984837873325ull, 47420935922132524ull,
23987963684927896ull, 11955116055547344ull, 5991147799191151ull,
2998982941588287ull, 1501077717772769ull, 750081082979285ull,
375261795343686ull, 187625172388393ull, 93822606204624ull,
46909513691883ull, 23456218233098ull, 11728086747027ull,
5864041509391ull, 2932024948977ull, 1466014921160ull, 733007198436ull,
366503839517ull, 183251896093ull, 91625960335ull, 45812983922ull,
22906489714ull, 11453246088ull, 5726623060ull};
constexpr static std::size_t const inv_sizes32_len =
sizeof(inv_sizes32) / sizeof(inv_sizes32[0]);
static boost::uint64_t inv_sizes32[];
static std::size_t const inv_sizes32_len;
#endif /* defined(BOOST_UNORDERED_FCA_HAS_64B_SIZE_T) */
template <std::size_t SizeIndex, std::size_t Size = sizes[SizeIndex]>
static std::size_t position(std::size_t hash)
{
return hash % Size;
}
constexpr static std::size_t (*positions[])(std::size_t) = {
#if !defined(BOOST_UNORDERED_FCA_HAS_64B_SIZE_T)
position<0, sizes[0]>,
position<1, sizes[1]>,
position<2, sizes[2]>,
position<3, sizes[3]>,
position<4, sizes[4]>,
position<5, sizes[5]>,
position<6, sizes[6]>,
position<7, sizes[7]>,
position<8, sizes[8]>,
position<9, sizes[9]>,
position<10, sizes[10]>,
position<11, sizes[11]>,
position<12, sizes[12]>,
position<13, sizes[13]>,
position<14, sizes[14]>,
position<15, sizes[15]>,
position<16, sizes[16]>,
position<17, sizes[17]>,
position<18, sizes[18]>,
position<19, sizes[19]>,
position<20, sizes[20]>,
position<21, sizes[21]>,
position<22, sizes[22]>,
position<23, sizes[23]>,
position<24, sizes[24]>,
position<25, sizes[25]>,
position<26, sizes[26]>,
position<27, sizes[27]>,
position<28, sizes[28]>,
position<29, sizes[29]>,
#else
position<29, sizes[29]>,
position<30, sizes[30]>,
position<31, sizes[31]>,
position<32, sizes[32]>,
position<33, sizes[33]>,
position<34, sizes[34]>,
position<35, sizes[35]>,
position<36, sizes[36]>,
position<37, sizes[37]>,
#endif
};
static inline std::size_t size_index(std::size_t n)
{
std::size_t i = 0;
@@ -134,6 +68,11 @@ namespace boost {
return sizes[size_index];
}
template <std::size_t Size> static std::size_t modulo(std::size_t hash)
{
return hash % Size;
}
#if defined(BOOST_UNORDERED_FCA_HAS_64B_SIZE_T)
// We emulate the techniques taken from:
// Faster Remainder by Direct Computation: Applications to Compilers and
@@ -179,8 +118,8 @@ namespace boost {
#if defined(BOOST_UNORDERED_FCA_HAS_64B_SIZE_T)
std::size_t sizes_under_32bit = inv_sizes32_len;
if (BOOST_LIKELY(size_index < sizes_under_32bit)) {
return fast_modulo(narrow_cast<boost::uint32_t>(hash) +
narrow_cast<boost::uint32_t>(hash >> 32),
return fast_modulo(
narrow_cast<boost::uint32_t>(hash) + narrow_cast<boost::uint32_t>(hash >> 32),
inv_sizes32[size_index], boost::uint32_t(sizes[size_index]));
} else {
return positions[size_index - sizes_under_32bit](hash);
@@ -191,24 +130,134 @@ namespace boost {
}
}; // prime_fmod_size
#if defined(BOOST_NO_CXX17_INLINE_VARIABLES)
// https://en.cppreference.com/w/cpp/language/static#Constant_static_members
// If a const non-inline (since C++17) static data member or a constexpr
// static data member (since C++11)(until C++17) is odr-used, a definition
// at namespace scope is still required, but it cannot have an
// initializer.
template <class T> constexpr std::size_t prime_fmod_size<T>::sizes[];
#define BOOST_UNORDERED_PRIME_FMOD_SIZES_32BIT_INCOMPLETE \
(13ul)(29ul)(53ul)(97ul)(193ul)(389ul)(769ul)(1543ul)(3079ul)(6151ul)( \
12289ul)(24593ul)(49157ul)(98317ul)(196613ul)(393241ul)(786433ul)( \
1572869ul)(3145739ul)(6291469ul)(12582917ul)(25165843ul)(50331653ul)( \
100663319ul)(201326611ul)(402653189ul)(805306457ul)(1610612741ul)( \
3221225473ul)
#if !defined(BOOST_UNORDERED_FCA_HAS_64B_SIZE_T)
#define BOOST_UNORDERED_PRIME_FMOD_SIZES_32BIT \
BOOST_UNORDERED_PRIME_FMOD_SIZES_32BIT_INCOMPLETE(4294967291ul)
#define BOOST_UNORDERED_PRIME_FMOD_SIZES_64BIT
#else
#define BOOST_UNORDERED_PRIME_FMOD_SIZES_32BIT \
BOOST_UNORDERED_PRIME_FMOD_SIZES_32BIT_INCOMPLETE
// The original sequence here is this:
// (6442450939ul)
// (12884901893ul)
// (25769803751ul)
// (51539607551ul)
// (103079215111ul)
// (206158430209ul)
// (412316860441ul)
// (824633720831ul)
// (1649267441651ul)
//
// but this causes problems on versions of mingw where the `long` type is 32
// bits, even for 64-bit targets. We work around this by replacing the literals
// with compile-time arithmetic, using bitshifts to reconstruct the number.
//
// clang-format off
#define BOOST_UNORDERED_PRIME_FMOD_SIZES_64BIT \
((boost::ulong_long_type(1ul) << 32) + boost::ulong_long_type(2147483643ul)) \
((boost::ulong_long_type(3ul) << 32) + boost::ulong_long_type(5ul)) \
((boost::ulong_long_type(5ul) << 32) + boost::ulong_long_type(4294967271ul)) \
((boost::ulong_long_type(11ul) << 32) + boost::ulong_long_type(4294967295ul)) \
((boost::ulong_long_type(24ul) << 32) + boost::ulong_long_type(7ul)) \
((boost::ulong_long_type(48ul) << 32) + boost::ulong_long_type(1ul)) \
((boost::ulong_long_type(96ul) << 32) + boost::ulong_long_type(25ul)) \
((boost::ulong_long_type(191ul) << 32) + boost::ulong_long_type(4294967295ul)) \
((boost::ulong_long_type(383ul) << 32) + boost::ulong_long_type(4294967283ul))
// clang-format on
#endif /* BOOST_UNORDERED_FCA_HAS_64B_SIZE_T */
#define BOOST_UNORDERED_PRIME_FMOD_SIZES \
BOOST_UNORDERED_PRIME_FMOD_SIZES_32BIT BOOST_UNORDERED_PRIME_FMOD_SIZES_64BIT
template <class T>
std::size_t prime_fmod_size<T>::sizes[] = {
BOOST_PP_SEQ_ENUM(BOOST_UNORDERED_PRIME_FMOD_SIZES)};
template <class T>
std::size_t const prime_fmod_size<T>::sizes_len = BOOST_PP_SEQ_SIZE(
BOOST_UNORDERED_PRIME_FMOD_SIZES);
// Similarly here, we have to re-express the integer initialization using
// arithmetic such that each literal can fit in a 32-bit value.
//
#if defined(BOOST_UNORDERED_FCA_HAS_64B_SIZE_T)
template <class T>
constexpr boost::uint64_t prime_fmod_size<T>::inv_sizes32[];
#endif
// clang-format off
template <class T>
boost::uint64_t prime_fmod_size<T>::inv_sizes32[] = {
(boost::ulong_long_type(330382099ul) << 32) + boost::ulong_long_type(2973438898ul) /* = 1418980313362273202 */,
(boost::ulong_long_type(148102320ul) << 32) + boost::ulong_long_type(2369637129ul) /* = 636094623231363849 */,
(boost::ulong_long_type(81037118ul) << 32) + boost::ulong_long_type(3403558990ul) /* = 348051774975651918 */,
(boost::ulong_long_type(44278013ul) << 32) + boost::ulong_long_type(1549730468ul) /* = 190172619316593316 */,
(boost::ulong_long_type(22253716ul) << 32) + boost::ulong_long_type(2403401389ul) /* = 95578984837873325 */,
(boost::ulong_long_type(11041047ul) << 32) + boost::ulong_long_type(143533612ul) /* = 47420935922132524 */,
(boost::ulong_long_type(5585133ul) << 32) + boost::ulong_long_type(106117528ul) /* = 23987963684927896 */,
(boost::ulong_long_type(2783517ul) << 32) + boost::ulong_long_type(1572687312ul) /* = 11955116055547344 */,
(boost::ulong_long_type(1394922ul) << 32) + boost::ulong_long_type(3428720239ul) /* = 5991147799191151 */,
(boost::ulong_long_type(698255ul) << 32) + boost::ulong_long_type(552319807ul) /* = 2998982941588287 */,
(boost::ulong_long_type(349496ul) << 32) + boost::ulong_long_type(3827689953ul) /* = 1501077717772769 */,
(boost::ulong_long_type(174641ul) << 32) + boost::ulong_long_type(3699438549ul) /* = 750081082979285 */,
(boost::ulong_long_type(87372ul) << 32) + boost::ulong_long_type(1912757574ul) /* = 375261795343686 */,
(boost::ulong_long_type(43684ul) << 32) + boost::ulong_long_type(3821029929ul) /* = 187625172388393 */,
(boost::ulong_long_type(21844ul) << 32) + boost::ulong_long_type(3340590800ul) /* = 93822606204624 */,
(boost::ulong_long_type(10921ul) << 32) + boost::ulong_long_type(4175852267ul) /* = 46909513691883 */,
(boost::ulong_long_type(5461ul) << 32) + boost::ulong_long_type(1401829642ul) /* = 23456218233098 */,
(boost::ulong_long_type(2730ul) << 32) + boost::ulong_long_type(2826028947ul) /* = 11728086747027 */,
(boost::ulong_long_type(1365ul) << 32) + boost::ulong_long_type(1411150351ul) /* = 5864041509391 */,
(boost::ulong_long_type(682ul) << 32) + boost::ulong_long_type(2857253105ul) /* = 2932024948977 */,
(boost::ulong_long_type(341ul) << 32) + boost::ulong_long_type(1431073224ul) /* = 1466014921160 */,
(boost::ulong_long_type(170ul) << 32) + boost::ulong_long_type(2862758116ul) /* = 733007198436 */,
(boost::ulong_long_type(85ul) << 32) + boost::ulong_long_type(1431619357ul) /* = 366503839517 */,
(boost::ulong_long_type(42ul) << 32) + boost::ulong_long_type(2863269661ul) /* = 183251896093 */,
(boost::ulong_long_type(21ul) << 32) + boost::ulong_long_type(1431647119ul) /* = 91625960335 */,
(boost::ulong_long_type(10ul) << 32) + boost::ulong_long_type(2863310962ul) /* = 45812983922 */,
(boost::ulong_long_type(5ul) << 32) + boost::ulong_long_type(1431653234ul) /* = 22906489714 */,
(boost::ulong_long_type(2ul) << 32) + boost::ulong_long_type(2863311496ul) /* = 11453246088 */,
(boost::ulong_long_type(1ul) << 32) + boost::ulong_long_type(1431655764ul) /* = 5726623060 */,
};
// clang-format on
template <class T>
constexpr std::size_t (*prime_fmod_size<T>::positions[])(std::size_t);
std::size_t const
prime_fmod_size<T>::inv_sizes32_len = sizeof(inv_sizes32) /
sizeof(inv_sizes32[0]);
#endif /* defined(BOOST_UNORDERED_FCA_HAS_64B_SIZE_T) */
#define BOOST_UNORDERED_PRIME_FMOD_POSITIONS_ELEMENT(z, _, n) \
prime_fmod_size<T>::template modulo<n>,
template <class T>
std::size_t (*prime_fmod_size<T>::positions[])(std::size_t) = {
#if !defined(BOOST_UNORDERED_FCA_HAS_64B_SIZE_T)
BOOST_PP_SEQ_FOR_EACH(BOOST_UNORDERED_PRIME_FMOD_POSITIONS_ELEMENT, ~,
BOOST_UNORDERED_PRIME_FMOD_SIZES_32BIT)
#else
BOOST_PP_SEQ_FOR_EACH(BOOST_UNORDERED_PRIME_FMOD_POSITIONS_ELEMENT, ~,
BOOST_UNORDERED_PRIME_FMOD_SIZES_64BIT)
#endif
};
#undef BOOST_UNORDERED_PRIME_FMOD_POSITIONS_ELEMENT
#undef BOOST_UNORDERED_PRIME_FMOD_SIZES
#undef BOOST_UNORDERED_PRIME_FMOD_SIZES_64BIT
#undef BOOST_UNORDERED_PRIME_FMOD_SIZES_32BIT
#undef BOOST_UNORDERED_PRIME_FMOD_SIZES_32BIT_INCOMPLETE
} // namespace detail
} // namespace unordered
} // namespace unordered
} // namespace boost
#endif // BOOST_UNORDERED_DETAIL_PRIME_FMOD_HPP
@@ -0,0 +1,21 @@
#ifndef BOOST_UNORDERED_DETAIL_REQUIRES_CXX11_HPP_INCLUDED
#define BOOST_UNORDERED_DETAIL_REQUIRES_CXX11_HPP_INCLUDED
// Copyright 2023 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/config.hpp>
#include <boost/config/pragma_message.hpp>
#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || \
defined(BOOST_NO_CXX11_RVALUE_REFERENCES) || \
defined(BOOST_NO_CXX11_DECLTYPE) || \
defined(BOOST_NO_CXX11_CONSTEXPR) || \
defined(BOOST_NO_CXX11_NOEXCEPT)
BOOST_PRAGMA_MESSAGE("C++03 support is deprecated in Boost.Unordered 1.82 and will be removed in Boost.Unordered 1.84.")
#endif
#endif // #ifndef BOOST_UNORDERED_DETAIL_REQUIRES_CXX11_HPP_INCLUDED
@@ -9,8 +9,12 @@
#ifndef BOOST_UNORDERED_DETAIL_SERIALIZE_CONTAINER_HPP
#define BOOST_UNORDERED_DETAIL_SERIALIZE_CONTAINER_HPP
#include <boost/core/addressof.hpp>
#include <boost/core/serialization.hpp>
#include <boost/move/move.hpp>
#include <boost/throw_exception.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/type_traits/remove_const.hpp>
#include <boost/unordered/detail/archive_constructed.hpp>
#include <boost/unordered/detail/bad_archive_exception.hpp>
#include <boost/unordered/detail/serialization_version.hpp>
@@ -62,7 +66,7 @@ template<typename Set> struct load_or_save_unordered_set<Set,true> /* save */
ar<<core::make_nvp("value_version",value_version);
for(const_iterator first=x.begin(),last=x.end();first!=last;++first){
core::save_construct_data_adl(ar,std::addressof(*first),value_version);
core::save_construct_data_adl(ar,boost::addressof(*first),value_version);
ar<<core::make_nvp("item",*first);
serialization_track(ar,first);
}
@@ -90,10 +94,10 @@ template<typename Set> struct load_or_save_unordered_set<Set,false> /* load */
archive_constructed<value_type> value("item",ar,value_version);
std::pair<iterator,bool> p=adapt_insert_return_type(
x.insert(std::move(value.get())));
x.insert(boost::move(value.get())));
if(!p.second)throw_exception(bad_archive_exception());
ar.reset_object_address(
std::addressof(*p.first),std::addressof(value.get()));
boost::addressof(*p.first),boost::addressof(value.get()));
serialization_track(ar,p.first);
}
}
@@ -106,9 +110,9 @@ template<typename Map> struct load_or_save_unordered_map<Map,true> /* save */
template<typename Archive>
void operator()(Archive& ar,const Map& x,unsigned int)const
{
typedef typename std::remove_const<
typedef typename boost::remove_const<
typename Map::key_type>::type key_type;
typedef typename std::remove_const<
typedef typename boost::remove_const<
typename Map::mapped_type>::type mapped_type;
typedef typename Map::const_iterator const_iterator;
@@ -128,10 +132,10 @@ template<typename Map> struct load_or_save_unordered_map<Map,true> /* save */
*/
core::save_construct_data_adl(
ar,std::addressof(first->first),key_version);
ar,boost::addressof(first->first),key_version);
ar<<core::make_nvp("key",first->first);
core::save_construct_data_adl(
ar,std::addressof(first->second),mapped_version);
ar,boost::addressof(first->second),mapped_version);
ar<<core::make_nvp("mapped",first->second);
serialization_track(ar,first);
}
@@ -143,9 +147,9 @@ template<typename Map> struct load_or_save_unordered_map<Map,false> /* load */
template<typename Archive>
void operator()(Archive& ar,Map& x,unsigned int)const
{
typedef typename std::remove_const<
typedef typename boost::remove_const<
typename Map::key_type>::type key_type;
typedef typename std::remove_const<
typedef typename boost::remove_const<
typename Map::mapped_type>::type mapped_type;
typedef typename Map::iterator iterator;
@@ -165,12 +169,12 @@ template<typename Map> struct load_or_save_unordered_map<Map,false> /* load */
archive_constructed<mapped_type> mapped("mapped",ar,mapped_version);
std::pair<iterator,bool> p=adapt_insert_return_type(
x.emplace(std::move(key.get()),std::move(mapped.get())));
x.emplace(boost::move(key.get()),boost::move(mapped.get())));
if(!p.second)throw_exception(bad_archive_exception());
ar.reset_object_address(
std::addressof(p.first->first),std::addressof(key.get()));
boost::addressof(p.first->first),boost::addressof(key.get()));
ar.reset_object_address(
std::addressof(p.first->second),std::addressof(mapped.get()));
boost::addressof(p.first->second),boost::addressof(mapped.get()));
serialization_track(ar,p.first);
}
}
@@ -192,7 +196,7 @@ void serialize_container(Archive& ar,Container& x,unsigned int version)
{
load_or_save_container<
Container,
std::is_same<
boost::is_same<
typename Container::key_type,typename Container::value_type>::value,
Archive::is_saving::value>()(ar,x,version);
}
@@ -9,13 +9,12 @@
#ifndef BOOST_UNORDERED_DETAIL_SERIALIZE_TRACKED_ADDRESS_HPP
#define BOOST_UNORDERED_DETAIL_SERIALIZE_TRACKED_ADDRESS_HPP
#include <boost/unordered/detail/bad_archive_exception.hpp>
#include <boost/core/pointer_traits.hpp>
#include <boost/core/serialization.hpp>
#include <boost/throw_exception.hpp>
#include <type_traits>
#include <boost/type_traits/remove_const.hpp>
#include <boost/type_traits/integral_constant.hpp>
#include <boost/unordered/detail/bad_archive_exception.hpp>
namespace boost{
namespace unordered{
@@ -45,7 +44,7 @@ template<typename Archive,typename Ptr>
void track_address(Archive& ar,Ptr p)
{
typedef typename boost::pointer_traits<Ptr> ptr_traits;
typedef typename std::remove_const<
typedef typename boost::remove_const<
typename ptr_traits::element_type>::type element_type;
if(p){
@@ -58,10 +57,10 @@ void track_address(Archive& ar,Ptr p)
}
template<typename Archive,typename Ptr>
void serialize_tracked_address(Archive& ar,Ptr& p,std::true_type /* save */)
void serialize_tracked_address(Archive& ar,Ptr& p,boost::true_type /* save */)
{
typedef typename boost::pointer_traits<Ptr> ptr_traits;
typedef typename std::remove_const<
typedef typename boost::remove_const<
typename ptr_traits::element_type>::type element_type;
typedef serialization_tracker<element_type> tracker;
@@ -74,10 +73,10 @@ void serialize_tracked_address(Archive& ar,Ptr& p,std::true_type /* save */)
}
template<typename Archive,typename Ptr>
void serialize_tracked_address(Archive& ar,Ptr& p,std::false_type /* load */)
void serialize_tracked_address(Archive& ar,Ptr& p,boost::false_type /* load */)
{
typedef typename boost::pointer_traits<Ptr> ptr_traits;
typedef typename std::remove_const<
typedef typename boost::remove_const<
typename ptr_traits::element_type>::type element_type;
typedef serialization_tracker<element_type> tracker;
@@ -94,7 +93,7 @@ void serialize_tracked_address(Archive& ar,Ptr& p)
{
serialize_tracked_address(
ar,p,
std::integral_constant<bool,Archive::is_saving::value>());
boost::integral_constant<bool,Archive::is_saving::value>());
}
} /* namespace detail */
@@ -1,16 +0,0 @@
// Copyright 2023 Christian Mazakas
// 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)
#ifndef BOOST_UNORDERED_DETAIL_STATIC_ASSERT_HPP
#define BOOST_UNORDERED_DETAIL_STATIC_ASSERT_HPP
#include <boost/config.hpp>
#if defined(BOOST_HAS_PRAGMA_ONCE)
#pragma once
#endif
#define BOOST_UNORDERED_STATIC_ASSERT(...) \
static_assert(__VA_ARGS__, #__VA_ARGS__)
#endif // BOOST_UNORDERED_DETAIL_STATIC_ASSERT_HPP
+19 -91
View File
@@ -1,4 +1,4 @@
// Copyright (C) 2022-2023 Christian Mazakas
// Copyright (C) 2022 Christian Mazakas
//
// 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)
@@ -11,14 +11,19 @@
#pragma once
#endif
#include <boost/config/workaround.hpp>
#include <boost/type_traits/integral_constant.hpp>
#include <boost/type_traits/is_convertible.hpp>
#include <boost/type_traits/make_void.hpp>
#include <boost/type_traits/type_identity.hpp>
#if !defined(BOOST_NO_CXX17_DEDUCTION_GUIDES)
#include <iterator>
#endif
#include <boost/type_traits/enable_if.hpp>
#include <boost/type_traits/is_integral.hpp>
#include <boost/type_traits/remove_const.hpp>
#include <type_traits>
#include <iterator>
#include <utility>
#endif
// BOOST_UNORDERED_TEMPLATE_DEDUCTION_GUIDES
@@ -35,96 +40,19 @@
namespace boost {
namespace unordered {
namespace detail {
template <class T> struct type_identity
{
using type = T;
};
template <typename... Ts> struct make_void
{
typedef void type;
};
template <typename... Ts> using void_t = typename make_void<Ts...>::type;
#if BOOST_WORKAROUND(BOOST_LIBSTDCXX_VERSION, < 50000)
/* std::is_trivially_default_constructible not provided */
template <class T>
struct is_trivially_default_constructible
: public std::integral_constant<bool,
std::is_default_constructible<T>::value &&
std::has_trivial_default_constructor<T>::value>
{
};
#else
using std::is_trivially_default_constructible;
#endif
#if BOOST_WORKAROUND(BOOST_LIBSTDCXX_VERSION, < 50000)
/* std::is_trivially_copy_constructible not provided */
template <class T>
struct is_trivially_copy_constructible
: public std::integral_constant<bool,
std::is_copy_constructible<T>::value &&
std::has_trivial_copy_constructor<T>::value>
{
};
#else
using std::is_trivially_copy_constructible;
#endif
#if BOOST_WORKAROUND(BOOST_LIBSTDCXX_VERSION, < 50000)
/* std::is_trivially_copy_assignable not provided */
template <class T>
struct is_trivially_copy_assignable
: public std::integral_constant<bool,
std::is_copy_assignable<T>::value &&
std::has_trivial_copy_assign<T>::value>
{
};
#else
using std::is_trivially_copy_assignable;
#endif
namespace type_traits_detail {
using std::swap;
template <class T, class = void> struct is_nothrow_swappable_helper
{
constexpr static bool const value = false;
};
template <class T>
struct is_nothrow_swappable_helper<T,
void_t<decltype(swap(std::declval<T&>(), std::declval<T&>()))> >
{
constexpr static bool const value =
noexcept(swap(std::declval<T&>(), std::declval<T&>()));
};
} // namespace type_traits_detail
template <class T>
struct is_nothrow_swappable
: public std::integral_constant<bool,
type_traits_detail::is_nothrow_swappable_helper<T>::value>
{
};
////////////////////////////////////////////////////////////////////////////
// Type checkers used for the transparent member functions added by C++20
// and up
template <class, class = void>
struct is_transparent : public std::false_type
struct is_transparent : public boost::false_type
{
};
template <class T>
struct is_transparent<T,
boost::unordered::detail::void_t<typename T::is_transparent> >
: public std::true_type
typename boost::make_void<typename T::is_transparent>::type>
: public boost::true_type
{
};
@@ -143,8 +71,8 @@ namespace boost {
static bool const value =
are_transparent<Key, hash, key_equal>::value &&
!std::is_convertible<Key, iterator>::value &&
!std::is_convertible<Key, const_iterator>::value;
!boost::is_convertible<Key, iterator>::value &&
!boost::is_convertible<Key, const_iterator>::value;
};
#if BOOST_UNORDERED_TEMPLATE_DEDUCTION_GUIDES
@@ -153,7 +81,7 @@ namespace boost {
template <class InputIterator>
constexpr bool const is_input_iterator_v =
!std::is_integral<InputIterator>::value;
!boost::is_integral<InputIterator>::value;
template <class A, class = void> struct is_allocator
{
@@ -162,7 +90,7 @@ namespace boost {
template <class A>
struct is_allocator<A,
boost::unordered::detail::void_t<typename A::value_type,
boost::void_t<typename A::value_type,
decltype(std::declval<A&>().allocate(std::size_t{}))> >
{
constexpr static bool const value = true;
@@ -173,7 +101,7 @@ namespace boost {
template <class H>
constexpr bool const is_hash_v =
!std::is_integral<H>::value && !is_allocator_v<H>;
!boost::is_integral<H>::value && !is_allocator_v<H>;
template <class P> constexpr bool const is_pred_v = !is_allocator_v<P>;
@@ -188,7 +116,7 @@ namespace boost {
typename std::pair<iter_key_t<T> const, iter_val_t<T> >;
#endif
} // namespace detail
} // namespace unordered
} // namespace unordered
} // namespace boost
#endif // BOOST_UNORDERED_DETAIL_TYPE_TRAITS_HPP
+5 -4
View File
@@ -11,7 +11,8 @@
#ifndef BOOST_UNORDERED_HASH_TRAITS_HPP
#define BOOST_UNORDERED_HASH_TRAITS_HPP
#include <boost/unordered/detail/type_traits.hpp>
#include <boost/type_traits/make_void.hpp>
#include <boost/type_traits/integral_constant.hpp>
namespace boost{
namespace unordered{
@@ -19,12 +20,12 @@ namespace unordered{
namespace detail{
template<typename Hash,typename=void>
struct hash_is_avalanching_impl: std::false_type{};
struct hash_is_avalanching_impl: boost::false_type{};
template<typename Hash>
struct hash_is_avalanching_impl<Hash,
boost::unordered::detail::void_t<typename Hash::is_avalanching> >:
std::true_type{};
typename boost::make_void<typename Hash::is_avalanching>::type>:
boost::true_type{};
} /* namespace detail */
+33 -33
View File
@@ -18,7 +18,7 @@
#include <boost/unordered/unordered_flat_map_fwd.hpp>
#include <boost/core/allocator_access.hpp>
#include <boost/container_hash/hash.hpp>
#include <boost/functional/hash.hpp>
#include <boost/throw_exception.hpp>
#include <initializer_list>
@@ -65,9 +65,9 @@ namespace boost {
using init_type = typename map_types::init_type;
using size_type = std::size_t;
using difference_type = std::ptrdiff_t;
using hasher = typename boost::unordered::detail::type_identity<Hash>::type;
using key_equal = typename boost::unordered::detail::type_identity<KeyEqual>::type;
using allocator_type = typename boost::unordered::detail::type_identity<Allocator>::type;
using hasher = typename boost::type_identity<Hash>::type;
using key_equal = typename boost::type_identity<KeyEqual>::type;
using allocator_type = typename boost::type_identity<Allocator>::type;
using reference = value_type&;
using const_reference = value_type const&;
using pointer = typename boost::allocator_pointer<allocator_type>::type;
@@ -717,10 +717,10 @@ namespace boost {
std::equal_to<boost::unordered::detail::iter_key_t<InputIterator> >,
class Allocator = std::allocator<
boost::unordered::detail::iter_to_alloc_t<InputIterator> >,
class = std::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
class = std::enable_if_t<detail::is_hash_v<Hash> >,
class = std::enable_if_t<detail::is_pred_v<Pred> >,
class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
class = boost::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
class = boost::enable_if_t<detail::is_hash_v<Hash> >,
class = boost::enable_if_t<detail::is_pred_v<Pred> >,
class = boost::enable_if_t<detail::is_allocator_v<Allocator> > >
unordered_flat_map(InputIterator, InputIterator,
std::size_t = boost::unordered::detail::foa::default_bucket_count,
Hash = Hash(), Pred = Pred(), Allocator = Allocator())
@@ -729,21 +729,21 @@ namespace boost {
Allocator>;
template <class Key, class T,
class Hash = boost::hash<std::remove_const_t<Key> >,
class Pred = std::equal_to<std::remove_const_t<Key> >,
class Hash = boost::hash<boost::remove_const_t<Key> >,
class Pred = std::equal_to<boost::remove_const_t<Key> >,
class Allocator = std::allocator<std::pair<const Key, T> >,
class = std::enable_if_t<detail::is_hash_v<Hash> >,
class = std::enable_if_t<detail::is_pred_v<Pred> >,
class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
class = boost::enable_if_t<detail::is_hash_v<Hash> >,
class = boost::enable_if_t<detail::is_pred_v<Pred> >,
class = boost::enable_if_t<detail::is_allocator_v<Allocator> > >
unordered_flat_map(std::initializer_list<std::pair<Key, T> >,
std::size_t = boost::unordered::detail::foa::default_bucket_count,
Hash = Hash(), Pred = Pred(), Allocator = Allocator())
-> unordered_flat_map<std::remove_const_t<Key>, T, Hash, Pred,
-> unordered_flat_map<boost::remove_const_t<Key>, T, Hash, Pred,
Allocator>;
template <class InputIterator, class Allocator,
class = std::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
class = boost::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
class = boost::enable_if_t<detail::is_allocator_v<Allocator> > >
unordered_flat_map(InputIterator, InputIterator, std::size_t, Allocator)
-> unordered_flat_map<boost::unordered::detail::iter_key_t<InputIterator>,
boost::unordered::detail::iter_val_t<InputIterator>,
@@ -752,8 +752,8 @@ namespace boost {
Allocator>;
template <class InputIterator, class Allocator,
class = std::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
class = boost::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
class = boost::enable_if_t<detail::is_allocator_v<Allocator> > >
unordered_flat_map(InputIterator, InputIterator, Allocator)
-> unordered_flat_map<boost::unordered::detail::iter_key_t<InputIterator>,
boost::unordered::detail::iter_val_t<InputIterator>,
@@ -762,9 +762,9 @@ namespace boost {
Allocator>;
template <class InputIterator, class Hash, class Allocator,
class = std::enable_if_t<detail::is_hash_v<Hash> >,
class = std::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
class = boost::enable_if_t<detail::is_hash_v<Hash> >,
class = boost::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
class = boost::enable_if_t<detail::is_allocator_v<Allocator> > >
unordered_flat_map(
InputIterator, InputIterator, std::size_t, Hash, Allocator)
-> unordered_flat_map<boost::unordered::detail::iter_key_t<InputIterator>,
@@ -773,25 +773,25 @@ namespace boost {
Allocator>;
template <class Key, class T, class Allocator,
class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
class = boost::enable_if_t<detail::is_allocator_v<Allocator> > >
unordered_flat_map(std::initializer_list<std::pair<Key, T> >, std::size_t,
Allocator) -> unordered_flat_map<std::remove_const_t<Key>, T,
boost::hash<std::remove_const_t<Key> >,
std::equal_to<std::remove_const_t<Key> >, Allocator>;
Allocator) -> unordered_flat_map<boost::remove_const_t<Key>, T,
boost::hash<boost::remove_const_t<Key> >,
std::equal_to<boost::remove_const_t<Key> >, Allocator>;
template <class Key, class T, class Allocator,
class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
class = boost::enable_if_t<detail::is_allocator_v<Allocator> > >
unordered_flat_map(std::initializer_list<std::pair<Key, T> >, Allocator)
-> unordered_flat_map<std::remove_const_t<Key>, T,
boost::hash<std::remove_const_t<Key> >,
std::equal_to<std::remove_const_t<Key> >, Allocator>;
-> unordered_flat_map<boost::remove_const_t<Key>, T,
boost::hash<boost::remove_const_t<Key> >,
std::equal_to<boost::remove_const_t<Key> >, Allocator>;
template <class Key, class T, class Hash, class Allocator,
class = std::enable_if_t<detail::is_hash_v<Hash> >,
class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
class = boost::enable_if_t<detail::is_hash_v<Hash> >,
class = boost::enable_if_t<detail::is_allocator_v<Allocator> > >
unordered_flat_map(std::initializer_list<std::pair<Key, T> >, std::size_t,
Hash, Allocator) -> unordered_flat_map<std::remove_const_t<Key>, T,
Hash, std::equal_to<std::remove_const_t<Key> >, Allocator>;
Hash, Allocator) -> unordered_flat_map<boost::remove_const_t<Key>, T,
Hash, std::equal_to<boost::remove_const_t<Key> >, Allocator>;
#endif
} // namespace unordered
@@ -11,7 +11,7 @@
#pragma once
#endif
#include <boost/container_hash/hash_fwd.hpp>
#include <boost/functional/hash_fwd.hpp>
#include <functional>
#include <memory>
+19 -19
View File
@@ -18,7 +18,7 @@
#include <boost/unordered/unordered_flat_set_fwd.hpp>
#include <boost/core/allocator_access.hpp>
#include <boost/container_hash/hash.hpp>
#include <boost/functional/hash.hpp>
#include <initializer_list>
#include <iterator>
@@ -535,10 +535,10 @@ namespace boost {
std::equal_to<typename std::iterator_traits<InputIterator>::value_type>,
class Allocator = std::allocator<
typename std::iterator_traits<InputIterator>::value_type>,
class = std::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
class = std::enable_if_t<detail::is_hash_v<Hash> >,
class = std::enable_if_t<detail::is_pred_v<Pred> >,
class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
class = boost::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
class = boost::enable_if_t<detail::is_hash_v<Hash> >,
class = boost::enable_if_t<detail::is_pred_v<Pred> >,
class = boost::enable_if_t<detail::is_allocator_v<Allocator> > >
unordered_flat_set(InputIterator, InputIterator,
std::size_t = boost::unordered::detail::foa::default_bucket_count,
Hash = Hash(), Pred = Pred(), Allocator = Allocator())
@@ -548,17 +548,17 @@ namespace boost {
template <class T, class Hash = boost::hash<T>,
class Pred = std::equal_to<T>, class Allocator = std::allocator<T>,
class = std::enable_if_t<detail::is_hash_v<Hash> >,
class = std::enable_if_t<detail::is_pred_v<Pred> >,
class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
class = boost::enable_if_t<detail::is_hash_v<Hash> >,
class = boost::enable_if_t<detail::is_pred_v<Pred> >,
class = boost::enable_if_t<detail::is_allocator_v<Allocator> > >
unordered_flat_set(std::initializer_list<T>,
std::size_t = boost::unordered::detail::foa::default_bucket_count,
Hash = Hash(), Pred = Pred(), Allocator = Allocator())
-> unordered_flat_set<T, Hash, Pred, Allocator>;
template <class InputIterator, class Allocator,
class = std::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
class = boost::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
class = boost::enable_if_t<detail::is_allocator_v<Allocator> > >
unordered_flat_set(InputIterator, InputIterator, std::size_t, Allocator)
-> unordered_flat_set<
typename std::iterator_traits<InputIterator>::value_type,
@@ -567,9 +567,9 @@ namespace boost {
Allocator>;
template <class InputIterator, class Hash, class Allocator,
class = std::enable_if_t<detail::is_hash_v<Hash> >,
class = std::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
class = boost::enable_if_t<detail::is_hash_v<Hash> >,
class = boost::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
class = boost::enable_if_t<detail::is_allocator_v<Allocator> > >
unordered_flat_set(
InputIterator, InputIterator, std::size_t, Hash, Allocator)
-> unordered_flat_set<
@@ -578,19 +578,19 @@ namespace boost {
Allocator>;
template <class T, class Allocator,
class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
class = boost::enable_if_t<detail::is_allocator_v<Allocator> > >
unordered_flat_set(std::initializer_list<T>, std::size_t, Allocator)
-> unordered_flat_set<T, boost::hash<T>, std::equal_to<T>, Allocator>;
template <class T, class Hash, class Allocator,
class = std::enable_if_t<detail::is_hash_v<Hash> >,
class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
class = boost::enable_if_t<detail::is_hash_v<Hash> >,
class = boost::enable_if_t<detail::is_allocator_v<Allocator> > >
unordered_flat_set(std::initializer_list<T>, std::size_t, Hash, Allocator)
-> unordered_flat_set<T, Hash, std::equal_to<T>, Allocator>;
template <class InputIterator, class Allocator,
class = std::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
class = boost::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
class = boost::enable_if_t<detail::is_allocator_v<Allocator> > >
unordered_flat_set(InputIterator, InputIterator, Allocator)
-> unordered_flat_set<
typename std::iterator_traits<InputIterator>::value_type,
@@ -599,7 +599,7 @@ namespace boost {
Allocator>;
template <class T, class Allocator,
class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
class = boost::enable_if_t<detail::is_allocator_v<Allocator> > >
unordered_flat_set(std::initializer_list<T>, Allocator)
-> unordered_flat_set<T, boost::hash<T>, std::equal_to<T>, Allocator>;
#endif
@@ -11,7 +11,7 @@
#pragma once
#endif
#include <boost/container_hash/hash_fwd.hpp>
#include <boost/functional/hash_fwd.hpp>
#include <functional>
#include <memory>
File diff suppressed because it is too large Load Diff
+10 -8
View File
@@ -1,6 +1,6 @@
// Copyright (C) 2008-2011 Daniel James.
// Copyright (C) 2022-2023 Christian Mazakas
// Copyright (C) 2022 Christian Mazakas
// 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)
@@ -12,7 +12,7 @@
#pragma once
#endif
#include <boost/container_hash/hash_fwd.hpp>
#include <boost/functional/hash_fwd.hpp>
#include <functional>
#include <memory>
@@ -30,8 +30,9 @@ namespace boost {
inline bool operator!=(
unordered_map<K, T, H, P, A> const&, unordered_map<K, T, H, P, A> const&);
template <class K, class T, class H, class P, class A>
inline void swap(unordered_map<K, T, H, P, A>& m1,
unordered_map<K, T, H, P, A>& m2) noexcept(noexcept(m1.swap(m2)));
inline void swap(
unordered_map<K, T, H, P, A>& m1, unordered_map<K, T, H, P, A>& m2)
BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR(m1.swap(m2)));
template <class K, class T, class H, class P, class A, class Predicate>
typename unordered_map<K, T, H, P, A>::size_type erase_if(
@@ -50,7 +51,8 @@ namespace boost {
unordered_multimap<K, T, H, P, A> const&);
template <class K, class T, class H, class P, class A>
inline void swap(unordered_multimap<K, T, H, P, A>& m1,
unordered_multimap<K, T, H, P, A>& m2) noexcept(noexcept(m1.swap(m2)));
unordered_multimap<K, T, H, P, A>& m2)
BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR(m1.swap(m2)));
template <class K, class T, class H, class P, class A, class Predicate>
typename unordered_multimap<K, T, H, P, A>::size_type erase_if(
@@ -58,13 +60,13 @@ namespace boost {
template <class N, class K, class T, class A> class node_handle_map;
template <class Iter, class NodeType> struct insert_return_type_map;
} // namespace unordered
}
using boost::unordered::swap;
using boost::unordered::unordered_map;
using boost::unordered::unordered_multimap;
using boost::unordered::swap;
using boost::unordered::operator==;
using boost::unordered::operator!=;
} // namespace boost
}
#endif
+33 -33
View File
@@ -19,7 +19,7 @@
#include <boost/unordered/unordered_node_map_fwd.hpp>
#include <boost/core/allocator_access.hpp>
#include <boost/container_hash/hash.hpp>
#include <boost/functional/hash.hpp>
#include <boost/throw_exception.hpp>
#include <initializer_list>
@@ -99,9 +99,9 @@ namespace boost {
using init_type = typename map_types::init_type;
using size_type = std::size_t;
using difference_type = std::ptrdiff_t;
using hasher = typename boost::unordered::detail::type_identity<Hash>::type;
using key_equal = typename boost::unordered::detail::type_identity<KeyEqual>::type;
using allocator_type = typename boost::unordered::detail::type_identity<Allocator>::type;
using hasher = typename boost::type_identity<Hash>::type;
using key_equal = typename boost::type_identity<KeyEqual>::type;
using allocator_type = typename boost::type_identity<Allocator>::type;
using reference = value_type&;
using const_reference = value_type const&;
using pointer = typename boost::allocator_pointer<allocator_type>::type;
@@ -810,10 +810,10 @@ namespace boost {
std::equal_to<boost::unordered::detail::iter_key_t<InputIterator> >,
class Allocator = std::allocator<
boost::unordered::detail::iter_to_alloc_t<InputIterator> >,
class = std::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
class = std::enable_if_t<detail::is_hash_v<Hash> >,
class = std::enable_if_t<detail::is_pred_v<Pred> >,
class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
class = boost::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
class = boost::enable_if_t<detail::is_hash_v<Hash> >,
class = boost::enable_if_t<detail::is_pred_v<Pred> >,
class = boost::enable_if_t<detail::is_allocator_v<Allocator> > >
unordered_node_map(InputIterator, InputIterator,
std::size_t = boost::unordered::detail::foa::default_bucket_count,
Hash = Hash(), Pred = Pred(), Allocator = Allocator())
@@ -822,21 +822,21 @@ namespace boost {
Allocator>;
template <class Key, class T,
class Hash = boost::hash<std::remove_const_t<Key> >,
class Pred = std::equal_to<std::remove_const_t<Key> >,
class Hash = boost::hash<boost::remove_const_t<Key> >,
class Pred = std::equal_to<boost::remove_const_t<Key> >,
class Allocator = std::allocator<std::pair<const Key, T> >,
class = std::enable_if_t<detail::is_hash_v<Hash> >,
class = std::enable_if_t<detail::is_pred_v<Pred> >,
class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
class = boost::enable_if_t<detail::is_hash_v<Hash> >,
class = boost::enable_if_t<detail::is_pred_v<Pred> >,
class = boost::enable_if_t<detail::is_allocator_v<Allocator> > >
unordered_node_map(std::initializer_list<std::pair<Key, T> >,
std::size_t = boost::unordered::detail::foa::default_bucket_count,
Hash = Hash(), Pred = Pred(), Allocator = Allocator())
-> unordered_node_map<std::remove_const_t<Key>, T, Hash, Pred,
-> unordered_node_map<boost::remove_const_t<Key>, T, Hash, Pred,
Allocator>;
template <class InputIterator, class Allocator,
class = std::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
class = boost::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
class = boost::enable_if_t<detail::is_allocator_v<Allocator> > >
unordered_node_map(InputIterator, InputIterator, std::size_t, Allocator)
-> unordered_node_map<boost::unordered::detail::iter_key_t<InputIterator>,
boost::unordered::detail::iter_val_t<InputIterator>,
@@ -845,8 +845,8 @@ namespace boost {
Allocator>;
template <class InputIterator, class Allocator,
class = std::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
class = boost::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
class = boost::enable_if_t<detail::is_allocator_v<Allocator> > >
unordered_node_map(InputIterator, InputIterator, Allocator)
-> unordered_node_map<boost::unordered::detail::iter_key_t<InputIterator>,
boost::unordered::detail::iter_val_t<InputIterator>,
@@ -855,9 +855,9 @@ namespace boost {
Allocator>;
template <class InputIterator, class Hash, class Allocator,
class = std::enable_if_t<detail::is_hash_v<Hash> >,
class = std::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
class = boost::enable_if_t<detail::is_hash_v<Hash> >,
class = boost::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
class = boost::enable_if_t<detail::is_allocator_v<Allocator> > >
unordered_node_map(
InputIterator, InputIterator, std::size_t, Hash, Allocator)
-> unordered_node_map<boost::unordered::detail::iter_key_t<InputIterator>,
@@ -866,25 +866,25 @@ namespace boost {
Allocator>;
template <class Key, class T, class Allocator,
class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
class = boost::enable_if_t<detail::is_allocator_v<Allocator> > >
unordered_node_map(std::initializer_list<std::pair<Key, T> >, std::size_t,
Allocator) -> unordered_node_map<std::remove_const_t<Key>, T,
boost::hash<std::remove_const_t<Key> >,
std::equal_to<std::remove_const_t<Key> >, Allocator>;
Allocator) -> unordered_node_map<boost::remove_const_t<Key>, T,
boost::hash<boost::remove_const_t<Key> >,
std::equal_to<boost::remove_const_t<Key> >, Allocator>;
template <class Key, class T, class Allocator,
class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
class = boost::enable_if_t<detail::is_allocator_v<Allocator> > >
unordered_node_map(std::initializer_list<std::pair<Key, T> >, Allocator)
-> unordered_node_map<std::remove_const_t<Key>, T,
boost::hash<std::remove_const_t<Key> >,
std::equal_to<std::remove_const_t<Key> >, Allocator>;
-> unordered_node_map<boost::remove_const_t<Key>, T,
boost::hash<boost::remove_const_t<Key> >,
std::equal_to<boost::remove_const_t<Key> >, Allocator>;
template <class Key, class T, class Hash, class Allocator,
class = std::enable_if_t<detail::is_hash_v<Hash> >,
class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
class = boost::enable_if_t<detail::is_hash_v<Hash> >,
class = boost::enable_if_t<detail::is_allocator_v<Allocator> > >
unordered_node_map(std::initializer_list<std::pair<Key, T> >, std::size_t,
Hash, Allocator) -> unordered_node_map<std::remove_const_t<Key>, T,
Hash, std::equal_to<std::remove_const_t<Key> >, Allocator>;
Hash, Allocator) -> unordered_node_map<boost::remove_const_t<Key>, T,
Hash, std::equal_to<boost::remove_const_t<Key> >, Allocator>;
#endif
} // namespace unordered
@@ -11,7 +11,7 @@
#pragma once
#endif
#include <boost/container_hash/hash_fwd.hpp>
#include <boost/functional/hash_fwd.hpp>
#include <functional>
#include <memory>
+19 -19
View File
@@ -19,7 +19,7 @@
#include <boost/unordered/unordered_node_set_fwd.hpp>
#include <boost/core/allocator_access.hpp>
#include <boost/container_hash/hash.hpp>
#include <boost/functional/hash.hpp>
#include <boost/throw_exception.hpp>
#include <initializer_list>
@@ -622,10 +622,10 @@ namespace boost {
std::equal_to<typename std::iterator_traits<InputIterator>::value_type>,
class Allocator = std::allocator<
typename std::iterator_traits<InputIterator>::value_type>,
class = std::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
class = std::enable_if_t<detail::is_hash_v<Hash> >,
class = std::enable_if_t<detail::is_pred_v<Pred> >,
class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
class = boost::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
class = boost::enable_if_t<detail::is_hash_v<Hash> >,
class = boost::enable_if_t<detail::is_pred_v<Pred> >,
class = boost::enable_if_t<detail::is_allocator_v<Allocator> > >
unordered_node_set(InputIterator, InputIterator,
std::size_t = boost::unordered::detail::foa::default_bucket_count,
Hash = Hash(), Pred = Pred(), Allocator = Allocator())
@@ -635,17 +635,17 @@ namespace boost {
template <class T, class Hash = boost::hash<T>,
class Pred = std::equal_to<T>, class Allocator = std::allocator<T>,
class = std::enable_if_t<detail::is_hash_v<Hash> >,
class = std::enable_if_t<detail::is_pred_v<Pred> >,
class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
class = boost::enable_if_t<detail::is_hash_v<Hash> >,
class = boost::enable_if_t<detail::is_pred_v<Pred> >,
class = boost::enable_if_t<detail::is_allocator_v<Allocator> > >
unordered_node_set(std::initializer_list<T>,
std::size_t = boost::unordered::detail::foa::default_bucket_count,
Hash = Hash(), Pred = Pred(), Allocator = Allocator())
-> unordered_node_set<T, Hash, Pred, Allocator>;
template <class InputIterator, class Allocator,
class = std::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
class = boost::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
class = boost::enable_if_t<detail::is_allocator_v<Allocator> > >
unordered_node_set(InputIterator, InputIterator, std::size_t, Allocator)
-> unordered_node_set<
typename std::iterator_traits<InputIterator>::value_type,
@@ -654,9 +654,9 @@ namespace boost {
Allocator>;
template <class InputIterator, class Hash, class Allocator,
class = std::enable_if_t<detail::is_hash_v<Hash> >,
class = std::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
class = boost::enable_if_t<detail::is_hash_v<Hash> >,
class = boost::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
class = boost::enable_if_t<detail::is_allocator_v<Allocator> > >
unordered_node_set(
InputIterator, InputIterator, std::size_t, Hash, Allocator)
-> unordered_node_set<
@@ -665,19 +665,19 @@ namespace boost {
Allocator>;
template <class T, class Allocator,
class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
class = boost::enable_if_t<detail::is_allocator_v<Allocator> > >
unordered_node_set(std::initializer_list<T>, std::size_t, Allocator)
-> unordered_node_set<T, boost::hash<T>, std::equal_to<T>, Allocator>;
template <class T, class Hash, class Allocator,
class = std::enable_if_t<detail::is_hash_v<Hash> >,
class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
class = boost::enable_if_t<detail::is_hash_v<Hash> >,
class = boost::enable_if_t<detail::is_allocator_v<Allocator> > >
unordered_node_set(std::initializer_list<T>, std::size_t, Hash, Allocator)
-> unordered_node_set<T, Hash, std::equal_to<T>, Allocator>;
template <class InputIterator, class Allocator,
class = std::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
class = boost::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
class = boost::enable_if_t<detail::is_allocator_v<Allocator> > >
unordered_node_set(InputIterator, InputIterator, Allocator)
-> unordered_node_set<
typename std::iterator_traits<InputIterator>::value_type,
@@ -686,7 +686,7 @@ namespace boost {
Allocator>;
template <class T, class Allocator,
class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
class = boost::enable_if_t<detail::is_allocator_v<Allocator> > >
unordered_node_set(std::initializer_list<T>, Allocator)
-> unordered_node_set<T, boost::hash<T>, std::equal_to<T>, Allocator>;
#endif
@@ -11,7 +11,7 @@
#pragma once
#endif
#include <boost/container_hash/hash_fwd.hpp>
#include <boost/functional/hash_fwd.hpp>
#include <functional>
#include <memory>
File diff suppressed because it is too large Load Diff
+11 -9
View File
@@ -12,7 +12,7 @@
#pragma once
#endif
#include <boost/container_hash/hash_fwd.hpp>
#include <boost/functional/hash_fwd.hpp>
#include <functional>
#include <memory>
@@ -29,8 +29,9 @@ namespace boost {
inline bool operator!=(
unordered_set<T, H, P, A> const&, unordered_set<T, H, P, A> const&);
template <class T, class H, class P, class A>
inline void swap(unordered_set<T, H, P, A>& m1,
unordered_set<T, H, P, A>& m2) noexcept(noexcept(m1.swap(m2)));
inline void swap(
unordered_set<T, H, P, A>& m1, unordered_set<T, H, P, A>& m2)
BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR(m1.swap(m2)));
template <class K, class H, class P, class A, class Predicate>
typename unordered_set<K, H, P, A>::size_type erase_if(
@@ -47,8 +48,9 @@ namespace boost {
inline bool operator!=(unordered_multiset<T, H, P, A> const&,
unordered_multiset<T, H, P, A> const&);
template <class T, class H, class P, class A>
inline void swap(unordered_multiset<T, H, P, A>& m1,
unordered_multiset<T, H, P, A>& m2) noexcept(noexcept(m1.swap(m2)));
inline void swap(
unordered_multiset<T, H, P, A>& m1, unordered_multiset<T, H, P, A>& m2)
BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR(m1.swap(m2)));
template <class K, class H, class P, class A, class Predicate>
typename unordered_multiset<K, H, P, A>::size_type erase_if(
@@ -56,13 +58,13 @@ namespace boost {
template <class N, class T, class A> class node_handle_set;
template <class Iter, class NodeType> struct insert_return_type_set;
} // namespace unordered
}
using boost::unordered::swap;
using boost::unordered::unordered_multiset;
using boost::unordered::unordered_set;
using boost::unordered::unordered_multiset;
using boost::unordered::swap;
using boost::unordered::operator==;
using boost::unordered::operator!=;
} // namespace boost
}
#endif
+5 -3
View File
@@ -5,12 +5,14 @@
"Daniel James"
],
"maintainers": [
"Christian Mazakas <christian.mazakas -at- gmail.com>",
"Joaquín M López Muñoz <joaquin.lopezmunoz -at- gmail.com>"
"Daniel James <dnljms -at- gmail.com>"
],
"description": "Unordered associative containers.",
"std": [
"tr1"
],
"category": [
"Containers"
],
"cxxstd": "11"
"cxxstd": "03"
}
+6 -1
View File
@@ -20,7 +20,7 @@ function(foa_tests)
endfunction()
function(cfoa_tests)
boost_test(PREFIX boost_unordered_cfoa LINK_LIBRARIES Boost::compat Boost::iterator Threads::Threads ${ARGN})
boost_test(PREFIX boost_unordered_cfoa LINK_LIBRARIES Boost::compat Threads::Threads ${ARGN})
endfunction()
# FCA tests
@@ -77,6 +77,11 @@ fca_tests(SOURCES exception/swap_exception_tests.cpp COMPILE_DEFINITIONS BOOST_U
fca_tests(SOURCES exception/merge_exception_tests.cpp)
fca_tests(SOURCES exception/less_tests.cpp)
fca_tests(SOURCES unordered/narrow_cast_tests.cpp)
fca_tests(SOURCES unordered/compile_set.cpp COMPILE_DEFINITIONS BOOST_UNORDERED_USE_MOVE NAME bmove_compile_set)
fca_tests(SOURCES unordered/compile_map.cpp COMPILE_DEFINITIONS BOOST_UNORDERED_USE_MOVE NAME bmove_compile_map)
fca_tests(SOURCES unordered/copy_tests.cpp COMPILE_DEFINITIONS BOOST_UNORDERED_USE_MOVE NAME bmove_copy)
fca_tests(SOURCES unordered/move_tests.cpp COMPILE_DEFINITIONS BOOST_UNORDERED_USE_MOVE NAME bmove_move)
fca_tests(SOURCES unordered/assign_tests.cpp COMPILE_DEFINITIONS BOOST_UNORDERED_USE_MOVE NAME bmove_assign)
fca_tests(SOURCES quick.cpp)
fca_tests(TYPE compile-fail NAME insert_node_type_fail_map COMPILE_DEFINITIONS UNORDERED_TEST_MAP SOURCES unordered/insert_node_type_fail.cpp)
+26 -2
View File
@@ -20,6 +20,21 @@ local msvc-flags = /wd4494 ;
project
: requirements
[ requires cxx11_rvalue_references
cxx11_auto_declarations
cxx11_nullptr
cxx11_defaulted_functions
cxx11_final
cxx11_hdr_type_traits
cxx11_hdr_initializer_list
cxx11_static_assert
cxx11_smart_ptr
cxx11_constexpr
cxx11_noexcept
cxx11_decltype
cxx11_alignas
]
<warnings>pedantic
<toolset>intel:<warnings>on
@@ -116,7 +131,6 @@ local FCA_TESTS =
swap_tests
transparent_tests
unnecessary_copy_tests
fancy_pointer_noleak
;
for local test in $(FCA_TESTS)
@@ -132,6 +146,12 @@ for local test in $(FCA_TESTS)
run unordered/link_test_1.cpp unordered/link_test_2.cpp : : : : link_test ;
run unordered/compile_set.cpp : : : <define>BOOST_UNORDERED_USE_MOVE : bmove_compile_set ;
run unordered/compile_map.cpp : : : <define>BOOST_UNORDERED_USE_MOVE : bmove_compile_map ;
run unordered/copy_tests.cpp : : : <define>BOOST_UNORDERED_USE_MOVE : bmove_copy ;
run unordered/move_tests.cpp : : : <define>BOOST_UNORDERED_USE_MOVE : bmove_move ;
run unordered/assign_tests.cpp : : : <define>BOOST_UNORDERED_USE_MOVE : bmove_assign ;
run unordered/serialization_tests.cpp
: $(BOOST_UNORDERED_TEST_DIR)
:
@@ -178,6 +198,11 @@ alias fca_tests :
$(FCA_TESTS)
$(FCA_EXCEPTION_TESTS)
link_test
bmove_compile_set
bmove_compile_map
bmove_copy
bmove_move
bmove_assign
insert_node_type_fail_map
insert_node_type_fail_multimap
insert_node_type_fail_set
@@ -221,7 +246,6 @@ local FOA_TESTS =
node_handle_tests
uses_allocator
hash_is_avalanching_test
fancy_pointer_noleak
;
for local test in $(FOA_TESTS)
+1 -1
View File
@@ -536,7 +536,7 @@ public:
T& operator[](std::ptrdiff_t s) const { return ptr_[s]; }
bool operator!() const { return !ptr_; }
static ptr pointer_to(T& p) { return ptr(std::addressof(p)); }
static ptr pointer_to(T& p) { return ptr(boost::addressof(p)); }
// I'm not using the safe bool idiom because the containers should be
// able to cope with bool conversions.
-155
View File
@@ -3,29 +3,13 @@
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <boost/config.hpp>
#include <boost/config/workaround.hpp>
#if BOOST_WORKAROUND(BOOST_GCC_VERSION, < 40900)
// warning triggered in transform_iterator.hpp transitive includes
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wconversion"
#pragma GCC diagnostic ignored "-Wsign-conversion"
#endif
#include "helpers.hpp"
#include <boost/unordered/concurrent_flat_map.hpp>
#include <boost/unordered/concurrent_flat_set.hpp>
#include <boost/core/ignore_unused.hpp>
#include <boost/iterator/transform_iterator.hpp>
#if BOOST_WORKAROUND(BOOST_GCC_VERSION, < 40900)
#pragma GCC diagnostic pop
#endif
#include <algorithm>
#include <array>
#include <functional>
#include <vector>
@@ -841,129 +825,6 @@ namespace {
check_raii_counts();
}
struct regular_key_extractor
{
template<typename T>
auto operator()(const T& x) const -> decltype(get_key(x))
{
return get_key(x);
}
} regular_key_extract;
struct transp_key_extractor
{
template<typename T>
auto operator()(const T& x) const -> decltype((get_key(x).x_))
{
return get_key(x).x_;
}
} transp_key_extract;
template <class X, class KeyExtractor, class GF>
void bulk_visit(
X*, KeyExtractor key_extract, GF gen_factory, test::random_generator rg)
{
using key_type = typename X::key_type;
using value_type = typename X::value_type;
// concurrent_flat_set visit is always const access
using arg_type = typename std::conditional<
std::is_same<key_type, value_type>::value,
value_type const,
value_type
>::type;
auto gen = gen_factory.template get<X>();
auto values = make_random_values(16384 * 16, [&] { return gen(rg); });
using values_type = decltype(values);
using span_value_type = typename values_type::value_type;
raii::reset_counts();
{
X x;
for (auto const& v: values) {
if (get_key(v).x_ % 3 != 0) x.insert(v);
}
X const& cx = x;
std::uint64_t old_default_constructor = raii::default_constructor;
std::uint64_t old_copy_constructor = raii::copy_constructor;
std::uint64_t old_move_constructor = raii::move_constructor;
std::uint64_t old_copy_assignment = raii::copy_assignment;
std::uint64_t old_move_assignment = raii::move_assignment;
std::atomic<std::size_t> num_visits{0};
thread_runner(values, [&x, &cx, &num_visits, key_extract]
(boost::span<span_value_type> s) {
auto it = boost::make_transform_iterator(s.begin(), key_extract);
std::size_t n = s.size(), m = 0, q = 0;
auto found = [&it, &m](value_type const& v) {
return std::find(
it, it + (std::ptrdiff_t)m, get_key(v)) != it + (std::ptrdiff_t)m;
};
while (n) {
if (m > n) m = n;
switch (q % 3) {
case 0:
x.visit(
it, it + (std::ptrdiff_t)m,
[&num_visits, &found](arg_type& v) {
if ( found(v) ) ++num_visits;
});
break;
case 1:
cx.visit(
it, it + (std::ptrdiff_t)m,
[&num_visits, &found](value_type const& v) {
if ( found(v) ) ++num_visits;
});
break;
case 2:
cx.cvisit(
it, it + (std::ptrdiff_t)m,
[&num_visits, &found](value_type const& v) {
if ( found(v) ) ++num_visits;
});
break;
default:
break;
}
it += (std::ptrdiff_t)m;
n -= m;
++m;
if (m > 5*X::bulk_visit_size){
m = 0;
++ q;
}
}
});
BOOST_TEST_EQ(num_visits, x.size());
BOOST_TEST_EQ(old_default_constructor, raii::default_constructor);
BOOST_TEST_EQ(old_copy_constructor, raii::copy_constructor);
BOOST_TEST_EQ(old_move_constructor, raii::move_constructor);
BOOST_TEST_EQ(old_copy_assignment, raii::copy_assignment);
BOOST_TEST_EQ(old_move_assignment, raii::move_assignment);
}
BOOST_TEST_GE(raii::default_constructor, 0u);
BOOST_TEST_GE(raii::copy_constructor, 0u);
BOOST_TEST_GE(raii::move_constructor, 0u);
BOOST_TEST_GT(raii::destructor, 0u);
BOOST_TEST_EQ(raii::default_constructor + raii::copy_constructor +
raii::move_constructor,
raii::destructor);
}
boost::unordered::concurrent_flat_map<raii, raii>* map;
boost::unordered::concurrent_flat_map<raii, raii, transp_hash,
transp_key_equal>* transp_map;
@@ -1008,22 +869,6 @@ UNORDERED_TEST(
((sequential))
)
UNORDERED_TEST(
bulk_visit,
((map)(set))
((regular_key_extract))
((value_type_generator_factory))
((sequential))
)
UNORDERED_TEST(
bulk_visit,
((transp_map)(transp_set))
((transp_key_extract))
((value_type_generator_factory))
((sequential))
)
// clang-format on
RUN_TESTS()
@@ -10,9 +10,6 @@
#include "../helpers/random_values.hpp"
#include "../helpers/strong.hpp"
#include "../helpers/tracker.hpp"
#include <boost/tuple/tuple.hpp>
#include <cmath>
#include <string>
@@ -44,7 +44,7 @@ template <class T> struct move_assign_base : public test::exception_base
test::exceptions_enable disable_exceptions(false);
T y1 = y;
disable_exceptions.release();
x1 = std::move(y1);
x1 = boost::move(y1);
DISABLE_EXCEPTIONS;
test::check_container(x1, y_values);
+8 -6
View File
@@ -6,15 +6,11 @@
#if !defined(BOOST_UNORDERED_TEST_TEST_HEADER)
#define BOOST_UNORDERED_TEST_TEST_HEADER
#include <boost/unordered/detail/fwd.hpp>
#include <boost/core/lightweight_test.hpp>
#include <boost/preprocessor/cat.hpp>
#include <boost/preprocessor/stringize.hpp>
#include <boost/type_traits/is_nothrow_move_assignable.hpp>
#include <boost/type_traits/is_nothrow_move_constructible.hpp>
#include <boost/type_traits/is_nothrow_swappable.hpp>
#include <boost/type_traits/make_void.hpp>
#define UNORDERED_AUTO_TEST(x) \
struct BOOST_PP_CAT(x, _type) : public ::test::registered_test_base \
{ \
@@ -124,7 +120,7 @@ namespace test {
static state instance;
return instance;
}
} // namespace test
}
#if defined(__cplusplus)
#define BOOST_UNORDERED_CPLUSPLUS __cplusplus
@@ -138,6 +134,12 @@ namespace test {
<< "Compiler: " << BOOST_COMPILER << "\n" \
<< "Library: " << BOOST_STDLIB << "\n" \
<< "__cplusplus: " << BOOST_UNORDERED_CPLUSPLUS << "\n\n" \
<< "BOOST_UNORDERED_HAVE_PIECEWISE_CONSTRUCT: " \
<< BOOST_UNORDERED_HAVE_PIECEWISE_CONSTRUCT << "\n" \
<< "BOOST_UNORDERED_EMPLACE_LIMIT: " << BOOST_UNORDERED_EMPLACE_LIMIT \
<< "\n" \
<< "BOOST_UNORDERED_CXX11_CONSTRUCTION: " \
<< BOOST_UNORDERED_CXX11_CONSTRUCTION << "\n\n" \
<< std::flush; \
}
+1
View File
@@ -14,6 +14,7 @@
#include <boost/unordered/unordered_node_map.hpp>
#include <boost/unordered/unordered_node_set.hpp>
#include <boost/unordered/detail/implementation.hpp>
#include <boost/unordered/detail/fwd.hpp>
#else
#include <boost/unordered_set.hpp>
#include <boost/unordered_map.hpp>
+18 -3
View File
@@ -182,7 +182,9 @@ namespace test
~cxx11_allocator_base() { detail::tracker.allocator_unref(); }
#if !defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS)
cxx11_allocator_base& operator=(cxx11_allocator_base const& x) = default;
#endif
pointer address(reference r) { return pointer(&r); }
@@ -212,12 +214,21 @@ namespace test
::operator delete((void*)p);
}
template <class U, typename... Args>
void construct(U* p, Args&&... args)
#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template <class U, class V>
void construct(U* p, V const& v)
{
detail::tracker.track_construct((void*)p, sizeof(U), tag_);
new (p) U(std::forward<Args>(args)...);
new (p) U(v);
}
#else
template <class U, typename... Args>
void construct(U* p, BOOST_FWD_REF(Args)... args)
{
detail::tracker.track_construct((void*)p, sizeof(U), tag_);
new (p) U(boost::forward<Args>(args)...);
}
#endif
template <class U>
void destroy(U* p)
@@ -261,7 +272,9 @@ namespace test
cxx11_allocator(cxx11_allocator const& x) : cxx11_allocator_base<T>(x) {}
#if !defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS)
cxx11_allocator& operator=(cxx11_allocator const& x) = default;
#endif
// When not propagating swap, allocators are always equal
// to avoid undefined behaviour.
@@ -306,7 +319,9 @@ namespace test
cxx11_allocator(cxx11_allocator const& x) : cxx11_allocator_base<T>(x) {}
#if !defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS)
cxx11_allocator& operator=(cxx11_allocator const& x) = default;
#endif
// When not propagating swap, allocators are always equal
// to avoid undefined behaviour.

Some files were not shown because too many files have changed in this diff Show More