Merge pull request #215 from cmazakas/cxx03_deprecation

cxx03 deprecation
This commit is contained in:
Christian Mazakas
2023-09-29 14:59:59 -07:00
committed by GitHub
77 changed files with 1670 additions and 4309 deletions

View File

@ -31,25 +31,6 @@ environment:
B2_VARIANT: debug,release B2_VARIANT: debug,release
matrix: 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 - FLAVOR: Visual Studio 2015
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
B2_TOOLSET: msvc-14.0 B2_TOOLSET: msvc-14.0
@ -69,13 +50,6 @@ environment:
B2_CXXSTD: latest B2_CXXSTD: latest
B2_TOOLSET: msvc-14.1 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) - FLAVOR: cygwin (32-bit, C++11)
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
ADDPATH: C:\cygwin\bin; ADDPATH: C:\cygwin\bin;
@ -97,15 +71,6 @@ environment:
B2_CXXSTD: 1z B2_CXXSTD: 1z
B2_TOOLSET: gcc 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) - FLAVOR: cygwin (64-bit, latest, C++11)
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2022 APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2022
ADDPATH: C:\cygwin64\bin; ADDPATH: C:\cygwin64\bin;
@ -133,13 +98,6 @@ environment:
B2_FLAGS: "include=libs/unordered/test/unordered include=libs/unordered/test/exception" B2_FLAGS: "include=libs/unordered/test/unordered include=libs/unordered/test/exception"
B2_VARIANT: release 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 - FLAVOR: mingw-w64, 32 bit, C++11
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
ADDPATH: C:\mingw-w64\i686-8.1.0-posix-dwarf-rt_v6-rev0\mingw32\bin; ADDPATH: C:\mingw-w64\i686-8.1.0-posix-dwarf-rt_v6-rev0\mingw32\bin;
@ -168,13 +126,6 @@ environment:
B2_TOOLSET: gcc B2_TOOLSET: gcc
B2_ADDRESS_MODEL: 32 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 - FLAVOR: mingw-w64, 64 bit, C++11
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
ADDPATH: C:\mingw-w64\x86_64-8.1.0-posix-seh-rt_v6-rev0\mingw64\bin; ADDPATH: C:\mingw-w64\x86_64-8.1.0-posix-seh-rt_v6-rev0\mingw64\bin;

View File

@ -100,40 +100,16 @@ 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_pipeline(
"Linux 14.04 GCC 4.8* 32/64", "Linux 14.04 GCC 4.8* 32/64",
"cppalliance/droneubuntu1404:1", "cppalliance/droneubuntu1404:1",
{ TOOLSET: 'gcc', COMPILER: 'g++', CXXSTD: '03,11', ADDRMD: '32,64' }, { TOOLSET: 'gcc', COMPILER: 'g++', CXXSTD: '11', ADDRMD: '32,64' },
), ),
linux_pipeline( linux_pipeline(
"Linux 14.04 GCC 4.9 32/64", "Linux 14.04 GCC 4.9 32/64",
"cppalliance/droneubuntu1404:1", "cppalliance/droneubuntu1404:1",
{ TOOLSET: 'gcc', COMPILER: 'g++-4.9', CXXSTD: '03,11', ADDRMD: '32,64' }, { TOOLSET: 'gcc', COMPILER: 'g++-4.9', CXXSTD: '11', ADDRMD: '32,64' },
"g++-4.9-multilib", "g++-4.9-multilib",
[ "ppa:ubuntu-toolchain-r/test" ], [ "ppa:ubuntu-toolchain-r/test" ],
), ),
@ -141,26 +117,26 @@ local windows_pipeline(name, image, environment, arch = "amd64") =
linux_pipeline( linux_pipeline(
"Linux 16.04 GCC 5* 32/64", "Linux 16.04 GCC 5* 32/64",
"cppalliance/droneubuntu1604:1", "cppalliance/droneubuntu1604:1",
{ TOOLSET: 'gcc', COMPILER: 'g++', CXXSTD: '03,11,14', ADDRMD: '32,64' }, { TOOLSET: 'gcc', COMPILER: 'g++', CXXSTD: '11,14', ADDRMD: '32,64' },
), ),
linux_pipeline( linux_pipeline(
"Linux 18.04 GCC 6 32/64", "Linux 18.04 GCC 6 32/64",
"cppalliance/droneubuntu1804:1", "cppalliance/droneubuntu1804:1",
{ TOOLSET: 'gcc', COMPILER: 'g++-6', CXXSTD: '03,11,14', ADDRMD: '32,64' }, { TOOLSET: 'gcc', COMPILER: 'g++-6', CXXSTD: '11,14', ADDRMD: '32,64' },
"g++-6-multilib", "g++-6-multilib",
), ),
linux_pipeline( linux_pipeline(
"Linux 18.04 GCC 7* 32/64", "Linux 18.04 GCC 7* 32/64",
"cppalliance/droneubuntu1804:1", "cppalliance/droneubuntu1804:1",
{ TOOLSET: 'gcc', COMPILER: 'g++', CXXSTD: '03,11,14,17', ADDRMD: '32,64' }, { TOOLSET: 'gcc', COMPILER: 'g++', CXXSTD: '11,14,17', ADDRMD: '32,64' },
), ),
linux_pipeline( linux_pipeline(
"Linux 18.04 GCC 8 32/64 (03,11)", "Linux 18.04 GCC 8 32/64 (11)",
"cppalliance/droneubuntu1804:1", "cppalliance/droneubuntu1804:1",
{ TOOLSET: 'gcc', COMPILER: 'g++-8', CXXSTD: '03,11', ADDRMD: '32,64' }, { TOOLSET: 'gcc', COMPILER: 'g++-8', CXXSTD: '11', ADDRMD: '32,64' },
"g++-8-multilib", "g++-8-multilib",
), ),
@ -172,9 +148,9 @@ local windows_pipeline(name, image, environment, arch = "amd64") =
), ),
linux_pipeline( linux_pipeline(
"Linux 20.04 GCC 9* 32/64 (03,11,14)", "Linux 20.04 GCC 9* 32/64 (11,14)",
"cppalliance/droneubuntu2004:1", "cppalliance/droneubuntu2004:1",
{ TOOLSET: 'gcc', COMPILER: 'g++', CXXSTD: '03,11,14', ADDRMD: '32,64' }, { TOOLSET: 'gcc', COMPILER: 'g++', CXXSTD: '11,14', ADDRMD: '32,64' },
), ),
linux_pipeline( linux_pipeline(
@ -186,14 +162,14 @@ local windows_pipeline(name, image, environment, arch = "amd64") =
linux_pipeline( linux_pipeline(
"Linux 20.04 GCC 9* ARM64", "Linux 20.04 GCC 9* ARM64",
"cppalliance/droneubuntu2004:multiarch", "cppalliance/droneubuntu2004:multiarch",
{ TOOLSET: 'gcc', COMPILER: 'g++', CXXSTD: '03,11,14,17,2a' }, { TOOLSET: 'gcc', COMPILER: 'g++', CXXSTD: '11,14,17,2a' },
arch="arm64", arch="arm64",
), ),
linux_pipeline( linux_pipeline(
"Linux 20.04 GCC 9* S390x (03,11,14)", "Linux 20.04 GCC 9* S390x (11,14)",
"cppalliance/droneubuntu2004:multiarch", "cppalliance/droneubuntu2004:multiarch",
{ TOOLSET: 'gcc', COMPILER: 'g++', CXXSTD: '03,11,14' }, { TOOLSET: 'gcc', COMPILER: 'g++', CXXSTD: '11,14' },
arch="s390x", arch="s390x",
), ),
@ -205,9 +181,9 @@ local windows_pipeline(name, image, environment, arch = "amd64") =
), ),
linux_pipeline( linux_pipeline(
"Linux 20.04 GCC 10 32/64 (03,11,14)", "Linux 20.04 GCC 10 32/64 (11,14)",
"cppalliance/droneubuntu2004:1", "cppalliance/droneubuntu2004:1",
{ TOOLSET: 'gcc', COMPILER: 'g++-10', CXXSTD: '03,11,14', ADDRMD: '32,64' }, { TOOLSET: 'gcc', COMPILER: 'g++-10', CXXSTD: '11,14', ADDRMD: '32,64' },
"g++-10-multilib", "g++-10-multilib",
), ),
@ -219,9 +195,9 @@ local windows_pipeline(name, image, environment, arch = "amd64") =
), ),
linux_pipeline( linux_pipeline(
"Linux 22.04 GCC 11* 32/64 (03,11,14)", "Linux 22.04 GCC 11* 32/64 (11,14)",
"cppalliance/droneubuntu2204:1", "cppalliance/droneubuntu2204:1",
{ TOOLSET: 'gcc', COMPILER: 'g++', CXXSTD: '03,11,14', ADDRMD: '32,64' }, { TOOLSET: 'gcc', COMPILER: 'g++', CXXSTD: '11,14', ADDRMD: '32,64' },
), ),
linux_pipeline( linux_pipeline(
@ -231,9 +207,9 @@ local windows_pipeline(name, image, environment, arch = "amd64") =
), ),
linux_pipeline( linux_pipeline(
"Linux 22.04 GCC 12 32 ASAN (03,11,14)", "Linux 22.04 GCC 12 32 ASAN (11,14)",
"cppalliance/droneubuntu2204:1", "cppalliance/droneubuntu2204:1",
{ TOOLSET: 'gcc', COMPILER: 'g++-12', CXXSTD: '03,11', ADDRMD: '32' } + asan, { TOOLSET: 'gcc', COMPILER: 'g++-12', CXXSTD: '11', ADDRMD: '32' } + asan,
"g++-12-multilib", "g++-12-multilib",
), ),
@ -266,9 +242,9 @@ local windows_pipeline(name, image, environment, arch = "amd64") =
), ),
linux_pipeline( linux_pipeline(
"Linux 22.04 GCC 12 64 ASAN (03,11,14)", "Linux 22.04 GCC 12 64 ASAN (11,14)",
"cppalliance/droneubuntu2204:1", "cppalliance/droneubuntu2204:1",
{ TOOLSET: 'gcc', COMPILER: 'g++-12', CXXSTD: '03,11,14', ADDRMD: '64' } + asan, { TOOLSET: 'gcc', COMPILER: 'g++-12', CXXSTD: '11,14', ADDRMD: '64' } + asan,
"g++-12-multilib", "g++-12-multilib",
), ),
@ -301,9 +277,9 @@ local windows_pipeline(name, image, environment, arch = "amd64") =
), ),
linux_pipeline( linux_pipeline(
"Linux 23.04 GCC 13 32/64 (03,11,14)", "Linux 23.04 GCC 13 32/64 (11,14)",
"cppalliance/droneubuntu2304:1", "cppalliance/droneubuntu2304:1",
{ TOOLSET: 'gcc', COMPILER: 'g++-13', CXXSTD: '03,11,14', ADDRMD: '32,64' }, { TOOLSET: 'gcc', COMPILER: 'g++-13', CXXSTD: '11,14', ADDRMD: '32,64' },
"g++-13 g++-13-multilib", "g++-13 g++-13-multilib",
), ),
@ -317,112 +293,112 @@ local windows_pipeline(name, image, environment, arch = "amd64") =
linux_pipeline( linux_pipeline(
"Linux 16.04 Clang 3.5", "Linux 16.04 Clang 3.5",
"cppalliance/droneubuntu1604:1", "cppalliance/droneubuntu1604:1",
{ TOOLSET: 'clang', COMPILER: 'clang++-3.5', CXXSTD: '03,11' }, { TOOLSET: 'clang', COMPILER: 'clang++-3.5', CXXSTD: '11' },
"clang-3.5", "clang-3.5",
), ),
linux_pipeline( linux_pipeline(
"Linux 16.04 Clang 3.6", "Linux 16.04 Clang 3.6",
"cppalliance/droneubuntu1604:1", "cppalliance/droneubuntu1604:1",
{ TOOLSET: 'clang', COMPILER: 'clang++-3.6', CXXSTD: '03,11,14' }, { TOOLSET: 'clang', COMPILER: 'clang++-3.6', CXXSTD: '11,14' },
"clang-3.6", "clang-3.6",
), ),
linux_pipeline( linux_pipeline(
"Linux 16.04 Clang 3.7", "Linux 16.04 Clang 3.7",
"cppalliance/droneubuntu1604:1", "cppalliance/droneubuntu1604:1",
{ TOOLSET: 'clang', COMPILER: 'clang++-3.7', CXXSTD: '03,11,14' }, { TOOLSET: 'clang', COMPILER: 'clang++-3.7', CXXSTD: '11,14' },
"clang-3.7", "clang-3.7",
), ),
linux_pipeline( linux_pipeline(
"Linux 16.04 Clang 3.8", "Linux 16.04 Clang 3.8",
"cppalliance/droneubuntu1604:1", "cppalliance/droneubuntu1604:1",
{ TOOLSET: 'clang', COMPILER: 'clang++-3.8', CXXSTD: '03,11,14' }, { TOOLSET: 'clang', COMPILER: 'clang++-3.8', CXXSTD: '11,14' },
"clang-3.8", "clang-3.8",
), ),
linux_pipeline( linux_pipeline(
"Linux 18.04 Clang 3.9", "Linux 18.04 Clang 3.9",
"cppalliance/droneubuntu1804:1", "cppalliance/droneubuntu1804:1",
{ TOOLSET: 'clang', COMPILER: 'clang++-3.9', CXXSTD: '03,11,14' }, { TOOLSET: 'clang', COMPILER: 'clang++-3.9', CXXSTD: '11,14' },
"clang-3.9", "clang-3.9",
), ),
linux_pipeline( linux_pipeline(
"Linux 18.04 Clang 4.0", "Linux 18.04 Clang 4.0",
"cppalliance/droneubuntu1804:1", "cppalliance/droneubuntu1804:1",
{ TOOLSET: 'clang', COMPILER: 'clang++-4.0', CXXSTD: '03,11,14' }, { TOOLSET: 'clang', COMPILER: 'clang++-4.0', CXXSTD: '11,14' },
"clang-4.0", "clang-4.0",
), ),
linux_pipeline( linux_pipeline(
"Linux 18.04 Clang 5.0", "Linux 18.04 Clang 5.0",
"cppalliance/droneubuntu1804:1", "cppalliance/droneubuntu1804:1",
{ TOOLSET: 'clang', COMPILER: 'clang++-5.0', CXXSTD: '03,11,14,1z' }, { TOOLSET: 'clang', COMPILER: 'clang++-5.0', CXXSTD: '11,14,1z' },
"clang-5.0", "clang-5.0",
), ),
linux_pipeline( linux_pipeline(
"Linux 18.04 Clang 6.0", "Linux 18.04 Clang 6.0",
"cppalliance/droneubuntu1804:1", "cppalliance/droneubuntu1804:1",
{ TOOLSET: 'clang', COMPILER: 'clang++-6.0', CXXSTD: '03,11,14,17' }, { TOOLSET: 'clang', COMPILER: 'clang++-6.0', CXXSTD: '11,14,17' },
"clang-6.0", "clang-6.0",
), ),
linux_pipeline( linux_pipeline(
"Linux 20.04 Clang 7", "Linux 20.04 Clang 7",
"cppalliance/droneubuntu2004:1", "cppalliance/droneubuntu2004:1",
{ TOOLSET: 'clang', COMPILER: 'clang++-7', CXXSTD: '03,11,14,17' }, { TOOLSET: 'clang', COMPILER: 'clang++-7', CXXSTD: '11,14,17' },
"clang-7", "clang-7",
), ),
linux_pipeline( linux_pipeline(
"Linux 20.04 Clang 8", "Linux 20.04 Clang 8",
"cppalliance/droneubuntu2004:1", "cppalliance/droneubuntu2004:1",
{ TOOLSET: 'clang', COMPILER: 'clang++-8', CXXSTD: '03,11,14,17' }, { TOOLSET: 'clang', COMPILER: 'clang++-8', CXXSTD: '11,14,17' },
"clang-8", "clang-8",
), ),
linux_pipeline( linux_pipeline(
"Linux 20.04 Clang 9", "Linux 20.04 Clang 9",
"cppalliance/droneubuntu2004:1", "cppalliance/droneubuntu2004:1",
{ TOOLSET: 'clang', COMPILER: 'clang++-9', CXXSTD: '03,11,14,17,2a' }, { TOOLSET: 'clang', COMPILER: 'clang++-9', CXXSTD: '11,14,17,2a' },
"clang-9", "clang-9",
), ),
linux_pipeline( linux_pipeline(
"Linux 20.04 Clang 10", "Linux 20.04 Clang 10",
"cppalliance/droneubuntu2004:1", "cppalliance/droneubuntu2004:1",
{ TOOLSET: 'clang', COMPILER: 'clang++-10', CXXSTD: '03,11,14,17,2a' }, { TOOLSET: 'clang', COMPILER: 'clang++-10', CXXSTD: '11,14,17,2a' },
"clang-10", "clang-10",
), ),
linux_pipeline( linux_pipeline(
"Linux 20.04 Clang 11", "Linux 20.04 Clang 11",
"cppalliance/droneubuntu2004:1", "cppalliance/droneubuntu2004:1",
{ TOOLSET: 'clang', COMPILER: 'clang++-11', CXXSTD: '03,11,14,17,2a' }, { TOOLSET: 'clang', COMPILER: 'clang++-11', CXXSTD: '11,14,17,2a' },
"clang-11", "clang-11",
), ),
linux_pipeline( linux_pipeline(
"Linux 20.04 Clang 12", "Linux 20.04 Clang 12",
"cppalliance/droneubuntu2004:1", "cppalliance/droneubuntu2004:1",
{ TOOLSET: 'clang', COMPILER: 'clang++-12', CXXSTD: '03,11,14,17,2a' }, { TOOLSET: 'clang', COMPILER: 'clang++-12', CXXSTD: '11,14,17,2a' },
"clang-12", "clang-12",
), ),
linux_pipeline( linux_pipeline(
"Linux 22.04 Clang 13", "Linux 22.04 Clang 13",
"cppalliance/droneubuntu2204:1", "cppalliance/droneubuntu2204:1",
{ TOOLSET: 'clang', COMPILER: 'clang++-13', CXXSTD: '03,11,14,17,20' }, { TOOLSET: 'clang', COMPILER: 'clang++-13', CXXSTD: '11,14,17,20' },
"clang-13", "clang-13",
), ),
linux_pipeline( linux_pipeline(
"Linux 22.04 Clang 14 UBSAN (03,11,14)", "Linux 22.04 Clang 14 UBSAN (11,14)",
"cppalliance/droneubuntu2204:1", "cppalliance/droneubuntu2204:1",
{ TOOLSET: 'clang', COMPILER: 'clang++-14', CXXSTD: '03,11,14' } + ubsan, { TOOLSET: 'clang', COMPILER: 'clang++-14', CXXSTD: '11,14' } + ubsan,
"clang-14", "clang-14",
), ),
@ -434,9 +410,9 @@ local windows_pipeline(name, image, environment, arch = "amd64") =
), ),
linux_pipeline( linux_pipeline(
"Linux 22.04 Clang 14 ASAN (03,11,14)", "Linux 22.04 Clang 14 ASAN (11,14)",
"cppalliance/droneubuntu2204:1", "cppalliance/droneubuntu2204:1",
{ TOOLSET: 'clang', COMPILER: 'clang++-14', CXXSTD: '03,11,14' } + asan, { TOOLSET: 'clang', COMPILER: 'clang++-14', CXXSTD: '11,14' } + asan,
"clang-14", "clang-14",
), ),
@ -457,14 +433,14 @@ local windows_pipeline(name, image, environment, arch = "amd64") =
linux_pipeline( linux_pipeline(
"Linux 22.04 Clang 15", "Linux 22.04 Clang 15",
"cppalliance/droneubuntu2204:1", "cppalliance/droneubuntu2204:1",
{ TOOLSET: 'clang', COMPILER: 'clang++-15', CXXSTD: '03,11,14,17,20,2b' }, { TOOLSET: 'clang', COMPILER: 'clang++-15', CXXSTD: '11,14,17,20,2b' },
"clang-15", "clang-15",
["deb http://apt.llvm.org/jammy/ llvm-toolchain-jammy-15 main"], ["deb http://apt.llvm.org/jammy/ llvm-toolchain-jammy-15 main"],
), ),
macos_pipeline( macos_pipeline(
"MacOS 10.15 Xcode 12.2 UBSAN (03,11)", "MacOS 10.15 Xcode 12.2 UBSAN (11)",
{ TOOLSET: 'clang', COMPILER: 'clang++', CXXSTD: '03,11' } + ubsan, { TOOLSET: 'clang', COMPILER: 'clang++', CXXSTD: '11' } + ubsan,
), ),
macos_pipeline( macos_pipeline(
@ -479,7 +455,7 @@ local windows_pipeline(name, image, environment, arch = "amd64") =
macos_pipeline( macos_pipeline(
"MacOS 12.4 Xcode 13.4.1 ASAN", "MacOS 12.4 Xcode 13.4.1 ASAN",
{ TOOLSET: 'clang', COMPILER: 'clang++', CXXSTD: '03,11,14,1z' } + asan, { TOOLSET: 'clang', COMPILER: 'clang++', CXXSTD: '11,14,1z' } + asan,
xcode_version = "13.4.1", osx_version = "monterey", arch = "arm64", xcode_version = "13.4.1", osx_version = "monterey", arch = "arm64",
), ),

View File

@ -52,49 +52,65 @@ jobs:
matrix: matrix:
include: include:
# Linux, gcc # Linux, gcc
- { compiler: gcc-7, cxxstd: '03,11,14,17', os: 'ubuntu-20.04', install: 'g++-7' } - { compiler: gcc-7, cxxstd: '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-8, cxxstd: '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-9, cxxstd: '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-10, cxxstd: '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' } - { compiler: gcc-11, cxxstd: '11,14,17,20', os: 'ubuntu-22.04', install: 'g++-11' }
- { name: "gcc-12 w/ sanitizers (03,11,14)", sanitize: yes, - { name: "gcc-12 w/ sanitizers (11)", sanitize: yes,
compiler: gcc-12, cxxstd: '03,11,14', os: 'ubuntu-22.04', ccache_key: "san1" } compiler: gcc-12, cxxstd: '11', os: 'ubuntu-22.04', ccache_key: "san1" }
- { name: "gcc-12 w/ sanitizers (17,20,2b)", sanitize: yes, - { name: "gcc-12 w/ sanitizers (14)", sanitize: yes,
compiler: gcc-12, cxxstd: '17,20,2b', os: 'ubuntu-22.04', ccache_key: "san2" } 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" }
- { name: Collect coverage, coverage: yes, - { name: Collect coverage, coverage: yes,
compiler: gcc-12, cxxstd: '03,20', os: 'ubuntu-22.04', install: 'g++-12-multilib', address-model: '32,64', ccache_key: "cov" } compiler: gcc-12, cxxstd: '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, - { 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" } targets: 'libs/unordered/test//cfoa_tests', thread-sanitize: yes, ccache_key: "tsan" }
# Linux, clang, libc++ # Linux, clang, libc++
- { 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-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: '03,11,14,17,20', os: 'ubuntu-20.04', stdlib: libc++, install: 'clang-10 libc++-10-dev libc++abi-10-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: '03,11,14,17,20', os: 'ubuntu-22.04', stdlib: libc++, install: 'clang-11 libc++-11-dev libc++abi-11-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' }
# clang-12 doesn't work on 'ubuntu-22.04', the linker can't find -lunwind for some reason # clang-12 doesn't work on 'ubuntu-22.04', the linker can't find -lunwind for some reason
- { name: "clang-12 w/ sanitizers (03,11,14)", sanitize: yes, - { name: "clang-12 w/ sanitizers (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" } 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,20,2b)", sanitize: yes, - { name: "clang-12 w/ sanitizers (17)", 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-12, cxxstd: '17', 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' } - { 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' }
# not using libc++ because of https://github.com/llvm/llvm-project/issues/52771 # not using libc++ because of https://github.com/llvm/llvm-project/issues/52771
- { name: "clang-14 w/ sanitizers (03,11,14)", sanitize: yes, - { name: "clang-14 w/ sanitizers (11,14)", sanitize: yes,
compiler: clang-14, cxxstd: '03,11,14', os: 'ubuntu-22.04', ccache_key: "san1" } compiler: clang-14, cxxstd: '11,14', os: 'ubuntu-22.04', ccache_key: "san1" }
- { name: "clang-14 w/ sanitizers (17,20,2b)", sanitize: yes, - { name: "clang-14 w/ sanitizers (17)", sanitize: yes,
compiler: clang-14, cxxstd: '17,20,2b', os: 'ubuntu-22.04', ccache_key: "san2" } 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: "cfoa tsan (clang-14)", cxxstd: '11,14,17,20,2b', os: 'ubuntu-22.04', compiler: clang-14, - { 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, targets: 'libs/unordered/test//cfoa_tests', thread-sanitize: yes,
stdlib: libc++, install: 'clang-14 libc++-14-dev libc++abi-14-dev', ccache_key: "tsan" } stdlib: libc++, install: 'clang-14 libc++-14-dev libc++abi-14-dev', ccache_key: "tsan" }
- { 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' } - { 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' }
# OSX, clang # OSX, clang
- { compiler: clang, cxxstd: '03,11,14,17,2a', os: 'macos-11' } - { compiler: clang, cxxstd: '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', 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,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' } - { compiler: clang, cxxstd: '11,14,17,20,2b', os: 'macos-13' }
timeout-minutes: 360 timeout-minutes: 360
# posix (gcc-12 w/ sanitizers is taking longer than 210 minutes # posix (gcc-12 w/ sanitizers is taking longer than 210 minutes
@ -250,7 +266,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: '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: 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: clang-win, cxxstd: '14,17,latest', addrmd: '32,64', os: 'windows-2022', variant: 'debug,release' }
- { toolset: gcc, cxxstd: '03,11,14,17,2a', addrmd: '64', os: 'windows-2019', variant: 'debug,release' } - { toolset: gcc, cxxstd: '11,14,17,2a', addrmd: '64', os: 'windows-2019', variant: 'debug,release' }
needs: [runner-selection] needs: [runner-selection]
runs-on: ${{ fromJSON(needs.runner-selection.outputs.labelmatrix)[matrix.os] }} runs-on: ${{ fromJSON(needs.runner-selection.outputs.labelmatrix)[matrix.os] }}
@ -307,8 +323,8 @@ jobs:
fail-fast: false fail-fast: false
matrix: matrix:
include: include:
- { sys: MINGW32, compiler: gcc, cxxstd: '03,11,17,20' } - { sys: MINGW32, compiler: gcc, cxxstd: '11,17,20' }
- { sys: MINGW64, compiler: gcc, cxxstd: '03,11,17,20' } - { sys: MINGW64, compiler: gcc, cxxstd: '11,17,20' }
needs: [runner-selection] needs: [runner-selection]
runs-on: ${{ fromJSON(needs.runner-selection.outputs.labelmatrix)['windows-latest'] }} runs-on: ${{ fromJSON(needs.runner-selection.outputs.labelmatrix)['windows-latest'] }}

View File

@ -18,6 +18,8 @@ a concurrent container from user code.
* Added Boost.Serialization support to all containers and their (non-local) iterator types. * Added Boost.Serialization support to all containers and their (non-local) iterator types.
* Added support for fancy pointers to open-addressing and concurrent containers. * 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. 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 == Release 1.83.0 - Major update

View File

@ -7,116 +7,54 @@
== Closed-addressing Containers == Closed-addressing Containers
`unordered_[multi]set` and `unordered_[multi]map` are intended to provide a conformant `boost::unordered_[multi]set` and `boost::unordered_[multi]map` provide a conformant
implementation of the {cpp}20 standard that will work with {cpp}98 upwards. implementation for {cpp}11 (or later) compilers of the latest standard revision of
This wide compatibility does mean some compromises have to be made. {cpp} unordered associative containers, with very minor deviations as noted.
With a compiler and library that fully support {cpp}11, the differences should The containers are fully https://en.cppreference.com/w/cpp/named_req/AllocatorAwareContainer[AllocatorAware^]
be minor. and support https://en.cppreference.com/w/cpp/named_req/Allocator#Fancy_pointers[fancy pointers^].
=== Move Emulation === Deduction Guides
Support for move semantics is implemented using Boost.Move. If rvalue Deduction guides for
references are available it will use them, but if not it uses a close, https://en.cppreference.com/w/cpp/language/class_template_argument_deduction[class template argument deduction (CTAD)^]
but imperfect emulation. On such compilers: are only available on {cpp}17 (or later) compilers.
* Non-copyable objects can be stored in the containers. === Piecewise Pair Emplacement
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.
=== Use of Allocators In accordance with the standard specification,
`boost::unordered_[multi]map::emplace` supports piecewise pair construction:
{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++] [source,c++]
---- ----
boost::unordered_multimap<std::string, std::complex> x; 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( x.emplace(
boost::unordered::piecewise_construct, boost::unordered::piecewise_construct,
boost::make_tuple("key"), boost::make_tuple(1, 2)); boost::make_tuple("key"), boost::make_tuple(1, 2));
---- ----
Older drafts of the standard also supported variadic constructors This feature has been retained for backwards compatibility with
for `std::pair`, where the first argument would be used for the previous versions of Boost.Unordered: users are encouraged to
first part of the pair, and the remaining for the second part. update their code to use `std::piecewise_construct` and
``std::tuple``s instead.
=== Miscellaneous === Swap
When swapping, `Pred` and `Hash` are not currently swapped by calling 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. 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 == Open-addressing Containers
The C++ standard does not currently provide any open-addressing container The C++ standard does not currently provide any open-addressing container
@ -129,7 +67,9 @@ radically different from that imposed by the standard (closed addressing).
Open-addressing containers provided by Boost.Unordered only work with reasonably Open-addressing containers provided by Boost.Unordered only work with reasonably
compliant C++11 (or later) compilers. Language-level features such as move semantics compliant C++11 (or later) compilers. Language-level features such as move semantics
and variadic template parameters are then not emulated. and variadic template parameters are then not emulated.
The containers are fully https://en.cppreference.com/w/cpp/named_req/AllocatorAwareContainer[AllocatorAware^]. 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 main differences with C++ unordered associative containers are: The main differences with C++ unordered associative containers are:
@ -156,7 +96,9 @@ due to their inherent problems in concurrent scenarios (high contention, prone t
so, Boost.Unordered concurrent containers are technically not models of so, Boost.Unordered concurrent containers are technically not models of
https://en.cppreference.com/w/cpp/named_req/Container[Container^], although 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^] they meet all the requirements of https://en.cppreference.com/w/cpp/named_req/AllocatorAwareContainer[AllocatorAware^]
containers except those implying iterators. containers (including
https://en.cppreference.com/w/cpp/named_req/Allocator#Fancy_pointers[fancy pointer^] support)
except those implying iterators.
In a non-concurrent unordered container, iterators serve two main purposes: In a non-concurrent unordered container, iterators serve two main purposes:

View File

@ -1045,13 +1045,13 @@ if there is an element with an equivalent key; otherwise, the construction is of
```c++ ```c++
// first two overloads // first two overloads
value_type(std::piecewise_construct, value_type(std::piecewise_construct,
std::forward_as_tuple(boost::forward<Key>(k)), std::forward_as_tuple(std::forward<Key>(k)),
std::forward_as_tuple(boost::forward<Args>(args)...)) std::forward_as_tuple(std::forward<Args>(args)...))
// third overload // third overload
value_type(std::piecewise_construct, value_type(std::piecewise_construct,
std::forward_as_tuple(boost::forward<K>(k)), std::forward_as_tuple(std::forward<K>(k)),
std::forward_as_tuple(boost::forward<Args>(args)...)) std::forward_as_tuple(std::forward<Args>(args)...))
``` ```
unlike xref:#concurrent_flat_map_emplace[emplace], which simply forwards all arguments to ``value_type``'s constructor. unlike xref:#concurrent_flat_map_emplace[emplace], which simply forwards all arguments to ``value_type``'s constructor.
@ -1093,13 +1093,13 @@ if there is an element with an equivalent key; otherwise, the construction is of
```c++ ```c++
// first four overloads // first four overloads
value_type(std::piecewise_construct, value_type(std::piecewise_construct,
std::forward_as_tuple(boost::forward<Key>(k)), std::forward_as_tuple(std::forward<Key>(k)),
std::forward_as_tuple(boost::forward<Args>(args)...)) std::forward_as_tuple(std::forward<Args>(args)...))
// last two overloads // last two overloads
value_type(std::piecewise_construct, value_type(std::piecewise_construct,
std::forward_as_tuple(boost::forward<K>(k)), std::forward_as_tuple(std::forward<K>(k)),
std::forward_as_tuple(boost::forward<Args>(args)...)) std::forward_as_tuple(std::forward<Args>(args)...))
``` ```
Invalidates pointers and references to elements if a rehashing is issued. Invalidates pointers and references to elements if a rehashing is issued.
@ -1121,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. 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 `boost::forward<M>(obj)`. If there is an element with key `k`, then it is updated by assigning `std::forward<M>(obj)`.
If there is no such element, it is added to the table as: If there is no such element, it is added to the table as:
```c++ ```c++
// first two overloads // first two overloads
value_type(std::piecewise_construct, value_type(std::piecewise_construct,
std::forward_as_tuple(boost::forward<Key>(k)), std::forward_as_tuple(std::forward<Key>(k)),
std::forward_as_tuple(boost::forward<M>(obj))) std::forward_as_tuple(std::forward<M>(obj)))
// third overload // third overload
value_type(std::piecewise_construct, value_type(std::piecewise_construct,
std::forward_as_tuple(boost::forward<K>(k)), std::forward_as_tuple(std::forward<K>(k)),
std::forward_as_tuple(boost::forward<M>(obj))) std::forward_as_tuple(std::forward<M>(obj)))
``` ```
[horizontal] [horizontal]

View File

@ -909,13 +909,13 @@ if there is an element with an equivalent key; otherwise, the construction is of
```c++ ```c++
// first two overloads // first two overloads
value_type(std::piecewise_construct, value_type(std::piecewise_construct,
std::forward_as_tuple(boost::forward<Key>(k)), std::forward_as_tuple(std::forward<Key>(k)),
std::forward_as_tuple(boost::forward<Args>(args)...)) std::forward_as_tuple(std::forward<Args>(args)...))
// third overload // third overload
value_type(std::piecewise_construct, value_type(std::piecewise_construct,
std::forward_as_tuple(boost::forward<K>(k)), std::forward_as_tuple(std::forward<K>(k)),
std::forward_as_tuple(boost::forward<Args>(args)...)) std::forward_as_tuple(std::forward<Args>(args)...))
``` ```
unlike xref:#unordered_flat_map_emplace[emplace], which simply forwards all arguments to ``value_type``'s constructor. 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++ ```c++
// first two overloads // first two overloads
value_type(std::piecewise_construct, value_type(std::piecewise_construct,
std::forward_as_tuple(boost::forward<Key>(k)), std::forward_as_tuple(std::forward<Key>(k)),
std::forward_as_tuple(boost::forward<Args>(args)...)) std::forward_as_tuple(std::forward<Args>(args)...))
// third overload // third overload
value_type(std::piecewise_construct, value_type(std::piecewise_construct,
std::forward_as_tuple(boost::forward<K>(k)), std::forward_as_tuple(std::forward<K>(k)),
std::forward_as_tuple(boost::forward<Args>(args)...)) std::forward_as_tuple(std::forward<Args>(args)...))
``` ```
unlike xref:#unordered_flat_map_emplace_hint[emplace_hint], which simply forwards all arguments to ``value_type``'s constructor. 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. 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 `boost::forward<M>(obj)`. If there is an element with key `k`, then it is updated by assigning `std::forward<M>(obj)`.
If there is no such element, it is added to the container as: If there is no such element, it is added to the container as:
```c++ ```c++
// first two overloads // first two overloads
value_type(std::piecewise_construct, value_type(std::piecewise_construct,
std::forward_as_tuple(boost::forward<Key>(k)), std::forward_as_tuple(std::forward<Key>(k)),
std::forward_as_tuple(boost::forward<M>(obj))) std::forward_as_tuple(std::forward<M>(obj)))
// third overload // third overload
value_type(std::piecewise_construct, value_type(std::piecewise_construct,
std::forward_as_tuple(boost::forward<K>(k)), std::forward_as_tuple(std::forward<K>(k)),
std::forward_as_tuple(boost::forward<M>(obj))) std::forward_as_tuple(std::forward<M>(obj)))
``` ```
[horizontal] [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. 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 `boost::forward<M>(obj)`. If there is an element with key `k`, then it is updated by assigning `std::forward<M>(obj)`.
If there is no such element, it is added to the container as: If there is no such element, it is added to the container as:
```c++ ```c++
// first two overloads // first two overloads
value_type(std::piecewise_construct, value_type(std::piecewise_construct,
std::forward_as_tuple(boost::forward<Key>(k)), std::forward_as_tuple(std::forward<Key>(k)),
std::forward_as_tuple(boost::forward<M>(obj))) std::forward_as_tuple(std::forward<M>(obj)))
// third overload // third overload
value_type(std::piecewise_construct, value_type(std::piecewise_construct,
std::forward_as_tuple(boost::forward<K>(k)), std::forward_as_tuple(std::forward<K>(k)),
std::forward_as_tuple(boost::forward<M>(obj))) std::forward_as_tuple(std::forward<M>(obj)))
``` ```
`hint` is a suggestion to where the element should be inserted. This implementation ignores it. `hint` is a suggestion to where the element should be inserted. This implementation ignores it.

View File

@ -26,12 +26,12 @@ namespace boost {
using hasher = Hash; using hasher = Hash;
using key_equal = Pred; using key_equal = Pred;
using allocator_type = Allocator; using allocator_type = Allocator;
using pointer = typename boost::allocator_traits<Allocator>::pointer; using pointer = typename std::allocator_traits<Allocator>::pointer;
using const_pointer = typename boost::allocator_traits<Allocator>::const_pointer; using const_pointer = typename std::allocator_traits<Allocator>::const_pointer;
using reference = value_type&; using reference = value_type&;
using const_reference = const value_type&; using const_reference = const value_type&;
using size_type = _implementation-defined_; using size_type = std::size_t;
using difference_type = _implementation-defined_; using difference_type = std::ptrdiff_t;
using iterator = _implementation-defined_; using iterator = _implementation-defined_;
using const_iterator = _implementation-defined_; using const_iterator = _implementation-defined_;
@ -316,6 +316,7 @@ namespace boost {
|_Allocator_ |_Allocator_
|An allocator whose value type is the same as the container's value type. |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.
|=== |===
@ -332,47 +333,6 @@ a Boost.Serialization archive with a version of Boost prior to Boost 1.84.
=== Typedefs === 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] [source,c++,subs=+quotes]
---- ----
typedef _implementation-defined_ iterator; typedef _implementation-defined_ iterator;
@ -424,7 +384,8 @@ A const_local_iterator object can be used to iterate through a single bucket.
typedef _implementation-defined_ node_type; typedef _implementation-defined_ node_type;
---- ----
See node_handle_map for details. A class for holding extracted container elements, modelling
https://en.cppreference.com/w/cpp/container/node_handle[NodeHandle].
--- ---
@ -433,7 +394,20 @@ See node_handle_map for details.
typedef _implementation-defined_ insert_return_type; typedef _implementation-defined_ insert_return_type;
---- ----
Structure returned by inserting node_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`.
--- ---
@ -513,10 +487,7 @@ The move constructor.
[horizontal] [horizontal]
Notes:;; This is implemented using Boost.Move. 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.
--- ---
@ -716,7 +687,6 @@ 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. 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] [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. Requires:;; `value_type` is move constructible.
--- ---
@ -827,11 +797,7 @@ 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. 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. + 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`.
--- ---
@ -852,11 +818,7 @@ 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. + 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`.
--- ---
@ -1034,13 +996,13 @@ Notes:;; This function is similiar to xref:#unordered_map_emplace[emplace] excep
```c++ ```c++
// first two overloads // first two overloads
value_type(std::piecewise_construct, value_type(std::piecewise_construct,
std::forward_as_tuple(boost::forward<Key>(k)), std::forward_as_tuple(std::forward<Key>(k)),
std::forward_as_tuple(boost::forward<Args>(args)...)) std::forward_as_tuple(std::forward<Args>(args)...))
// third overload // third overload
value_type(std::piecewise_construct, value_type(std::piecewise_construct,
std::forward_as_tuple(boost::forward<K>(k)), std::forward_as_tuple(std::forward<K>(k)),
std::forward_as_tuple(boost::forward<Args>(args)...)) std::forward_as_tuple(std::forward<Args>(args)...))
``` ```
instead of xref:#unordered_map_emplace[emplace] which simply forwards all arguments to ``value_type``'s constructor. instead of xref:#unordered_map_emplace[emplace] which simply forwards all arguments to ``value_type``'s constructor.
@ -1050,10 +1012,6 @@ Can invalidate iterators, but only if the insert causes the load factor to be gr
Pointers and references to elements are never invalidated. 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. 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`.
-- --
--- ---
@ -1083,13 +1041,13 @@ Notes:;; This function is similiar to xref:#unordered_map_emplace_hint[emplace_h
```c++ ```c++
// first two overloads // first two overloads
value_type(std::piecewise_construct, value_type(std::piecewise_construct,
std::forward_as_tuple(boost::forward<Key>(k)), std::forward_as_tuple(std::forward<Key>(k)),
std::forward_as_tuple(boost::forward<Args>(args)...)) std::forward_as_tuple(std::forward<Args>(args)...))
// third overload // third overload
value_type(std::piecewise_construct, value_type(std::piecewise_construct,
std::forward_as_tuple(boost::forward<K>(k)), std::forward_as_tuple(std::forward<K>(k)),
std::forward_as_tuple(boost::forward<Args>(args)...)) std::forward_as_tuple(std::forward<Args>(args)...))
``` ```
instead of xref:#unordered_map_emplace_hint[emplace_hint] which simply forwards all arguments to ``value_type``'s constructor. instead of xref:#unordered_map_emplace_hint[emplace_hint] which simply forwards all arguments to ``value_type``'s constructor.
@ -1101,10 +1059,6 @@ Can invalidate iterators, but only if the insert causes the load factor to be gr
Pointers and references to elements are never invalidated. 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. 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`.
-- --
--- ---
@ -1121,19 +1075,19 @@ template<class K, class M>
Inserts a new element into the container or updates an existing one by assigning to the contained value. 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 `boost::forward<M>(obj)`. If there is an element with key `k`, then it is updated by assigning `std::forward<M>(obj)`.
If there is no such element, it is added to the container as: If there is no such element, it is added to the container as:
```c++ ```c++
// first two overloads // first two overloads
value_type(std::piecewise_construct, value_type(std::piecewise_construct,
std::forward_as_tuple(boost::forward<Key>(k)), std::forward_as_tuple(std::forward<Key>(k)),
std::forward_as_tuple(boost::forward<M>(obj))) std::forward_as_tuple(std::forward<M>(obj)))
// third overload // third overload
value_type(std::piecewise_construct, value_type(std::piecewise_construct,
std::forward_as_tuple(boost::forward<K>(k)), std::forward_as_tuple(std::forward<K>(k)),
std::forward_as_tuple(boost::forward<M>(obj))) std::forward_as_tuple(std::forward<M>(obj)))
``` ```
[horizontal] [horizontal]
@ -1161,19 +1115,19 @@ template<class K, class M>
Inserts a new element into the container or updates an existing one by assigning to the contained value. 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 `boost::forward<M>(obj)`. If there is an element with key `k`, then it is updated by assigning `std::forward<M>(obj)`.
If there is no such element, it is added to the container as: If there is no such element, it is added to the container as:
```c++ ```c++
// first two overloads // first two overloads
value_type(std::piecewise_construct, value_type(std::piecewise_construct,
std::forward_as_tuple(boost::forward<Key>(k)), std::forward_as_tuple(std::forward<Key>(k)),
std::forward_as_tuple(boost::forward<M>(obj))) std::forward_as_tuple(std::forward<M>(obj)))
// third overload // third overload
value_type(std::piecewise_construct, value_type(std::piecewise_construct,
std::forward_as_tuple(boost::forward<K>(k)), std::forward_as_tuple(std::forward<K>(k)),
std::forward_as_tuple(boost::forward<M>(obj))) std::forward_as_tuple(std::forward<M>(obj)))
``` ```
`hint` is a suggestion to where the element should be inserted. `hint` is a suggestion to where the element should be inserted.
@ -1766,9 +1720,7 @@ 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). 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] [horizontal]
Notes:;; The behavior of this function was changed to match the C++11 standard in Boost 1.48. + Notes:;; Behavior is undefined if the two containers don't have equivalent equality predicates.
+
Behavior is undefined if the two containers don't have equivalent equality predicates.
--- ---
@ -1782,9 +1734,7 @@ 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). 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] [horizontal]
Notes:;; The behavior of this function was changed to match the C++11 standard in Boost 1.48. + Notes:;; Behavior is undefined if the two containers don't have equivalent equality predicates.
+
Behavior is undefined if the two containers don't have equivalent equality predicates.
=== Swap === Swap
```c++ ```c++

View File

@ -26,12 +26,12 @@ namespace boost {
using hasher = Hash; using hasher = Hash;
using key_equal = Pred; using key_equal = Pred;
using allocator_type = Allocator; using allocator_type = Allocator;
using pointer = typename boost::allocator_traits<Allocator>::pointer; using pointer = typename std::allocator_traits<Allocator>::pointer;
using const_pointer = typename boost::allocator_traits<Allocator>::const_pointer; using const_pointer = typename std::allocator_traits<Allocator>::const_pointer;
using reference = value_type&; using reference = value_type&;
using const_reference = const value_type&; using const_reference = const value_type&;
using size_type = _implementation-defined_; using size_type = std::size_t;
using difference_type = _implementation-defined_; using difference_type = std::ptrdiff_t;
using iterator = _implementation-defined_; using iterator = _implementation-defined_;
using const_iterator = _implementation-defined_; using const_iterator = _implementation-defined_;
@ -283,6 +283,7 @@ namespace boost {
|_Allocator_ |_Allocator_
|An allocator whose value type is the same as the container's value type. |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.
|=== |===
@ -299,47 +300,6 @@ a Boost.Serialization archive with a version of Boost prior to Boost 1.84.
=== Typedefs === 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] [source,c++,subs=+quotes]
---- ----
typedef _implementation-defined_ iterator; typedef _implementation-defined_ iterator;
@ -471,10 +431,7 @@ The move constructor.
[horizontal] [horizontal]
Notes:;; This is implemented using Boost.Move. 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.
--- ---
@ -673,7 +630,6 @@ 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. 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] [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. Requires:;; `value_type` is move constructible.
--- ---
@ -782,11 +738,7 @@ 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. 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. + 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`.
--- ---
@ -807,11 +759,7 @@ 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. + 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`.
--- ---
@ -1493,9 +1441,7 @@ 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). 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] [horizontal]
Notes:;; The behavior of this function was changed to match the C++11 standard in Boost 1.48. + Notes:;; Behavior is undefined if the two containers don't have equivalent equality predicates.
+
Behavior is undefined if the two containers don't have equivalent equality predicates.
--- ---
@ -1509,9 +1455,7 @@ 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). 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] [horizontal]
Notes:;; The behavior of this function was changed to match the C++11 standard in Boost 1.48. + Notes:;; Behavior is undefined if the two containers don't have equivalent equality predicates.
+
Behavior is undefined if the two containers don't have equivalent equality predicates.
--- ---

View File

@ -24,12 +24,12 @@ namespace boost {
using hasher = Hash; using hasher = Hash;
using key_equal = Pred; using key_equal = Pred;
using allocator_type = Allocator; using allocator_type = Allocator;
using pointer = typename boost::allocator_traits<Allocator>::pointer; using pointer = typename std::allocator_traits<Allocator>::pointer;
using const_pointer = typename boost::allocator_traits<Allocator>::const_pointer; using const_pointer = typename std::allocator_traits<Allocator>::const_pointer;
using reference = value_type&; using reference = value_type&;
using const_reference = const value_type&; using const_reference = const value_type&;
using size_type = _implementation-defined_; using size_type = std::size_t;
using difference_type = _implementation-defined_; using difference_type = std::ptrdiff_t;
using iterator = _implementation-defined_; using iterator = _implementation-defined_;
using const_iterator = _implementation-defined_; using const_iterator = _implementation-defined_;
@ -271,6 +271,7 @@ namespace boost {
|_Allocator_ |_Allocator_
|An allocator whose value type is the same as the container's value type. |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.
|=== |===
@ -287,46 +288,6 @@ a Boost.Serialization archive with a version of Boost prior to Boost 1.84.
=== Typedefs === 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] [source,c++,subs=+quotes]
---- ----
typedef _implementation-defined_ iterator; typedef _implementation-defined_ iterator;
@ -458,10 +419,7 @@ The move constructor.
[horizontal] [horizontal]
Notes:;; This is implemented using Boost.Move. 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.
--- ---
@ -661,7 +619,6 @@ 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. 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] [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. Requires:;; `value_type` is move constructible.
--- ---
@ -772,11 +729,7 @@ 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. 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. + 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`.
--- ---
@ -797,11 +750,7 @@ 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. + 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`.
--- ---
@ -1424,9 +1373,7 @@ 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). 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] [horizontal]
Notes:;; The behavior of this function was changed to match the C++11 standard in Boost 1.48. + Notes:;; Behavior is undefined if the two containers don't have equivalent equality predicates.
+
Behavior is undefined if the two containers don't have equivalent equality predicates.
--- ---
@ -1440,9 +1387,7 @@ 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). 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] [horizontal]
Notes:;; The behavior of this function was changed to match the C++11 standard in Boost 1.48. + Notes:;; Behavior is undefined if the two containers don't have equivalent equality predicates.
+
Behavior is undefined if the two containers don't have equivalent equality predicates.
--- ---

View File

@ -962,13 +962,13 @@ if there is an element with an equivalent key; otherwise, the construction is of
```c++ ```c++
// first two overloads // first two overloads
value_type(std::piecewise_construct, value_type(std::piecewise_construct,
std::forward_as_tuple(boost::forward<Key>(k)), std::forward_as_tuple(std::forward<Key>(k)),
std::forward_as_tuple(boost::forward<Args>(args)...)) std::forward_as_tuple(std::forward<Args>(args)...))
// third overload // third overload
value_type(std::piecewise_construct, value_type(std::piecewise_construct,
std::forward_as_tuple(boost::forward<K>(k)), std::forward_as_tuple(std::forward<K>(k)),
std::forward_as_tuple(boost::forward<Args>(args)...)) std::forward_as_tuple(std::forward<Args>(args)...))
``` ```
unlike xref:#unordered_node_map_emplace[emplace], which simply forwards all arguments to ``value_type``'s constructor. 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++ ```c++
// first two overloads // first two overloads
value_type(std::piecewise_construct, value_type(std::piecewise_construct,
std::forward_as_tuple(boost::forward<Key>(k)), std::forward_as_tuple(std::forward<Key>(k)),
std::forward_as_tuple(boost::forward<Args>(args)...)) std::forward_as_tuple(std::forward<Args>(args)...))
// third overload // third overload
value_type(std::piecewise_construct, value_type(std::piecewise_construct,
std::forward_as_tuple(boost::forward<K>(k)), std::forward_as_tuple(std::forward<K>(k)),
std::forward_as_tuple(boost::forward<Args>(args)...)) std::forward_as_tuple(std::forward<Args>(args)...))
``` ```
unlike xref:#unordered_node_map_emplace_hint[emplace_hint], which simply forwards all arguments to ``value_type``'s constructor. 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. 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 `boost::forward<M>(obj)`. If there is an element with key `k`, then it is updated by assigning `std::forward<M>(obj)`.
If there is no such element, it is added to the container as: If there is no such element, it is added to the container as:
```c++ ```c++
// first two overloads // first two overloads
value_type(std::piecewise_construct, value_type(std::piecewise_construct,
std::forward_as_tuple(boost::forward<Key>(k)), std::forward_as_tuple(std::forward<Key>(k)),
std::forward_as_tuple(boost::forward<M>(obj))) std::forward_as_tuple(std::forward<M>(obj)))
// third overload // third overload
value_type(std::piecewise_construct, value_type(std::piecewise_construct,
std::forward_as_tuple(boost::forward<K>(k)), std::forward_as_tuple(std::forward<K>(k)),
std::forward_as_tuple(boost::forward<M>(obj))) std::forward_as_tuple(std::forward<M>(obj)))
``` ```
[horizontal] [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. 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 `boost::forward<M>(obj)`. If there is an element with key `k`, then it is updated by assigning `std::forward<M>(obj)`.
If there is no such element, it is added to the container as: If there is no such element, it is added to the container as:
```c++ ```c++
// first two overloads // first two overloads
value_type(std::piecewise_construct, value_type(std::piecewise_construct,
std::forward_as_tuple(boost::forward<Key>(k)), std::forward_as_tuple(std::forward<Key>(k)),
std::forward_as_tuple(boost::forward<M>(obj))) std::forward_as_tuple(std::forward<M>(obj)))
// third overload // third overload
value_type(std::piecewise_construct, value_type(std::piecewise_construct,
std::forward_as_tuple(boost::forward<K>(k)), std::forward_as_tuple(std::forward<K>(k)),
std::forward_as_tuple(boost::forward<M>(obj))) std::forward_as_tuple(std::forward<M>(obj)))
``` ```
`hint` is a suggestion to where the element should be inserted. This implementation ignores it. `hint` is a suggestion to where the element should be inserted. This implementation ignores it.

View File

@ -24,12 +24,12 @@ namespace boost {
using hasher = Hash; using hasher = Hash;
using key_equal = Pred; using key_equal = Pred;
using allocator_type = Allocator; using allocator_type = Allocator;
using pointer = typename boost::allocator_traits<Allocator>::pointer; using pointer = typename std::allocator_traits<Allocator>::pointer;
using const_pointer = typename boost::allocator_traits<Allocator>::const_pointer; using const_pointer = typename std::allocator_traits<Allocator>::const_pointer;
using reference = value_type&; using reference = value_type&;
using const_reference = const value_type&; using const_reference = const value_type&;
using size_type = _implementation-defined_; using size_type = std::size_t;
using difference_type = _implementation-defined_; using difference_type = std::ptrdiff_t;
using iterator = _implementation-defined_; using iterator = _implementation-defined_;
using const_iterator = _implementation-defined_; using const_iterator = _implementation-defined_;
@ -272,6 +272,7 @@ namespace boost {
|_Allocator_ |_Allocator_
|An allocator whose value type is the same as the container's value type. |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,47 +289,6 @@ a Boost.Serialization archive with a version of Boost prior to Boost 1.84.
=== Typedefs === 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] [source,c++,subs=+quotes]
---- ----
typedef _implementation-defined_ iterator; typedef _implementation-defined_ iterator;
@ -380,7 +340,8 @@ A const_local_iterator object can be used to iterate through a single bucket.
typedef _implementation-defined_ node_type; typedef _implementation-defined_ node_type;
---- ----
See node_handle_set for details. A class for holding extracted container elements, modelling
https://en.cppreference.com/w/cpp/container/node_handle[NodeHandle].
--- ---
@ -389,7 +350,20 @@ See node_handle_set for details.
typedef _implementation-defined_ insert_return_type; typedef _implementation-defined_ insert_return_type;
---- ----
Structure returned by inserting node_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`.
--- ---
@ -469,10 +443,7 @@ The move constructor.
[horizontal] [horizontal]
Notes:;; This is implemented using Boost.Move. 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.
--- ---
@ -672,7 +643,6 @@ 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. 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] [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. Requires:;; `value_type` is move constructible.
--- ---
@ -785,11 +755,7 @@ 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. 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. + 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`.
--- ---
@ -810,11 +776,7 @@ 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. + 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`.
--- ---
@ -1489,9 +1451,7 @@ 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). 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] [horizontal]
Notes:;; The behavior of this function was changed to match the C++11 standard in Boost 1.48. + Notes:;; Behavior is undefined if the two containers don't have equivalent equality predicates.
+
Behavior is undefined if the two containers don't have equivalent equality predicates.
--- ---
@ -1505,9 +1465,7 @@ 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). 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] [horizontal]
Notes:;; The behavior of this function was changed to match the C++11 standard in Boost 1.48. + Notes:;; Behavior is undefined if the two containers don't have equivalent equality predicates.
+
Behavior is undefined if the two containers don't have equivalent equality predicates.
--- ---

View File

@ -14,7 +14,7 @@
#define BOOST_HASH_EXAMPLES_CASE_INSENSITIVE_HEADER #define BOOST_HASH_EXAMPLES_CASE_INSENSITIVE_HEADER
#include <boost/algorithm/string/predicate.hpp> #include <boost/algorithm/string/predicate.hpp>
#include <boost/functional/hash.hpp> #include <boost/container_hash/hash.hpp>
namespace hash_examples namespace hash_examples
{ {

View File

@ -21,7 +21,6 @@
#include <boost/container_hash/hash.hpp> #include <boost/container_hash/hash.hpp>
#include <boost/core/allocator_access.hpp> #include <boost/core/allocator_access.hpp>
#include <boost/core/serialization.hpp> #include <boost/core/serialization.hpp>
#include <boost/type_traits/type_identity.hpp>
#include <type_traits> #include <type_traits>
@ -65,9 +64,9 @@ namespace boost {
using init_type = typename type_policy::init_type; using init_type = typename type_policy::init_type;
using size_type = std::size_t; using size_type = std::size_t;
using difference_type = std::ptrdiff_t; using difference_type = std::ptrdiff_t;
using hasher = typename boost::type_identity<Hash>::type; using hasher = typename boost::unordered::detail::type_identity<Hash>::type;
using key_equal = typename boost::type_identity<Pred>::type; using key_equal = typename boost::unordered::detail::type_identity<Pred>::type;
using allocator_type = typename boost::type_identity<Allocator>::type; using allocator_type = typename boost::unordered::detail::type_identity<Allocator>::type;
using reference = value_type&; using reference = value_type&;
using const_reference = value_type const&; using const_reference = value_type const&;
using pointer = typename boost::allocator_pointer<allocator_type>::type; using pointer = typename boost::allocator_pointer<allocator_type>::type;
@ -757,8 +756,8 @@ namespace boost {
Allocator>; Allocator>;
template <class Key, class T, template <class Key, class T,
class Hash = boost::hash<boost::remove_const_t<Key> >, class Hash = boost::hash<std::remove_const_t<Key> >,
class Pred = std::equal_to<boost::remove_const_t<Key> >, class Pred = std::equal_to<std::remove_const_t<Key> >,
class Allocator = std::allocator<std::pair<const Key, T> >, class Allocator = std::allocator<std::pair<const Key, T> >,
class = boost::enable_if_t<detail::is_hash_v<Hash> >, 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_pred_v<Pred> >,
@ -766,7 +765,7 @@ namespace boost {
concurrent_flat_map(std::initializer_list<std::pair<Key, T> >, concurrent_flat_map(std::initializer_list<std::pair<Key, T> >,
std::size_t = boost::unordered::detail::foa::default_bucket_count, std::size_t = boost::unordered::detail::foa::default_bucket_count,
Hash = Hash(), Pred = Pred(), Allocator = Allocator()) Hash = Hash(), Pred = Pred(), Allocator = Allocator())
-> concurrent_flat_map<boost::remove_const_t<Key>, T, Hash, Pred, -> concurrent_flat_map<std::remove_const_t<Key>, T, Hash, Pred,
Allocator>; Allocator>;
template <class InputIterator, class Allocator, template <class InputIterator, class Allocator,
@ -806,23 +805,23 @@ namespace boost {
template <class Key, class T, class Allocator, template <class Key, class T, class Allocator,
class = boost::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, concurrent_flat_map(std::initializer_list<std::pair<Key, T> >, std::size_t,
Allocator) -> concurrent_flat_map<boost::remove_const_t<Key>, T, Allocator) -> concurrent_flat_map<std::remove_const_t<Key>, T,
boost::hash<boost::remove_const_t<Key> >, boost::hash<std::remove_const_t<Key> >,
std::equal_to<boost::remove_const_t<Key> >, Allocator>; std::equal_to<std::remove_const_t<Key> >, Allocator>;
template <class Key, class T, class Allocator, template <class Key, class T, class Allocator,
class = boost::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::initializer_list<std::pair<Key, T> >, Allocator)
-> concurrent_flat_map<boost::remove_const_t<Key>, T, -> concurrent_flat_map<std::remove_const_t<Key>, T,
boost::hash<boost::remove_const_t<Key> >, boost::hash<std::remove_const_t<Key> >,
std::equal_to<boost::remove_const_t<Key> >, Allocator>; std::equal_to<std::remove_const_t<Key> >, Allocator>;
template <class Key, class T, class Hash, class Allocator, template <class Key, class T, class Hash, class Allocator,
class = boost::enable_if_t<detail::is_hash_v<Hash> >, class = boost::enable_if_t<detail::is_hash_v<Hash> >,
class = boost::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, concurrent_flat_map(std::initializer_list<std::pair<Key, T> >, std::size_t,
Hash, Allocator) -> concurrent_flat_map<boost::remove_const_t<Key>, T, Hash, Allocator) -> concurrent_flat_map<std::remove_const_t<Key>, T,
Hash, std::equal_to<boost::remove_const_t<Key> >, Allocator>; Hash, std::equal_to<std::remove_const_t<Key> >, Allocator>;
#endif #endif

View File

@ -22,7 +22,6 @@
#include <boost/container_hash/hash.hpp> #include <boost/container_hash/hash.hpp>
#include <boost/core/allocator_access.hpp> #include <boost/core/allocator_access.hpp>
#include <boost/core/serialization.hpp> #include <boost/core/serialization.hpp>
#include <boost/type_traits/type_identity.hpp>
#include <utility> #include <utility>
@ -60,9 +59,9 @@ namespace boost {
using init_type = typename type_policy::init_type; using init_type = typename type_policy::init_type;
using size_type = std::size_t; using size_type = std::size_t;
using difference_type = std::ptrdiff_t; using difference_type = std::ptrdiff_t;
using hasher = typename boost::type_identity<Hash>::type; using hasher = typename boost::unordered::detail::type_identity<Hash>::type;
using key_equal = typename boost::type_identity<Pred>::type; using key_equal = typename boost::unordered::detail::type_identity<Pred>::type;
using allocator_type = typename boost::type_identity<Allocator>::type; using allocator_type = typename boost::unordered::detail::type_identity<Allocator>::type;
using reference = value_type&; using reference = value_type&;
using const_reference = value_type const&; using const_reference = value_type const&;
using pointer = typename boost::allocator_pointer<allocator_type>::type; using pointer = typename boost::allocator_pointer<allocator_type>::type;

View File

@ -9,13 +9,12 @@
#ifndef BOOST_UNORDERED_DETAIL_ARCHIVE_CONSTRUCTED_HPP #ifndef BOOST_UNORDERED_DETAIL_ARCHIVE_CONSTRUCTED_HPP
#define 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/config.hpp>
#include <boost/core/addressof.hpp>
#include <boost/core/no_exceptions_support.hpp> #include <boost/core/no_exceptions_support.hpp>
#include <boost/core/noncopyable.hpp> #include <boost/core/noncopyable.hpp>
#include <boost/core/serialization.hpp> #include <boost/core/serialization.hpp>
#include <boost/type_traits/aligned_storage.hpp>
#include <boost/type_traits/alignment_of.hpp>
namespace boost{ namespace boost{
namespace unordered{ namespace unordered{
@ -29,7 +28,7 @@ struct archive_constructed:private noncopyable
template<class Archive> template<class Archive>
archive_constructed(const char* name,Archive& ar,unsigned int version) archive_constructed(const char* name,Archive& ar,unsigned int version)
{ {
core::load_construct_data_adl(ar,boost::addressof(get()),version); core::load_construct_data_adl(ar,std::addressof(get()),version);
BOOST_TRY{ BOOST_TRY{
ar>>core::make_nvp(name,get()); ar>>core::make_nvp(name,get());
} }
@ -54,7 +53,7 @@ struct archive_constructed:private noncopyable
#pragma GCC diagnostic ignored "-Wstrict-aliasing" #pragma GCC diagnostic ignored "-Wstrict-aliasing"
#endif #endif
T& get(){return *reinterpret_cast<T*>(&space);} T& get(){return *space.address();}
#if defined(BOOST_UNORDERED_IGNORE_WSTRICT_ALIASING) #if defined(BOOST_UNORDERED_IGNORE_WSTRICT_ALIASING)
#pragma GCC diagnostic pop #pragma GCC diagnostic pop
@ -62,7 +61,7 @@ struct archive_constructed:private noncopyable
#endif #endif
private: private:
typename aligned_storage<sizeof(T),alignment_of<T>::value>::type space; opt_storage<T> space;
}; };
} /* namespace detail */ } /* namespace detail */

View File

@ -115,8 +115,9 @@ to normal separate chaining implementations.
#include <boost/unordered/detail/prime_fmod.hpp> #include <boost/unordered/detail/prime_fmod.hpp>
#include <boost/unordered/detail/serialize_tracked_address.hpp> #include <boost/unordered/detail/serialize_tracked_address.hpp>
#include <boost/unordered/detail/opt_storage.hpp>
#include <boost/core/addressof.hpp> #include <boost/assert.hpp>
#include <boost/core/allocator_access.hpp> #include <boost/core/allocator_access.hpp>
#include <boost/core/bit.hpp> #include <boost/core/bit.hpp>
#include <boost/core/empty_value.hpp> #include <boost/core/empty_value.hpp>
@ -124,10 +125,6 @@ to normal separate chaining implementations.
#include <boost/core/no_exceptions_support.hpp> #include <boost/core/no_exceptions_support.hpp>
#include <boost/core/serialization.hpp> #include <boost/core/serialization.hpp>
#include <boost/cstdint.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> #include <boost/config.hpp>
@ -144,19 +141,18 @@ namespace boost {
node>::type node_pointer; node>::type node_pointer;
node_pointer next; node_pointer next;
typename boost::aligned_storage<sizeof(value_type), opt_storage<value_type> buf;
boost::alignment_of<value_type>::value>::type buf;
node() BOOST_NOEXCEPT : next(), buf() {} node() noexcept : next(), buf() {}
value_type* value_ptr() BOOST_NOEXCEPT value_type* value_ptr() noexcept
{ {
return reinterpret_cast<value_type*>(buf.address()); return buf.address();
} }
value_type& value() BOOST_NOEXCEPT value_type& value() noexcept
{ {
return *reinterpret_cast<value_type*>(buf.address()); return *buf.address();
} }
}; };
@ -170,7 +166,7 @@ namespace boost {
node_pointer next; node_pointer next;
bucket() BOOST_NOEXCEPT : next() {} bucket() noexcept : next() {}
}; };
template <class Bucket> struct bucket_group template <class Bucket> struct bucket_group
@ -186,7 +182,7 @@ namespace boost {
std::size_t bitmask; std::size_t bitmask;
bucket_group_pointer next, prev; bucket_group_pointer next, prev;
bucket_group() BOOST_NOEXCEPT : buckets(), bitmask(0), next(), prev() {} bucket_group() noexcept : buckets(), bitmask(0), next(), prev() {}
~bucket_group() {} ~bucket_group() {}
}; };
@ -224,33 +220,28 @@ namespace boost {
public: public:
grouped_bucket_iterator() : p(), pbg() {} grouped_bucket_iterator() : p(), pbg() {}
reference operator*() const BOOST_NOEXCEPT { return dereference(); } reference operator*() const noexcept { return dereference(); }
pointer operator->() const BOOST_NOEXCEPT pointer operator->() const noexcept { return boost::to_address(p); }
{
return boost::to_address(p);
}
grouped_bucket_iterator& operator++() BOOST_NOEXCEPT grouped_bucket_iterator& operator++() noexcept
{ {
increment(); increment();
return *this; return *this;
} }
grouped_bucket_iterator operator++(int) BOOST_NOEXCEPT grouped_bucket_iterator operator++(int) noexcept
{ {
grouped_bucket_iterator old = *this; grouped_bucket_iterator old = *this;
increment(); increment();
return old; return old;
} }
bool operator==( bool operator==(grouped_bucket_iterator const& other) const noexcept
grouped_bucket_iterator const& other) const BOOST_NOEXCEPT
{ {
return equal(other); return equal(other);
} }
bool operator!=( bool operator!=(grouped_bucket_iterator const& other) const noexcept
grouped_bucket_iterator const& other) const BOOST_NOEXCEPT
{ {
return !equal(other); return !equal(other);
} }
@ -266,14 +257,14 @@ namespace boost {
{ {
} }
Bucket& dereference() const BOOST_NOEXCEPT { return *p; } Bucket& dereference() const noexcept { return *p; }
bool equal(const grouped_bucket_iterator& x) const BOOST_NOEXCEPT bool equal(const grouped_bucket_iterator& x) const noexcept
{ {
return p == x.p; return p == x.p;
} }
void increment() BOOST_NOEXCEPT void increment() noexcept
{ {
std::size_t const offset = static_cast<std::size_t>(p - pbg->buckets); std::size_t const offset = static_cast<std::size_t>(p - pbg->buckets);
@ -290,7 +281,7 @@ namespace boost {
} }
} }
template<typename Archive> template <typename Archive>
friend void serialization_track( friend void serialization_track(
Archive& ar, grouped_bucket_iterator const& x) Archive& ar, grouped_bucket_iterator const& x)
{ {
@ -301,8 +292,7 @@ namespace boost {
friend class boost::serialization::access; friend class boost::serialization::access;
template<typename Archive> template <typename Archive> void serialize(Archive& ar, unsigned int)
void serialize(Archive& ar,unsigned int)
{ {
// requires: not at end() position // requires: not at end() position
serialize_tracked_address(ar, p); serialize_tracked_address(ar, p);
@ -326,20 +316,17 @@ namespace boost {
grouped_local_bucket_iterator() : p() {} grouped_local_bucket_iterator() : p() {}
reference operator*() const BOOST_NOEXCEPT { return dereference(); } reference operator*() const noexcept { return dereference(); }
pointer operator->() const BOOST_NOEXCEPT pointer operator->() const noexcept { return boost::to_address(p); }
{
return boost::to_address(p);
}
grouped_local_bucket_iterator& operator++() BOOST_NOEXCEPT grouped_local_bucket_iterator& operator++() noexcept
{ {
increment(); increment();
return *this; return *this;
} }
grouped_local_bucket_iterator operator++(int) BOOST_NOEXCEPT grouped_local_bucket_iterator operator++(int) noexcept
{ {
grouped_local_bucket_iterator old = *this; grouped_local_bucket_iterator old = *this;
increment(); increment();
@ -347,13 +334,13 @@ namespace boost {
} }
bool operator==( bool operator==(
grouped_local_bucket_iterator const& other) const BOOST_NOEXCEPT grouped_local_bucket_iterator const& other) const noexcept
{ {
return equal(other); return equal(other);
} }
bool operator!=( bool operator!=(
grouped_local_bucket_iterator const& other) const BOOST_NOEXCEPT grouped_local_bucket_iterator const& other) const noexcept
{ {
return !equal(other); return !equal(other);
} }
@ -366,14 +353,14 @@ namespace boost {
grouped_local_bucket_iterator(node_pointer p_) : p(p_) {} grouped_local_bucket_iterator(node_pointer p_) : p(p_) {}
value_type& dereference() const BOOST_NOEXCEPT { return p->value(); } value_type& dereference() const noexcept { return p->value(); }
bool equal(const grouped_local_bucket_iterator& x) const BOOST_NOEXCEPT bool equal(const grouped_local_bucket_iterator& x) const noexcept
{ {
return p == x.p; return p == x.p;
} }
void increment() BOOST_NOEXCEPT { p = p->next; } void increment() noexcept { p = p->next; }
node_pointer p; node_pointer p;
}; };
@ -397,20 +384,17 @@ namespace boost {
{ {
} }
reference operator*() const BOOST_NOEXCEPT { return dereference(); } reference operator*() const noexcept { return dereference(); }
pointer operator->() const BOOST_NOEXCEPT pointer operator->() const noexcept { return boost::to_address(p); }
{
return boost::to_address(p);
}
const_grouped_local_bucket_iterator& operator++() BOOST_NOEXCEPT const_grouped_local_bucket_iterator& operator++() noexcept
{ {
increment(); increment();
return *this; return *this;
} }
const_grouped_local_bucket_iterator operator++(int) BOOST_NOEXCEPT const_grouped_local_bucket_iterator operator++(int) noexcept
{ {
const_grouped_local_bucket_iterator old = *this; const_grouped_local_bucket_iterator old = *this;
increment(); increment();
@ -418,13 +402,13 @@ namespace boost {
} }
bool operator==( bool operator==(
const_grouped_local_bucket_iterator const& other) const BOOST_NOEXCEPT const_grouped_local_bucket_iterator const& other) const noexcept
{ {
return equal(other); return equal(other);
} }
bool operator!=( bool operator!=(
const_grouped_local_bucket_iterator const& other) const BOOST_NOEXCEPT const_grouped_local_bucket_iterator const& other) const noexcept
{ {
return !equal(other); return !equal(other);
} }
@ -435,23 +419,22 @@ namespace boost {
const_grouped_local_bucket_iterator(node_pointer p_) : p(p_) {} const_grouped_local_bucket_iterator(node_pointer p_) : p(p_) {}
value_type& dereference() const BOOST_NOEXCEPT { return p->value(); } value_type& dereference() const noexcept { return p->value(); }
bool equal( bool equal(const const_grouped_local_bucket_iterator& x) const noexcept
const const_grouped_local_bucket_iterator& x) const BOOST_NOEXCEPT
{ {
return p == x.p; return p == x.p;
} }
void increment() BOOST_NOEXCEPT { p = p->next; } void increment() noexcept { p = p->next; }
node_pointer p; node_pointer p;
}; };
template <class T> struct span template <class T> struct span
{ {
T* begin() const BOOST_NOEXCEPT { return data; } T* begin() const noexcept { return data; }
T* end() const BOOST_NOEXCEPT { return data + size; } T* end() const noexcept { return data + size; }
T* data; T* data;
std::size_t size; std::size_t size;
@ -466,8 +449,6 @@ namespace boost {
typename boost::allocator_void_pointer<Allocator>::type> >:: typename boost::allocator_void_pointer<Allocator>::type> >::
type> type>
{ {
BOOST_MOVABLE_BUT_NOT_COPYABLE(grouped_bucket_array)
typedef typename boost::allocator_value_type<Allocator>::type typedef typename boost::allocator_value_type<Allocator>::type
allocator_value_type; allocator_value_type;
typedef typedef
@ -532,8 +513,7 @@ namespace boost {
grouped_bucket_array(size_type n, const Allocator& al) grouped_bucket_array(size_type n, const Allocator& al)
: empty_value<node_allocator_type>(empty_init_t(), al), : empty_value<node_allocator_type>(empty_init_t(), al),
size_index_(0), size_index_(0), size_(0), buckets(), groups()
size_(0), buckets(), groups()
{ {
if (n == 0) { if (n == 0) {
return; return;
@ -582,8 +562,10 @@ namespace boost {
~grouped_bucket_array() { this->deallocate(); } ~grouped_bucket_array() { this->deallocate(); }
grouped_bucket_array( grouped_bucket_array(grouped_bucket_array const&) = delete;
BOOST_RV_REF(grouped_bucket_array) other) BOOST_NOEXCEPT grouped_bucket_array& operator=(grouped_bucket_array const&) = delete;
grouped_bucket_array(grouped_bucket_array&& other) noexcept
: empty_value<node_allocator_type>( : empty_value<node_allocator_type>(
empty_init_t(), other.get_node_allocator()), empty_init_t(), other.get_node_allocator()),
size_index_(other.size_index_), size_index_(other.size_index_),
@ -597,13 +579,12 @@ namespace boost {
other.groups = group_pointer(); other.groups = group_pointer();
} }
grouped_bucket_array& operator=( grouped_bucket_array& operator=(grouped_bucket_array&& other) noexcept
BOOST_RV_REF(grouped_bucket_array) other) BOOST_NOEXCEPT
{ {
BOOST_ASSERT( BOOST_ASSERT(
this->get_node_allocator() == other.get_node_allocator()); this->get_node_allocator() == other.get_node_allocator());
if (this == boost::addressof(other)) { if (this == std::addressof(other)) {
return *this; return *this;
} }
@ -622,7 +603,7 @@ namespace boost {
return *this; return *this;
} }
void deallocate() BOOST_NOEXCEPT void deallocate() noexcept
{ {
if (buckets) { if (buckets) {
bucket_allocator_type bucket_alloc = this->get_bucket_allocator(); bucket_allocator_type bucket_alloc = this->get_bucket_allocator();
@ -651,7 +632,8 @@ namespace boost {
bool b = boost::allocator_propagate_on_container_swap< bool b = boost::allocator_propagate_on_container_swap<
allocator_type>::type::value; allocator_type>::type::value;
if (b) { if (b) {
boost::core::invoke_swap(get_node_allocator(), other.get_node_allocator()); boost::core::invoke_swap(
get_node_allocator(), other.get_node_allocator());
} }
} }
@ -675,12 +657,9 @@ namespace boost {
return this->get_node_allocator(); return this->get_node_allocator();
} }
size_type buckets_len() const BOOST_NOEXCEPT { return size_ + 1; } size_type buckets_len() const noexcept { return size_ + 1; }
size_type groups_len() const BOOST_NOEXCEPT size_type groups_len() const noexcept { return size_ / group::N + 1; }
{
return size_ / group::N + 1;
}
void reset_allocator(Allocator const& allocator_) void reset_allocator(Allocator const& allocator_)
{ {
@ -713,7 +692,7 @@ namespace boost {
local_iterator end(size_type) const { return local_iterator(); } local_iterator end(size_type) const { return local_iterator(); }
size_type capacity() const BOOST_NOEXCEPT { return size_; } size_type capacity() const noexcept { return size_; }
iterator at(size_type n) const iterator at(size_type n) const
{ {
@ -747,7 +726,7 @@ namespace boost {
size_ = 0; size_ = 0;
} }
void append_bucket_group(iterator itb) BOOST_NOEXCEPT void append_bucket_group(iterator itb) noexcept
{ {
std::size_t const N = group::N; std::size_t const N = group::N;
@ -777,7 +756,7 @@ namespace boost {
} }
} }
void insert_node(iterator itb, node_pointer p) BOOST_NOEXCEPT void insert_node(iterator itb, node_pointer p) noexcept
{ {
this->append_bucket_group(itb); this->append_bucket_group(itb);
@ -786,7 +765,7 @@ namespace boost {
} }
void insert_node_hint( void insert_node_hint(
iterator itb, node_pointer p, node_pointer hint) BOOST_NOEXCEPT iterator itb, node_pointer p, node_pointer hint) noexcept
{ {
this->append_bucket_group(itb); this->append_bucket_group(itb);
@ -799,24 +778,24 @@ namespace boost {
} }
} }
void extract_node(iterator itb, node_pointer p) BOOST_NOEXCEPT void extract_node(iterator itb, node_pointer p) noexcept
{ {
node_pointer* pp = boost::addressof(itb->next); node_pointer* pp = std::addressof(itb->next);
while ((*pp) != p) while ((*pp) != p)
pp = boost::addressof((*pp)->next); pp = std::addressof((*pp)->next);
*pp = p->next; *pp = p->next;
if (!itb->next) if (!itb->next)
unlink_bucket(itb); unlink_bucket(itb);
} }
void extract_node_after(iterator itb, node_pointer* pp) BOOST_NOEXCEPT void extract_node_after(iterator itb, node_pointer* pp) noexcept
{ {
*pp = (*pp)->next; *pp = (*pp)->next;
if (!itb->next) if (!itb->next)
unlink_bucket(itb); unlink_bucket(itb);
} }
void unlink_empty_buckets() BOOST_NOEXCEPT void unlink_empty_buckets() noexcept
{ {
std::size_t const N = group::N; std::size_t const N = group::N;
@ -864,7 +843,7 @@ namespace boost {
} }
}; };
} // namespace detail } // namespace detail
} // namespace unordered } // namespace unordered
} // namespace boost } // namespace boost
#endif // BOOST_UNORDERED_DETAIL_FCA_HPP #endif // BOOST_UNORDERED_DETAIL_FCA_HPP

View File

@ -19,7 +19,6 @@
#include <boost/core/serialization.hpp> #include <boost/core/serialization.hpp>
#include <boost/cstdint.hpp> #include <boost/cstdint.hpp>
#include <boost/mp11/tuple.hpp> #include <boost/mp11/tuple.hpp>
#include <boost/static_assert.hpp>
#include <boost/throw_exception.hpp> #include <boost/throw_exception.hpp>
#include <boost/unordered/detail/archive_constructed.hpp> #include <boost/unordered/detail/archive_constructed.hpp>
#include <boost/unordered/detail/bad_archive_exception.hpp> #include <boost/unordered/detail/bad_archive_exception.hpp>
@ -28,6 +27,7 @@
#include <boost/unordered/detail/foa/rw_spinlock.hpp> #include <boost/unordered/detail/foa/rw_spinlock.hpp>
#include <boost/unordered/detail/foa/tuple_rotate_right.hpp> #include <boost/unordered/detail/foa/tuple_rotate_right.hpp>
#include <boost/unordered/detail/serialization_version.hpp> #include <boost/unordered/detail/serialization_version.hpp>
#include <boost/unordered/detail/static_assert.hpp>
#include <cstddef> #include <cstddef>
#include <functional> #include <functional>
#include <initializer_list> #include <initializer_list>
@ -88,7 +88,7 @@ private:
static constexpr std::size_t element_offset= static constexpr std::size_t element_offset=
(sizeof(T)+cacheline_size-1)/cacheline_size*cacheline_size; (sizeof(T)+cacheline_size-1)/cacheline_size*cacheline_size;
BOOST_STATIC_ASSERT(alignof(T)<=cacheline_size); BOOST_UNORDERED_STATIC_ASSERT(alignof(T)<=cacheline_size);
T* data(std::size_t pos)noexcept T* data(std::size_t pos)noexcept
{ {
@ -126,7 +126,7 @@ template<typename Mutex>
class shared_lock class shared_lock
{ {
public: 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();} ~shared_lock()noexcept{if(owns)m.unlock_shared();}
/* not used but VS in pre-C++17 mode needs to see it for RVO */ /* not used but VS in pre-C++17 mode needs to see it for RVO */
@ -148,7 +148,7 @@ template<typename Mutex>
class lock_guard class lock_guard
{ {
public: public:
lock_guard(Mutex& m_)noexcept:m{m_}{m.lock();} lock_guard(Mutex& m_)noexcept:m(m_){m.lock();}
~lock_guard()noexcept{m.unlock();} ~lock_guard()noexcept{m.unlock();}
/* not used but VS in pre-C++17 mode needs to see it for RVO */ /* not used but VS in pre-C++17 mode needs to see it for RVO */
@ -341,7 +341,7 @@ struct concurrent_table_arrays:table_arrays<Value,Group,SizePolicy,Allocator>
struct atomic_size_control struct atomic_size_control
{ {
static constexpr auto atomic_size_t_size=sizeof(std::atomic<std::size_t>); static constexpr auto atomic_size_t_size=sizeof(std::atomic<std::size_t>);
BOOST_STATIC_ASSERT(atomic_size_t_size<cacheline_size); BOOST_UNORDERED_STATIC_ASSERT(atomic_size_t_size<cacheline_size);
atomic_size_control(std::size_t ml_,std::size_t size_): atomic_size_control(std::size_t ml_,std::size_t size_):
pad0_{},ml{ml_},pad1_{},size{size_}{} pad0_{},ml{ml_},pad1_{},size{size_}{}
@ -1029,7 +1029,7 @@ private:
erase_on_exit( erase_on_exit(
concurrent_table& x_, concurrent_table& x_,
group_type* pg_,unsigned int pos_,element_type* p_): 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);} ~erase_on_exit(){if(!rollback_)x.super::erase(pg,pos,p);}
void rollback(){rollback_=true;} void rollback(){rollback_=true;}
@ -1283,7 +1283,7 @@ private:
struct reserve_size struct reserve_size
{ {
reserve_size(concurrent_table& x_):x{x_} reserve_size(concurrent_table& x_):x(x_)
{ {
size_=++x.size_ctrl.size; size_=++x.size_ctrl.size;
} }

View File

@ -22,13 +22,10 @@
#include <boost/core/pointer_traits.hpp> #include <boost/core/pointer_traits.hpp>
#include <boost/cstdint.hpp> #include <boost/cstdint.hpp>
#include <boost/predef.h> #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/narrow_cast.hpp>
#include <boost/unordered/detail/mulx.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 <boost/unordered/hash_traits.hpp>
#include <climits> #include <climits>
#include <cmath> #include <cmath>
@ -133,10 +130,10 @@
#define BOOST_UNORDERED_THREAD_SANITIZER #define BOOST_UNORDERED_THREAD_SANITIZER
#endif #endif
#define BOOST_UNORDERED_STATIC_ASSERT_HASH_PRED(Hash, Pred) \ #define BOOST_UNORDERED_STATIC_ASSERT_HASH_PRED(Hash, Pred) \
static_assert(boost::is_nothrow_swappable<Hash>::value, \ static_assert(boost::unordered::detail::is_nothrow_swappable<Hash>::value, \
"Template parameter Hash is required to be nothrow Swappable."); \ "Template parameter Hash is required to be nothrow Swappable."); \
static_assert(boost::is_nothrow_swappable<Pred>::value, \ static_assert(boost::unordered::detail::is_nothrow_swappable<Pred>::value, \
"Template parameter Pred is required to be nothrow Swappable"); "Template parameter Pred is required to be nothrow Swappable");
namespace boost{ namespace boost{
@ -311,7 +308,7 @@ struct group15
private: private:
using slot_type=IntegralWrapper<unsigned char>; using slot_type=IntegralWrapper<unsigned char>;
BOOST_STATIC_ASSERT(sizeof(slot_type)==1); BOOST_UNORDERED_STATIC_ASSERT(sizeof(slot_type)==1);
static constexpr unsigned char available_=0, static constexpr unsigned char available_=0,
sentinel_=1; sentinel_=1;
@ -514,7 +511,7 @@ struct group15
private: private:
using slot_type=IntegralWrapper<unsigned char>; using slot_type=IntegralWrapper<unsigned char>;
BOOST_STATIC_ASSERT(sizeof(slot_type)==1); BOOST_UNORDERED_STATIC_ASSERT(sizeof(slot_type)==1);
static constexpr unsigned char available_=0, static constexpr unsigned char available_=0,
sentinel_=1; sentinel_=1;
@ -707,7 +704,7 @@ struct group15
private: private:
using word_type=IntegralWrapper<uint64_t>; using word_type=IntegralWrapper<uint64_t>;
BOOST_STATIC_ASSERT(sizeof(word_type)==8); BOOST_UNORDERED_STATIC_ASSERT(sizeof(word_type)==8);
static constexpr unsigned char available_=0, static constexpr unsigned char available_=0,
sentinel_=1; sentinel_=1;
@ -1045,15 +1042,7 @@ struct table_arrays
initialize_groups( initialize_groups(
arrays.groups(),groups_size, arrays.groups(),groups_size,
std::integral_constant< is_trivially_default_constructible<group_type>{});
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(); arrays.groups()[groups_size-1].set_sentinel();
} }
@ -2026,13 +2015,7 @@ private:
x, x,
std::integral_constant< std::integral_constant<
bool, bool,
#if BOOST_WORKAROUND(BOOST_LIBSTDCXX_VERSION,<50000) is_trivially_copy_constructible<element_type>::value&&(
/* 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|| is_std_allocator<Allocator>::value||
!alloc_has_construct<Allocator,value_type*,const value_type&>::value) !alloc_has_construct<Allocator,value_type*,const value_type&>::value)
>{} >{}
@ -2074,15 +2057,7 @@ private:
} }
void copy_groups_array_from(const table_core& x) { void copy_groups_array_from(const table_core& x) {
copy_groups_array_from(x, std::integral_constant<bool, copy_groups_array_from(x,is_trivially_copy_assignable<group_type>{});
#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( void copy_groups_array_from(

View File

@ -9,6 +9,8 @@
#ifndef BOOST_UNORDERED_DETAIL_FOA_NODE_HANDLE_HPP #ifndef BOOST_UNORDERED_DETAIL_FOA_NODE_HANDLE_HPP
#define 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/config.hpp>
#include <boost/core/allocator_access.hpp> #include <boost/core/allocator_access.hpp>
@ -25,14 +27,6 @@ struct insert_return_type
NodeType node; NodeType node;
}; };
template <class T>
union opt_storage {
BOOST_ATTRIBUTE_NO_UNIQUE_ADDRESS T t_;
opt_storage(){}
~opt_storage(){}
};
template <class TypePolicy,class Allocator> template <class TypePolicy,class Allocator>
struct node_handle_base struct node_handle_base
{ {

View File

@ -106,7 +106,7 @@ public:
using element_type= using element_type=
typename std::conditional<Const,value_type const,value_type>::type; typename std::conditional<Const,value_type const,value_type>::type;
table_iterator()=default; table_iterator():pc_{nullptr},p_{nullptr}{};
template<bool Const2,typename std::enable_if<!Const2>::type* =nullptr> template<bool Const2,typename std::enable_if<!Const2>::type* =nullptr>
table_iterator(const table_iterator<TypePolicy,GroupPtr,Const2>& x): table_iterator(const table_iterator<TypePolicy,GroupPtr,Const2>& x):
pc_{x.pc_},p_{x.p_}{} pc_{x.pc_},p_{x.p_}{}
@ -133,10 +133,10 @@ private:
template<typename> friend class table_erase_return_type; template<typename> friend class table_erase_return_type;
template<typename,typename,typename,typename> friend class table; template<typename,typename,typename,typename> friend class table;
table_iterator(group_type* pg,std::size_t n,const table_element_type* p): table_iterator(group_type* pg,std::size_t n,const table_element_type* ptet):
pc_{to_pointer<char_pointer>( pc_{to_pointer<char_pointer>(
reinterpret_cast<unsigned char*>(const_cast<group_type*>(pg))+n)}, reinterpret_cast<unsigned char*>(const_cast<group_type*>(pg))+n)},
p_{to_pointer<table_element_pointer>(const_cast<table_element_type*>(p))} p_{to_pointer<table_element_pointer>(const_cast<table_element_type*>(ptet))}
{} {}
unsigned char* pc()const noexcept{return boost::to_address(pc_);} unsigned char* pc()const noexcept{return boost::to_address(pc_);}
@ -568,7 +568,7 @@ private:
struct erase_on_exit 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);} ~erase_on_exit(){if(!rollback_)x.erase(it);}
void rollback(){rollback_=true;} void rollback(){rollback_=true;}

View File

@ -1,150 +0,0 @@
// 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

View File

@ -9,21 +9,21 @@
#ifndef BOOST_UNORDERED_DETAIL_NARROW_CAST_HPP #ifndef BOOST_UNORDERED_DETAIL_NARROW_CAST_HPP
#define 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 <boost/config.hpp>
#include <boost/static_assert.hpp> #include <type_traits>
#include <boost/type_traits/is_integral.hpp>
#include <boost/type_traits/make_unsigned.hpp>
namespace boost{ namespace boost{
namespace unordered{ namespace unordered{
namespace detail{ namespace detail{
template<typename To,typename From> template<typename To,typename From>
BOOST_CONSTEXPR To narrow_cast(From x) BOOST_NOEXCEPT constexpr To narrow_cast(From x) noexcept
{ {
BOOST_STATIC_ASSERT(boost::is_integral<From>::value); BOOST_UNORDERED_STATIC_ASSERT(std::is_integral<From>::value);
BOOST_STATIC_ASSERT(boost::is_integral<To>::value); BOOST_UNORDERED_STATIC_ASSERT(std::is_integral<To>::value);
BOOST_STATIC_ASSERT(sizeof(From)>=sizeof(To)); BOOST_UNORDERED_STATIC_ASSERT(sizeof(From)>=sizeof(To));
return static_cast<To>( return static_cast<To>(
x x
@ -32,7 +32,7 @@ BOOST_CONSTEXPR To narrow_cast(From x) BOOST_NOEXCEPT
/* Avoids VS's "Run-Time Check Failure #1 - A cast to a smaller data type /* Avoids VS's "Run-Time Check Failure #1 - A cast to a smaller data type
* has caused a loss of data." * has caused a loss of data."
*/ */
&static_cast<typename boost::make_unsigned<To>::type>(~static_cast<To>(0)) &static_cast<typename std::make_unsigned<To>::type>(~static_cast<To>(0))
#endif #endif
); );
} }

View File

@ -0,0 +1,30 @@
// 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

View File

@ -1,5 +1,5 @@
// Copyright (C) 2022 Joaquin M Lopez Munoz. // Copyright (C) 2022 Joaquin M Lopez Munoz.
// Copyright (C) 2022 Christian Mazakas // Copyright (C) 2022-2023 Christian Mazakas
// //
// Distributed under the Boost Software License, Version 1.0. (See accompanying // 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) // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@ -7,13 +7,10 @@
#ifndef BOOST_UNORDERED_DETAIL_PRIME_FMOD_HPP #ifndef BOOST_UNORDERED_DETAIL_PRIME_FMOD_HPP
#define 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/unordered/detail/narrow_cast.hpp>
#include <boost/config.hpp> #include <boost/config.hpp>
#include <boost/cstdint.hpp>
#include <climits> #include <climits>
#include <cstddef> #include <cstddef>
@ -37,21 +34,90 @@ namespace boost {
namespace detail { namespace detail {
template <class = void> struct prime_fmod_size template <class = void> struct prime_fmod_size
{ {
// Because we compile for C++03, we don't have access to any inline constexpr static std::size_t const sizes[] = {13ul, 29ul, 53ul, 97ul,
// initialization for array data members so the definitions must exist 193ul, 389ul, 769ul, 1543ul, 3079ul, 6151ul, 12289ul, 24593ul,
// out-of-line. To keep the library header-only, we introduce a dummy 49157ul, 98317ul, 196613ul, 393241ul, 786433ul, 1572869ul, 3145739ul,
// template parameter which permits the definition to be included in 6291469ul, 12582917ul, 25165843ul, 50331653ul, 100663319ul,
// multiple TUs without conflict. 201326611ul, 402653189ul, 805306457ul, 1610612741ul, 3221225473ul,
// #if !defined(BOOST_UNORDERED_FCA_HAS_64B_SIZE_T)
static std::size_t sizes[]; 4294967291ul
static std::size_t const sizes_len; #else
static std::size_t (*positions[])(std::size_t); 6442450939ull, 12884901893ull, 25769803751ull, 51539607551ull,
103079215111ull, 206158430209ull, 412316860441ull, 824633720831ull,
1649267441651ull
#endif
};
constexpr static std::size_t const sizes_len =
sizeof(sizes) / sizeof(sizes[0]);
#if defined(BOOST_UNORDERED_FCA_HAS_64B_SIZE_T) #if defined(BOOST_UNORDERED_FCA_HAS_64B_SIZE_T)
static boost::uint64_t inv_sizes32[]; constexpr static boost::uint64_t const inv_sizes32[] = {
static std::size_t const inv_sizes32_len; 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]);
#endif /* defined(BOOST_UNORDERED_FCA_HAS_64B_SIZE_T) */ #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) static inline std::size_t size_index(std::size_t n)
{ {
std::size_t i = 0; std::size_t i = 0;
@ -68,11 +134,6 @@ namespace boost {
return sizes[size_index]; 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) #if defined(BOOST_UNORDERED_FCA_HAS_64B_SIZE_T)
// We emulate the techniques taken from: // We emulate the techniques taken from:
// Faster Remainder by Direct Computation: Applications to Compilers and // Faster Remainder by Direct Computation: Applications to Compilers and
@ -118,8 +179,8 @@ namespace boost {
#if defined(BOOST_UNORDERED_FCA_HAS_64B_SIZE_T) #if defined(BOOST_UNORDERED_FCA_HAS_64B_SIZE_T)
std::size_t sizes_under_32bit = inv_sizes32_len; std::size_t sizes_under_32bit = inv_sizes32_len;
if (BOOST_LIKELY(size_index < sizes_under_32bit)) { if (BOOST_LIKELY(size_index < sizes_under_32bit)) {
return fast_modulo( return fast_modulo(narrow_cast<boost::uint32_t>(hash) +
narrow_cast<boost::uint32_t>(hash) + narrow_cast<boost::uint32_t>(hash >> 32), narrow_cast<boost::uint32_t>(hash >> 32),
inv_sizes32[size_index], boost::uint32_t(sizes[size_index])); inv_sizes32[size_index], boost::uint32_t(sizes[size_index]));
} else { } else {
return positions[size_index - sizes_under_32bit](hash); return positions[size_index - sizes_under_32bit](hash);
@ -130,134 +191,24 @@ namespace boost {
} }
}; // prime_fmod_size }; // prime_fmod_size
#define BOOST_UNORDERED_PRIME_FMOD_SIZES_32BIT_INCOMPLETE \ #if defined(BOOST_NO_CXX17_INLINE_VARIABLES)
(13ul)(29ul)(53ul)(97ul)(193ul)(389ul)(769ul)(1543ul)(3079ul)(6151ul)( \ // https://en.cppreference.com/w/cpp/language/static#Constant_static_members
12289ul)(24593ul)(49157ul)(98317ul)(196613ul)(393241ul)(786433ul)( \ // If a const non-inline (since C++17) static data member or a constexpr
1572869ul)(3145739ul)(6291469ul)(12582917ul)(25165843ul)(50331653ul)( \ // static data member (since C++11)(until C++17) is odr-used, a definition
100663319ul)(201326611ul)(402653189ul)(805306457ul)(1610612741ul)( \ // at namespace scope is still required, but it cannot have an
3221225473ul) // initializer.
template <class T> constexpr std::size_t prime_fmod_size<T>::sizes[];
#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) #if defined(BOOST_UNORDERED_FCA_HAS_64B_SIZE_T)
// 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> template <class T>
std::size_t const constexpr boost::uint64_t prime_fmod_size<T>::inv_sizes32[];
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 #endif
};
#undef BOOST_UNORDERED_PRIME_FMOD_POSITIONS_ELEMENT template <class T>
#undef BOOST_UNORDERED_PRIME_FMOD_SIZES constexpr std::size_t (*prime_fmod_size<T>::positions[])(std::size_t);
#undef BOOST_UNORDERED_PRIME_FMOD_SIZES_64BIT #endif
#undef BOOST_UNORDERED_PRIME_FMOD_SIZES_32BIT
#undef BOOST_UNORDERED_PRIME_FMOD_SIZES_32BIT_INCOMPLETE
} // namespace detail } // namespace detail
} // namespace unordered } // namespace unordered
} // namespace boost } // namespace boost
#endif // BOOST_UNORDERED_DETAIL_PRIME_FMOD_HPP #endif // BOOST_UNORDERED_DETAIL_PRIME_FMOD_HPP

View File

@ -1,21 +0,0 @@
#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

View File

@ -9,12 +9,8 @@
#ifndef BOOST_UNORDERED_DETAIL_SERIALIZE_CONTAINER_HPP #ifndef BOOST_UNORDERED_DETAIL_SERIALIZE_CONTAINER_HPP
#define 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/core/serialization.hpp>
#include <boost/move/move.hpp>
#include <boost/throw_exception.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/archive_constructed.hpp>
#include <boost/unordered/detail/bad_archive_exception.hpp> #include <boost/unordered/detail/bad_archive_exception.hpp>
#include <boost/unordered/detail/serialization_version.hpp> #include <boost/unordered/detail/serialization_version.hpp>
@ -66,7 +62,7 @@ template<typename Set> struct load_or_save_unordered_set<Set,true> /* save */
ar<<core::make_nvp("value_version",value_version); ar<<core::make_nvp("value_version",value_version);
for(const_iterator first=x.begin(),last=x.end();first!=last;++first){ for(const_iterator first=x.begin(),last=x.end();first!=last;++first){
core::save_construct_data_adl(ar,boost::addressof(*first),value_version); core::save_construct_data_adl(ar,std::addressof(*first),value_version);
ar<<core::make_nvp("item",*first); ar<<core::make_nvp("item",*first);
serialization_track(ar,first); serialization_track(ar,first);
} }
@ -94,10 +90,10 @@ template<typename Set> struct load_or_save_unordered_set<Set,false> /* load */
archive_constructed<value_type> value("item",ar,value_version); archive_constructed<value_type> value("item",ar,value_version);
std::pair<iterator,bool> p=adapt_insert_return_type( std::pair<iterator,bool> p=adapt_insert_return_type(
x.insert(boost::move(value.get()))); x.insert(std::move(value.get())));
if(!p.second)throw_exception(bad_archive_exception()); if(!p.second)throw_exception(bad_archive_exception());
ar.reset_object_address( ar.reset_object_address(
boost::addressof(*p.first),boost::addressof(value.get())); std::addressof(*p.first),std::addressof(value.get()));
serialization_track(ar,p.first); serialization_track(ar,p.first);
} }
} }
@ -110,9 +106,9 @@ template<typename Map> struct load_or_save_unordered_map<Map,true> /* save */
template<typename Archive> template<typename Archive>
void operator()(Archive& ar,const Map& x,unsigned int)const void operator()(Archive& ar,const Map& x,unsigned int)const
{ {
typedef typename boost::remove_const< typedef typename std::remove_const<
typename Map::key_type>::type key_type; typename Map::key_type>::type key_type;
typedef typename boost::remove_const< typedef typename std::remove_const<
typename Map::mapped_type>::type mapped_type; typename Map::mapped_type>::type mapped_type;
typedef typename Map::const_iterator const_iterator; typedef typename Map::const_iterator const_iterator;
@ -132,10 +128,10 @@ template<typename Map> struct load_or_save_unordered_map<Map,true> /* save */
*/ */
core::save_construct_data_adl( core::save_construct_data_adl(
ar,boost::addressof(first->first),key_version); ar,std::addressof(first->first),key_version);
ar<<core::make_nvp("key",first->first); ar<<core::make_nvp("key",first->first);
core::save_construct_data_adl( core::save_construct_data_adl(
ar,boost::addressof(first->second),mapped_version); ar,std::addressof(first->second),mapped_version);
ar<<core::make_nvp("mapped",first->second); ar<<core::make_nvp("mapped",first->second);
serialization_track(ar,first); serialization_track(ar,first);
} }
@ -147,9 +143,9 @@ template<typename Map> struct load_or_save_unordered_map<Map,false> /* load */
template<typename Archive> template<typename Archive>
void operator()(Archive& ar,Map& x,unsigned int)const void operator()(Archive& ar,Map& x,unsigned int)const
{ {
typedef typename boost::remove_const< typedef typename std::remove_const<
typename Map::key_type>::type key_type; typename Map::key_type>::type key_type;
typedef typename boost::remove_const< typedef typename std::remove_const<
typename Map::mapped_type>::type mapped_type; typename Map::mapped_type>::type mapped_type;
typedef typename Map::iterator iterator; typedef typename Map::iterator iterator;
@ -169,12 +165,12 @@ template<typename Map> struct load_or_save_unordered_map<Map,false> /* load */
archive_constructed<mapped_type> mapped("mapped",ar,mapped_version); archive_constructed<mapped_type> mapped("mapped",ar,mapped_version);
std::pair<iterator,bool> p=adapt_insert_return_type( std::pair<iterator,bool> p=adapt_insert_return_type(
x.emplace(boost::move(key.get()),boost::move(mapped.get()))); x.emplace(std::move(key.get()),std::move(mapped.get())));
if(!p.second)throw_exception(bad_archive_exception()); if(!p.second)throw_exception(bad_archive_exception());
ar.reset_object_address( ar.reset_object_address(
boost::addressof(p.first->first),boost::addressof(key.get())); std::addressof(p.first->first),std::addressof(key.get()));
ar.reset_object_address( ar.reset_object_address(
boost::addressof(p.first->second),boost::addressof(mapped.get())); std::addressof(p.first->second),std::addressof(mapped.get()));
serialization_track(ar,p.first); serialization_track(ar,p.first);
} }
} }
@ -196,7 +192,7 @@ void serialize_container(Archive& ar,Container& x,unsigned int version)
{ {
load_or_save_container< load_or_save_container<
Container, Container,
boost::is_same< std::is_same<
typename Container::key_type,typename Container::value_type>::value, typename Container::key_type,typename Container::value_type>::value,
Archive::is_saving::value>()(ar,x,version); Archive::is_saving::value>()(ar,x,version);
} }

View File

@ -9,12 +9,13 @@
#ifndef BOOST_UNORDERED_DETAIL_SERIALIZE_TRACKED_ADDRESS_HPP #ifndef BOOST_UNORDERED_DETAIL_SERIALIZE_TRACKED_ADDRESS_HPP
#define 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/pointer_traits.hpp>
#include <boost/core/serialization.hpp> #include <boost/core/serialization.hpp>
#include <boost/throw_exception.hpp> #include <boost/throw_exception.hpp>
#include <boost/type_traits/remove_const.hpp>
#include <boost/type_traits/integral_constant.hpp> #include <type_traits>
#include <boost/unordered/detail/bad_archive_exception.hpp>
namespace boost{ namespace boost{
namespace unordered{ namespace unordered{
@ -44,7 +45,7 @@ template<typename Archive,typename Ptr>
void track_address(Archive& ar,Ptr p) void track_address(Archive& ar,Ptr p)
{ {
typedef typename boost::pointer_traits<Ptr> ptr_traits; typedef typename boost::pointer_traits<Ptr> ptr_traits;
typedef typename boost::remove_const< typedef typename std::remove_const<
typename ptr_traits::element_type>::type element_type; typename ptr_traits::element_type>::type element_type;
if(p){ if(p){
@ -57,10 +58,10 @@ void track_address(Archive& ar,Ptr p)
} }
template<typename Archive,typename Ptr> template<typename Archive,typename Ptr>
void serialize_tracked_address(Archive& ar,Ptr& p,boost::true_type /* save */) void serialize_tracked_address(Archive& ar,Ptr& p,std::true_type /* save */)
{ {
typedef typename boost::pointer_traits<Ptr> ptr_traits; typedef typename boost::pointer_traits<Ptr> ptr_traits;
typedef typename boost::remove_const< typedef typename std::remove_const<
typename ptr_traits::element_type>::type element_type; typename ptr_traits::element_type>::type element_type;
typedef serialization_tracker<element_type> tracker; typedef serialization_tracker<element_type> tracker;
@ -73,10 +74,10 @@ void serialize_tracked_address(Archive& ar,Ptr& p,boost::true_type /* save */)
} }
template<typename Archive,typename Ptr> template<typename Archive,typename Ptr>
void serialize_tracked_address(Archive& ar,Ptr& p,boost::false_type /* load */) void serialize_tracked_address(Archive& ar,Ptr& p,std::false_type /* load */)
{ {
typedef typename boost::pointer_traits<Ptr> ptr_traits; typedef typename boost::pointer_traits<Ptr> ptr_traits;
typedef typename boost::remove_const< typedef typename std::remove_const<
typename ptr_traits::element_type>::type element_type; typename ptr_traits::element_type>::type element_type;
typedef serialization_tracker<element_type> tracker; typedef serialization_tracker<element_type> tracker;
@ -93,7 +94,7 @@ void serialize_tracked_address(Archive& ar,Ptr& p)
{ {
serialize_tracked_address( serialize_tracked_address(
ar,p, ar,p,
boost::integral_constant<bool,Archive::is_saving::value>()); std::integral_constant<bool,Archive::is_saving::value>());
} }
} /* namespace detail */ } /* namespace detail */

View File

@ -0,0 +1,16 @@
// 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

View File

@ -1,4 +1,4 @@
// Copyright (C) 2022 Christian Mazakas // Copyright (C) 2022-2023 Christian Mazakas
// //
// Distributed under the Boost Software License, Version 1.0. (See accompanying // 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) // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@ -11,20 +11,15 @@
#pragma once #pragma once
#endif #endif
#include <boost/type_traits/integral_constant.hpp> #include <boost/config/workaround.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) #if !defined(BOOST_NO_CXX17_DEDUCTION_GUIDES)
#include <boost/type_traits/enable_if.hpp>
#include <boost/type_traits/is_integral.hpp>
#include <boost/type_traits/remove_const.hpp>
#include <iterator> #include <iterator>
#include <utility>
#endif #endif
#include <type_traits>
#include <utility>
// BOOST_UNORDERED_TEMPLATE_DEDUCTION_GUIDES // BOOST_UNORDERED_TEMPLATE_DEDUCTION_GUIDES
#if !defined(BOOST_UNORDERED_TEMPLATE_DEDUCTION_GUIDES) #if !defined(BOOST_UNORDERED_TEMPLATE_DEDUCTION_GUIDES)
@ -40,19 +35,96 @@
namespace boost { namespace boost {
namespace unordered { namespace unordered {
namespace detail { 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 // Type checkers used for the transparent member functions added by C++20
// and up // and up
template <class, class = void> template <class, class = void>
struct is_transparent : public boost::false_type struct is_transparent : public std::false_type
{ {
}; };
template <class T> template <class T>
struct is_transparent<T, struct is_transparent<T,
typename boost::make_void<typename T::is_transparent>::type> boost::unordered::detail::void_t<typename T::is_transparent> >
: public boost::true_type : public std::true_type
{ {
}; };
@ -71,8 +143,8 @@ namespace boost {
static bool const value = static bool const value =
are_transparent<Key, hash, key_equal>::value && are_transparent<Key, hash, key_equal>::value &&
!boost::is_convertible<Key, iterator>::value && !std::is_convertible<Key, iterator>::value &&
!boost::is_convertible<Key, const_iterator>::value; !std::is_convertible<Key, const_iterator>::value;
}; };
#if BOOST_UNORDERED_TEMPLATE_DEDUCTION_GUIDES #if BOOST_UNORDERED_TEMPLATE_DEDUCTION_GUIDES
@ -81,7 +153,7 @@ namespace boost {
template <class InputIterator> template <class InputIterator>
constexpr bool const is_input_iterator_v = constexpr bool const is_input_iterator_v =
!boost::is_integral<InputIterator>::value; !std::is_integral<InputIterator>::value;
template <class A, class = void> struct is_allocator template <class A, class = void> struct is_allocator
{ {
@ -90,7 +162,7 @@ namespace boost {
template <class A> template <class A>
struct is_allocator<A, struct is_allocator<A,
boost::void_t<typename A::value_type, boost::unordered::detail::void_t<typename A::value_type,
decltype(std::declval<A&>().allocate(std::size_t{}))> > decltype(std::declval<A&>().allocate(std::size_t{}))> >
{ {
constexpr static bool const value = true; constexpr static bool const value = true;
@ -101,7 +173,7 @@ namespace boost {
template <class H> template <class H>
constexpr bool const is_hash_v = constexpr bool const is_hash_v =
!boost::is_integral<H>::value && !is_allocator_v<H>; !std::is_integral<H>::value && !is_allocator_v<H>;
template <class P> constexpr bool const is_pred_v = !is_allocator_v<P>; template <class P> constexpr bool const is_pred_v = !is_allocator_v<P>;
@ -116,7 +188,7 @@ namespace boost {
typename std::pair<iter_key_t<T> const, iter_val_t<T> >; typename std::pair<iter_key_t<T> const, iter_val_t<T> >;
#endif #endif
} // namespace detail } // namespace detail
} // namespace unordered } // namespace unordered
} // namespace boost } // namespace boost
#endif // BOOST_UNORDERED_DETAIL_TYPE_TRAITS_HPP #endif // BOOST_UNORDERED_DETAIL_TYPE_TRAITS_HPP

View File

@ -11,8 +11,7 @@
#ifndef BOOST_UNORDERED_HASH_TRAITS_HPP #ifndef BOOST_UNORDERED_HASH_TRAITS_HPP
#define BOOST_UNORDERED_HASH_TRAITS_HPP #define BOOST_UNORDERED_HASH_TRAITS_HPP
#include <boost/type_traits/make_void.hpp> #include <boost/unordered/detail/type_traits.hpp>
#include <boost/type_traits/integral_constant.hpp>
namespace boost{ namespace boost{
namespace unordered{ namespace unordered{
@ -20,12 +19,12 @@ namespace unordered{
namespace detail{ namespace detail{
template<typename Hash,typename=void> template<typename Hash,typename=void>
struct hash_is_avalanching_impl: boost::false_type{}; struct hash_is_avalanching_impl: std::false_type{};
template<typename Hash> template<typename Hash>
struct hash_is_avalanching_impl<Hash, struct hash_is_avalanching_impl<Hash,
typename boost::make_void<typename Hash::is_avalanching>::type>: boost::unordered::detail::void_t<typename Hash::is_avalanching> >:
boost::true_type{}; std::true_type{};
} /* namespace detail */ } /* namespace detail */

View File

@ -18,7 +18,7 @@
#include <boost/unordered/unordered_flat_map_fwd.hpp> #include <boost/unordered/unordered_flat_map_fwd.hpp>
#include <boost/core/allocator_access.hpp> #include <boost/core/allocator_access.hpp>
#include <boost/functional/hash.hpp> #include <boost/container_hash/hash.hpp>
#include <boost/throw_exception.hpp> #include <boost/throw_exception.hpp>
#include <initializer_list> #include <initializer_list>
@ -65,9 +65,9 @@ namespace boost {
using init_type = typename map_types::init_type; using init_type = typename map_types::init_type;
using size_type = std::size_t; using size_type = std::size_t;
using difference_type = std::ptrdiff_t; using difference_type = std::ptrdiff_t;
using hasher = typename boost::type_identity<Hash>::type; using hasher = typename boost::unordered::detail::type_identity<Hash>::type;
using key_equal = typename boost::type_identity<KeyEqual>::type; using key_equal = typename boost::unordered::detail::type_identity<KeyEqual>::type;
using allocator_type = typename boost::type_identity<Allocator>::type; using allocator_type = typename boost::unordered::detail::type_identity<Allocator>::type;
using reference = value_type&; using reference = value_type&;
using const_reference = value_type const&; using const_reference = value_type const&;
using pointer = typename boost::allocator_pointer<allocator_type>::type; using pointer = typename boost::allocator_pointer<allocator_type>::type;
@ -729,8 +729,8 @@ namespace boost {
Allocator>; Allocator>;
template <class Key, class T, template <class Key, class T,
class Hash = boost::hash<boost::remove_const_t<Key> >, class Hash = boost::hash<std::remove_const_t<Key> >,
class Pred = std::equal_to<boost::remove_const_t<Key> >, class Pred = std::equal_to<std::remove_const_t<Key> >,
class Allocator = std::allocator<std::pair<const Key, T> >, class Allocator = std::allocator<std::pair<const Key, T> >,
class = boost::enable_if_t<detail::is_hash_v<Hash> >, 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_pred_v<Pred> >,
@ -738,7 +738,7 @@ namespace boost {
unordered_flat_map(std::initializer_list<std::pair<Key, T> >, unordered_flat_map(std::initializer_list<std::pair<Key, T> >,
std::size_t = boost::unordered::detail::foa::default_bucket_count, std::size_t = boost::unordered::detail::foa::default_bucket_count,
Hash = Hash(), Pred = Pred(), Allocator = Allocator()) Hash = Hash(), Pred = Pred(), Allocator = Allocator())
-> unordered_flat_map<boost::remove_const_t<Key>, T, Hash, Pred, -> unordered_flat_map<std::remove_const_t<Key>, T, Hash, Pred,
Allocator>; Allocator>;
template <class InputIterator, class Allocator, template <class InputIterator, class Allocator,
@ -775,23 +775,23 @@ namespace boost {
template <class Key, class T, class Allocator, template <class Key, class T, class Allocator,
class = boost::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, unordered_flat_map(std::initializer_list<std::pair<Key, T> >, std::size_t,
Allocator) -> unordered_flat_map<boost::remove_const_t<Key>, T, Allocator) -> unordered_flat_map<std::remove_const_t<Key>, T,
boost::hash<boost::remove_const_t<Key> >, boost::hash<std::remove_const_t<Key> >,
std::equal_to<boost::remove_const_t<Key> >, Allocator>; std::equal_to<std::remove_const_t<Key> >, Allocator>;
template <class Key, class T, class Allocator, template <class Key, class T, class Allocator,
class = boost::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::initializer_list<std::pair<Key, T> >, Allocator)
-> unordered_flat_map<boost::remove_const_t<Key>, T, -> unordered_flat_map<std::remove_const_t<Key>, T,
boost::hash<boost::remove_const_t<Key> >, boost::hash<std::remove_const_t<Key> >,
std::equal_to<boost::remove_const_t<Key> >, Allocator>; std::equal_to<std::remove_const_t<Key> >, Allocator>;
template <class Key, class T, class Hash, class Allocator, template <class Key, class T, class Hash, class Allocator,
class = boost::enable_if_t<detail::is_hash_v<Hash> >, class = boost::enable_if_t<detail::is_hash_v<Hash> >,
class = boost::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, unordered_flat_map(std::initializer_list<std::pair<Key, T> >, std::size_t,
Hash, Allocator) -> unordered_flat_map<boost::remove_const_t<Key>, T, Hash, Allocator) -> unordered_flat_map<std::remove_const_t<Key>, T,
Hash, std::equal_to<boost::remove_const_t<Key> >, Allocator>; Hash, std::equal_to<std::remove_const_t<Key> >, Allocator>;
#endif #endif
} // namespace unordered } // namespace unordered

View File

@ -11,7 +11,7 @@
#pragma once #pragma once
#endif #endif
#include <boost/functional/hash_fwd.hpp> #include <boost/container_hash/hash_fwd.hpp>
#include <functional> #include <functional>
#include <memory> #include <memory>

View File

@ -18,7 +18,7 @@
#include <boost/unordered/unordered_flat_set_fwd.hpp> #include <boost/unordered/unordered_flat_set_fwd.hpp>
#include <boost/core/allocator_access.hpp> #include <boost/core/allocator_access.hpp>
#include <boost/functional/hash.hpp> #include <boost/container_hash/hash.hpp>
#include <initializer_list> #include <initializer_list>
#include <iterator> #include <iterator>

View File

@ -11,7 +11,7 @@
#pragma once #pragma once
#endif #endif
#include <boost/functional/hash_fwd.hpp> #include <boost/container_hash/hash_fwd.hpp>
#include <functional> #include <functional>
#include <memory> #include <memory>

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
// Copyright (C) 2008-2011 Daniel James. // Copyright (C) 2008-2011 Daniel James.
// Copyright (C) 2022 Christian Mazakas // Copyright (C) 2022-2023 Christian Mazakas
// Distributed under the Boost Software License, Version 1.0. (See accompanying // 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) // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@ -12,7 +12,7 @@
#pragma once #pragma once
#endif #endif
#include <boost/functional/hash_fwd.hpp> #include <boost/container_hash/hash_fwd.hpp>
#include <functional> #include <functional>
#include <memory> #include <memory>
@ -30,9 +30,8 @@ namespace boost {
inline bool operator!=( inline bool operator!=(
unordered_map<K, T, H, P, A> const&, unordered_map<K, T, H, P, A> const&); 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> template <class K, class T, class H, class P, class A>
inline void swap( inline void swap(unordered_map<K, T, H, P, A>& m1,
unordered_map<K, T, H, P, A>& m1, unordered_map<K, T, H, P, A>& m2) unordered_map<K, T, H, P, A>& m2) noexcept(noexcept(m1.swap(m2)));
BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR(m1.swap(m2)));
template <class K, class T, class H, class P, class A, class Predicate> 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( typename unordered_map<K, T, H, P, A>::size_type erase_if(
@ -51,8 +50,7 @@ namespace boost {
unordered_multimap<K, T, H, P, A> const&); unordered_multimap<K, T, H, P, A> const&);
template <class K, class T, class H, class P, class A> template <class K, class T, class H, class P, class A>
inline void swap(unordered_multimap<K, T, H, P, A>& m1, inline void swap(unordered_multimap<K, T, H, P, A>& m1,
unordered_multimap<K, T, H, P, A>& m2) unordered_multimap<K, T, H, P, A>& m2) noexcept(noexcept(m1.swap(m2)));
BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR(m1.swap(m2)));
template <class K, class T, class H, class P, class A, class Predicate> 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( typename unordered_multimap<K, T, H, P, A>::size_type erase_if(
@ -60,13 +58,13 @@ namespace boost {
template <class N, class K, class T, class A> class node_handle_map; template <class N, class K, class T, class A> class node_handle_map;
template <class Iter, class NodeType> struct insert_return_type_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_map;
using boost::unordered::unordered_multimap; using boost::unordered::unordered_multimap;
using boost::unordered::swap;
using boost::unordered::operator==; using boost::unordered::operator==;
using boost::unordered::operator!=; using boost::unordered::operator!=;
} } // namespace boost
#endif #endif

View File

@ -19,7 +19,7 @@
#include <boost/unordered/unordered_node_map_fwd.hpp> #include <boost/unordered/unordered_node_map_fwd.hpp>
#include <boost/core/allocator_access.hpp> #include <boost/core/allocator_access.hpp>
#include <boost/functional/hash.hpp> #include <boost/container_hash/hash.hpp>
#include <boost/throw_exception.hpp> #include <boost/throw_exception.hpp>
#include <initializer_list> #include <initializer_list>
@ -99,9 +99,9 @@ namespace boost {
using init_type = typename map_types::init_type; using init_type = typename map_types::init_type;
using size_type = std::size_t; using size_type = std::size_t;
using difference_type = std::ptrdiff_t; using difference_type = std::ptrdiff_t;
using hasher = typename boost::type_identity<Hash>::type; using hasher = typename boost::unordered::detail::type_identity<Hash>::type;
using key_equal = typename boost::type_identity<KeyEqual>::type; using key_equal = typename boost::unordered::detail::type_identity<KeyEqual>::type;
using allocator_type = typename boost::type_identity<Allocator>::type; using allocator_type = typename boost::unordered::detail::type_identity<Allocator>::type;
using reference = value_type&; using reference = value_type&;
using const_reference = value_type const&; using const_reference = value_type const&;
using pointer = typename boost::allocator_pointer<allocator_type>::type; using pointer = typename boost::allocator_pointer<allocator_type>::type;
@ -822,8 +822,8 @@ namespace boost {
Allocator>; Allocator>;
template <class Key, class T, template <class Key, class T,
class Hash = boost::hash<boost::remove_const_t<Key> >, class Hash = boost::hash<std::remove_const_t<Key> >,
class Pred = std::equal_to<boost::remove_const_t<Key> >, class Pred = std::equal_to<std::remove_const_t<Key> >,
class Allocator = std::allocator<std::pair<const Key, T> >, class Allocator = std::allocator<std::pair<const Key, T> >,
class = boost::enable_if_t<detail::is_hash_v<Hash> >, 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_pred_v<Pred> >,
@ -831,7 +831,7 @@ namespace boost {
unordered_node_map(std::initializer_list<std::pair<Key, T> >, unordered_node_map(std::initializer_list<std::pair<Key, T> >,
std::size_t = boost::unordered::detail::foa::default_bucket_count, std::size_t = boost::unordered::detail::foa::default_bucket_count,
Hash = Hash(), Pred = Pred(), Allocator = Allocator()) Hash = Hash(), Pred = Pred(), Allocator = Allocator())
-> unordered_node_map<boost::remove_const_t<Key>, T, Hash, Pred, -> unordered_node_map<std::remove_const_t<Key>, T, Hash, Pred,
Allocator>; Allocator>;
template <class InputIterator, class Allocator, template <class InputIterator, class Allocator,
@ -868,23 +868,23 @@ namespace boost {
template <class Key, class T, class Allocator, template <class Key, class T, class Allocator,
class = boost::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, unordered_node_map(std::initializer_list<std::pair<Key, T> >, std::size_t,
Allocator) -> unordered_node_map<boost::remove_const_t<Key>, T, Allocator) -> unordered_node_map<std::remove_const_t<Key>, T,
boost::hash<boost::remove_const_t<Key> >, boost::hash<std::remove_const_t<Key> >,
std::equal_to<boost::remove_const_t<Key> >, Allocator>; std::equal_to<std::remove_const_t<Key> >, Allocator>;
template <class Key, class T, class Allocator, template <class Key, class T, class Allocator,
class = boost::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::initializer_list<std::pair<Key, T> >, Allocator)
-> unordered_node_map<boost::remove_const_t<Key>, T, -> unordered_node_map<std::remove_const_t<Key>, T,
boost::hash<boost::remove_const_t<Key> >, boost::hash<std::remove_const_t<Key> >,
std::equal_to<boost::remove_const_t<Key> >, Allocator>; std::equal_to<std::remove_const_t<Key> >, Allocator>;
template <class Key, class T, class Hash, class Allocator, template <class Key, class T, class Hash, class Allocator,
class = boost::enable_if_t<detail::is_hash_v<Hash> >, class = boost::enable_if_t<detail::is_hash_v<Hash> >,
class = boost::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, unordered_node_map(std::initializer_list<std::pair<Key, T> >, std::size_t,
Hash, Allocator) -> unordered_node_map<boost::remove_const_t<Key>, T, Hash, Allocator) -> unordered_node_map<std::remove_const_t<Key>, T,
Hash, std::equal_to<boost::remove_const_t<Key> >, Allocator>; Hash, std::equal_to<std::remove_const_t<Key> >, Allocator>;
#endif #endif
} // namespace unordered } // namespace unordered

View File

@ -11,7 +11,7 @@
#pragma once #pragma once
#endif #endif
#include <boost/functional/hash_fwd.hpp> #include <boost/container_hash/hash_fwd.hpp>
#include <functional> #include <functional>
#include <memory> #include <memory>

View File

@ -19,7 +19,7 @@
#include <boost/unordered/unordered_node_set_fwd.hpp> #include <boost/unordered/unordered_node_set_fwd.hpp>
#include <boost/core/allocator_access.hpp> #include <boost/core/allocator_access.hpp>
#include <boost/functional/hash.hpp> #include <boost/container_hash/hash.hpp>
#include <boost/throw_exception.hpp> #include <boost/throw_exception.hpp>
#include <initializer_list> #include <initializer_list>

View File

@ -11,7 +11,7 @@
#pragma once #pragma once
#endif #endif
#include <boost/functional/hash_fwd.hpp> #include <boost/container_hash/hash_fwd.hpp>
#include <functional> #include <functional>
#include <memory> #include <memory>

File diff suppressed because it is too large Load Diff

View File

@ -12,7 +12,7 @@
#pragma once #pragma once
#endif #endif
#include <boost/functional/hash_fwd.hpp> #include <boost/container_hash/hash_fwd.hpp>
#include <functional> #include <functional>
#include <memory> #include <memory>
@ -29,9 +29,8 @@ namespace boost {
inline bool operator!=( inline bool operator!=(
unordered_set<T, H, P, A> const&, unordered_set<T, H, P, A> const&); unordered_set<T, H, P, A> const&, unordered_set<T, H, P, A> const&);
template <class T, class H, class P, class A> template <class T, class H, class P, class A>
inline void swap( inline void swap(unordered_set<T, H, P, A>& m1,
unordered_set<T, H, P, A>& m1, unordered_set<T, H, P, A>& m2) unordered_set<T, H, P, A>& m2) noexcept(noexcept(m1.swap(m2)));
BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR(m1.swap(m2)));
template <class K, class H, class P, class A, class Predicate> template <class K, class H, class P, class A, class Predicate>
typename unordered_set<K, H, P, A>::size_type erase_if( typename unordered_set<K, H, P, A>::size_type erase_if(
@ -48,9 +47,8 @@ namespace boost {
inline bool operator!=(unordered_multiset<T, H, P, A> const&, inline bool operator!=(unordered_multiset<T, H, P, A> const&,
unordered_multiset<T, H, P, A> const&); unordered_multiset<T, H, P, A> const&);
template <class T, class H, class P, class A> template <class T, class H, class P, class A>
inline void swap( inline void swap(unordered_multiset<T, H, P, A>& m1,
unordered_multiset<T, H, P, A>& m1, unordered_multiset<T, H, P, A>& m2) unordered_multiset<T, H, P, A>& m2) noexcept(noexcept(m1.swap(m2)));
BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR(m1.swap(m2)));
template <class K, class H, class P, class A, class Predicate> template <class K, class H, class P, class A, class Predicate>
typename unordered_multiset<K, H, P, A>::size_type erase_if( typename unordered_multiset<K, H, P, A>::size_type erase_if(
@ -58,13 +56,13 @@ namespace boost {
template <class N, class T, class A> class node_handle_set; template <class N, class T, class A> class node_handle_set;
template <class Iter, class NodeType> struct insert_return_type_set; template <class Iter, class NodeType> struct insert_return_type_set;
} } // namespace unordered
using boost::unordered::unordered_set;
using boost::unordered::unordered_multiset;
using boost::unordered::swap; using boost::unordered::swap;
using boost::unordered::unordered_multiset;
using boost::unordered::unordered_set;
using boost::unordered::operator==; using boost::unordered::operator==;
using boost::unordered::operator!=; using boost::unordered::operator!=;
} } // namespace boost
#endif #endif

View File

@ -5,14 +5,12 @@
"Daniel James" "Daniel James"
], ],
"maintainers": [ "maintainers": [
"Daniel James <dnljms -at- gmail.com>" "Christian Mazakas <christian.mazakas -at- gmail.com>",
"Joaquín M López Muñoz <joaquin.lopezmunoz -at- gmail.com>"
], ],
"description": "Unordered associative containers.", "description": "Unordered associative containers.",
"std": [
"tr1"
],
"category": [ "category": [
"Containers" "Containers"
], ],
"cxxstd": "03" "cxxstd": "11"
} }

View File

@ -77,11 +77,6 @@ fca_tests(SOURCES exception/swap_exception_tests.cpp COMPILE_DEFINITIONS BOOST_U
fca_tests(SOURCES exception/merge_exception_tests.cpp) fca_tests(SOURCES exception/merge_exception_tests.cpp)
fca_tests(SOURCES exception/less_tests.cpp) fca_tests(SOURCES exception/less_tests.cpp)
fca_tests(SOURCES unordered/narrow_cast_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(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) fca_tests(TYPE compile-fail NAME insert_node_type_fail_map COMPILE_DEFINITIONS UNORDERED_TEST_MAP SOURCES unordered/insert_node_type_fail.cpp)

View File

@ -20,21 +20,6 @@ local msvc-flags = /wd4494 ;
project project
: requirements : 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 <warnings>pedantic
<toolset>intel:<warnings>on <toolset>intel:<warnings>on
@ -146,12 +131,6 @@ for local test in $(FCA_TESTS)
run unordered/link_test_1.cpp unordered/link_test_2.cpp : : : : link_test ; 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 run unordered/serialization_tests.cpp
: $(BOOST_UNORDERED_TEST_DIR) : $(BOOST_UNORDERED_TEST_DIR)
: :
@ -198,11 +177,6 @@ alias fca_tests :
$(FCA_TESTS) $(FCA_TESTS)
$(FCA_EXCEPTION_TESTS) $(FCA_EXCEPTION_TESTS)
link_test link_test
bmove_compile_set
bmove_compile_map
bmove_copy
bmove_move
bmove_assign
insert_node_type_fail_map insert_node_type_fail_map
insert_node_type_fail_multimap insert_node_type_fail_multimap
insert_node_type_fail_set insert_node_type_fail_set

View File

@ -536,7 +536,7 @@ public:
T& operator[](std::ptrdiff_t s) const { return ptr_[s]; } T& operator[](std::ptrdiff_t s) const { return ptr_[s]; }
bool operator!() const { return !ptr_; } bool operator!() const { return !ptr_; }
static ptr pointer_to(T& p) { return ptr(boost::addressof(p)); } static ptr pointer_to(T& p) { return ptr(std::addressof(p)); }
// I'm not using the safe bool idiom because the containers should be // I'm not using the safe bool idiom because the containers should be
// able to cope with bool conversions. // able to cope with bool conversions.

View File

@ -10,6 +10,9 @@
#include "../helpers/random_values.hpp" #include "../helpers/random_values.hpp"
#include "../helpers/strong.hpp" #include "../helpers/strong.hpp"
#include "../helpers/tracker.hpp" #include "../helpers/tracker.hpp"
#include <boost/tuple/tuple.hpp>
#include <cmath> #include <cmath>
#include <string> #include <string>

View File

@ -44,7 +44,7 @@ template <class T> struct move_assign_base : public test::exception_base
test::exceptions_enable disable_exceptions(false); test::exceptions_enable disable_exceptions(false);
T y1 = y; T y1 = y;
disable_exceptions.release(); disable_exceptions.release();
x1 = boost::move(y1); x1 = std::move(y1);
DISABLE_EXCEPTIONS; DISABLE_EXCEPTIONS;
test::check_container(x1, y_values); test::check_container(x1, y_values);

View File

@ -6,11 +6,15 @@
#if !defined(BOOST_UNORDERED_TEST_TEST_HEADER) #if !defined(BOOST_UNORDERED_TEST_TEST_HEADER)
#define 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/core/lightweight_test.hpp>
#include <boost/preprocessor/cat.hpp> #include <boost/preprocessor/cat.hpp>
#include <boost/preprocessor/stringize.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) \ #define UNORDERED_AUTO_TEST(x) \
struct BOOST_PP_CAT(x, _type) : public ::test::registered_test_base \ struct BOOST_PP_CAT(x, _type) : public ::test::registered_test_base \
{ \ { \
@ -120,7 +124,7 @@ namespace test {
static state instance; static state instance;
return instance; return instance;
} }
} } // namespace test
#if defined(__cplusplus) #if defined(__cplusplus)
#define BOOST_UNORDERED_CPLUSPLUS __cplusplus #define BOOST_UNORDERED_CPLUSPLUS __cplusplus
@ -134,12 +138,6 @@ namespace test {
<< "Compiler: " << BOOST_COMPILER << "\n" \ << "Compiler: " << BOOST_COMPILER << "\n" \
<< "Library: " << BOOST_STDLIB << "\n" \ << "Library: " << BOOST_STDLIB << "\n" \
<< "__cplusplus: " << BOOST_UNORDERED_CPLUSPLUS << "\n\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; \ << std::flush; \
} }

View File

@ -14,7 +14,6 @@
#include <boost/unordered/unordered_node_map.hpp> #include <boost/unordered/unordered_node_map.hpp>
#include <boost/unordered/unordered_node_set.hpp> #include <boost/unordered/unordered_node_set.hpp>
#include <boost/unordered/detail/implementation.hpp> #include <boost/unordered/detail/implementation.hpp>
#include <boost/unordered/detail/fwd.hpp>
#else #else
#include <boost/unordered_set.hpp> #include <boost/unordered_set.hpp>
#include <boost/unordered_map.hpp> #include <boost/unordered_map.hpp>

View File

@ -182,9 +182,7 @@ namespace test
~cxx11_allocator_base() { detail::tracker.allocator_unref(); } ~cxx11_allocator_base() { detail::tracker.allocator_unref(); }
#if !defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS)
cxx11_allocator_base& operator=(cxx11_allocator_base const& x) = default; cxx11_allocator_base& operator=(cxx11_allocator_base const& x) = default;
#endif
pointer address(reference r) { return pointer(&r); } pointer address(reference r) { return pointer(&r); }
@ -214,21 +212,12 @@ namespace test
::operator delete((void*)p); ::operator delete((void*)p);
} }
#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(v);
}
#else
template <class U, typename... Args> template <class U, typename... Args>
void construct(U* p, BOOST_FWD_REF(Args)... args) void construct(U* p, Args&&... args)
{ {
detail::tracker.track_construct((void*)p, sizeof(U), tag_); detail::tracker.track_construct((void*)p, sizeof(U), tag_);
new (p) U(boost::forward<Args>(args)...); new (p) U(std::forward<Args>(args)...);
} }
#endif
template <class U> template <class U>
void destroy(U* p) void destroy(U* p)
@ -272,9 +261,7 @@ namespace test
cxx11_allocator(cxx11_allocator const& x) : cxx11_allocator_base<T>(x) {} 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; cxx11_allocator& operator=(cxx11_allocator const& x) = default;
#endif
// When not propagating swap, allocators are always equal // When not propagating swap, allocators are always equal
// to avoid undefined behaviour. // to avoid undefined behaviour.
@ -319,9 +306,7 @@ namespace test
cxx11_allocator(cxx11_allocator const& x) : cxx11_allocator_base<T>(x) {} 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; cxx11_allocator& operator=(cxx11_allocator const& x) = default;
#endif
// When not propagating swap, allocators are always equal // When not propagating swap, allocators are always equal
// to avoid undefined behaviour. // to avoid undefined behaviour.

View File

@ -501,28 +501,15 @@ namespace test {
} }
} }
#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) template <class U, class... Args> void construct(U* p, Args&&... args)
template <class U, class Arg>
void construct(U* p, Arg const& t)
{ {
UNORDERED_SCOPE(allocator::construct(U*, Arg)) UNORDERED_SCOPE(allocator::construct(U*, Args&&...))
{ {
UNORDERED_EPOINT("Mock allocator construct function.") UNORDERED_EPOINT("Mock allocator construct function.")
new (p) U(t); new (p) U(std::forward<Args>(args)...);
} }
test::detail::tracker.track_construct((void*)p, sizeof(U), tag_); test::detail::tracker.track_construct((void*)p, sizeof(U), tag_);
} }
#else
template <class U, class... Args> void construct(U* p, BOOST_FWD_REF(Args)... args)
{
UNORDERED_SCOPE(allocator::construct(U*, BOOST_FWD_REF(Args)...))
{
UNORDERED_EPOINT("Mock allocator construct function.")
new (p) U(boost::forward<Args>(args)...);
}
test::detail::tracker.track_construct((void*)p, sizeof(U), tag_);
}
#endif
template <class U> template <class U>
void destroy(U* p) void destroy(U* p)
@ -682,29 +669,16 @@ namespace test {
} }
} }
#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template <class U, class V>
void construct(U* p, V const& v)
{
UNORDERED_SCOPE(allocator2::construct(U*, V))
{
UNORDERED_EPOINT("Mock allocator2 construct function.")
new (p) U(v);
}
test::detail::tracker.track_construct((void*)p, sizeof(U), tag_);
}
#else
template <class U, class... Args> template <class U, class... Args>
void construct(U* p, BOOST_FWD_REF(Args)... args) void construct(U* p, Args&&... args)
{ {
UNORDERED_SCOPE(allocator2::construct(U*, BOOST_FWD_REF(Args)...)) UNORDERED_SCOPE(allocator2::construct(U*, Args&&...))
{ {
UNORDERED_EPOINT("Mock allocator2 construct function.") UNORDERED_EPOINT("Mock allocator2 construct function.")
new (p) U(boost::forward<Args>(args)...); new (p) U(std::forward<Args>(args)...);
} }
test::detail::tracker.track_construct((void*)p, sizeof(U), tag_); test::detail::tracker.track_construct((void*)p, sizeof(U), tag_);
} }
#endif
template <class U> template <class U>
void destroy(U* p) void destroy(U* p)

View File

@ -14,7 +14,6 @@
#include <boost/core/addressof.hpp> #include <boost/core/addressof.hpp>
#include <boost/core/lightweight_test.hpp> #include <boost/core/lightweight_test.hpp>
#include <boost/core/pointer_traits.hpp> #include <boost/core/pointer_traits.hpp>
#include <boost/move/move.hpp>
#include <cstddef> #include <cstddef>
#include <utility> #include <utility>
@ -165,19 +164,18 @@ namespace test {
class movable1 class movable1
{ {
BOOST_MOVABLE_BUT_NOT_COPYABLE(movable1)
public: public:
movable1(constructor_param const&) {} movable1(constructor_param const&) {}
movable1() {} movable1() {}
explicit movable1(movable_init) {} explicit movable1(movable_init) {}
movable1(BOOST_RV_REF(movable1)) {} movable1(movable1 const&) = delete;
movable1& operator=(BOOST_RV_REF(movable1)) { return *this; } movable1& operator=(movable1 const&) = delete;
movable1(movable1&&) {}
movable1& operator=(movable1&&) { return *this; }
~movable1() {} ~movable1() {}
void dummy_member() const {} void dummy_member() const {}
}; };
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
class movable2 class movable2
{ {
public: public:
@ -193,9 +191,6 @@ namespace test {
movable2(movable2 const&); movable2(movable2 const&);
movable2& operator=(movable2 const&); movable2& operator=(movable2 const&);
}; };
#else
typedef movable1 movable2;
#endif
template <class T> class hash template <class T> class hash
{ {
@ -344,7 +339,7 @@ namespace test {
bool operator!() const { return !ptr_; } bool operator!() const { return !ptr_; }
static ptr pointer_to(T& p) { static ptr pointer_to(T& p) {
return ptr(boost::addressof(p)); return ptr(std::addressof(p));
} }
// I'm not using the safe bool idiom because the containers should be // I'm not using the safe bool idiom because the containers should be
@ -461,18 +456,11 @@ namespace test {
::operator delete((void*)p.ptr_); ::operator delete((void*)p.ptr_);
} }
#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template <class U, class V> void construct(U* p, V const& v)
{
new ((void*)p) U(v);
}
#else
template <class U, class... Args> template <class U, class... Args>
void construct(U* p, BOOST_FWD_REF(Args)... args) void construct(U* p, Args&&... args)
{ {
new ((void*)p) U(boost::forward<Args>(args)...); new ((void*)p) U(std::forward<Args>(args)...);
} }
#endif
template <class U> void destroy(U* p) { p->~U(); } template <class U> void destroy(U* p) { p->~U(); }
@ -535,18 +523,11 @@ namespace test {
::operator delete((void*)p.ptr_); ::operator delete((void*)p.ptr_);
} }
#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template <class U> void construct(U* p, U const& t)
{
new (p) U(t);
}
#else
template <class U, class... Args> template <class U, class... Args>
void construct(U* p, BOOST_FWD_REF(Args)... args) void construct(U* p, Args&&... args)
{ {
new (p) U(boost::forward<Args>(args)...); new (p) U(std::forward<Args>(args)...);
} }
#endif
template <class U> void destroy(U* p) { p->~U(); } template <class U> void destroy(U* p) { p->~U(); }
@ -613,18 +594,11 @@ namespace test {
void deallocate(T* p, std::size_t) { ::operator delete((void*)p); } void deallocate(T* p, std::size_t) { ::operator delete((void*)p); }
#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template <class U, class V> void construct(U* p, V const& v)
{
new ((void*)p) U(v);
}
#else
template <class U, class... Args> template <class U, class... Args>
void construct(U* p, BOOST_FWD_REF(Args)... args) void construct(U* p, Args&&... args)
{ {
new ((void*)p) U(boost::forward<Args>(args)...); new ((void*)p) U(std::forward<Args>(args)...);
} }
#endif
template <class U> void destroy(U* p) { p->~U(); } template <class U> void destroy(U* p) { p->~U(); }

View File

@ -96,7 +96,6 @@ namespace test {
friend class less; friend class less;
int tag1_, tag2_; int tag1_, tag2_;
BOOST_COPYABLE_AND_MOVABLE(movable)
public: public:
explicit movable(int t1 = 0, int t2 = 0) : tag1_(t1), tag2_(t2) {} explicit movable(int t1 = 0, int t2 = 0) : tag1_(t1), tag2_(t2) {}
@ -106,7 +105,7 @@ namespace test {
BOOST_TEST(x.tag1_ != -1); BOOST_TEST(x.tag1_ != -1);
} }
movable(BOOST_RV_REF(movable) x) movable(movable&& x)
: counted_object(x), tag1_(x.tag1_), tag2_(x.tag2_) : counted_object(x), tag1_(x.tag1_), tag2_(x.tag2_)
{ {
BOOST_TEST(x.tag1_ != -1); BOOST_TEST(x.tag1_ != -1);
@ -114,7 +113,7 @@ namespace test {
x.tag2_ = -1; x.tag2_ = -1;
} }
movable& operator=(BOOST_COPY_ASSIGN_REF(movable) x) // Copy assignment movable& operator=(movable const& x) // Copy assignment
{ {
BOOST_TEST(x.tag1_ != -1); BOOST_TEST(x.tag1_ != -1);
tag1_ = x.tag1_; tag1_ = x.tag1_;
@ -122,7 +121,7 @@ namespace test {
return *this; return *this;
} }
movable& operator=(BOOST_RV_REF(movable) x) // Move assignment movable& operator=(movable&& x) // Move assignment
{ {
BOOST_TEST(x.tag1_ != -1); BOOST_TEST(x.tag1_ != -1);
tag1_ = x.tag1_; tag1_ = x.tag1_;
@ -410,11 +409,10 @@ namespace test {
::operator delete((void*)p); ::operator delete((void*)p);
} }
#if BOOST_UNORDERED_CXX11_CONSTRUCTION
template <typename U, typename... Args> void construct(U* p, Args&&... args) template <typename U, typename... Args> void construct(U* p, Args&&... args)
{ {
detail::tracker.track_construct((void*)p, sizeof(U), tag_); detail::tracker.track_construct((void*)p, sizeof(U), tag_);
new (p) U(boost::forward<Args>(args)...); new (p) U(std::forward<Args>(args)...);
} }
template <typename U> void destroy(U* p) template <typename U> void destroy(U* p)
@ -425,22 +423,6 @@ namespace test {
// Work around MSVC buggy unused parameter warning. // Work around MSVC buggy unused parameter warning.
ignore_variable(&p); ignore_variable(&p);
} }
#else
private:
// I'm going to claim in the documentation that construct/destroy
// is never used when C++11 support isn't available, so might as
// well check that in the text.
// TODO: Or maybe just disallow them for values?
template <typename U> void construct(U* p);
template <typename U, typename A0> void construct(U* p, A0 const&);
template <typename U, typename A0, typename A1>
void construct(U* p, A0 const&, A1 const&);
template <typename U, typename A0, typename A1, typename A2>
void construct(U* p, A0 const&, A1 const&, A2 const&);
template <typename U> void destroy(U* p);
public:
#endif
bool operator==(allocator1 const& x) const { return tag_ == x.tag_; } bool operator==(allocator1 const& x) const { return tag_ == x.tag_; }
@ -674,20 +656,12 @@ namespace test {
::operator delete((void*)p.ptr_); ::operator delete((void*)p.ptr_);
} }
#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(v);
}
#else
template <class U, class... Args> template <class U, class... Args>
void construct(U* p, BOOST_FWD_REF(Args)... args) void construct(U* p, Args&&... args)
{ {
detail::tracker.track_construct((void*)p, sizeof(U), tag_); detail::tracker.track_construct((void*)p, sizeof(U), tag_);
new (p) U(boost::forward<Args>(args)...); new (p) U(std::forward<Args>(args)...);
} }
#endif
template <class U> void destroy(U* p) template <class U> void destroy(U* p)
{ {

View File

@ -111,12 +111,8 @@ void test_empty_allocator()
{ {
typedef empty_allocator<int> allocator; typedef empty_allocator<int> allocator;
typedef boost::unordered::detail::allocator_traits<allocator> traits; typedef boost::unordered::detail::allocator_traits<allocator> traits;
#if !defined(BOOST_NO_CXX11_ALLOCATOR)
BOOST_STATIC_ASSERT((boost::is_same<traits::size_type, BOOST_STATIC_ASSERT((boost::is_same<traits::size_type,
std::make_unsigned<std::ptrdiff_t>::type>::value)); std::make_unsigned<std::ptrdiff_t>::type>::value));
#else
BOOST_STATIC_ASSERT((boost::is_same<traits::size_type, std::size_t>::value));
#endif
BOOST_STATIC_ASSERT( BOOST_STATIC_ASSERT(
(boost::is_same<traits::difference_type, std::ptrdiff_t>::value)); (boost::is_same<traits::difference_type, std::ptrdiff_t>::value));
BOOST_STATIC_ASSERT((boost::is_same<traits::pointer, int*>::value)); BOOST_STATIC_ASSERT((boost::is_same<traits::pointer, int*>::value));
@ -153,12 +149,8 @@ void test_allocator1()
{ {
typedef allocator1<int> allocator; typedef allocator1<int> allocator;
typedef boost::unordered::detail::allocator_traits<allocator> traits; typedef boost::unordered::detail::allocator_traits<allocator> traits;
#if !defined(BOOST_NO_CXX11_ALLOCATOR)
BOOST_STATIC_ASSERT((boost::is_same<traits::size_type, BOOST_STATIC_ASSERT((boost::is_same<traits::size_type,
std::make_unsigned<std::ptrdiff_t>::type>::value)); std::make_unsigned<std::ptrdiff_t>::type>::value));
#else
BOOST_STATIC_ASSERT((boost::is_same<traits::size_type, std::size_t>::value));
#endif
BOOST_STATIC_ASSERT( BOOST_STATIC_ASSERT(
(boost::is_same<traits::difference_type, std::ptrdiff_t>::value)); (boost::is_same<traits::difference_type, std::ptrdiff_t>::value));
BOOST_STATIC_ASSERT((boost::is_same<traits::pointer, int*>::value)); BOOST_STATIC_ASSERT((boost::is_same<traits::pointer, int*>::value));
@ -213,15 +205,7 @@ void test_allocator2()
BOOST_TEST(!traits::propagate_on_container_move_assignment::value); BOOST_TEST(!traits::propagate_on_container_move_assignment::value);
BOOST_TEST(!traits::propagate_on_container_swap::value); BOOST_TEST(!traits::propagate_on_container_swap::value);
BOOST_TEST(!traits::is_always_equal::value); BOOST_TEST(!traits::is_always_equal::value);
#if !defined(BOOST_NO_CXX11_ALLOCATOR)
// conditionally compile this assertion as all C++03 emulations of expression
// SFINAE are broken one way or another and the benefits of using Core's
// `allocator_traits` outweigh the costs of breaking this kind of code (i.e.
// inheriting SOCCC via a base)
//
BOOST_TEST(call_select<allocator>() == 1); BOOST_TEST(call_select<allocator>() == 1);
#endif
} }
// allocator 3 // allocator 3

View File

@ -436,8 +436,6 @@ namespace assign_tests {
(default_generator)(generate_collisions)(limited_range))) (default_generator)(generate_collisions)(limited_range)))
#endif #endif
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
UNORDERED_AUTO_TEST (assign_default_initializer_list) { UNORDERED_AUTO_TEST (assign_default_initializer_list) {
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Initializer List Tests\n"; BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Initializer List Tests\n";
std::initializer_list<std::pair<int const, int> > init; std::initializer_list<std::pair<int const, int> > init;
@ -459,9 +457,6 @@ namespace assign_tests {
BOOST_TEST(x1.empty()); BOOST_TEST(x1.empty());
} }
#endif
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
UNORDERED_AUTO_TEST (assign_initializer_list) { UNORDERED_AUTO_TEST (assign_initializer_list) {
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Initializer List Tests\n"; BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Initializer List Tests\n";
@ -482,8 +477,6 @@ namespace assign_tests {
BOOST_TEST(x.find(10) == x.end()); BOOST_TEST(x.find(10) == x.end());
BOOST_TEST(x.find(-10) != x.end()); BOOST_TEST(x.find(-10) != x.end());
} }
#endif
} }
RUN_TESTS() RUN_TESTS()

View File

@ -23,6 +23,7 @@
#include <boost/limits.hpp> #include <boost/limits.hpp>
#include <boost/predef.h> #include <boost/predef.h>
#include <boost/static_assert.hpp> #include <boost/static_assert.hpp>
#include <boost/tuple/tuple.hpp>
#include <boost/type_traits/cv_traits.hpp> #include <boost/type_traits/cv_traits.hpp>
#include <boost/type_traits/is_const.hpp> #include <boost/type_traits/is_const.hpp>
#include <boost/type_traits/is_convertible.hpp> #include <boost/type_traits/is_convertible.hpp>
@ -34,22 +35,9 @@ template <class T> void sink(T const&) {}
template <class T> T rvalue(T const& v) { return v; } template <class T> T rvalue(T const& v) { return v; }
template <class T> T rvalue_default() { return T(); } template <class T> T rvalue_default() { return T(); }
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
template <class T> T implicit_construct() { return {}; } template <class T> T implicit_construct() { return {}; }
#else
template <class T> int implicit_construct()
{
T x;
sink(x);
return 0;
}
#endif
#if !defined(BOOST_NO_CXX11_NOEXCEPT) #define TEST_NOEXCEPT_EXPR(x) BOOST_STATIC_ASSERT((noexcept(x)));
#define TEST_NOEXCEPT_EXPR(x) BOOST_STATIC_ASSERT((BOOST_NOEXCEPT_EXPR(x)));
#else
#define TEST_NOEXCEPT_EXPR(x)
#endif
template <class X, class T> void container_test(X& r, T const&) template <class X, class T> void container_test(X& r, T const&)
{ {
@ -143,13 +131,11 @@ template <class X, class T> void container_test(X& r, T const&)
// I don't test the runtime post-conditions here. // I don't test the runtime post-conditions here.
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
// It isn't specified in the container requirements that the no argument // It isn't specified in the container requirements that the no argument
// constructor is implicit, but it is defined that way in the concrete // constructor is implicit, but it is defined that way in the concrete
// container specification. // container specification.
X u_implicit = {}; X u_implicit = {};
sink(u_implicit); sink(u_implicit);
#endif
X u; X u;
BOOST_TEST(u.size() == 0); BOOST_TEST(u.size() == 0);
@ -191,10 +177,10 @@ template <class X, class T> void container_test(X& r, T const&)
node_type n1; node_type n1;
node_type n2(rvalue_default<node_type>()); node_type n2(rvalue_default<node_type>());
#if !BOOST_COMP_GNUC || BOOST_COMP_GNUC >= BOOST_VERSION_NUMBER(4, 8, 0) #if !BOOST_COMP_GNUC || BOOST_COMP_GNUC >= BOOST_VERSION_NUMBER(4, 8, 0)
TEST_NOEXCEPT_EXPR(node_type(boost::move(n1))); TEST_NOEXCEPT_EXPR(node_type(std::move(n1)));
#endif #endif
node_type n3; node_type n3;
n3 = boost::move(n2); n3 = std::move(n2);
n1.swap(n3); n1.swap(n3);
swap(n1, n3); swap(n1, n3);
// TODO: noexcept for swap? // TODO: noexcept for swap?
@ -229,13 +215,11 @@ template <class X> void unordered_destructible_test(X&)
X x1; X x1;
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
X x2(rvalue_default<X>()); X x2(rvalue_default<X>());
X x3 = rvalue_default<X>(); X x3 = rvalue_default<X>();
// This can only be done if propagate_on_container_move_assignment::value // This can only be done if propagate_on_container_move_assignment::value
// is true. // is true.
// x2 = rvalue_default<X>(); // x2 = rvalue_default<X>();
#endif
X* ptr = new X(); X* ptr = new X();
X& a1 = *ptr; X& a1 = *ptr;
@ -350,7 +334,7 @@ template <class X, class Key> void unordered_set_test(X& r, Key const&)
test::minimal::constructor_param v; test::minimal::constructor_param v;
Key k_lvalue(v); Key k_lvalue(v);
r.emplace(boost::move(k_lvalue)); r.emplace(std::move(k_lvalue));
node_type n1 = r.extract(r.begin()); node_type n1 = r.extract(r.begin());
test::check_return_type<value_type>::equals_ref(n1.value()); test::check_return_type<value_type>::equals_ref(n1.value());
#endif #endif
@ -493,11 +477,11 @@ void unordered_map_test(X& r, Key const& k, T const& v)
test::check_return_type<key_type>::equals_ref(n1.key()); test::check_return_type<key_type>::equals_ref(n1.key());
test::check_return_type<T>::equals_ref(n1.mapped()); test::check_return_type<T>::equals_ref(n1.mapped());
node_type n2 = boost::move(n1); node_type n2 = std::move(n1);
r.insert(boost::move(n2)); r.insert(std::move(n2));
r.insert(r.extract(r.begin())); r.insert(r.extract(r.begin()));
n2 = r.extract(r.begin()); n2 = r.extract(r.begin());
r.insert(r.begin(), boost::move(n2)); r.insert(r.begin(), std::move(n2));
r.insert(r.end(), r.extract(r.begin())); r.insert(r.end(), r.extract(r.begin()));
node_type n = r.extract(r.begin()); node_type n = r.extract(r.begin());
@ -530,11 +514,11 @@ template <class X, class T> void unordered_unique_test(X& r, T const& t)
// TODO; // TODO;
// boost::function_requires< // boost::function_requires<
// boost::MoveConstructibleConcept<insert_return_type> // std::moveConstructibleConcept<insert_return_type>
// >(); // >();
// TODO; // TODO;
// boost::function_requires< // boost::function_requires<
// boost::MoveAssignableConcept<insert_return_type> // std::moveAssignableConcept<insert_return_type>
// >(); // >();
boost::function_requires< boost::function_requires<
boost::DefaultConstructibleConcept<insert_return_type> >(); boost::DefaultConstructibleConcept<insert_return_type> >();
@ -738,9 +722,7 @@ void unordered_test(X& x, Key& k, Hash& hf, Pred& eq)
a.rehash(100); a.rehash(100);
a.merge(a2); a.merge(a2);
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
a.merge(rvalue_default<X>()); a.merge(rvalue_default<X>());
#endif
// Avoid unused variable warnings: // Avoid unused variable warnings:
@ -793,7 +775,6 @@ void unordered_copyable_test(X& x, Key& k, T& t, Hash& hf, Pred& eq)
// X a8a(i, j, m); // X a8a(i, j, m);
// sink(a8a); // sink(a8a);
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
std::size_t min_buckets = 10; std::size_t min_buckets = 10;
X({t}); X({t});
X({t}, min_buckets); X({t}, min_buckets);
@ -803,7 +784,6 @@ void unordered_copyable_test(X& x, Key& k, T& t, Hash& hf, Pred& eq)
X({t}, min_buckets, m); X({t}, min_buckets, m);
X({t}, min_buckets, hf, m); X({t}, min_buckets, hf, m);
X({t}, min_buckets, hf, eq, m); X({t}, min_buckets, hf, eq, m);
#endif
X const b; X const b;
sink(X(b)); sink(X(b));
@ -826,7 +806,6 @@ void unordered_copyable_test(X& x, Key& k, T& t, Hash& hf, Pred& eq)
test::check_return_type<iterator>::equals(a.emplace_hint(q, t)); test::check_return_type<iterator>::equals(a.emplace_hint(q, t));
a.insert(i, j); a.insert(i, j);
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
std::initializer_list<T> list = {t}; std::initializer_list<T> list = {t};
a.insert(list); a.insert(list);
a.insert({t, t, t}); a.insert({t, t, t});
@ -837,7 +816,6 @@ void unordered_copyable_test(X& x, Key& k, T& t, Hash& hf, Pred& eq)
a.insert({}); a.insert({});
a.insert({t}); a.insert({t});
a.insert({t, t}); a.insert({t, t});
#endif
#endif #endif
X a10; X a10;
@ -879,12 +857,10 @@ void unordered_movable_test(X& x, Key& k, T& /* t */, Hash& hf, Pred& eq)
typedef typename X::const_iterator const_iterator; typedef typename X::const_iterator const_iterator;
typedef typename X::allocator_type allocator_type; typedef typename X::allocator_type allocator_type;
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
X x1(rvalue_default<X>()); X x1(rvalue_default<X>());
X x2(boost::move(x1)); X x2(std::move(x1));
x1 = rvalue_default<X>(); x1 = rvalue_default<X>();
x2 = boost::move(x1); x2 = std::move(x1);
#endif
X a; X a;
allocator_type m = a.get_allocator(); allocator_type m = a.get_allocator();
@ -922,19 +898,19 @@ void unordered_movable_test(X& x, Key& k, T& /* t */, Hash& hf, Pred& eq)
test::check_return_type<iterator>::equals(a.emplace_hint(q, v)); test::check_return_type<iterator>::equals(a.emplace_hint(q, v));
T v1(v); T v1(v);
a.emplace(boost::move(v1)); a.emplace(std::move(v1));
T v2(v); T v2(v);
a.insert(boost::move(v2)); a.insert(std::move(v2));
T v3(v); T v3(v);
test::check_return_type<iterator>::equals(a.emplace_hint(q, boost::move(v3))); test::check_return_type<iterator>::equals(a.emplace_hint(q, std::move(v3)));
T v4(v); T v4(v);
test::check_return_type<iterator>::equals(a.insert(q, boost::move(v4))); test::check_return_type<iterator>::equals(a.insert(q, std::move(v4)));
a.insert(i, j); a.insert(i, j);
X a10; X a10;
T v5(v); T v5(v);
a10.insert(boost::move(v5)); a10.insert(std::move(v5));
q = a10.cbegin(); q = a10.cbegin();
#ifdef BOOST_UNORDERED_FOA_TESTS #ifdef BOOST_UNORDERED_FOA_TESTS
test::check_return_type<iterator>::convertible(a10.erase(q)); test::check_return_type<iterator>::convertible(a10.erase(q));

View File

@ -324,7 +324,6 @@ namespace constructor_tests {
test::check_equivalent_keys(x); test::check_equivalent_keys(x);
} }
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
typedef typename T::value_type value_type; typedef typename T::value_type value_type;
std::initializer_list<value_type> list; std::initializer_list<value_type> list;
@ -525,7 +524,6 @@ namespace constructor_tests {
test::check_container(x, expected); test::check_container(x, expected);
} }
} }
#endif
} }
template <class T> template <class T>
@ -608,7 +606,6 @@ namespace constructor_tests {
BOOST_TEST_EQ(test::detail::tracker.count_allocations, 0u); BOOST_TEST_EQ(test::detail::tracker.count_allocations, 0u);
} }
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
UNORDERED_SUB_TEST("Initializer list 1") UNORDERED_SUB_TEST("Initializer list 1")
{ {
std::initializer_list<typename T::value_type> list; std::initializer_list<typename T::value_type> list;
@ -633,7 +630,6 @@ namespace constructor_tests {
BOOST_TEST_GT(test::detail::tracker.count_allocations, 0u); BOOST_TEST_GT(test::detail::tracker.count_allocations, 0u);
} }
} }
#endif
} }
template <class T> template <class T>
@ -721,8 +717,6 @@ namespace constructor_tests {
(default_generator)(generate_collisions)(limited_range))) (default_generator)(generate_collisions)(limited_range)))
#endif #endif
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
UNORDERED_AUTO_TEST (test_default_initializer_list) { UNORDERED_AUTO_TEST (test_default_initializer_list) {
std::initializer_list<int> init; std::initializer_list<int> init;
#ifdef BOOST_UNORDERED_FOA_TESTS #ifdef BOOST_UNORDERED_FOA_TESTS
@ -735,10 +729,6 @@ namespace constructor_tests {
BOOST_TEST(x1.empty()); BOOST_TEST(x1.empty());
} }
#endif
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
UNORDERED_AUTO_TEST (test_initializer_list) { UNORDERED_AUTO_TEST (test_initializer_list) {
#ifdef BOOST_UNORDERED_FOA_TESTS #ifdef BOOST_UNORDERED_FOA_TESTS
boost::unordered_flat_set<int> x1 = {2, 10, 45, -5}; boost::unordered_flat_set<int> x1 = {2, 10, 45, -5};
@ -752,8 +742,6 @@ namespace constructor_tests {
BOOST_TEST(x1.find(10) != x1.end()); BOOST_TEST(x1.find(10) != x1.end());
BOOST_TEST(x1.find(46) == x1.end()); BOOST_TEST(x1.find(46) == x1.end());
} }
#endif
} // namespace constructor_tests } // namespace constructor_tests
RUN_TESTS_QUIET() RUN_TESTS_QUIET()

View File

@ -35,8 +35,8 @@ template <typename T> struct test_allocator
typedef T value_type; typedef T value_type;
test_allocator() = default; test_allocator() = default;
template <typename T2> test_allocator(test_allocator<T2> const&) {} template <typename T2> test_allocator(test_allocator<T2> const&) {}
T* allocate(std::size_t n) const { return (T*)malloc(sizeof(T) * n); } T* allocate(std::size_t n) const { return (T*)(::operator new(sizeof(T) * n)); }
void deallocate(T* ptr, std::size_t) const { free(ptr); } void deallocate(T* ptr, std::size_t) const { ::operator delete(ptr); }
bool operator==(test_allocator const&) const { return true; } bool operator==(test_allocator const&) const { return true; }
bool operator!=(test_allocator const&) const { return false; } bool operator!=(test_allocator const&) const { return false; }
}; };

View File

@ -6,14 +6,19 @@
#include "../helpers/unordered.hpp" #include "../helpers/unordered.hpp"
#include <boost/functional/hash/hash.hpp>
#include "../helpers/test.hpp"
#include "../helpers/count.hpp" #include "../helpers/count.hpp"
#include "../helpers/test.hpp"
#include <boost/container_hash/hash.hpp>
#include <boost/tuple/tuple.hpp>
#include <string> #include <string>
#include <type_traits>
// Test that various emplace methods work with different numbers of // Test that various emplace methods work with different numbers of
// arguments. // arguments.
BOOST_UNORDERED_STATIC_ASSERT(std::is_same<std::piecewise_construct_t,
boost::unordered::piecewise_construct_t>::value);
namespace emplace_tests { namespace emplace_tests {
// Constructible with 2 to 10 arguments // Constructible with 2 to 10 arguments
struct emplace_value : private test::counted_object struct emplace_value : private test::counted_object
@ -386,6 +391,7 @@ namespace emplace_tests {
template <class X> static void emplace_map(X*) template <class X> static void emplace_map(X*)
{ {
#ifdef BOOST_UNORDERED_FOA_TESTS
test::check_instances check_; test::check_instances check_;
typedef X container; typedef X container;
@ -394,7 +400,6 @@ namespace emplace_tests {
container x(10); container x(10);
return_type r1, r2; return_type r1, r2;
#ifdef BOOST_UNORDERED_FOA_TESTS
// 5/8 args + duplicate // 5/8 args + duplicate
emplace_value k1(5, "", 'b', 4, 5); emplace_value k1(5, "", 'b', 4, 5);
BOOST_TEST_EQ(check_.constructions(), 1); BOOST_TEST_EQ(check_.constructions(), 1);
@ -450,63 +455,138 @@ namespace emplace_tests {
BOOST_TEST_EQ(check_.instances(), 8); BOOST_TEST_EQ(check_.instances(), 8);
BOOST_TEST_EQ(check_.constructions(), 20); BOOST_TEST_EQ(check_.constructions(), 20);
#else #else
// 5/8 args + duplicate {
emplace_value k1(5, "", 'b', 4, 5); test::check_instances check_;
emplace_value m1(8, "xxx", 'z', 4, 5, 6, 7, 8);
r1 = x.emplace(boost::unordered::piecewise_construct,
boost::make_tuple(5, "", 'b', 4, 5),
boost::make_tuple(8, "xxx", 'z', 4, 5, 6, 7, 8));
BOOST_TEST_EQ(x.size(), 1u);
BOOST_TEST(r1.second);
BOOST_TEST(x.find(k1) == r1.first);
BOOST_TEST(x.find(k1)->second == m1);
BOOST_TEST_EQ(check_.instances(), 4);
BOOST_TEST_EQ(check_.constructions(), 4);
r2 = x.emplace(boost::unordered::piecewise_construct, typedef X container;
boost::make_tuple(5, "", 'b', 4, 5), typedef typename container::iterator iterator;
boost::make_tuple(8, "xxx", 'z', 4, 5, 6, 7, 8)); typedef std::pair<iterator, bool> return_type;
BOOST_TEST_EQ(x.size(), 1u); container x(10);
BOOST_TEST(!r2.second); return_type r1, r2;
BOOST_TEST(r1.first == r2.first);
BOOST_TEST(x.find(k1)->second == m1);
BOOST_TEST_EQ(check_.instances(), 4);
// constructions could possibly be 5 if the implementation only
// constructed the key.
BOOST_TEST_EQ(check_.constructions(), 6);
// 9/3 args + duplicates with hints, different mapped value. // 5/8 args + duplicate
emplace_value k1(5, "", 'b', 4, 5);
emplace_value m1(8, "xxx", 'z', 4, 5, 6, 7, 8);
r1 =
x.emplace(std::piecewise_construct, std::make_tuple(5, "", 'b', 4, 5),
std::make_tuple(8, "xxx", 'z', 4, 5, 6, 7, 8));
BOOST_TEST_EQ(x.size(), 1u);
BOOST_TEST(r1.second);
BOOST_TEST(x.find(k1) == r1.first);
BOOST_TEST(x.find(k1)->second == m1);
BOOST_TEST_EQ(check_.instances(), 4);
BOOST_TEST_EQ(check_.constructions(), 4);
emplace_value k2(9, "", 'b', 4, 5, 6, 7, 8, 9); r2 =
emplace_value m2(3, "aaa", 'm'); x.emplace(std::piecewise_construct, std::make_tuple(5, "", 'b', 4, 5),
r1 = x.emplace(boost::unordered::piecewise_construct, std::make_tuple(8, "xxx", 'z', 4, 5, 6, 7, 8));
boost::make_tuple(9, "", 'b', 4, 5, 6, 7, 8, 9), BOOST_TEST_EQ(x.size(), 1u);
boost::make_tuple(3, "aaa", 'm')); BOOST_TEST(!r2.second);
BOOST_TEST_EQ(x.size(), 2u); BOOST_TEST(r1.first == r2.first);
BOOST_TEST(r1.second); BOOST_TEST(x.find(k1)->second == m1);
BOOST_TEST(r1.first->first.arg_count == 9); BOOST_TEST_EQ(check_.instances(), 4);
BOOST_TEST(r1.first->second.arg_count == 3); // constructions could possibly be 5 if the implementation only
BOOST_TEST(x.find(k2) == r1.first); // constructed the key.
BOOST_TEST(x.find(k2)->second == m2); BOOST_TEST_EQ(check_.constructions(), 6);
BOOST_TEST_EQ(check_.instances(), 8);
BOOST_TEST_EQ(check_.constructions(), 10);
BOOST_TEST(r1.first == x.emplace_hint(r1.first, // 9/3 args + duplicates with hints, different mapped value.
boost::unordered::piecewise_construct,
boost::make_tuple(9, "", 'b', 4, 5, 6, 7, 8, 9), emplace_value k2(9, "", 'b', 4, 5, 6, 7, 8, 9);
boost::make_tuple(15, "jkjk"))); emplace_value m2(3, "aaa", 'm');
BOOST_TEST(r1.first == x.emplace_hint(r2.first, r1 = x.emplace(std::piecewise_construct,
boost::unordered::piecewise_construct, std::make_tuple(9, "", 'b', 4, 5, 6, 7, 8, 9),
boost::make_tuple(9, "", 'b', 4, 5, 6, 7, 8, 9), std::make_tuple(3, "aaa", 'm'));
boost::make_tuple(275, "xxx", 'm', 6))); BOOST_TEST_EQ(x.size(), 2u);
BOOST_TEST( BOOST_TEST(r1.second);
r1.first == x.emplace_hint(x.end(), boost::unordered::piecewise_construct, BOOST_TEST(r1.first->first.arg_count == 9);
boost::make_tuple(9, "", 'b', 4, 5, 6, 7, 8, 9), BOOST_TEST(r1.first->second.arg_count == 3);
boost::make_tuple(-10, "blah blah", '\0'))); BOOST_TEST(x.find(k2) == r1.first);
BOOST_TEST_EQ(x.size(), 2u); BOOST_TEST(x.find(k2)->second == m2);
BOOST_TEST(x.find(k2)->second == m2); BOOST_TEST_EQ(check_.instances(), 8);
BOOST_TEST_EQ(check_.instances(), 8); BOOST_TEST_EQ(check_.constructions(), 10);
BOOST_TEST_EQ(check_.constructions(), 16);
BOOST_TEST(r1.first == x.emplace_hint(r1.first, std::piecewise_construct,
std::make_tuple(9, "", 'b', 4, 5, 6, 7, 8, 9),
std::make_tuple(15, "jkjk")));
BOOST_TEST(r1.first == x.emplace_hint(r2.first, std::piecewise_construct,
std::make_tuple(9, "", 'b', 4, 5, 6, 7, 8, 9),
std::make_tuple(275, "xxx", 'm', 6)));
BOOST_TEST(r1.first == x.emplace_hint(x.end(), std::piecewise_construct,
std::make_tuple(9, "", 'b', 4, 5, 6, 7, 8, 9),
std::make_tuple(-10, "blah blah", '\0')));
BOOST_TEST_EQ(x.size(), 2u);
BOOST_TEST(x.find(k2)->second == m2);
BOOST_TEST_EQ(check_.instances(), 8);
BOOST_TEST_EQ(check_.constructions(), 16);
}
{
test::check_instances check_;
typedef X container;
typedef typename container::iterator iterator;
typedef std::pair<iterator, bool> return_type;
container x(10);
return_type r1, r2;
// 5/8 args + duplicate
emplace_value k1(5, "", 'b', 4, 5);
emplace_value m1(8, "xxx", 'z', 4, 5, 6, 7, 8);
r1 =
x.emplace(boost::unordered::piecewise_construct, boost::make_tuple(5, "", 'b', 4, 5),
boost::make_tuple(8, "xxx", 'z', 4, 5, 6, 7, 8));
BOOST_TEST_EQ(x.size(), 1u);
BOOST_TEST(r1.second);
BOOST_TEST(x.find(k1) == r1.first);
BOOST_TEST(x.find(k1)->second == m1);
BOOST_TEST_EQ(check_.instances(), 4);
BOOST_TEST_EQ(check_.constructions(), 4);
r2 =
x.emplace(boost::unordered::piecewise_construct, boost::make_tuple(5, "", 'b', 4, 5),
boost::make_tuple(8, "xxx", 'z', 4, 5, 6, 7, 8));
BOOST_TEST_EQ(x.size(), 1u);
BOOST_TEST(!r2.second);
BOOST_TEST(r1.first == r2.first);
BOOST_TEST(x.find(k1)->second == m1);
BOOST_TEST_EQ(check_.instances(), 4);
// constructions could possibly be 5 if the implementation only
// constructed the key.
BOOST_TEST_EQ(check_.constructions(), 6);
// 9/3 args + duplicates with hints, different mapped value.
emplace_value k2(9, "", 'b', 4, 5, 6, 7, 8, 9);
emplace_value m2(3, "aaa", 'm');
r1 = x.emplace(boost::unordered::piecewise_construct,
boost::make_tuple(9, "", 'b', 4, 5, 6, 7, 8, 9),
boost::make_tuple(3, "aaa", 'm'));
BOOST_TEST_EQ(x.size(), 2u);
BOOST_TEST(r1.second);
BOOST_TEST(r1.first->first.arg_count == 9);
BOOST_TEST(r1.first->second.arg_count == 3);
BOOST_TEST(x.find(k2) == r1.first);
BOOST_TEST(x.find(k2)->second == m2);
BOOST_TEST_EQ(check_.instances(), 8);
BOOST_TEST_EQ(check_.constructions(), 10);
BOOST_TEST(r1.first == x.emplace_hint(r1.first,
boost::unordered::piecewise_construct,
boost::make_tuple(9, "", 'b', 4, 5, 6, 7, 8, 9),
boost::make_tuple(15, "jkjk")));
BOOST_TEST(r1.first == x.emplace_hint(r2.first,
boost::unordered::piecewise_construct,
boost::make_tuple(9, "", 'b', 4, 5, 6, 7, 8, 9),
boost::make_tuple(275, "xxx", 'm', 6)));
BOOST_TEST(r1.first == x.emplace_hint(x.end(),
boost::unordered::piecewise_construct,
boost::make_tuple(9, "", 'b', 4, 5, 6, 7, 8, 9),
boost::make_tuple(-10, "blah blah", '\0')));
BOOST_TEST_EQ(x.size(), 2u);
BOOST_TEST(x.find(k2)->second == m2);
BOOST_TEST_EQ(check_.instances(), 8);
BOOST_TEST_EQ(check_.constructions(), 16);
}
#endif #endif
} }

View File

@ -16,6 +16,7 @@
#include "../helpers/list.hpp" #include "../helpers/list.hpp"
#include "../helpers/invariants.hpp" #include "../helpers/invariants.hpp"
#include "../helpers/helpers.hpp" #include "../helpers/helpers.hpp"
#include <algorithm>
#include <set> #include <set>
#include <iterator> #include <iterator>
#include "../objects/test.hpp" #include "../objects/test.hpp"

View File

@ -9,11 +9,7 @@
#include <boost/config.hpp> #include <boost/config.hpp>
#include <string> #include <string>
#if !defined(BOOST_NO_CXX11_REF_QUALIFIERS)
#define UNORDERED_LVALUE_QUAL & #define UNORDERED_LVALUE_QUAL &
#else
#define UNORDERED_LVALUE_QUAL
#endif
namespace test { namespace test {
struct is_even struct is_even

View File

@ -17,7 +17,7 @@
#include "../helpers/input_iterator.hpp" #include "../helpers/input_iterator.hpp"
#include "../helpers/helpers.hpp" #include "../helpers/helpers.hpp"
#include <boost/move/core.hpp> #include <boost/tuple/tuple.hpp>
#include <vector> #include <vector>
namespace insert_tests { namespace insert_tests {
@ -75,7 +75,7 @@ namespace insert_tests {
float b = x.max_load_factor(); float b = x.max_load_factor();
typename X::value_type value = *it; typename X::value_type value = *it;
std::pair<iterator, bool> r1 = x.insert(boost::move(value)); std::pair<iterator, bool> r1 = x.insert(std::move(value));
std::pair<typename ordered::iterator, bool> r2 = tracker.insert(*it); std::pair<typename ordered::iterator, bool> r2 = tracker.insert(*it);
BOOST_TEST(r1.second == r2.second); BOOST_TEST(r1.second == r2.second);
@ -137,7 +137,7 @@ namespace insert_tests {
float b = x.max_load_factor(); float b = x.max_load_factor();
typename X::value_type value = *it; typename X::value_type value = *it;
typename X::iterator r1 = x.insert(boost::move(value)); typename X::iterator r1 = x.insert(std::move(value));
typename test::ordered<X>::iterator r2 = tracker.insert(*it); typename test::ordered<X>::iterator r2 = tracker.insert(*it);
BOOST_TEST(*r1 == *r2); BOOST_TEST(*r1 == *r2);
@ -258,7 +258,7 @@ namespace insert_tests {
float b = x.max_load_factor(); float b = x.max_load_factor();
typename X::value_type value = *it; typename X::value_type value = *it;
pos = x.insert(pos, boost::move(value)); pos = x.insert(pos, std::move(value));
tracker_iterator r2 = tracker.insert(tracker.begin(), *it); tracker_iterator r2 = tracker.insert(tracker.begin(), *it);
BOOST_TEST(*pos == *r2); BOOST_TEST(*pos == *r2);
tracker.compare_key(x, *it); tracker.compare_key(x, *it);
@ -484,7 +484,7 @@ namespace insert_tests {
float b = x.max_load_factor(); float b = x.max_load_factor();
typename X::value_type value = *it; typename X::value_type value = *it;
x.emplace(boost::move(value)); x.emplace(std::move(value));
tracker.insert(*it); tracker.insert(*it);
tracker.compare_key(x, *it); tracker.compare_key(x, *it);
@ -499,7 +499,6 @@ namespace insert_tests {
template <class X> void default_emplace_tests(X*, test::random_generator) template <class X> void default_emplace_tests(X*, test::random_generator)
{ {
#if !BOOST_UNORDERED_SUN_WORKAROUNDS1
bool is_unique = test::has_unique_keys<X>::value; bool is_unique = test::has_unique_keys<X>::value;
X x; X x;
@ -529,7 +528,6 @@ namespace insert_tests {
BOOST_TEST(x.count(test::get_key<X>(y)) == (is_unique ? 1u : 2u)); BOOST_TEST(x.count(test::get_key<X>(y)) == (is_unique ? 1u : 2u));
BOOST_TEST(*x.equal_range(test::get_key<X>(y)).first == y); BOOST_TEST(*x.equal_range(test::get_key<X>(y)).first == y);
#endif
} }
template <class X> void map_tests(X*, test::random_generator generator) template <class X> void map_tests(X*, test::random_generator generator)
@ -701,7 +699,7 @@ namespace insert_tests {
pointer_constructible(int x_) : x(x_) {} pointer_constructible(int x_) : x(x_) {}
pointer_constructible(pointer_constructible const& p) : x(p.x) {} pointer_constructible(pointer_constructible const& p) : x(p.x) {}
pointer_constructible(pointer_constructible* const&) : x(-1) {} pointer_constructible(pointer_constructible* const&) : x(-1) {}
pointer_constructible(BOOST_RV_REF(pointer_constructible*)) : x(-1) {} pointer_constructible(pointer_constructible*&&) : x(-1) {}
}; };
struct pointer_constructible_hash struct pointer_constructible_hash
@ -1079,8 +1077,6 @@ namespace insert_tests {
UNORDERED_TEST(set_tests2, ((test_pc_set))) UNORDERED_TEST(set_tests2, ((test_pc_set)))
#endif #endif
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
struct initialize_from_two_ints struct initialize_from_two_ints
{ {
int a, b; int a, b;
@ -1201,8 +1197,6 @@ namespace insert_tests {
BOOST_TEST_EQ(multimap.size(), 3u); BOOST_TEST_EQ(multimap.size(), 3u);
BOOST_TEST_EQ(multimap.count("a"), 2u); BOOST_TEST_EQ(multimap.count("a"), 2u);
} }
#endif
#endif #endif
struct overloaded_constructor struct overloaded_constructor
@ -1233,11 +1227,9 @@ namespace insert_tests {
template <class X> static void map_emplace_test(X*) template <class X> static void map_emplace_test(X*)
{ {
X x; X x;
#if !BOOST_UNORDERED_SUN_WORKAROUNDS1
x.emplace(); x.emplace();
BOOST_TEST( BOOST_TEST(
x.find(0) != x.end() && x.find(0)->second == overloaded_constructor()); x.find(0) != x.end() && x.find(0)->second == overloaded_constructor());
#endif
x.emplace(2, 3); x.emplace(2, 3);
BOOST_TEST( BOOST_TEST(
@ -1252,11 +1244,9 @@ namespace insert_tests {
template <class X> static void multimap_emplace_test(X*) template <class X> static void multimap_emplace_test(X*)
{ {
X x; X x;
#if !BOOST_UNORDERED_SUN_WORKAROUNDS1
x.emplace(); x.emplace();
BOOST_TEST( BOOST_TEST(
x.find(0) != x.end() && x.find(0)->second == overloaded_constructor()); x.find(0) != x.end() && x.find(0)->second == overloaded_constructor());
#endif
x.emplace(2, 3); x.emplace(2, 3);
BOOST_TEST( BOOST_TEST(
@ -1296,10 +1286,8 @@ namespace insert_tests {
X x; X x;
overloaded_constructor check; overloaded_constructor check;
#if !BOOST_UNORDERED_SUN_WORKAROUNDS1
x.emplace(); x.emplace();
BOOST_TEST(x.find(check) != x.end() && *x.find(check) == check); BOOST_TEST(x.find(check) != x.end() && *x.find(check) == check);
#endif
x.clear(); x.clear();
x.emplace(1); x.emplace(1);
@ -1354,10 +1342,6 @@ namespace insert_tests {
#ifndef BOOST_UNORDERED_FOA_TESTS #ifndef BOOST_UNORDERED_FOA_TESTS
UNORDERED_AUTO_TEST (map_emplace_test2) { UNORDERED_AUTO_TEST (map_emplace_test2) {
// Emulating piecewise construction with boost::tuple bypasses the
// allocator's construct method, but still uses test destroy method.
test::detail::disable_construction_tracking _scoped;
{ {
boost::unordered_map<overloaded_constructor, overloaded_constructor, boost::unordered_map<overloaded_constructor, overloaded_constructor,
boost::hash<overloaded_constructor>, boost::hash<overloaded_constructor>,
@ -1497,7 +1481,11 @@ namespace insert_tests {
#define EMULATING_PIECEWISE_CONSTRUCTION 1 #define EMULATING_PIECEWISE_CONSTRUCTION 1
#include "./insert_tests.cpp" #include "./insert_tests.cpp"
#if BOOST_UNORDERED_HAVE_PIECEWISE_CONSTRUCT #define PIECEWISE_TEST_NAME std_tuple_boost_piecewise_tests
#define PIECEWISE_NAMESPACE boost::unordered
#define TUPLE_NAMESPACE std
#define EMULATING_PIECEWISE_CONSTRUCTION 0
#include "./insert_tests.cpp"
#define PIECEWISE_TEST_NAME boost_tuple_std_piecewise_tests #define PIECEWISE_TEST_NAME boost_tuple_std_piecewise_tests
#define PIECEWISE_NAMESPACE std #define PIECEWISE_NAMESPACE std
@ -1507,21 +1495,6 @@ namespace insert_tests {
#endif #endif
#if !defined(BOOST_NO_CXX11_HDR_TUPLE)
#define PIECEWISE_TEST_NAME std_tuple_boost_piecewise_tests
#define PIECEWISE_NAMESPACE boost::unordered
#define TUPLE_NAMESPACE std
#define EMULATING_PIECEWISE_CONSTRUCTION 0
#include "./insert_tests.cpp"
#endif
#endif
#if !defined(BOOST_NO_CXX11_HDR_TUPLE) && \
BOOST_UNORDERED_HAVE_PIECEWISE_CONSTRUCT
#ifdef BOOST_UNORDERED_FOA_TESTS #ifdef BOOST_UNORDERED_FOA_TESTS
static boost::unordered_flat_set<std::pair<overloaded_constructor, static boost::unordered_flat_set<std::pair<overloaded_constructor,
overloaded_constructor> >* test_pair_oc_set; overloaded_constructor> >* test_pair_oc_set;
@ -1535,8 +1508,6 @@ namespace insert_tests {
#define TUPLE_NAMESPACE std #define TUPLE_NAMESPACE std
#define EMULATING_PIECEWISE_CONSTRUCTION 0 #define EMULATING_PIECEWISE_CONSTRUCTION 0
#include "./insert_tests.cpp" #include "./insert_tests.cpp"
#endif
} }
RUN_TESTS_QUIET() RUN_TESTS_QUIET()
@ -1549,10 +1520,6 @@ RUN_TESTS_QUIET()
template <class X> template <class X>
static void MAP_PIECEWISE_TEST(X*) static void MAP_PIECEWISE_TEST(X*)
{ {
#if EMULATING_PIECEWISE_CONSTRUCTION
test::detail::disable_construction_tracking _scoped;
#endif
X x; X x;
x.emplace(PIECEWISE_NAMESPACE::piecewise_construct, x.emplace(PIECEWISE_NAMESPACE::piecewise_construct,
@ -1601,10 +1568,6 @@ RUN_TESTS_QUIET()
template <class X> template <class X>
static void SET_PIECEWISE_TEST(X*) static void SET_PIECEWISE_TEST(X*)
{ {
#if EMULATING_PIECEWISE_CONSTRUCTION
test::detail::disable_construction_tracking _scoped;
#endif
X x; X x;
std::pair<overloaded_constructor, overloaded_constructor> check; std::pair<overloaded_constructor, overloaded_constructor> check;
@ -1645,9 +1608,6 @@ RUN_TESTS_QUIET()
#ifndef BOOST_UNORDERED_FOA_TESTS #ifndef BOOST_UNORDERED_FOA_TESTS
UNORDERED_AUTO_TEST (BOOST_PP_CAT(multimap_, PIECEWISE_TEST_NAME)) { UNORDERED_AUTO_TEST (BOOST_PP_CAT(multimap_, PIECEWISE_TEST_NAME)) {
{ {
#if EMULATING_PIECEWISE_CONSTRUCTION
test::detail::disable_construction_tracking _scoped;
#endif
boost::unordered_multimap<overloaded_constructor, overloaded_constructor, boost::unordered_multimap<overloaded_constructor, overloaded_constructor,
boost::hash<overloaded_constructor>, boost::hash<overloaded_constructor>,
std::equal_to<overloaded_constructor>, std::equal_to<overloaded_constructor>,

View File

@ -48,13 +48,8 @@ template <typename T> void test_simple_allocator()
BOOST_STATIC_ASSERT( BOOST_STATIC_ASSERT(
(boost::is_same<typename traits::difference_type, std::ptrdiff_t>::value)); (boost::is_same<typename traits::difference_type, std::ptrdiff_t>::value));
#if !defined(BOOST_NO_CXX11_ALLOCATOR)
BOOST_STATIC_ASSERT((boost::is_same<typename traits::size_type, BOOST_STATIC_ASSERT((boost::is_same<typename traits::size_type,
std::make_unsigned<std::ptrdiff_t>::type>::value)); std::make_unsigned<std::ptrdiff_t>::type>::value));
#else
BOOST_STATIC_ASSERT(
(boost::is_same<typename traits::size_type, std::size_t>::value));
#endif
BOOST_TEST(!traits::propagate_on_container_copy_assignment::value); BOOST_TEST(!traits::propagate_on_container_copy_assignment::value);
BOOST_TEST(!traits::propagate_on_container_move_assignment::value); BOOST_TEST(!traits::propagate_on_container_move_assignment::value);

View File

@ -23,12 +23,7 @@
namespace move_tests { namespace move_tests {
test::seed_t initialize_seed(98624); test::seed_t initialize_seed(98624);
#if defined(BOOST_UNORDERED_USE_MOVE) || \
!defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
#define BOOST_UNORDERED_TEST_MOVING 1 #define BOOST_UNORDERED_TEST_MOVING 1
#else
#define BOOST_UNORDERED_TEST_MOVING 0
#endif
template <class T> T empty(T*) { return T(); } template <class T> T empty(T*) { return T(); }
@ -73,8 +68,6 @@ namespace move_tests {
BOOST_TEST(y.max_load_factor() == 1.0); BOOST_TEST(y.max_load_factor() == 1.0);
#endif #endif
test::check_equivalent_keys(y); test::check_equivalent_keys(y);
#if defined(BOOST_UNORDERED_USE_MOVE) || \
!defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
#ifdef BOOST_UNORDERED_FOA_TESTS #ifdef BOOST_UNORDERED_FOA_TESTS
using allocator_type = typename T::allocator_type; using allocator_type = typename T::allocator_type;
@ -86,7 +79,6 @@ namespace move_tests {
} }
#else #else
BOOST_TEST_EQ(test::detail::tracker.count_allocations, 0u); BOOST_TEST_EQ(test::detail::tracker.count_allocations, 0u);
#endif
#endif #endif
} }
@ -126,8 +118,7 @@ namespace move_tests {
T y; T y;
y = empty(p); y = empty(p);
#if defined(BOOST_UNORDERED_USE_MOVE) || \
!defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
#ifdef BOOST_UNORDERED_FOA_TESTS #ifdef BOOST_UNORDERED_FOA_TESTS
using allocator_type = typename T::allocator_type; using allocator_type = typename T::allocator_type;
using value_type = using value_type =
@ -138,7 +129,6 @@ namespace move_tests {
} }
#else #else
BOOST_TEST_EQ(test::detail::tracker.count_allocations, 0u); BOOST_TEST_EQ(test::detail::tracker.count_allocations, 0u);
#endif
#endif #endif
test::check_container(y, v); test::check_container(y, v);
test::check_equivalent_keys(y); test::check_equivalent_keys(y);
@ -200,23 +190,8 @@ namespace move_tests {
test::random_values<T> v(25, generator); test::random_values<T> v(25, generator);
T y(create(v, count, hf, eq, al, 1.0), al); T y(create(v, count, hf, eq, al, 1.0), al);
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
BOOST_TEST(count == test::global_object_count); BOOST_TEST(count == test::global_object_count);
#elif defined(BOOST_HAS_NRVO)
BOOST_TEST(
static_cast<std::size_t>(
test::global_object_count.constructions - count.constructions) <=
(test::is_set<T>::value ? 1 : 2) *
(test::has_unique_keys<T>::value ? 25 : v.size()));
BOOST_TEST(count.instances == test::global_object_count.instances);
#else
BOOST_TEST(
static_cast<std::size_t>(
test::global_object_count.constructions - count.constructions) <=
(test::is_set<T>::value ? 2 : 4) *
(test::has_unique_keys<T>::value ? 25 : v.size()));
BOOST_TEST(count.instances == test::global_object_count.instances);
#endif
test::check_container(y, v); test::check_container(y, v);
BOOST_TEST(test::equivalent(y.hash_function(), hf)); BOOST_TEST(test::equivalent(y.hash_function(), hf));
BOOST_TEST(test::equivalent(y.key_eq(), eq)); BOOST_TEST(test::equivalent(y.key_eq(), eq));
@ -313,9 +288,8 @@ namespace move_tests {
BOOST_TEST_EQ(test::detail::tracker.count_allocations, 0u); BOOST_TEST_EQ(test::detail::tracker.count_allocations, 0u);
#endif #endif
y = boost::move(x); y = std::move(x);
#if defined(BOOST_UNORDERED_USE_MOVE) || \
!defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
#ifdef BOOST_UNORDERED_FOA_TESTS #ifdef BOOST_UNORDERED_FOA_TESTS
{ {
using value_type = using value_type =
@ -327,7 +301,6 @@ namespace move_tests {
} }
#else #else
BOOST_TEST_EQ(test::detail::tracker.count_allocations, 0u); BOOST_TEST_EQ(test::detail::tracker.count_allocations, 0u);
#endif
#endif #endif
test::check_container(y, v); test::check_container(y, v);
test::check_equivalent_keys(y); test::check_equivalent_keys(y);
@ -357,7 +330,7 @@ namespace move_tests {
x.insert(v.begin(), v.end()); x.insert(v.begin(), v.end());
test::object_count count = test::global_object_count; test::object_count count = test::global_object_count;
y = boost::move(x); y = std::move(x);
if (BOOST_UNORDERED_TEST_MOVING && allocator_type::is_propagate_on_move) { if (BOOST_UNORDERED_TEST_MOVING && allocator_type::is_propagate_on_move) {
BOOST_TEST(count == test::global_object_count); BOOST_TEST(count == test::global_object_count);
} }
@ -391,7 +364,7 @@ namespace move_tests {
test::object_count count1 = test::global_object_count; test::object_count count1 = test::global_object_count;
T y(v1.begin(), v1.end(), 0, hf, eq, al1); T y(v1.begin(), v1.end(), 0, hf, eq, al1);
y = boost::move(x); y = std::move(x);
test::object_count count2 = test::global_object_count; test::object_count count2 = test::global_object_count;

View File

@ -4,6 +4,8 @@
// Distributed under the Boost Software License, Version 1.0. (See accompanying // 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) // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <boost/config.hpp>
#include "../helpers/postfix.hpp" #include "../helpers/postfix.hpp"
#include "../helpers/prefix.hpp" #include "../helpers/prefix.hpp"
#include "../helpers/unordered.hpp" #include "../helpers/unordered.hpp"
@ -17,6 +19,11 @@
#include <set> #include <set>
#include <string> #include <string>
#if defined(BOOST_GCC) && BOOST_GCC >= 130000
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wself-move"
#endif
template <template <class Key, class T, class Hash = boost::hash<Key>, template <template <class Key, class T, class Hash = boost::hash<Key>,
class Pred = std::equal_to<Key>, class Pred = std::equal_to<Key>,
class Allocator = std::allocator<std::pair<Key const, T> > > class Allocator = std::allocator<std::pair<Key const, T> > >
@ -119,12 +126,12 @@ static void failed_insertion_with_hint()
typename Set<int>::node_type nh = src.extract(10); typename Set<int>::node_type nh = src.extract(10);
BOOST_TEST(dst.insert(dst.find(10), boost::move(nh)) == dst.find(10)); BOOST_TEST(dst.insert(dst.find(10), std::move(nh)) == dst.find(10));
BOOST_TEST(nh); BOOST_TEST(nh);
BOOST_TEST(!nh.empty()); BOOST_TEST(!nh.empty());
BOOST_TEST(nh.value() == 10); BOOST_TEST(nh.value() == 10);
BOOST_TEST(dst.insert(dst.find(20), boost::move(nh)) == dst.find(10)); BOOST_TEST(dst.insert(dst.find(20), std::move(nh)) == dst.find(10));
BOOST_TEST(nh); BOOST_TEST(nh);
BOOST_TEST(!nh.empty()); BOOST_TEST(!nh.empty());
BOOST_TEST(nh.value() == 10); BOOST_TEST(nh.value() == 10);
@ -144,14 +151,14 @@ static void failed_insertion_with_hint()
dst.emplace(20, 2); dst.emplace(20, 2);
typename Map<int, int>::node_type nh = src.extract(10); typename Map<int, int>::node_type nh = src.extract(10);
BOOST_TEST(dst.insert(dst.find(10), boost::move(nh)) == dst.find(10)); BOOST_TEST(dst.insert(dst.find(10), std::move(nh)) == dst.find(10));
BOOST_TEST(nh); BOOST_TEST(nh);
BOOST_TEST(!nh.empty()); BOOST_TEST(!nh.empty());
BOOST_TEST(nh.key() == 10); BOOST_TEST(nh.key() == 10);
BOOST_TEST(nh.mapped() == 30); BOOST_TEST(nh.mapped() == 30);
BOOST_TEST(dst[10] == 20); BOOST_TEST(dst[10] == 20);
BOOST_TEST(dst.insert(dst.find(20), boost::move(nh)) == dst.find(10)); BOOST_TEST(dst.insert(dst.find(20), std::move(nh)) == dst.find(10));
BOOST_TEST(nh); BOOST_TEST(nh);
BOOST_TEST(!nh.empty()); BOOST_TEST(!nh.empty());
BOOST_TEST(nh.key() == 10); BOOST_TEST(nh.key() == 10);
@ -195,7 +202,7 @@ template <typename Container> void node_handle_tests_impl(Container& c)
BOOST_TEST(!n2.empty()); BOOST_TEST(!n2.empty());
node_handle_compare(n2, value); node_handle_compare(n2, value);
node_type n3 = boost::move(n2); node_type n3 = std::move(n2);
BOOST_TEST(n3); BOOST_TEST(n3);
BOOST_TEST(!n2); BOOST_TEST(!n2);
node_handle_compare(n3, value); node_handle_compare(n3, value);
@ -203,16 +210,16 @@ template <typename Container> void node_handle_tests_impl(Container& c)
// Maybe by swapping and observing that the allocator is // Maybe by swapping and observing that the allocator is
// swapped rather than moved? // swapped rather than moved?
n1 = boost::move(n3); n1 = std::move(n3);
BOOST_TEST(n1); BOOST_TEST(n1);
BOOST_TEST(!n3); BOOST_TEST(!n3);
node_handle_compare(n1, value); node_handle_compare(n1, value);
// Self move-assignment empties the node_handle. // Self move-assignment empties the node_handle.
n1 = boost::move(n1); n1 = std::move(n1);
BOOST_TEST(!n1); BOOST_TEST(!n1);
n3 = boost::move(n3); n3 = std::move(n3);
BOOST_TEST(!n3); BOOST_TEST(!n3);
typename Container::value_type value1 = *c.begin(); typename Container::value_type value1 = *c.begin();

View File

@ -57,13 +57,10 @@ namespace noexcept_tests {
bool nothrow_swap> bool nothrow_swap>
class hash_nothrow : boost::hash<int> class hash_nothrow : boost::hash<int>
{ {
BOOST_COPYABLE_AND_MOVABLE(hash_nothrow)
typedef boost::hash<int> base; typedef boost::hash<int> base;
public: public:
hash_nothrow(BOOST_RV_REF(hash_nothrow)) hash_nothrow(hash_nothrow&&) noexcept(nothrow_move_construct)
BOOST_NOEXCEPT_IF(nothrow_move_construct)
{ {
if (!nothrow_move_construct) { if (!nothrow_move_construct) {
test_throw("Move Constructor"); test_throw("Move Constructor");
@ -72,13 +69,13 @@ namespace noexcept_tests {
hash_nothrow() { test_throw("Constructor"); } hash_nothrow() { test_throw("Constructor"); }
hash_nothrow(hash_nothrow const&) { test_throw("Copy"); } hash_nothrow(hash_nothrow const&) { test_throw("Copy"); }
hash_nothrow& operator=(BOOST_COPY_ASSIGN_REF(hash_nothrow)) hash_nothrow& operator=(hash_nothrow const&)
{ {
test_throw("Assign"); test_throw("Assign");
return *this; return *this;
} }
hash_nothrow& operator=(BOOST_RV_REF(hash_nothrow)) hash_nothrow& operator=(hash_nothrow&&)
BOOST_NOEXCEPT_IF(nothrow_move_assign) noexcept(nothrow_move_assign)
{ {
if (!nothrow_move_assign) { if (!nothrow_move_assign) {
test_throw("Move Assign"); test_throw("Move Assign");
@ -90,8 +87,7 @@ namespace noexcept_tests {
test_throw("Operator"); test_throw("Operator");
return static_cast<base const&>(*this)(x); return static_cast<base const&>(*this)(x);
} }
friend void swap(hash_nothrow&, hash_nothrow&) friend void swap(hash_nothrow&, hash_nothrow&) noexcept(nothrow_swap)
BOOST_NOEXCEPT_IF(nothrow_swap)
{ {
if (!nothrow_swap) { if (!nothrow_swap) {
test_throw("Swap"); test_throw("Swap");
@ -107,13 +103,11 @@ namespace noexcept_tests {
bool nothrow_swap> bool nothrow_swap>
class equal_to_nothrow class equal_to_nothrow
{ {
BOOST_COPYABLE_AND_MOVABLE(equal_to_nothrow)
typedef boost::hash<int> base; typedef boost::hash<int> base;
public: public:
equal_to_nothrow(BOOST_RV_REF(equal_to_nothrow)) equal_to_nothrow(equal_to_nothrow&&)
BOOST_NOEXCEPT_IF(nothrow_move_construct) noexcept(nothrow_move_construct)
{ {
if (!nothrow_move_construct) { if (!nothrow_move_construct) {
test_throw("Move Constructor"); test_throw("Move Constructor");
@ -122,13 +116,13 @@ namespace noexcept_tests {
equal_to_nothrow() { test_throw("Constructor"); } equal_to_nothrow() { test_throw("Constructor"); }
equal_to_nothrow(equal_to_nothrow const&) { test_throw("Copy"); } equal_to_nothrow(equal_to_nothrow const&) { test_throw("Copy"); }
equal_to_nothrow& operator=(BOOST_COPY_ASSIGN_REF(equal_to_nothrow)) equal_to_nothrow& operator=(equal_to_nothrow const&)
{ {
test_throw("Assign"); test_throw("Assign");
return *this; return *this;
} }
equal_to_nothrow& operator=(BOOST_RV_REF(equal_to_nothrow)) equal_to_nothrow& operator=(equal_to_nothrow&&)
BOOST_NOEXCEPT_IF(nothrow_move_assign) noexcept(nothrow_move_assign)
{ {
if (!nothrow_move_assign) { if (!nothrow_move_assign) {
test_throw("Move Assign"); test_throw("Move Assign");
@ -141,7 +135,7 @@ namespace noexcept_tests {
return x == y; return x == y;
} }
friend void swap(equal_to_nothrow&, equal_to_nothrow&) friend void swap(equal_to_nothrow&, equal_to_nothrow&)
BOOST_NOEXCEPT_IF(nothrow_swap) noexcept(nothrow_swap)
{ {
if (!nothrow_swap) { if (!nothrow_swap) {
test_throw("Swap"); test_throw("Swap");
@ -178,18 +172,9 @@ namespace noexcept_tests {
boost::is_nothrow_swappable<hash_nothrow_swap>::value; boost::is_nothrow_swappable<hash_nothrow_swap>::value;
// Check that the traits work when expected. // Check that the traits work when expected.
#if !defined(BOOST_NO_CXX11_NOEXCEPT) && !defined(BOOST_NO_SFINAE_EXPR) && \
!BOOST_WORKAROUND(BOOST_GCC_VERSION, < 40800)
BOOST_TEST(have_is_nothrow_move); BOOST_TEST(have_is_nothrow_move);
BOOST_TEST(have_is_nothrow_move_assign); BOOST_TEST(have_is_nothrow_move_assign);
#endif
#if !defined(BOOST_NO_SFINAE_EXPR) && !defined(BOOST_NO_CXX11_NOEXCEPT) && \
!defined(BOOST_NO_CXX11_DECLTYPE) && \
!defined(BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS) && \
!BOOST_WORKAROUND(BOOST_GCC_VERSION, < 40700)
BOOST_TEST(have_is_nothrow_swap); BOOST_TEST(have_is_nothrow_swap);
#endif
BOOST_LIGHTWEIGHT_TEST_OSTREAM BOOST_LIGHTWEIGHT_TEST_OSTREAM
<< "have_is_nothrow_move: " << have_is_nothrow_move << std::endl << "have_is_nothrow_move: " << have_is_nothrow_move << std::endl
@ -257,7 +242,7 @@ namespace noexcept_tests {
try { try {
throwing_test_exception = true; throwing_test_exception = true;
X x2 = boost::move(x1); X x2 = std::move(x1);
BOOST_TEST(x2.size() == 2); BOOST_TEST(x2.size() == 2);
BOOST_TEST(*x2.begin() == 10 || *x2.begin() == 50); BOOST_TEST(*x2.begin() == 10 || *x2.begin() == 50);
BOOST_TEST(have_is_nothrow_move); BOOST_TEST(have_is_nothrow_move);
@ -289,7 +274,7 @@ namespace noexcept_tests {
try { try {
throwing_test_exception = true; throwing_test_exception = true;
x2 = boost::move(x1); x2 = std::move(x1);
BOOST_TEST(x2.size() == 2); BOOST_TEST(x2.size() == 2);
BOOST_TEST(*x2.begin() == 10 || *x2.begin() == 50); BOOST_TEST(*x2.begin() == 10 || *x2.begin() == 50);
BOOST_TEST(have_is_nothrow_move_assign); BOOST_TEST(have_is_nothrow_move_assign);
@ -318,7 +303,7 @@ namespace noexcept_tests {
try { try {
throwing_test_exception = true; throwing_test_exception = true;
x1 = boost::move(x2); x1 = std::move(x2);
BOOST_TEST(x1.size() == 100); BOOST_TEST(x1.size() == 100);
BOOST_TEST(have_is_nothrow_move_assign); BOOST_TEST(have_is_nothrow_move_assign);
} catch (test_exception) { } catch (test_exception) {
@ -367,9 +352,8 @@ namespace noexcept_tests {
template <class T> class allocator1 template <class T> class allocator1
{ {
BOOST_COPYABLE_AND_MOVABLE(allocator1) allocator1 operator=(allocator1 const&);
allocator1 operator=(BOOST_COPY_ASSIGN_REF(allocator1)); allocator1 operator=(allocator1&&);
allocator1 operator=(BOOST_RV_REF(allocator1));
public: public:
typedef T value_type; typedef T value_type;
@ -393,8 +377,7 @@ public:
template <class T> class allocator2 template <class T> class allocator2
{ {
BOOST_COPYABLE_AND_MOVABLE(allocator2) allocator2 operator=(allocator2 const&);
allocator2 operator=(BOOST_COPY_ASSIGN_REF(allocator2));
public: public:
typedef T value_type; typedef T value_type;
@ -405,7 +388,7 @@ public:
template <class U> allocator2(allocator2<U> const&) {} template <class U> allocator2(allocator2<U> const&) {}
allocator2& operator=(BOOST_RV_REF(allocator2)) { return *this; } allocator2& operator=(allocator2&&) { return *this; }
T* allocate(std::size_t n) T* allocate(std::size_t n)
{ {

View File

@ -21,12 +21,7 @@
namespace move_tests { namespace move_tests {
test::seed_t initialize_seed(98624); test::seed_t initialize_seed(98624);
#if defined(BOOST_UNORDERED_USE_MOVE) || \
!defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
#define BOOST_UNORDERED_TEST_MOVING 1 #define BOOST_UNORDERED_TEST_MOVING 1
#else
#define BOOST_UNORDERED_TEST_MOVING 0
#endif
template <class T> T empty(T*) { return T(); } template <class T> T empty(T*) { return T(); }
@ -322,7 +317,7 @@ namespace move_tests {
{ {
T x(v.begin(), v.end()); T x(v.begin(), v.end());
std::size_t const size = x.size(); std::size_t const size = x.size();
y = boost::move(x); y = std::move(x);
BOOST_TEST_GE(y.size(), size); BOOST_TEST_GE(y.size(), size);
BOOST_TEST_EQ(y.size(), BOOST_TEST_EQ(y.size(),
static_cast<typename T::size_type>(std::distance(y.begin(), y.end()))); static_cast<typename T::size_type>(std::distance(y.begin(), y.end())));
@ -393,7 +388,7 @@ namespace move_tests {
template <class T> template <class T>
static void double_move_construct(T& y, test::random_values<T> const&) static void double_move_construct(T& y, test::random_values<T> const&)
{ {
T x = boost::move(y); T x = std::move(y);
x.clear(); x.clear();
BOOST_TEST_EQ(y.size(), BOOST_TEST_EQ(y.size(),
static_cast<typename T::size_type>(std::distance(y.begin(), y.end()))); static_cast<typename T::size_type>(std::distance(y.begin(), y.end())));
@ -405,7 +400,7 @@ namespace move_tests {
static void double_move_assign(T& y, test::random_values<T> const&) static void double_move_assign(T& y, test::random_values<T> const&)
{ {
T x; T x;
x = boost::move(y); x = std::move(y);
x.clear(); x.clear();
BOOST_TEST_EQ(y.size(), BOOST_TEST_EQ(y.size(),
static_cast<typename T::size_type>(std::distance(y.begin(), y.end()))); static_cast<typename T::size_type>(std::distance(y.begin(), y.end())));
@ -461,10 +456,8 @@ namespace move_tests {
unsigned num_allocs = test::detail::tracker.count_allocations; unsigned num_allocs = test::detail::tracker.count_allocations;
(void)num_allocs; (void)num_allocs;
T x(boost::move(y)); T x(std::move(y));
#if defined(BOOST_UNORDERED_USE_MOVE) || \
!defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
BOOST_TEST(y.empty()); BOOST_TEST(y.empty());
BOOST_TEST(y.begin() == y.end()); BOOST_TEST(y.begin() == y.end());
@ -482,8 +475,6 @@ namespace move_tests {
#else #else
BOOST_TEST_EQ(y.bucket_count(), 0u); BOOST_TEST_EQ(y.bucket_count(), 0u);
BOOST_TEST_EQ(test::detail::tracker.count_allocations, num_allocs); BOOST_TEST_EQ(test::detail::tracker.count_allocations, num_allocs);
#endif
#endif #endif
fps[i](y, v); fps[i](y, v);
@ -503,7 +494,7 @@ namespace move_tests {
test::random_values<T> v(1000, generator); test::random_values<T> v(1000, generator);
test::object_count count; test::object_count count;
T y(v.begin(), v.end(), 0, hf, eq, al1); T y(v.begin(), v.end(), 0, hf, eq, al1);
T x(boost::move(y), al2); T x(std::move(y), al2);
#ifdef BOOST_UNORDERED_FOA_TESTS #ifdef BOOST_UNORDERED_FOA_TESTS
BOOST_TEST(y.empty()); BOOST_TEST(y.empty());
@ -530,10 +521,8 @@ namespace move_tests {
(void)num_allocs; (void)num_allocs;
T x(empty(ptr)); T x(empty(ptr));
x = boost::move(y); x = std::move(y);
#if defined(BOOST_UNORDERED_USE_MOVE) || \
!defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
BOOST_TEST(y.empty()); BOOST_TEST(y.empty());
BOOST_TEST(y.begin() == y.end()); BOOST_TEST(y.begin() == y.end());
@ -551,8 +540,6 @@ namespace move_tests {
#else #else
BOOST_TEST_EQ(y.bucket_count(), 0u); BOOST_TEST_EQ(y.bucket_count(), 0u);
BOOST_TEST_EQ(test::detail::tracker.count_allocations, num_allocs); BOOST_TEST_EQ(test::detail::tracker.count_allocations, num_allocs);
#endif
#endif #endif
fps[i](y, v); fps[i](y, v);
@ -577,22 +564,15 @@ namespace move_tests {
(void)num_allocs; (void)num_allocs;
T x(al2); T x(al2);
x = boost::move(y); x = std::move(y);
bool b = boost::allocator_propagate_on_container_move_assignment< bool b = boost::allocator_propagate_on_container_move_assignment<
typename T::allocator_type>::type::value; typename T::allocator_type>::type::value;
if (b) { if (b) {
#if defined(BOOST_UNORDERED_USE_MOVE) || \
!defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
BOOST_TEST(y.empty()); BOOST_TEST(y.empty());
BOOST_TEST(y.begin() == y.end()); BOOST_TEST(y.begin() == y.end());
BOOST_TEST_EQ(y.bucket_count(), 0u); BOOST_TEST_EQ(y.bucket_count(), 0u);
BOOST_TEST_EQ(test::detail::tracker.count_allocations, num_allocs); BOOST_TEST_EQ(test::detail::tracker.count_allocations, num_allocs);
#else
BOOST_TEST_NOT(y.empty());
BOOST_TEST(y.begin() != y.end());
#endif
} else { } else {
#ifdef BOOST_UNORDERED_FOA_TESTS #ifdef BOOST_UNORDERED_FOA_TESTS
BOOST_TEST(y.empty()); BOOST_TEST(y.empty());

View File

@ -64,7 +64,7 @@ void prime_sizes_test()
BOOST_TEST(!is_prime(100)); BOOST_TEST(!is_prime(100));
BOOST_TEST(!is_prime(49)); BOOST_TEST(!is_prime(49));
std::size_t* sizes = boost::unordered::detail::prime_fmod_size<>::sizes; std::size_t const* sizes = boost::unordered::detail::prime_fmod_size<>::sizes;
std::size_t sizes_len = std::size_t sizes_len =
boost::unordered::detail::prime_fmod_size<>::sizes_len; boost::unordered::detail::prime_fmod_size<>::sizes_len;
@ -88,7 +88,7 @@ void prime_sizes_test()
// correct amount of them, i.e. one for every entry in sizes[] that fits in 32 // correct amount of them, i.e. one for every entry in sizes[] that fits in 32
// bits // bits
// //
boost::uint64_t* inv_sizes32 = boost::uint64_t const* inv_sizes32 =
boost::unordered::detail::prime_fmod_size<>::inv_sizes32; boost::unordered::detail::prime_fmod_size<>::inv_sizes32;
std::size_t inv_sizes32_len = std::size_t inv_sizes32_len =
@ -171,7 +171,7 @@ void get_remainder_test()
void modulo_test() void modulo_test()
{ {
std::size_t* sizes = boost::unordered::detail::prime_fmod_size<>::sizes; std::size_t const* sizes = boost::unordered::detail::prime_fmod_size<>::sizes;
std::size_t const sizes_len = std::size_t const sizes_len =
boost::unordered::detail::prime_fmod_size<>::sizes_len; boost::unordered::detail::prime_fmod_size<>::sizes_len;

View File

@ -451,14 +451,14 @@ namespace rehash_tests {
typedef typename X::iterator iterator; typedef typename X::iterator iterator;
for (iterator pos = x.begin(); pos != x.end(); ++pos) { for (iterator pos = x.begin(); pos != x.end(); ++pos) {
elements.insert(boost::addressof(*pos)); elements.insert(std::addressof(*pos));
} }
x.rehash(2 * x.bucket_count()); x.rehash(2 * x.bucket_count());
for (iterator pos = x.begin(); pos != x.end(); ++pos) { for (iterator pos = x.begin(); pos != x.end(); ++pos) {
if (!BOOST_TEST( if (!BOOST_TEST(
elements.find(boost::addressof(*pos)) != elements.end())) { elements.find(std::addressof(*pos)) != elements.end())) {
break; break;
} }
} }

View File

@ -24,19 +24,19 @@ template <typename T> struct A
A() : i(++count) {} A() : i(++count) {}
template <class U> A(const A<U>& a) BOOST_NOEXCEPT : i(a.i) {} template <class U> A(const A<U>& a) noexcept : i(a.i) {}
T* allocate(std::size_t n) T* allocate(std::size_t n)
{ {
total_allocation += n * sizeof(T); total_allocation += n * sizeof(T);
++num_allocations; ++num_allocations;
return (T*)std::calloc(n, sizeof(T)); return (T*)(::operator new(n * sizeof(T)));
} }
void deallocate(T* p, std::size_t n) BOOST_NOEXCEPT void deallocate(T* p, std::size_t n) noexcept
{ {
total_allocation -= n * sizeof(T); total_allocation -= n * sizeof(T);
std::free(p); ::operator delete(p);
} }
bool operator==(A const& a) const { return i == a.i; } bool operator==(A const& a) const { return i == a.i; }

View File

@ -87,15 +87,11 @@ public:
::operator delete((void*)p.operator->()); ::operator delete((void*)p.operator->());
} }
#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template <class U, class V> void construct(U* p, V const& v) { new (p) U(v); }
#else
template <class U, class... Args> template <class U, class... Args>
void construct(U* p, BOOST_FWD_REF(Args)... args) void construct(U* p, Args&&... args)
{ {
new (p) U(boost::forward<Args>(args)...); new (p) U(std::forward<Args>(args)...);
} }
#endif
// msvc-12.0 and msvc-14.0 seem to eliminate the destructor call as we're only // msvc-12.0 and msvc-14.0 seem to eliminate the destructor call as we're only
// ever using it with an int with has a trivial destructor so it eliminates // ever using it with an int with has a trivial destructor so it eliminates
@ -171,15 +167,11 @@ public:
void deallocate(pointer p, size_type) { ::operator delete((void*)p.ptr_); } void deallocate(pointer p, size_type) { ::operator delete((void*)p.ptr_); }
#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template <class U, class V> void construct(U* p, V const& v) { new (p) U(v); }
#else
template <class U, class... Args> template <class U, class... Args>
void construct(U* p, BOOST_FWD_REF(Args)... args) void construct(U* p, Args&&... args)
{ {
new (p) U(boost::forward<Args>(args)...); new (p) U(std::forward<Args>(args)...);
} }
#endif
// msvc-12.0 and msvc-14.0 seem to eliminate the destructor call as we're only // msvc-12.0 and msvc-14.0 seem to eliminate the destructor call as we're only
// ever using it with an int with has a trivial destructor so it eliminates // ever using it with an int with has a trivial destructor so it eliminates

View File

@ -27,13 +27,7 @@
#include <cstdio> #include <cstdio>
#include <fstream> #include <fstream>
#if defined(BOOST_NO_CXX11_HDR_RANDOM) || BOOST_WORKAROUND(BOOST_MSVC, < 1700)
#define BOOST_UNORDERED_TEST_USE_STD_RANDOM_SHUFFLE
#endif
#ifndef BOOST_UNORDERED_TEST_USE_STD_RANDOM_SHUFFLE
#include <random> #include <random>
#endif
namespace { namespace {

View File

@ -1845,7 +1845,7 @@ template <class UnorderedSet> void test_set_transparent_extract(UnorderedSet*)
BOOST_TEST_EQ(nh.value(), 0); BOOST_TEST_EQ(nh.value(), 0);
BOOST_TEST_EQ(count, set_size - 3); BOOST_TEST_EQ(count, set_size - 3);
set.insert(boost::move(nh)); set.insert(std::move(nh));
nh = set.extract(1); nh = set.extract(1);
count = set.count(1); count = set.count(1);
@ -1853,7 +1853,7 @@ template <class UnorderedSet> void test_set_transparent_extract(UnorderedSet*)
BOOST_TEST_EQ(nh.value(), 1); BOOST_TEST_EQ(nh.value(), 1);
BOOST_TEST_EQ(count, 0u); BOOST_TEST_EQ(count, 0u);
set.insert(boost::move(nh)); set.insert(std::move(nh));
nh = set.extract(1337); nh = set.extract(1337);
BOOST_TEST(nh.empty()); BOOST_TEST(nh.empty());
@ -1897,7 +1897,7 @@ void test_set_non_transparent_extract(UnorderedSet*)
BOOST_TEST_EQ(nh.value(), 0); BOOST_TEST_EQ(nh.value(), 0);
BOOST_TEST_EQ(count, set_size - 3); BOOST_TEST_EQ(count, set_size - 3);
set.insert(boost::move(nh)); set.insert(std::move(nh));
nh = set.extract(1); nh = set.extract(1);
++key_count; ++key_count;
@ -1909,7 +1909,7 @@ void test_set_non_transparent_extract(UnorderedSet*)
BOOST_TEST_EQ(nh.value(), 1); BOOST_TEST_EQ(nh.value(), 1);
BOOST_TEST_EQ(count, 0u); BOOST_TEST_EQ(count, 0u);
set.insert(boost::move(nh)); set.insert(std::move(nh));
nh = set.extract(1337); nh = set.extract(1337);
++key_count; ++key_count;

View File

@ -12,11 +12,11 @@
#include "../helpers/test.hpp" #include "../helpers/test.hpp"
#include <boost/tuple/tuple.hpp>
namespace unnecessary_copy_tests { namespace unnecessary_copy_tests {
struct count_copies struct count_copies
{ {
private:
BOOST_COPYABLE_AND_MOVABLE(count_copies)
public: public:
static int copies; static int copies;
static int moves; static int moves;
@ -56,7 +56,7 @@ namespace unnecessary_copy_tests {
trace_op("Copy construct"); trace_op("Copy construct");
} }
count_copies(BOOST_RV_REF(count_copies) x) : tag_(x.tag_), id_(++id_count) count_copies(count_copies&& x) : tag_(x.tag_), id_(++id_count)
{ {
x.tag_ = -1; x.tag_ = -1;
++moves; ++moves;
@ -64,7 +64,7 @@ namespace unnecessary_copy_tests {
} }
count_copies& operator=( count_copies& operator=(
BOOST_COPY_ASSIGN_REF(count_copies) p) // Copy assignment count_copies const& p) // Copy assignment
{ {
tag_ = p.tag_; tag_ = p.tag_;
++copies; ++copies;
@ -72,7 +72,7 @@ namespace unnecessary_copy_tests {
return *this; return *this;
} }
count_copies& operator=(BOOST_RV_REF(count_copies) p) // Move assignment count_copies& operator=(count_copies&& p) // Move assignment
{ {
tag_ = p.tag_; tag_ = p.tag_;
++moves; ++moves;
@ -189,13 +189,13 @@ namespace unnecessary_copy_tests {
T x; T x;
typename T::value_type a; typename T::value_type a;
reset(); reset();
x.insert(boost::move(a)); x.insert(std::move(a));
COPY_COUNT(0); COPY_COUNT(0);
MOVE_COUNT(1); MOVE_COUNT(1);
typename T::value_type a2; typename T::value_type a2;
reset(); reset();
x.insert(boost::move(a)); x.insert(std::move(a));
COPY_COUNT(0); COPY_COUNT(0);
MOVE_COUNT((x.size() == 2 ? 1 : 0)); MOVE_COUNT((x.size() == 2 ? 1 : 0));
} }
@ -209,25 +209,17 @@ namespace unnecessary_copy_tests {
T x; T x;
typename T::value_type a; typename T::value_type a;
reset(); reset();
x.insert(boost::move(a)); x.insert(std::move(a));
#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
COPY_COUNT(1);
MOVE_COUNT(0);
#else
COPY_COUNT(0); COPY_COUNT(0);
MOVE_COUNT(1); MOVE_COUNT(1);
#endif
typename T::value_type a2; typename T::value_type a2;
reset(); reset();
x.insert(boost::move(a)); x.insert(std::move(a));
#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
COPY_COUNT((x.size() == 2 ? 1 : 0));
MOVE_COUNT(0);
#else
COPY_COUNT(0); COPY_COUNT(0);
MOVE_COUNT((x.size() == 2 ? 1 : 0)); MOVE_COUNT((x.size() == 2 ? 1 : 0));
#endif
} }
boost::unordered_set<count_copies>* set; boost::unordered_set<count_copies>* set;
@ -254,11 +246,7 @@ namespace unnecessary_copy_tests {
reset(); reset();
T x; T x;
x.emplace(source<typename T::value_type>()); x.emplace(source<typename T::value_type>());
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
COPY_COUNT(1); COPY_COUNT(1);
#else
COPY_COUNT(2);
#endif
} }
UNORDERED_TEST( UNORDERED_TEST(
@ -266,7 +254,6 @@ namespace unnecessary_copy_tests {
UNORDERED_TEST( UNORDERED_TEST(
unnecessary_copy_emplace_rvalue_test, ((set)(multiset)(map)(multimap))) unnecessary_copy_emplace_rvalue_test, ((set)(multiset)(map)(multimap)))
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
template <class T> void unnecessary_copy_emplace_std_move_test(T*) template <class T> void unnecessary_copy_emplace_std_move_test(T*)
{ {
reset(); reset();
@ -281,7 +268,6 @@ namespace unnecessary_copy_tests {
UNORDERED_TEST( UNORDERED_TEST(
unnecessary_copy_emplace_std_move_test, ((set)(multiset)(map)(multimap))) unnecessary_copy_emplace_std_move_test, ((set)(multiset)(map)(multimap)))
#endif
template <class T> void unnecessary_copy_emplace_boost_move_test(T*) template <class T> void unnecessary_copy_emplace_boost_move_test(T*)
{ {
@ -290,15 +276,9 @@ namespace unnecessary_copy_tests {
typename T::value_type a; typename T::value_type a;
COPY_COUNT(1); COPY_COUNT(1);
MOVE_COUNT_EXTRA(0, 1); MOVE_COUNT_EXTRA(0, 1);
x.emplace(boost::move(a)); x.emplace(std::move(a));
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
COPY_COUNT(1); COPY_COUNT(1);
MOVE_COUNT(1); MOVE_COUNT(1);
#else
// Since std::pair isn't movable, move only works for sets.
COPY_COUNT_RANGE(1, 2);
MOVE_COUNT_RANGE(0, 1);
#endif
} }
UNORDERED_TEST( UNORDERED_TEST(
@ -311,7 +291,7 @@ namespace unnecessary_copy_tests {
typename T::value_type a; typename T::value_type a;
COPY_COUNT(1); COPY_COUNT(1);
MOVE_COUNT(0); MOVE_COUNT(0);
x.emplace(boost::move(a)); x.emplace(std::move(a));
COPY_COUNT(1); COPY_COUNT(1);
MOVE_COUNT(1); MOVE_COUNT(1);
} }
@ -328,14 +308,10 @@ namespace unnecessary_copy_tests {
typename T::value_type a; typename T::value_type a;
COPY_COUNT(1); COPY_COUNT(1);
MOVE_COUNT_EXTRA(0, 1); MOVE_COUNT_EXTRA(0, 1);
x.emplace(boost::move(a)); x.emplace(std::move(a));
#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
COPY_COUNT(2);
MOVE_COUNT_EXTRA(0, 1);
#else
COPY_COUNT(1); COPY_COUNT(1);
MOVE_COUNT(1); MOVE_COUNT(1);
#endif
} }
UNORDERED_TEST( UNORDERED_TEST(
@ -362,7 +338,6 @@ namespace unnecessary_copy_tests {
// 0 arguments // 0 arguments
// //
#if !BOOST_UNORDERED_SUN_WORKAROUNDS1
// The container will have to create a copy in order to compare with // The container will have to create a copy in order to compare with
// the existing element. // the existing element.
reset(); reset();
@ -371,7 +346,6 @@ namespace unnecessary_copy_tests {
// source_cost doesn't make much sense here, but it seems to fit. // source_cost doesn't make much sense here, but it seems to fit.
COPY_COUNT(1); COPY_COUNT(1);
MOVE_COUNT(source_cost); MOVE_COUNT(source_cost);
#endif
// //
// 1 argument // 1 argument
@ -393,7 +367,7 @@ namespace unnecessary_copy_tests {
// No move should take place. // No move should take place.
reset(); reset();
x.emplace(boost::move(a)); x.emplace(std::move(a));
COPY_COUNT(0); COPY_COUNT(0);
MOVE_COUNT(0); MOVE_COUNT(0);
@ -450,14 +424,13 @@ namespace unnecessary_copy_tests {
// 0 arguments // 0 arguments
// //
#if !BOOST_UNORDERED_SUN_WORKAROUNDS1
// COPY_COUNT(1) would be okay here. // COPY_COUNT(1) would be okay here.
reset(); reset();
x.emplace(); x.emplace();
#if BOOST_WORKAROUND(BOOST_MSVC, == 1700) #if BOOST_WORKAROUND(BOOST_MSVC, == 1700)
// This is a little odd, Visual C++ 11 seems to move the pair, which // This is a little odd, Visual C++ 11 seems to move the pair, which
// results in one copy (for the const key) and one move (for the // results in one copy (for the const key) and one move (for the
// non-const mapped value). Since 'emplace(boost::move(a))' (see below) // non-const mapped value). Since 'emplace(std::move(a))' (see below)
// has the normal result, it must be some odd consequence of how // has the normal result, it must be some odd consequence of how
// Visual C++ 11 handles calling move for default arguments. // Visual C++ 11 handles calling move for default arguments.
COPY_COUNT(3); COPY_COUNT(3);
@ -465,7 +438,6 @@ namespace unnecessary_copy_tests {
#else #else
COPY_COUNT_EXTRA(2, 1); COPY_COUNT_EXTRA(2, 1);
MOVE_COUNT_EXTRA(0, 1); MOVE_COUNT_EXTRA(0, 1);
#endif
#endif #endif
reset(); reset();
@ -504,7 +476,7 @@ namespace unnecessary_copy_tests {
// No move should take place. // No move should take place.
// (since a is already in the container) // (since a is already in the container)
reset(); reset();
x.emplace(boost::move(a)); x.emplace(std::move(a));
COPY_COUNT(0); COPY_COUNT(0);
MOVE_COUNT(0); MOVE_COUNT(0);
@ -542,10 +514,8 @@ namespace unnecessary_copy_tests {
COPY_COUNT(0); COPY_COUNT(0);
MOVE_COUNT(0); MOVE_COUNT(0);
#if BOOST_UNORDERED_TUPLE_ARGS
reset(); reset();
x.emplace(boost::unordered::piecewise_construct, x.emplace(std::piecewise_construct,
std::make_tuple(std::ref(b.first)), std::make_tuple(std::ref(b.second))); std::make_tuple(std::ref(b.first)), std::make_tuple(std::ref(b.second)));
COPY_COUNT(0); COPY_COUNT(0);
MOVE_COUNT(0); MOVE_COUNT(0);
@ -559,23 +529,17 @@ namespace unnecessary_copy_tests {
std::pair<count_copies const, count_copies> move_source; std::pair<count_copies const, count_copies> move_source;
reset(); reset();
x.emplace(boost::unordered::piecewise_construct, x.emplace(std::piecewise_construct,
std::make_tuple(std::move(move_source.first)), std::make_tuple(std::move(move_source.first)),
std::make_tuple(std::move(move_source.second))); std::make_tuple(std::move(move_source.second)));
COPY_COUNT(tuple_copy_cost); COPY_COUNT(tuple_copy_cost);
MOVE_COUNT(tuple_move_cost); MOVE_COUNT(tuple_move_cost);
#if !defined(BOOST_NO_CXX11_HDR_TUPLE) && \
!(defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ < 6) && \
!(defined(BOOST_MSVC) && BOOST_MSVC < 1700)
reset(); reset();
x.emplace(boost::unordered::piecewise_construct, x.emplace(std::piecewise_construct,
std::forward_as_tuple(b.first), std::forward_as_tuple(b.second)); std::forward_as_tuple(b.first), std::forward_as_tuple(b.second));
COPY_COUNT(0); COPY_COUNT(0);
MOVE_COUNT(0); MOVE_COUNT(0);
#endif
#endif
} }
} }