mirror of
https://github.com/boostorg/unordered.git
synced 2026-08-06 05:34:09 +02:00
Compare commits
20 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 665371e6da | |||
| c70208609e | |||
| 11e05a3c4c | |||
| e9ca2a2def | |||
| 9c8da06481 | |||
| e01b7b52a6 | |||
| 4ec5cb59cd | |||
| 09d6416755 | |||
| 4b76ac84ec | |||
| dcc485bcb5 | |||
| cc9a787f14 | |||
| 6fd63ab727 | |||
| 59e2a562ed | |||
| 164cbe4e0f | |||
| a64d81a378 | |||
| 628c8c445e | |||
| 3dde65b2ef | |||
| 2907fe8c98 | |||
| 28663ad5ce | |||
| 5417494fae |
+4
-119
@@ -31,121 +31,10 @@ environment:
|
||||
B2_VARIANT: debug,release
|
||||
|
||||
matrix:
|
||||
- FLAVOR: VS2015 (32 bit)
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
||||
B2_TOOLSET: msvc-14.0
|
||||
B2_ADDRESS_MODEL: 32
|
||||
|
||||
- FLAVOR: VS2015 (64 bit)
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
||||
B2_TOOLSET: msvc-14.0
|
||||
B2_ADDRESS_MODEL: 64
|
||||
|
||||
- FLAVOR: VS2017 (32 bit, C++14, Debug)
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
||||
B2_CXXSTD: 14
|
||||
B2_TOOLSET: msvc-14.1
|
||||
B2_ADDRESS_MODEL: 32
|
||||
B2_VARIANT: debug
|
||||
|
||||
- FLAVOR: VS2017 (32 bit, C++17, Release)
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
||||
B2_CXXSTD: 17
|
||||
B2_TOOLSET: msvc-14.1
|
||||
B2_ADDRESS_MODEL: 32
|
||||
B2_VARIANT: release
|
||||
|
||||
- FLAVOR: VS2017 (32 bit, C++latest, Debug)
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
||||
B2_CXXSTD: latest
|
||||
B2_TOOLSET: msvc-14.1
|
||||
B2_ADDRESS_MODEL: 32
|
||||
B2_VARIANT: debug
|
||||
|
||||
- FLAVOR: VS2017 (64 bit, C++14, Release)
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
||||
B2_CXXSTD: 14
|
||||
B2_TOOLSET: msvc-14.1
|
||||
B2_ADDRESS_MODEL: 64
|
||||
B2_VARIANT: release
|
||||
|
||||
- FLAVOR: VS2017 (64 bit, C++17, Debug)
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
||||
B2_CXXSTD: 17
|
||||
B2_TOOLSET: msvc-14.1
|
||||
B2_ADDRESS_MODEL: 64
|
||||
B2_VARIANT: debug
|
||||
|
||||
- FLAVOR: VS2017 (64 bit, C++latest, Release)
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
||||
B2_CXXSTD: latest
|
||||
B2_TOOLSET: msvc-14.1
|
||||
B2_ADDRESS_MODEL: 64
|
||||
B2_VARIANT: release
|
||||
|
||||
- FLAVOR: Cygwin (32 bit, C++11, Release)
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
||||
ADDPATH: C:\cygwin\bin;
|
||||
B2_ADDRESS_MODEL: 32
|
||||
B2_CXXSTD: 11
|
||||
B2_TOOLSET: gcc
|
||||
B2_VARIANT: release
|
||||
|
||||
- FLAVOR: Cygwin (32 bit, C++14, Debug)
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
||||
ADDPATH: C:\cygwin\bin;
|
||||
B2_ADDRESS_MODEL: 32
|
||||
B2_CXXSTD: 14
|
||||
B2_TOOLSET: gcc
|
||||
B2_VARIANT: debug
|
||||
|
||||
- FLAVOR: Cygwin (32 bit, C++1z, Release)
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
||||
ADDPATH: C:\cygwin\bin;
|
||||
B2_ADDRESS_MODEL: 32
|
||||
B2_CXXSTD: 1z
|
||||
B2_TOOLSET: gcc
|
||||
B2_VARIANT: release
|
||||
|
||||
- FLAVOR: Cygwin (64 bit, C++11, Debug)
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2022
|
||||
ADDPATH: C:\cygwin64\bin;
|
||||
B2_ADDRESS_MODEL: 64
|
||||
B2_CXXSTD: 11
|
||||
B2_TOOLSET: gcc
|
||||
B2_FLAGS: "include=libs/unordered/test/unordered include=libs/unordered/test/exception"
|
||||
B2_VARIANT: debug
|
||||
|
||||
- FLAVOR: Cygwin (64 bit, C++14, Debug)
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2022
|
||||
ADDPATH: C:\cygwin64\bin;
|
||||
B2_ADDRESS_MODEL: 64
|
||||
B2_CXXSTD: 14
|
||||
B2_TOOLSET: gcc
|
||||
B2_FLAGS: "include=libs/unordered/test/unordered include=libs/unordered/test/exception"
|
||||
B2_VARIANT: debug
|
||||
|
||||
- FLAVOR: Cygwin (64 bit, C++17, Debug)
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2022
|
||||
ADDPATH: C:\cygwin64\bin;
|
||||
B2_ADDRESS_MODEL: 64
|
||||
B2_CXXSTD: 17
|
||||
B2_TOOLSET: gcc
|
||||
B2_FLAGS: "include=libs/unordered/test/unordered include=libs/unordered/test/exception"
|
||||
B2_VARIANT: debug
|
||||
|
||||
- FLAVOR: Cygwin (64 bit, C++2a, Debug)
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2022
|
||||
ADDPATH: C:\cygwin64\bin;
|
||||
B2_ADDRESS_MODEL: 64
|
||||
B2_CXXSTD: 2a
|
||||
B2_TOOLSET: gcc
|
||||
B2_FLAGS: "include=libs/unordered/test/unordered include=libs/unordered/test/exception"
|
||||
B2_VARIANT: debug
|
||||
|
||||
- FLAVOR: MinGW-w64 (32 bit, C++11)
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
|
||||
ADDPATH: C:\mingw-w64\i686-8.1.0-posix-dwarf-rt_v6-rev0\mingw32\bin;
|
||||
B2_CXXFLAGS: -g0 # Reduce compiler's memory consumption
|
||||
B2_CXXSTD: 11
|
||||
B2_TOOLSET: gcc
|
||||
B2_ADDRESS_MODEL: 32
|
||||
@@ -153,6 +42,7 @@ environment:
|
||||
- FLAVOR: MinGW-w64 (32 bit, C++14)
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
|
||||
ADDPATH: C:\mingw-w64\i686-8.1.0-posix-dwarf-rt_v6-rev0\mingw32\bin;
|
||||
B2_CXXFLAGS: -g0 # Reduce compiler's memory consumption
|
||||
B2_CXXSTD: 14
|
||||
B2_TOOLSET: gcc
|
||||
B2_ADDRESS_MODEL: 32
|
||||
@@ -160,6 +50,7 @@ environment:
|
||||
- FLAVOR: MinGW-w64 (32 bit, C++17)
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
|
||||
ADDPATH: C:\mingw-w64\i686-8.1.0-posix-dwarf-rt_v6-rev0\mingw32\bin;
|
||||
B2_CXXFLAGS: -g0 # Reduce compiler's memory consumption
|
||||
B2_CXXSTD: 17
|
||||
B2_TOOLSET: gcc
|
||||
B2_ADDRESS_MODEL: 32
|
||||
@@ -167,6 +58,7 @@ environment:
|
||||
- FLAVOR: MinGW-w64 (32 bit, C++2a)
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
|
||||
ADDPATH: C:\mingw-w64\i686-8.1.0-posix-dwarf-rt_v6-rev0\mingw32\bin;
|
||||
B2_CXXFLAGS: -g0 # Reduce compiler's memory consumption
|
||||
B2_CXXSTD: 2a
|
||||
B2_TOOLSET: gcc
|
||||
B2_ADDRESS_MODEL: 32
|
||||
@@ -199,13 +91,6 @@ environment:
|
||||
B2_TOOLSET: gcc
|
||||
B2_ADDRESS_MODEL: 64
|
||||
|
||||
#- FLAVOR: CodeCov (VS 2019)
|
||||
# APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
|
||||
# B2_CXXFLAGS: -permissive-
|
||||
# B2_CXXSTD: 14
|
||||
# B2_TOOLSET: msvc-14.2
|
||||
# COVERAGE: true
|
||||
|
||||
install:
|
||||
- git clone --depth 1 https://github.com/boostorg/boost-ci.git C:\boost-ci-cloned
|
||||
# Copy ci folder if not testing Boost.CI
|
||||
|
||||
+5
-2
@@ -34,8 +34,9 @@ local linux_pipeline(name, image, environment, packages = "", sources = [], arch
|
||||
commands:
|
||||
[
|
||||
'set -e',
|
||||
'echo $DRONE_STAGE_MACHINE',
|
||||
'uname -a',
|
||||
'wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | apt-key add -',
|
||||
'curl -sSL --retry 5 https://apt.llvm.org/llvm-snapshot.gpg.key | sudo gpg --dearmor -o /etc/apt/trusted.gpg.d/llvm-snapshot.gpg',
|
||||
] +
|
||||
(if sources != [] then [ ('apt-add-repository "' + source + '"') for source in sources ] else []) +
|
||||
(if packages != "" then [ 'apt-get update', 'apt-get -y install ' + packages ] else []) +
|
||||
@@ -66,6 +67,8 @@ local macos_pipeline(name, environment, xcode_version = "12.2", osx_version = "c
|
||||
environment: environment + { "DEVELOPER_DIR": "/Applications/Xcode-" + xcode_version + ".app/Contents/Developer" },
|
||||
commands:
|
||||
[
|
||||
'echo $DRONE_STAGE_MACHINE',
|
||||
'sw_vers',
|
||||
'uname -a',
|
||||
'export LIBRARY=' + library,
|
||||
'./.drone/drone.sh',
|
||||
@@ -475,7 +478,7 @@ local windows_pipeline(name, image, environment, arch = "amd64") =
|
||||
windows_pipeline(
|
||||
"Windows VS2017 msvc-14.1",
|
||||
"cppalliance/dronevs2017",
|
||||
{ TOOLSET: 'msvc-14.1', CXXSTD: '14,17,latest' },
|
||||
{ TOOLSET: 'msvc-14.1', CXXSTD: '14,17,latest', ADDRMD: '32,64' },
|
||||
),
|
||||
|
||||
windows_pipeline(
|
||||
|
||||
@@ -101,6 +101,10 @@ jobs:
|
||||
- { compiler: 'clang-17', cxxstd: '17,20,2b', os: 'ubuntu-24.04', stdlib: libc++, install: 'clang-17 libc++-17-dev libc++abi-17-dev' }
|
||||
- { compiler: 'clang-18', cxxstd: '11,14', os: 'ubuntu-24.04', stdlib: libc++, install: 'clang-18 libc++-18-dev libc++abi-18-dev' }
|
||||
- { compiler: 'clang-18', cxxstd: '17,20,2b', os: 'ubuntu-24.04', stdlib: libc++, install: 'clang-18 libc++-18-dev libc++abi-18-dev' }
|
||||
- { compiler: 'clang-19', cxxstd: '11,14', os: 'ubuntu-24.04', stdlib: libc++, install: 'clang-19 libc++-19-dev libc++abi-19-dev' }
|
||||
- { compiler: 'clang-19', cxxstd: '17,20,2b', os: 'ubuntu-24.04', stdlib: libc++, install: 'clang-19 libc++-19-dev libc++abi-19-dev' }
|
||||
- { compiler: 'clang-20', cxxstd: '11,14,17', os: 'ubuntu-24.04', stdlib: libc++, install: 'clang-20 libc++-20-dev libc++abi-20-dev' }
|
||||
- { compiler: 'clang-20', cxxstd: '20,23,2c', os: 'ubuntu-24.04', stdlib: libc++, install: 'clang-20 libc++-20-dev libc++abi-20-dev' }
|
||||
|
||||
# not using libc++ because of https://github.com/llvm/llvm-project/issues/52771
|
||||
- { name: "clang-18 w/ sanitizers (11,14)", sanitize: yes,
|
||||
@@ -117,10 +121,12 @@ jobs:
|
||||
stdlib: libc++, install: 'clang-18 libc++-18-dev libc++abi-18-dev', ccache_key: "tsan" }
|
||||
|
||||
# OSX, clang
|
||||
- { compiler: clang, cxxstd: '11,14,17,20,2b', os: 'macos-13', sanitize: yes, ccache_key: "san1" }
|
||||
- { compiler: clang, cxxstd: '11,14,17,20,2b', os: 'macos-13', thread-sanitize: yes, targets: 'libs/unordered/test//cfoa_tests', ccache_key: "tsan" }
|
||||
- { compiler: clang, cxxstd: '11,14,17,20,2b', os: 'macos-latest', sanitize: yes, ccache: no, ccache_key: "san1" }
|
||||
- { compiler: clang, cxxstd: '11,14,17,20,2b', os: 'macos-latest', thread-sanitize: yes, targets: 'libs/unordered/test//cfoa_tests', ccache: no, ccache_key: "tsan" }
|
||||
|
||||
- { compiler: clang, cxxstd: '11,14,17,20,2b', os: 'macos-14' }
|
||||
- { compiler: clang, cxxstd: '11,14,17,20,2b', os: 'macos-15' }
|
||||
- { compiler: clang, cxxstd: '11,14,17,20,23,2c', os: 'macos-15' }
|
||||
- { compiler: clang, cxxstd: '11,14,17,20,23,2c', os: 'macos-26' }
|
||||
|
||||
timeout-minutes: 360
|
||||
# posix (gcc-12 w/ sanitizers is taking longer than 210 minutes
|
||||
@@ -285,6 +291,8 @@ jobs:
|
||||
- { 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,17', addrmd: '32,64', os: 'windows-2022', variant: 'debug,release', cxxflags: '/permissive-' }
|
||||
- { 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-2025', variant: 'debug,release' }
|
||||
- { toolset: msvc-14.3, cxxstd: '14,17,20,latest', addrmd: '32,64', os: 'windows-2025', variant: 'debug,release' }
|
||||
- { toolset: gcc, cxxstd: '11,14,17,2a', addrmd: '64', os: 'windows-2019', variant: 'debug,release' }
|
||||
|
||||
needs: [runner-selection]
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Boost.Unordered
|
||||
|
||||
[](https://github.com/boostorg/unordered/tree/master) [](https://github.com/boostorg/unordered/actions/workflows/ci.yml) [](https://drone.cpp.al/boostorg/unordered) [](https://ci.appveyor.com/project/cppalliance/unordered/branch/master) [](https://codecov.io/gh/boostorg/unordered/branch/master) [](https://pdimov.github.io/boostdep-report/master/unordered.html) [](https://www.boost.org/doc/libs/master/libs/unordered/index.html) [](http://www.boost.org/development/tests/master/developer/unordered.html)<br/>
|
||||
[](https://github.com/boostorg/unordered/tree/develop) [](https://github.com/boostorg/unordered/actions/workflows/ci.yml) [](https://drone.cpp.al/boostorg/unordered) [](https://ci.appveyor.com/project/cppalliance/unordered/branch/develop) [](https://codecov.io/gh/boostorg/unordered/branch/develop) [](https://pdimov.github.io/boostdep-report/develop/unordered.html) [](https://www.boost.org/doc/libs/develop/libs/unordered/index.html) [](http://www.boost.org/development/tests/develop/developer/unordered.html)<br/>
|
||||
[](https://github.com/boostorg/unordered/tree/master) [](https://github.com/boostorg/unordered/actions/workflows/ci.yml) [](https://drone.cpp.al/boostorg/unordered) [](https://ci.appveyor.com/project/cppalliance/unordered/branch/master) [](https://codecov.io/gh/boostorg/unordered/branch/master) [](https://pdimov.github.io/boostdep-report/master/unordered.html) [](https://www.boost.org/doc/libs/master/libs/unordered/index.html) [](https://regression.boost.org/master/developer/unordered.html)<br/>
|
||||
[](https://github.com/boostorg/unordered/tree/develop) [](https://github.com/boostorg/unordered/actions/workflows/ci.yml) [](https://drone.cpp.al/boostorg/unordered) [](https://ci.appveyor.com/project/cppalliance/unordered/branch/develop) [](https://codecov.io/gh/boostorg/unordered/branch/develop) [](https://pdimov.github.io/boostdep-report/develop/unordered.html) [](https://www.boost.org/doc/libs/develop/libs/unordered/index.html) [](https://regression.boost.org/develop/developer/unordered.html)<br/>
|
||||
[](https://www.boost.org/users/license.html) <img alt="C++11 required" src="https://img.shields.io/badge/standard-C%2b%2b11-blue.svg"> <img alt="Header-only library" src="https://img.shields.io/badge/build-header--only-blue.svg">
|
||||
|
||||
Boost.Unordered offers a catalog of hash containers with different standards compliance levels, performances and intented usage scenarios:
|
||||
|
||||
@@ -7,3 +7,4 @@ cd "$SCRIPT_DIR"
|
||||
|
||||
npm ci
|
||||
npx antora unordered-playbook.yml
|
||||
cp -f html/index.html html/unordered.html
|
||||
|
||||
@@ -6,6 +6,15 @@
|
||||
:github-pr-url: https://github.com/boostorg/unordered/pull
|
||||
:cpp: C++
|
||||
|
||||
== Release 1.89.0
|
||||
|
||||
* Deprecated `boost::unordered::hash_is_avalanching` is now a using-declaration of
|
||||
`boost::hash_is_avalanching` in `<boost/container_hash/hash_is_avalanching.hpp>`.
|
||||
Use that header directly instead. `<boost/unordered/hash_traits.hpp>` will be
|
||||
removed in the future.
|
||||
* Added `pull(const_iterator)` to open-addressing containers. This operation
|
||||
allows for efficient removal and retrieval of an element via move construction.
|
||||
|
||||
== Release 1.88.0
|
||||
|
||||
* Migrated the documentation to a multipage format using Antora.
|
||||
|
||||
@@ -43,7 +43,8 @@ struct my_string_hash_function
|
||||
----
|
||||
|
||||
By setting the
|
||||
`xref:reference/hash_traits.adoc#hash_traits_hash_is_avalanching[hash_is_avalanching]` trait, we inform Boost.Unordered
|
||||
`link:../../../../container_hash/doc/html/hash.html#ref_hash_is_avalanchinghash[hash_is_avalanching]`
|
||||
trait, we inform Boost.Unordered
|
||||
that `my_string_hash_function` is of sufficient quality to be used directly without
|
||||
any post-mixing safety net. This comes at the risk of degraded performance in the
|
||||
cases where the hash function is not as well-behaved as we've declared.
|
||||
|
||||
@@ -94,15 +94,16 @@ As it happens, `boost::hash` for integral and other basic types does not possess
|
||||
the statistical properties required by open addressing; to cope with this,
|
||||
we implement a post-mixing stage:
|
||||
|
||||
{nbsp}{nbsp}{nbsp}{nbsp} _a_ <- _h_ *mulx* _C_, +
|
||||
{nbsp}{nbsp}{nbsp}{nbsp} _a_ <- _h_ *mul* _C_, +
|
||||
{nbsp}{nbsp}{nbsp}{nbsp} _h_ <- *high*(_a_) *xor* *low*(_a_),
|
||||
|
||||
where *mulx* is an _extended multiplication_ (128 bits in 64-bit architectures, 64 bits in 32-bit environments),
|
||||
where *mul* is an _extended multiplication_ (128 bits in 64-bit architectures, 64 bits in 32-bit environments),
|
||||
and *high* and *low* are the upper and lower halves of an extended word, respectively.
|
||||
In 64-bit architectures, _C_ is the integer part of 2^64^∕https://en.wikipedia.org/wiki/Golden_ratio[_φ_],
|
||||
whereas in 32 bits _C_ = 0xE817FB2Du has been obtained from https://arxiv.org/abs/2001.05304[Steele and Vigna (2021)^].
|
||||
|
||||
When using a hash function directly suitable for open addressing, post-mixing can be opted out of via a dedicated `xref:reference/hash_traits.adoc#hash_traits_hash_is_avalanching[hash_is_avalanching]` trait.
|
||||
When using a hash function directly suitable for open addressing, post-mixing can be opted out of via a dedicated
|
||||
`link:../../../../container_hash/doc/html/hash.html#ref_hash_is_avalanchinghash[hash_is_avalanching]` trait.
|
||||
`boost::hash` specializations for string types are marked as avalanching.
|
||||
|
||||
=== Platform Interoperability
|
||||
|
||||
@@ -364,7 +364,7 @@ The size of the bucket array can be automatically increased by a call to `insert
|
||||
greater than `max_load_factor()`, except possibly for small sizes where the implementation may decide to
|
||||
allow for higher loads.
|
||||
|
||||
If `xref:reference/hash_traits.adoc#hash_traits_hash_is_avalanching[hash_is_avalanching]<Hash>::value` is `true`, the hash function
|
||||
If `link:../../../../../container_hash/doc/html/hash.html#ref_hash_is_avalanchinghash[hash_is_avalanching]<Hash>::value` is `true`, the hash function
|
||||
is used as-is; otherwise, a bit-mixing post-processing stage is added to increase the quality of hashing
|
||||
at the expense of extra computational cost.
|
||||
|
||||
@@ -1429,7 +1429,9 @@ Erases the element `x` with key equivalent to `k` if it exists and `f(x)` is `tr
|
||||
[horizontal]
|
||||
Returns:;; The number of elements erased (0 or 1).
|
||||
Throws:;; Only throws an exception if it is thrown by `hasher`, `key_equal` or `f`.
|
||||
Notes:;; The `template<class K, class F>` overload only participates in overload resolution if `std::is_execution_policy_v<std::remove_cvref_t<ExecutionPolicy>>` is `false`. +
|
||||
Notes:;; `f` is passed a non-const reference to `x`. +
|
||||
+
|
||||
The `template<class K, class F>` overload only participates in overload resolution if `std::is_execution_policy_v<std::remove_cvref_t<ExecutionPolicy>>` is `false`. +
|
||||
+
|
||||
The `template<class K, class F>` overload only participates in overload resolution if `Hash::is_transparent` and `Pred::is_transparent` are valid member typedefs. 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.
|
||||
|
||||
@@ -1440,7 +1442,7 @@ The `template<class K, class F>` overload only participates in overload resoluti
|
||||
template<class F> size_type erase_if(F f);
|
||||
```
|
||||
|
||||
Successively invokes `f` with references to each of the elements in the table, and erases those for which `f` returns `true`.
|
||||
Successively invokes `f` with non-const references to each of the elements in the table, and erases those for which `f` returns `true`.
|
||||
|
||||
[horizontal]
|
||||
Returns:;; The number of elements erased.
|
||||
@@ -1453,7 +1455,7 @@ Throws:;; Only throws an exception if it is thrown by `f`.
|
||||
template<class ExecutionPolicy, class F> void erase_if(ExecutionPolicy&& policy, F f);
|
||||
```
|
||||
|
||||
Invokes `f` with references to each of the elements in the table, and erases those for which `f` returns `true`.
|
||||
Invokes `f` with non-const references to each of the elements in the table, and erases those for which `f` returns `true`.
|
||||
Execution is parallelized according to the semantics of the execution policy specified.
|
||||
|
||||
[horizontal]
|
||||
|
||||
@@ -311,7 +311,7 @@ The size of the bucket array can be automatically increased by a call to `insert
|
||||
greater than `max_load_factor()`, except possibly for small sizes where the implementation may decide to
|
||||
allow for higher loads.
|
||||
|
||||
If `xref:reference/hash_traits.adoc#hash_traits_hash_is_avalanching[hash_is_avalanching]<Hash>::value` is `true`, the hash function
|
||||
If `link:../../../../../container_hash/doc/html/hash.html#ref_hash_is_avalanchinghash[hash_is_avalanching]<Hash>::value` is `true`, the hash function
|
||||
is used as-is; otherwise, a bit-mixing post-processing stage is added to increase the quality of hashing
|
||||
at the expense of extra computational cost.
|
||||
|
||||
|
||||
@@ -381,7 +381,7 @@ The size of the bucket array can be automatically increased by a call to `insert
|
||||
greater than `max_load_factor()`, except possibly for small sizes where the implementation may decide to
|
||||
allow for higher loads.
|
||||
|
||||
If `xref:reference/hash_traits.adoc#hash_traits_hash_is_avalanching[hash_is_avalanching]<Hash>::value` is `true`, the hash function
|
||||
If `link:../../../../../container_hash/doc/html/hash.html#ref_hash_is_avalanchinghash[hash_is_avalanching]<Hash>::value` is `true`, the hash function
|
||||
is used as-is; otherwise, a bit-mixing post-processing stage is added to increase the quality of hashing
|
||||
at the expense of extra computational cost.
|
||||
|
||||
@@ -1519,7 +1519,9 @@ Erases the element `x` with key equivalent to `k` if it exists and `f(x)` is `tr
|
||||
[horizontal]
|
||||
Returns:;; The number of elements erased (0 or 1).
|
||||
Throws:;; Only throws an exception if it is thrown by `hasher`, `key_equal` or `f`.
|
||||
Notes:;; The `template<class K, class F>` overload only participates in overload resolution if `std::is_execution_policy_v<std::remove_cvref_t<ExecutionPolicy>>` is `false`. +
|
||||
Notes:;; `f` is passed a non-const reference to `x`. +
|
||||
+
|
||||
The `template<class K, class F>` overload only participates in overload resolution if `std::is_execution_policy_v<std::remove_cvref_t<ExecutionPolicy>>` is `false`. +
|
||||
+
|
||||
The `template<class K, class F>` overload only participates in overload resolution if `Hash::is_transparent` and `Pred::is_transparent` are valid member typedefs. 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.
|
||||
|
||||
@@ -1530,7 +1532,7 @@ The `template<class K, class F>` overload only participates in overload resoluti
|
||||
template<class F> size_type erase_if(F f);
|
||||
```
|
||||
|
||||
Successively invokes `f` with references to each of the elements in the table, and erases those for which `f` returns `true`.
|
||||
Successively invokes `f` with non-const references to each of the elements in the table, and erases those for which `f` returns `true`.
|
||||
|
||||
[horizontal]
|
||||
Returns:;; The number of elements erased.
|
||||
@@ -1543,7 +1545,7 @@ Throws:;; Only throws an exception if it is thrown by `f`.
|
||||
template<class ExecutionPolicy, class F> void erase_if(ExecutionPolicy&& policy, F f);
|
||||
```
|
||||
|
||||
Invokes `f` with references to each of the elements in the table, and erases those for which `f` returns `true`.
|
||||
Invokes `f` with non-const references to each of the elements in the table, and erases those for which `f` returns `true`.
|
||||
Execution is parallelized according to the semantics of the execution policy specified.
|
||||
|
||||
[horizontal]
|
||||
|
||||
@@ -328,7 +328,7 @@ The size of the bucket array can be automatically increased by a call to `insert
|
||||
greater than `max_load_factor()`, except possibly for small sizes where the implementation may decide to
|
||||
allow for higher loads.
|
||||
|
||||
If `xref:reference/hash_traits.adoc#hash_traits_hash_is_avalanching[hash_is_avalanching]<Hash>::value` is `true`, the hash function
|
||||
If `link:../../../../../container_hash/doc/html/hash.html#ref_hash_is_avalanchinghash[hash_is_avalanching]<Hash>::value` is `true`, the hash function
|
||||
is used as-is; otherwise, a bit-mixing post-processing stage is added to increase the quality of hashing
|
||||
at the expense of extra computational cost.
|
||||
|
||||
|
||||
@@ -7,39 +7,22 @@
|
||||
|
||||
[listing,subs="+macros,+quotes"]
|
||||
-----
|
||||
#include <boost/container_hash/hash_is_avalanching.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace unordered {
|
||||
|
||||
template<typename Hash>
|
||||
struct xref:#hash_traits_hash_is_avalanching[hash_is_avalanching];
|
||||
using boost::hash_is_avalanching;
|
||||
|
||||
} // namespace unordered
|
||||
} // namespace boost
|
||||
-----
|
||||
|
||||
---
|
||||
|
||||
=== hash_is_avalanching
|
||||
```c++
|
||||
template<typename Hash>
|
||||
struct hash_is_avalanching;
|
||||
```
|
||||
|
||||
A hash function is said to have the _avalanching property_ if small changes in the input translate to
|
||||
large changes in the returned hash code —ideally, flipping one bit in the representation of
|
||||
the input value results in each bit of the hash code flipping with probability 50%. Approaching
|
||||
this property is critical for the proper behavior of open-addressing hash containers.
|
||||
|
||||
`hash_is_avalanching<Hash>::value` is:
|
||||
|
||||
* `false` if `Hash::is_avalanching` is not present,
|
||||
* `Hash::is_avalanching::value` if this is present and convertible at compile time to a `bool`,
|
||||
* `true` if `Hash::is_avalanching` is `void` (this usage is deprecated),
|
||||
* ill-formed otherwise.
|
||||
|
||||
Users can then declare a hash function `Hash` as avalanching either by embedding an appropriate `is_avalanching` typedef
|
||||
into the definition of `Hash`, or directly by specializing `hash_is_avalanching<Hash>` to a class with
|
||||
an embedded compile-time constant `value` set to `true`.
|
||||
[horizontal]
|
||||
Note:;; This header is deprecated. Use instead
|
||||
`link:../../../../../container_hash/doc/html/hash.html#ref_hash_is_avalanchinghash[boost::hash_is_avalanching]`
|
||||
defined in
|
||||
`link:../../../../../container_hash/doc/html/hash.html#ref_boostcontainer_hashhash_is_avalanching_hpp[<boost/container_hash/hash_is_avalanching.hpp>]`.
|
||||
|
||||
Open-addressing and concurrent containers
|
||||
use the provided hash function `Hash` as-is if `hash_is_avalanching<Hash>::value` is `true`; otherwise, they
|
||||
|
||||
@@ -66,6 +66,7 @@ If the supplied hash function has good quality, then:
|
||||
* For unsuccessful lookups, the average number of element comparisons should be close to 0.0.
|
||||
|
||||
These statistics can be used to determine if a given hash function
|
||||
can be marked as xref:reference/hash_traits.adoc#hash_traits_hash_is_avalanching[__avalanching__].
|
||||
can be marked as
|
||||
link:../../../../../container_hash/doc/html/hash.html#ref_hash_is_avalanchinghash[__avalanching__].
|
||||
|
||||
---
|
||||
|
||||
@@ -168,6 +168,7 @@ namespace unordered {
|
||||
void xref:#unordered_flat_map_swap[swap](unordered_flat_map& other)
|
||||
noexcept(boost::allocator_traits<Allocator>::is_always_equal::value ||
|
||||
boost::allocator_traits<Allocator>::propagate_on_container_swap::value);
|
||||
init_type xref:#unordered_flat_map_pull[pull](const_iterator position);
|
||||
void xref:#unordered_flat_map_clear[clear]() noexcept;
|
||||
|
||||
template<class H2, class P2>
|
||||
@@ -316,7 +317,7 @@ The size of the bucket array can be automatically increased by a call to `insert
|
||||
greater than `max_load_factor()`, except possibly for small sizes where the implementation may decide to
|
||||
allow for higher loads.
|
||||
|
||||
If `xref:reference/hash_traits.adoc#hash_traits_hash_is_avalanching[hash_is_avalanching]<Hash>::value` is `true`, the hash function
|
||||
If `link:../../../../../container_hash/doc/html/hash.html#ref_hash_is_avalanchinghash[hash_is_avalanching]<Hash>::value` is `true`, the hash function
|
||||
is used as-is; otherwise, a bit-mixing post-processing stage is added to increase the quality of hashing
|
||||
at the expense of extra computational cost.
|
||||
|
||||
@@ -1126,6 +1127,16 @@ Throws:;; Nothing unless `key_equal` or `hasher` throw on swapping.
|
||||
|
||||
---
|
||||
|
||||
==== pull
|
||||
```c++
|
||||
init_type pull(const_iterator position);
|
||||
```
|
||||
|
||||
Move-constructs an `init_value` `x` from the element pointed to by `position`,
|
||||
erases the element and returns `x`.
|
||||
|
||||
---
|
||||
|
||||
==== clear
|
||||
```c++
|
||||
void clear() noexcept;
|
||||
@@ -1503,6 +1514,8 @@ for (auto i = c.begin(), last = c.end(); i != last; ) {
|
||||
}
|
||||
return original_size - c.size();
|
||||
```
|
||||
+
|
||||
Note that the references passed to `pred` are non-const.
|
||||
|
||||
=== Serialization
|
||||
|
||||
|
||||
@@ -135,6 +135,7 @@ namespace unordered {
|
||||
void xref:#unordered_flat_set_swap[swap](unordered_flat_set& other)
|
||||
noexcept(boost::allocator_traits<Allocator>::is_always_equal::value ||
|
||||
boost::allocator_traits<Allocator>::propagate_on_container_swap::value);
|
||||
init_type xref:#unordered_flat_set_pull[pull](const_iterator position);
|
||||
void xref:#unordered_flat_set_clear[clear]() noexcept;
|
||||
|
||||
template<class H2, class P2>
|
||||
@@ -265,7 +266,7 @@ The size of the bucket array can be automatically increased by a call to `insert
|
||||
greater than `max_load_factor()`, except possibly for small sizes where the implementation may decide to
|
||||
allow for higher loads.
|
||||
|
||||
If `xref:reference/hash_traits.adoc#hash_traits_hash_is_avalanching[hash_is_avalanching]<Hash>::value` is `true`, the hash function
|
||||
If `link:../../../../../container_hash/doc/html/hash.html#ref_hash_is_avalanchinghash[hash_is_avalanching]<Hash>::value` is `true`, the hash function
|
||||
is used as-is; otherwise, a bit-mixing post-processing stage is added to increase the quality of hashing
|
||||
at the expense of extra computational cost.
|
||||
|
||||
@@ -932,6 +933,16 @@ Throws:;; Nothing unless `key_equal` or `hasher` throw on swapping.
|
||||
|
||||
---
|
||||
|
||||
==== pull
|
||||
```c++
|
||||
init_type pull(const_iterator position);
|
||||
```
|
||||
|
||||
Move-constructs an `init_value` `x` from the element pointed to by `position`,
|
||||
erases the element and returns `x`.
|
||||
|
||||
---
|
||||
|
||||
==== clear
|
||||
```c++
|
||||
void clear() noexcept;
|
||||
|
||||
@@ -1766,7 +1766,9 @@ for (auto i = c.begin(), last = c.end(); i != last; ) {
|
||||
}
|
||||
}
|
||||
return original_size - c.size();
|
||||
```
|
||||
```
|
||||
+
|
||||
Note that the references passed to `pred` are non-const.
|
||||
|
||||
=== Serialization
|
||||
|
||||
|
||||
@@ -1486,6 +1486,8 @@ for (auto i = c.begin(), last = c.end(); i != last; ) {
|
||||
}
|
||||
return original_size - c.size();
|
||||
```
|
||||
+
|
||||
Note that the references passed to `pred` are non-const.
|
||||
|
||||
=== Serialization
|
||||
|
||||
|
||||
@@ -172,6 +172,7 @@ namespace unordered {
|
||||
node_type xref:#unordered_node_map_extract_by_position[extract](const_iterator position);
|
||||
node_type xref:#unordered_node_map_extract_by_key[extract](const key_type& key);
|
||||
template<class K> node_type xref:#unordered_node_map_extract_by_key[extract](K&& key);
|
||||
init_type xref:#unordered_node_map_pull[pull](const_iterator position);
|
||||
void xref:#unordered_node_map_clear[clear]() noexcept;
|
||||
|
||||
template<class H2, class P2>
|
||||
@@ -319,7 +320,7 @@ The size of the bucket array can be automatically increased by a call to `insert
|
||||
greater than `max_load_factor()`, except possibly for small sizes where the implementation may decide to
|
||||
allow for higher loads.
|
||||
|
||||
If `xref:reference/hash_traits.adoc#hash_traits_hash_is_avalanching[hash_is_avalanching]<Hash>::value` is `true`, the hash function
|
||||
If `link:../../../../../container_hash/doc/html/hash.html#ref_hash_is_avalanchinghash[hash_is_avalanching]<Hash>::value` is `true`, the hash function
|
||||
is used as-is; otherwise, a bit-mixing post-processing stage is added to increase the quality of hashing
|
||||
at the expense of extra computational cost.
|
||||
|
||||
@@ -1224,6 +1225,16 @@ Notes:;; The `template<class K>` overload only participates in overload resoluti
|
||||
|
||||
---
|
||||
|
||||
==== pull
|
||||
```c++
|
||||
init_type pull(const_iterator position);
|
||||
```
|
||||
|
||||
Move-constructs an `init_value` `x` from the element pointed to by `position`,
|
||||
erases the element and returns `x`.
|
||||
|
||||
---
|
||||
|
||||
==== clear
|
||||
```c++
|
||||
void clear() noexcept;
|
||||
@@ -1607,6 +1618,8 @@ for (auto i = c.begin(), last = c.end(); i != last; ) {
|
||||
}
|
||||
return original_size - c.size();
|
||||
```
|
||||
+
|
||||
Note that the references passed to `pred` are non-const.
|
||||
|
||||
=== Serialization
|
||||
|
||||
|
||||
@@ -140,6 +140,7 @@ namespace unordered {
|
||||
node_type xref:#unordered_node_set_extract_by_position[extract](const_iterator position);
|
||||
node_type xref:#unordered_node_set_extract_by_key[extract](const key_type& key);
|
||||
template<class K> node_type xref:#unordered_node_set_extract_by_key[extract](K&& key);
|
||||
init_type xref:#unordered_node_set_pull[pull](const_iterator position);
|
||||
void xref:#unordered_node_set_clear[clear]() noexcept;
|
||||
|
||||
template<class H2, class P2>
|
||||
@@ -269,7 +270,7 @@ The size of the bucket array can be automatically increased by a call to `insert
|
||||
greater than `max_load_factor()`, except possibly for small sizes where the implementation may decide to
|
||||
allow for higher loads.
|
||||
|
||||
If `xref:reference/hash_traits.adoc#hash_traits_hash_is_avalanching[hash_is_avalanching]<Hash>::value` is `true`, the hash function
|
||||
If `link:../../../../../container_hash/doc/html/hash.html#ref_hash_is_avalanchinghash[hash_is_avalanching]<Hash>::value` is `true`, the hash function
|
||||
is used as-is; otherwise, a bit-mixing post-processing stage is added to increase the quality of hashing
|
||||
at the expense of extra computational cost.
|
||||
|
||||
@@ -1034,6 +1035,16 @@ Notes:;; The `template<class K>` overload only participates in overload resoluti
|
||||
|
||||
---
|
||||
|
||||
==== pull
|
||||
```c++
|
||||
init_type pull(const_iterator position);
|
||||
```
|
||||
|
||||
Move-constructs an `init_value` `x` from the element pointed to by `position`,
|
||||
erases the element and returns `x`.
|
||||
|
||||
---
|
||||
|
||||
==== clear
|
||||
```c++
|
||||
void clear() noexcept;
|
||||
|
||||
Generated
+1920
-1541
File diff suppressed because it is too large
Load Diff
+3
-3
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"devDependencies": {
|
||||
"@antora/cli": "3.1.10",
|
||||
"@antora/site-generator": "3.1.10",
|
||||
"antora": "3.1.10"
|
||||
"@antora/cli": ">=3.1.14",
|
||||
"@antora/site-generator": ">=3.1.14",
|
||||
"antora": ">=3.1.14"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Copyright 2024 Braden Ganetsky
|
||||
# Copyright 2024-2025 Braden Ganetsky
|
||||
# Distributed under the Boost Software License, Version 1.0.
|
||||
# https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
@@ -14,7 +14,7 @@ class BoostUnorderedHelpers:
|
||||
return n.cast(underlying_type)
|
||||
else:
|
||||
return n
|
||||
|
||||
|
||||
def maybe_unwrap_foa_element(e):
|
||||
if f"{e.type.strip_typedefs()}".startswith("boost::unordered::detail::foa::element_type<"):
|
||||
return e["p"]
|
||||
@@ -45,14 +45,15 @@ class BoostUnorderedPointerCustomizationPoint:
|
||||
|
||||
class BoostUnorderedFcaPrinter:
|
||||
def __init__(self, val):
|
||||
self.val = BoostUnorderedHelpers.maybe_unwrap_reference(val)
|
||||
self.name = f"{self.val.type.strip_typedefs()}".split("<")[0]
|
||||
val = BoostUnorderedHelpers.maybe_unwrap_reference(val)
|
||||
self.table = val["table_"]
|
||||
self.name = f"{val.type.strip_typedefs()}".split("<")[0]
|
||||
self.name = self.name.replace("boost::unordered::", "boost::")
|
||||
self.is_map = self.name.endswith("map")
|
||||
self.cpo = BoostUnorderedPointerCustomizationPoint(self.val["table_"]["buckets_"]["buckets"])
|
||||
self.cpo = BoostUnorderedPointerCustomizationPoint(self.table["buckets_"]["buckets"])
|
||||
|
||||
def to_string(self):
|
||||
size = self.val["table_"]["size_"]
|
||||
size = self.table["size_"]
|
||||
return f"{self.name} with {size} elements"
|
||||
|
||||
def display_hint(self):
|
||||
@@ -60,7 +61,7 @@ class BoostUnorderedFcaPrinter:
|
||||
|
||||
def children(self):
|
||||
def generator():
|
||||
grouped_buckets = self.val["table_"]["buckets_"]
|
||||
grouped_buckets = self.table["buckets_"]
|
||||
|
||||
size = grouped_buckets["size_"]
|
||||
buckets = grouped_buckets["buckets"]
|
||||
@@ -83,7 +84,7 @@ class BoostUnorderedFcaPrinter:
|
||||
count += 1
|
||||
node = self.cpo.to_address(node.dereference()["next"])
|
||||
bucket_index += 1
|
||||
|
||||
|
||||
return generator()
|
||||
|
||||
class BoostUnorderedFcaIteratorPrinter:
|
||||
@@ -118,7 +119,7 @@ class BoostUnorderedFoaTableCoreCumulativeStatsPrinter:
|
||||
yield "", member
|
||||
yield "", self.val[member]
|
||||
return generator()
|
||||
|
||||
|
||||
class BoostUnorderedFoaCumulativeStatsPrinter:
|
||||
def __init__(self, val):
|
||||
self.val = val
|
||||
@@ -127,7 +128,7 @@ class BoostUnorderedFoaCumulativeStatsPrinter:
|
||||
|
||||
def display_hint(self):
|
||||
return "map"
|
||||
|
||||
|
||||
def children(self):
|
||||
def generator():
|
||||
yield "", "count"
|
||||
@@ -154,14 +155,20 @@ class BoostUnorderedFoaCumulativeStatsPrinter:
|
||||
|
||||
class BoostUnorderedFoaPrinter:
|
||||
def __init__(self, val):
|
||||
self.val = BoostUnorderedHelpers.maybe_unwrap_reference(val)
|
||||
self.name = f"{self.val.type.strip_typedefs()}".split("<")[0]
|
||||
val = BoostUnorderedHelpers.maybe_unwrap_reference(val)
|
||||
self.table = val["table_"]
|
||||
self.name = f"{val.type.strip_typedefs()}".split("<")[0]
|
||||
self.name = self.name.replace("boost::unordered::", "boost::")
|
||||
self.is_map = self.name.endswith("map")
|
||||
self.cpo = BoostUnorderedPointerCustomizationPoint(self.val["table_"]["arrays"]["groups_"])
|
||||
self.cpo = BoostUnorderedPointerCustomizationPoint(self.table["arrays"]["groups_"])
|
||||
self.groups = self.cpo.to_address(self.table["arrays"]["groups_"])
|
||||
self.elements = self.cpo.to_address(self.table["arrays"]["elements_"])
|
||||
|
||||
self.N = 15 # `self.groups.dereference()["N"]` may be optimized out
|
||||
self.sentinel_ = 1 # `self.groups.dereference()["sentinel_"]` may be optimized out
|
||||
|
||||
def to_string(self):
|
||||
size = BoostUnorderedHelpers.maybe_unwrap_atomic(self.val["table_"]["size_ctrl"]["size"])
|
||||
size = BoostUnorderedHelpers.maybe_unwrap_atomic(self.table["size_ctrl"]["size"])
|
||||
return f"{self.name} with {size} elements"
|
||||
|
||||
def display_hint(self):
|
||||
@@ -191,30 +198,21 @@ class BoostUnorderedFoaPrinter:
|
||||
m = group["m"]
|
||||
at = lambda b: BoostUnorderedHelpers.maybe_unwrap_atomic(m[b]["n"])
|
||||
|
||||
N = group["N"]
|
||||
sentinel_ = group["sentinel_"]
|
||||
if self.is_regular_layout(group):
|
||||
return pos == N-1 and at(N-1) == sentinel_
|
||||
return pos == self.N-1 and at(self.N-1) == self.sentinel_
|
||||
else:
|
||||
return pos == N-1 and (at(0) & 0x4000400040004000) == 0x4000 and (at(1) & 0x4000400040004000) == 0
|
||||
return pos == self.N-1 and (at(0) & 0x4000400040004000) == 0x4000 and (at(1) & 0x4000400040004000) == 0
|
||||
|
||||
def children(self):
|
||||
def generator():
|
||||
table = self.val["table_"]
|
||||
groups = self.cpo.to_address(table["arrays"]["groups_"])
|
||||
elements = self.cpo.to_address(table["arrays"]["elements_"])
|
||||
|
||||
pc_ = groups.cast(gdb.lookup_type("unsigned char").pointer())
|
||||
p_ = elements
|
||||
pc_ = self.groups.cast(gdb.lookup_type("unsigned char").pointer())
|
||||
p_ = self.elements
|
||||
first_time = True
|
||||
mask = 0
|
||||
n0 = 0
|
||||
n = 0
|
||||
|
||||
count = 0
|
||||
while p_ != 0:
|
||||
# This if block mirrors the condition in the begin() call
|
||||
if (not first_time) or (self.match_occupied(groups.dereference()) & 1):
|
||||
if (not first_time) or (self.match_occupied(self.groups.dereference()) & 1):
|
||||
pointer = BoostUnorderedHelpers.maybe_unwrap_foa_element(p_)
|
||||
value = self.cpo.to_address(pointer).dereference()
|
||||
if self.is_map:
|
||||
@@ -228,17 +226,17 @@ class BoostUnorderedFoaPrinter:
|
||||
count += 1
|
||||
first_time = False
|
||||
|
||||
n0 = pc_.cast(gdb.lookup_type("uintptr_t")) % groups.dereference().type.sizeof
|
||||
n0 = pc_.cast(gdb.lookup_type("uintptr_t")) % self.groups.dereference().type.sizeof
|
||||
pc_ = self.cpo.next(pc_, -n0)
|
||||
|
||||
mask = (self.match_occupied(pc_.cast(groups.type).dereference()) >> (n0+1)) << (n0+1)
|
||||
mask = (self.match_occupied(pc_.cast(self.groups.type).dereference()) >> (n0+1)) << (n0+1)
|
||||
while mask == 0:
|
||||
pc_ = self.cpo.next(pc_, groups.dereference().type.sizeof)
|
||||
p_ = self.cpo.next(p_, groups.dereference()["N"])
|
||||
mask = self.match_occupied(pc_.cast(groups.type).dereference())
|
||||
|
||||
pc_ = self.cpo.next(pc_, self.groups.dereference().type.sizeof)
|
||||
p_ = self.cpo.next(p_, self.N)
|
||||
mask = self.match_occupied(pc_.cast(self.groups.type).dereference())
|
||||
|
||||
n = BoostUnorderedHelpers.countr_zero(mask)
|
||||
if self.is_sentinel(pc_.cast(groups.type).dereference(), n):
|
||||
if self.is_sentinel(pc_.cast(self.groups.type).dereference(), n):
|
||||
p_ = 0
|
||||
else:
|
||||
pc_ = self.cpo.next(pc_, n)
|
||||
@@ -284,7 +282,7 @@ def boost_unordered_build_pretty_printer():
|
||||
add_template_printer("boost::unordered::concurrent_flat_set", BoostUnorderedFoaPrinter)
|
||||
add_template_printer("boost::unordered::concurrent_node_map", BoostUnorderedFoaPrinter)
|
||||
add_template_printer("boost::unordered::concurrent_node_set", BoostUnorderedFoaPrinter)
|
||||
|
||||
|
||||
add_template_printer("boost::unordered::detail::foa::table_iterator", BoostUnorderedFoaIteratorPrinter)
|
||||
|
||||
add_concrete_printer("boost::unordered::detail::foa::table_core_cumulative_stats", BoostUnorderedFoaTableCoreCumulativeStatsPrinter)
|
||||
@@ -301,7 +299,7 @@ gdb.printing.register_pretty_printer(gdb.current_objfile(), boost_unordered_buil
|
||||
class BoostUnorderedFoaGetStatsMethod(gdb.xmethod.XMethod):
|
||||
def __init__(self):
|
||||
gdb.xmethod.XMethod.__init__(self, "get_stats")
|
||||
|
||||
|
||||
def get_worker(self, method_name):
|
||||
if method_name == "get_stats":
|
||||
return BoostUnorderedFoaGetStatsWorker()
|
||||
@@ -312,19 +310,19 @@ class BoostUnorderedFoaGetStatsWorker(gdb.xmethod.XMethodWorker):
|
||||
|
||||
def get_result_type(self, obj):
|
||||
return gdb.lookup_type("boost::unordered::detail::foa::table_core_cumulative_stats")
|
||||
|
||||
|
||||
def __call__(self, obj):
|
||||
try:
|
||||
return obj["table_"]["cstats"]
|
||||
except gdb.error:
|
||||
print("Error: Binary was compiled without stats. Recompile with `BOOST_UNORDERED_ENABLE_STATS` defined.")
|
||||
return
|
||||
|
||||
|
||||
class BoostUnorderedFoaMatcher(gdb.xmethod.XMethodMatcher):
|
||||
def __init__(self):
|
||||
gdb.xmethod.XMethodMatcher.__init__(self, 'BoostUnorderedFoaMatcher')
|
||||
self.methods = [BoostUnorderedFoaGetStatsMethod()]
|
||||
|
||||
|
||||
def match(self, class_type, method_name):
|
||||
template_name = f"{class_type.strip_typedefs()}".split("<")[0]
|
||||
regex = "^boost::unordered::(unordered|concurrent)_(flat|node)_(map|set)$"
|
||||
@@ -380,12 +378,12 @@ class MyFancyPtrPrinter:
|
||||
def boost_to_address(fancy_ptr):
|
||||
...
|
||||
return ...
|
||||
|
||||
|
||||
# Equivalent to `operator+()`
|
||||
def boost_next(raw_ptr, offset):
|
||||
...
|
||||
return ...
|
||||
|
||||
|
||||
...
|
||||
```
|
||||
"""
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright (C) 2022-2024 Joaquin M Lopez Munoz.
|
||||
// Copyright (C) 2022-2025 Joaquin M Lopez Munoz.
|
||||
// Copyright (C) 2022 Christian Mazakas
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
@@ -134,11 +134,37 @@ namespace boost {
|
||||
namespace unordered {
|
||||
namespace detail {
|
||||
|
||||
template <class ValueType, class VoidPtr> struct node;
|
||||
|
||||
// access to node::value_type and node::pointer for incomplete node
|
||||
|
||||
template<class Node> struct node_value_type_impl;
|
||||
|
||||
template <class ValueType, class VoidPtr>
|
||||
struct node_value_type_impl<node<ValueType, VoidPtr>>
|
||||
{
|
||||
typedef ValueType type;
|
||||
};
|
||||
|
||||
template<class Node> using node_value_type =
|
||||
typename node_value_type_impl<Node>::type;
|
||||
|
||||
template<class Node> struct node_pointer_impl;
|
||||
|
||||
template <class ValueType, class VoidPtr>
|
||||
struct node_pointer_impl<node<ValueType, VoidPtr>>
|
||||
{
|
||||
typedef typename boost::pointer_traits<VoidPtr>::template rebind_to<
|
||||
node<ValueType, VoidPtr>>::type type;
|
||||
};
|
||||
|
||||
template<class Node> using node_pointer =
|
||||
typename node_pointer_impl<Node>::type;
|
||||
|
||||
template <class ValueType, class VoidPtr> struct node
|
||||
{
|
||||
typedef ValueType value_type;
|
||||
typedef typename boost::pointer_traits<VoidPtr>::template rebind_to<
|
||||
node>::type node_pointer;
|
||||
typedef node_value_type<node> value_type;
|
||||
typedef detail::node_pointer<node> node_pointer;
|
||||
|
||||
node_pointer next;
|
||||
opt_storage<value_type> buf;
|
||||
@@ -304,10 +330,10 @@ namespace boost {
|
||||
|
||||
template <class Node> struct grouped_local_bucket_iterator
|
||||
{
|
||||
typedef typename Node::node_pointer node_pointer;
|
||||
typedef detail::node_pointer<Node> node_pointer;
|
||||
|
||||
public:
|
||||
typedef typename Node::value_type value_type;
|
||||
typedef detail::node_value_type<Node> value_type;
|
||||
typedef value_type element_type;
|
||||
typedef value_type* pointer;
|
||||
typedef value_type& reference;
|
||||
@@ -370,10 +396,10 @@ namespace boost {
|
||||
|
||||
template <class Node> struct const_grouped_local_bucket_iterator
|
||||
{
|
||||
typedef typename Node::node_pointer node_pointer;
|
||||
typedef detail::node_pointer<Node> node_pointer;
|
||||
|
||||
public:
|
||||
typedef typename Node::value_type const value_type;
|
||||
typedef detail::node_value_type<Node> const value_type;
|
||||
typedef value_type const element_type;
|
||||
typedef value_type const* pointer;
|
||||
typedef value_type const& reference;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* Common base for Boost.Unordered open-addressing tables.
|
||||
*
|
||||
* Copyright 2022-2024 Joaquin M Lopez Munoz.
|
||||
* Copyright 2022-2025 Joaquin M Lopez Munoz.
|
||||
* Copyright 2023 Christian Mazakas.
|
||||
* Copyright 2024 Braden Ganetsky.
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
@@ -16,6 +16,7 @@
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/config/workaround.hpp>
|
||||
#include <boost/container_hash/hash_is_avalanching.hpp>
|
||||
#include <boost/core/allocator_traits.hpp>
|
||||
#include <boost/core/bit.hpp>
|
||||
#include <boost/core/empty_value.hpp>
|
||||
@@ -28,8 +29,7 @@
|
||||
#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/unordered_printers.hpp>
|
||||
#include <boost/unordered/detail/unordered_printers.hpp>
|
||||
#include <climits>
|
||||
#include <cmath>
|
||||
#include <cstddef>
|
||||
@@ -923,6 +923,8 @@ inline unsigned int unchecked_countr_zero(int x)
|
||||
unsigned long r;
|
||||
_BitScanForward(&r,(unsigned long)x);
|
||||
return (unsigned int)r;
|
||||
#elif defined(BOOST_GCC)||defined(BOOST_CLANG)
|
||||
return (unsigned int)__builtin_ctz((unsigned int)x);
|
||||
#else
|
||||
BOOST_UNORDERED_ASSUME(x!=0);
|
||||
return (unsigned int)boost::core::countr_zero((unsigned int)x);
|
||||
@@ -1426,7 +1428,7 @@ public:
|
||||
using size_policy=pow2_size_policy;
|
||||
using prober=pow2_quadratic_prober;
|
||||
using mix_policy=typename std::conditional<
|
||||
hash_is_avalanching<Hash>::value,
|
||||
boost::hash_is_avalanching<Hash>::value,
|
||||
no_mix,
|
||||
mulx_mix
|
||||
>::type;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* Fast open-addressing hash table.
|
||||
*
|
||||
* Copyright 2022-2024 Joaquin M Lopez Munoz.
|
||||
* Copyright 2022-2025 Joaquin M Lopez Munoz.
|
||||
* Copyright 2023 Christian Mazakas.
|
||||
* Copyright 2024 Braden Ganetsky.
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
@@ -495,6 +495,14 @@ public:
|
||||
else return 0;
|
||||
}
|
||||
|
||||
BOOST_FORCEINLINE init_type pull(const_iterator pos)
|
||||
{
|
||||
BOOST_ASSERT(pos!=end());
|
||||
erase_on_exit e{*this,pos};
|
||||
(void)e;
|
||||
return type_policy::move(type_policy::value_from(*pos.p()));
|
||||
}
|
||||
|
||||
void swap(table& x)
|
||||
noexcept(noexcept(std::declval<super&>().swap(std::declval<super&>())))
|
||||
{
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
#include <boost/unordered/detail/serialize_tracked_address.hpp>
|
||||
#include <boost/unordered/detail/static_assert.hpp>
|
||||
#include <boost/unordered/detail/type_traits.hpp>
|
||||
#include <boost/unordered/unordered_printers.hpp>
|
||||
#include <boost/unordered/detail/unordered_printers.hpp>
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/core/allocator_traits.hpp>
|
||||
@@ -969,7 +969,7 @@ namespace boost {
|
||||
template <class Node, class Bucket> class iterator
|
||||
{
|
||||
public:
|
||||
typedef typename Node::value_type value_type;
|
||||
typedef typename detail::node_value_type<Node> value_type;
|
||||
typedef value_type element_type;
|
||||
typedef value_type* pointer;
|
||||
typedef value_type& reference;
|
||||
@@ -1023,7 +1023,7 @@ namespace boost {
|
||||
}
|
||||
|
||||
private:
|
||||
typedef typename Node::node_pointer node_pointer;
|
||||
typedef detail::node_pointer<Node> node_pointer;
|
||||
typedef grouped_bucket_iterator<Bucket> bucket_iterator;
|
||||
|
||||
node_pointer p;
|
||||
@@ -1076,7 +1076,7 @@ namespace boost {
|
||||
template <class Node, class Bucket> class c_iterator
|
||||
{
|
||||
public:
|
||||
typedef typename Node::value_type value_type;
|
||||
typedef typename detail::node_value_type<Node> value_type;
|
||||
typedef value_type const element_type;
|
||||
typedef value_type const* pointer;
|
||||
typedef value_type const& reference;
|
||||
@@ -1131,7 +1131,7 @@ namespace boost {
|
||||
}
|
||||
|
||||
private:
|
||||
typedef typename Node::node_pointer node_pointer;
|
||||
typedef detail::node_pointer<Node> node_pointer;
|
||||
typedef grouped_bucket_iterator<Bucket> bucket_iterator;
|
||||
|
||||
node_pointer p;
|
||||
|
||||
+33
-35
@@ -1,11 +1,11 @@
|
||||
// Copyright 2024 Braden Ganetsky
|
||||
// Copyright 2024-2025 Braden Ganetsky
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
// Generated on 2024-08-25T17:48:54
|
||||
// Generated on 2025-08-21T03:09:19
|
||||
|
||||
#ifndef BOOST_UNORDERED_UNORDERED_PRINTERS_HPP
|
||||
#define BOOST_UNORDERED_UNORDERED_PRINTERS_HPP
|
||||
#ifndef BOOST_UNORDERED_DETAIL_UNORDERED_PRINTERS_HPP
|
||||
#define BOOST_UNORDERED_DETAIL_UNORDERED_PRINTERS_HPP
|
||||
|
||||
#ifndef BOOST_ALL_NO_EMBEDDED_GDB_SCRIPTS
|
||||
#if defined(__ELF__)
|
||||
@@ -14,7 +14,7 @@
|
||||
#pragma clang diagnostic ignored "-Woverlength-strings"
|
||||
#endif
|
||||
__asm__(".pushsection \".debug_gdb_scripts\", \"MS\",%progbits,1\n"
|
||||
".ascii \"\\4gdb.inlined-script.BOOST_UNORDERED_UNORDERED_PRINTERS_HPP\\n\"\n"
|
||||
".ascii \"\\4gdb.inlined-script.BOOST_UNORDERED_DETAIL_UNORDERED_PRINTERS_HPP\\n\"\n"
|
||||
".ascii \"import gdb.printing\\n\"\n"
|
||||
".ascii \"import gdb.xmethod\\n\"\n"
|
||||
".ascii \"import re\\n\"\n"
|
||||
@@ -58,14 +58,15 @@ __asm__(".pushsection \".debug_gdb_scripts\", \"MS\",%progbits,1\n"
|
||||
|
||||
".ascii \"class BoostUnorderedFcaPrinter:\\n\"\n"
|
||||
".ascii \" def __init__(self, val):\\n\"\n"
|
||||
".ascii \" self.val = BoostUnorderedHelpers.maybe_unwrap_reference(val)\\n\"\n"
|
||||
".ascii \" self.name = f\\\"{self.val.type.strip_typedefs()}\\\".split(\\\"<\\\")[0]\\n\"\n"
|
||||
".ascii \" val = BoostUnorderedHelpers.maybe_unwrap_reference(val)\\n\"\n"
|
||||
".ascii \" self.table = val[\\\"table_\\\"]\\n\"\n"
|
||||
".ascii \" self.name = f\\\"{val.type.strip_typedefs()}\\\".split(\\\"<\\\")[0]\\n\"\n"
|
||||
".ascii \" self.name = self.name.replace(\\\"boost::unordered::\\\", \\\"boost::\\\")\\n\"\n"
|
||||
".ascii \" self.is_map = self.name.endswith(\\\"map\\\")\\n\"\n"
|
||||
".ascii \" self.cpo = BoostUnorderedPointerCustomizationPoint(self.val[\\\"table_\\\"][\\\"buckets_\\\"][\\\"buckets\\\"])\\n\"\n"
|
||||
".ascii \" self.cpo = BoostUnorderedPointerCustomizationPoint(self.table[\\\"buckets_\\\"][\\\"buckets\\\"])\\n\"\n"
|
||||
|
||||
".ascii \" def to_string(self):\\n\"\n"
|
||||
".ascii \" size = self.val[\\\"table_\\\"][\\\"size_\\\"]\\n\"\n"
|
||||
".ascii \" size = self.table[\\\"size_\\\"]\\n\"\n"
|
||||
".ascii \" return f\\\"{self.name} with {size} elements\\\"\\n\"\n"
|
||||
|
||||
".ascii \" def display_hint(self):\\n\"\n"
|
||||
@@ -73,7 +74,7 @@ __asm__(".pushsection \".debug_gdb_scripts\", \"MS\",%progbits,1\n"
|
||||
|
||||
".ascii \" def children(self):\\n\"\n"
|
||||
".ascii \" def generator():\\n\"\n"
|
||||
".ascii \" grouped_buckets = self.val[\\\"table_\\\"][\\\"buckets_\\\"]\\n\"\n"
|
||||
".ascii \" grouped_buckets = self.table[\\\"buckets_\\\"]\\n\"\n"
|
||||
|
||||
".ascii \" size = grouped_buckets[\\\"size_\\\"]\\n\"\n"
|
||||
".ascii \" buckets = grouped_buckets[\\\"buckets\\\"]\\n\"\n"
|
||||
@@ -167,14 +168,20 @@ __asm__(".pushsection \".debug_gdb_scripts\", \"MS\",%progbits,1\n"
|
||||
|
||||
".ascii \"class BoostUnorderedFoaPrinter:\\n\"\n"
|
||||
".ascii \" def __init__(self, val):\\n\"\n"
|
||||
".ascii \" self.val = BoostUnorderedHelpers.maybe_unwrap_reference(val)\\n\"\n"
|
||||
".ascii \" self.name = f\\\"{self.val.type.strip_typedefs()}\\\".split(\\\"<\\\")[0]\\n\"\n"
|
||||
".ascii \" val = BoostUnorderedHelpers.maybe_unwrap_reference(val)\\n\"\n"
|
||||
".ascii \" self.table = val[\\\"table_\\\"]\\n\"\n"
|
||||
".ascii \" self.name = f\\\"{val.type.strip_typedefs()}\\\".split(\\\"<\\\")[0]\\n\"\n"
|
||||
".ascii \" self.name = self.name.replace(\\\"boost::unordered::\\\", \\\"boost::\\\")\\n\"\n"
|
||||
".ascii \" self.is_map = self.name.endswith(\\\"map\\\")\\n\"\n"
|
||||
".ascii \" self.cpo = BoostUnorderedPointerCustomizationPoint(self.val[\\\"table_\\\"][\\\"arrays\\\"][\\\"groups_\\\"])\\n\"\n"
|
||||
".ascii \" self.cpo = BoostUnorderedPointerCustomizationPoint(self.table[\\\"arrays\\\"][\\\"groups_\\\"])\\n\"\n"
|
||||
".ascii \" self.groups = self.cpo.to_address(self.table[\\\"arrays\\\"][\\\"groups_\\\"])\\n\"\n"
|
||||
".ascii \" self.elements = self.cpo.to_address(self.table[\\\"arrays\\\"][\\\"elements_\\\"])\\n\"\n"
|
||||
|
||||
".ascii \" self.N = 15 # `self.groups.dereference()[\\\"N\\\"]` may be optimized out\\n\"\n"
|
||||
".ascii \" self.sentinel_ = 1 # `self.groups.dereference()[\\\"sentinel_\\\"]` may be optimized out\\n\"\n"
|
||||
|
||||
".ascii \" def to_string(self):\\n\"\n"
|
||||
".ascii \" size = BoostUnorderedHelpers.maybe_unwrap_atomic(self.val[\\\"table_\\\"][\\\"size_ctrl\\\"][\\\"size\\\"])\\n\"\n"
|
||||
".ascii \" size = BoostUnorderedHelpers.maybe_unwrap_atomic(self.table[\\\"size_ctrl\\\"][\\\"size\\\"])\\n\"\n"
|
||||
".ascii \" return f\\\"{self.name} with {size} elements\\\"\\n\"\n"
|
||||
|
||||
".ascii \" def display_hint(self):\\n\"\n"
|
||||
@@ -204,30 +211,21 @@ __asm__(".pushsection \".debug_gdb_scripts\", \"MS\",%progbits,1\n"
|
||||
".ascii \" m = group[\\\"m\\\"]\\n\"\n"
|
||||
".ascii \" at = lambda b: BoostUnorderedHelpers.maybe_unwrap_atomic(m[b][\\\"n\\\"])\\n\"\n"
|
||||
|
||||
".ascii \" N = group[\\\"N\\\"]\\n\"\n"
|
||||
".ascii \" sentinel_ = group[\\\"sentinel_\\\"]\\n\"\n"
|
||||
".ascii \" if self.is_regular_layout(group):\\n\"\n"
|
||||
".ascii \" return pos == N-1 and at(N-1) == sentinel_\\n\"\n"
|
||||
".ascii \" return pos == self.N-1 and at(self.N-1) == self.sentinel_\\n\"\n"
|
||||
".ascii \" else:\\n\"\n"
|
||||
".ascii \" return pos == N-1 and (at(0) & 0x4000400040004000) == 0x4000 and (at(1) & 0x4000400040004000) == 0\\n\"\n"
|
||||
".ascii \" return pos == self.N-1 and (at(0) & 0x4000400040004000) == 0x4000 and (at(1) & 0x4000400040004000) == 0\\n\"\n"
|
||||
|
||||
".ascii \" def children(self):\\n\"\n"
|
||||
".ascii \" def generator():\\n\"\n"
|
||||
".ascii \" table = self.val[\\\"table_\\\"]\\n\"\n"
|
||||
".ascii \" groups = self.cpo.to_address(table[\\\"arrays\\\"][\\\"groups_\\\"])\\n\"\n"
|
||||
".ascii \" elements = self.cpo.to_address(table[\\\"arrays\\\"][\\\"elements_\\\"])\\n\"\n"
|
||||
|
||||
".ascii \" pc_ = groups.cast(gdb.lookup_type(\\\"unsigned char\\\").pointer())\\n\"\n"
|
||||
".ascii \" p_ = elements\\n\"\n"
|
||||
".ascii \" pc_ = self.groups.cast(gdb.lookup_type(\\\"unsigned char\\\").pointer())\\n\"\n"
|
||||
".ascii \" p_ = self.elements\\n\"\n"
|
||||
".ascii \" first_time = True\\n\"\n"
|
||||
".ascii \" mask = 0\\n\"\n"
|
||||
".ascii \" n0 = 0\\n\"\n"
|
||||
".ascii \" n = 0\\n\"\n"
|
||||
|
||||
".ascii \" count = 0\\n\"\n"
|
||||
".ascii \" while p_ != 0:\\n\"\n"
|
||||
".ascii \" # This if block mirrors the condition in the begin() call\\n\"\n"
|
||||
".ascii \" if (not first_time) or (self.match_occupied(groups.dereference()) & 1):\\n\"\n"
|
||||
".ascii \" if (not first_time) or (self.match_occupied(self.groups.dereference()) & 1):\\n\"\n"
|
||||
".ascii \" pointer = BoostUnorderedHelpers.maybe_unwrap_foa_element(p_)\\n\"\n"
|
||||
".ascii \" value = self.cpo.to_address(pointer).dereference()\\n\"\n"
|
||||
".ascii \" if self.is_map:\\n\"\n"
|
||||
@@ -241,17 +239,17 @@ __asm__(".pushsection \".debug_gdb_scripts\", \"MS\",%progbits,1\n"
|
||||
".ascii \" count += 1\\n\"\n"
|
||||
".ascii \" first_time = False\\n\"\n"
|
||||
|
||||
".ascii \" n0 = pc_.cast(gdb.lookup_type(\\\"uintptr_t\\\")) % groups.dereference().type.sizeof\\n\"\n"
|
||||
".ascii \" n0 = pc_.cast(gdb.lookup_type(\\\"uintptr_t\\\")) % self.groups.dereference().type.sizeof\\n\"\n"
|
||||
".ascii \" pc_ = self.cpo.next(pc_, -n0)\\n\"\n"
|
||||
|
||||
".ascii \" mask = (self.match_occupied(pc_.cast(groups.type).dereference()) >> (n0+1)) << (n0+1)\\n\"\n"
|
||||
".ascii \" mask = (self.match_occupied(pc_.cast(self.groups.type).dereference()) >> (n0+1)) << (n0+1)\\n\"\n"
|
||||
".ascii \" while mask == 0:\\n\"\n"
|
||||
".ascii \" pc_ = self.cpo.next(pc_, groups.dereference().type.sizeof)\\n\"\n"
|
||||
".ascii \" p_ = self.cpo.next(p_, groups.dereference()[\\\"N\\\"])\\n\"\n"
|
||||
".ascii \" mask = self.match_occupied(pc_.cast(groups.type).dereference())\\n\"\n"
|
||||
".ascii \" pc_ = self.cpo.next(pc_, self.groups.dereference().type.sizeof)\\n\"\n"
|
||||
".ascii \" p_ = self.cpo.next(p_, self.N)\\n\"\n"
|
||||
".ascii \" mask = self.match_occupied(pc_.cast(self.groups.type).dereference())\\n\"\n"
|
||||
|
||||
".ascii \" n = BoostUnorderedHelpers.countr_zero(mask)\\n\"\n"
|
||||
".ascii \" if self.is_sentinel(pc_.cast(groups.type).dereference(), n):\\n\"\n"
|
||||
".ascii \" if self.is_sentinel(pc_.cast(self.groups.type).dereference(), n):\\n\"\n"
|
||||
".ascii \" p_ = 0\\n\"\n"
|
||||
".ascii \" else:\\n\"\n"
|
||||
".ascii \" pc_ = self.cpo.next(pc_, n)\\n\"\n"
|
||||
@@ -411,4 +409,4 @@ __asm__(".pushsection \".debug_gdb_scripts\", \"MS\",%progbits,1\n"
|
||||
#endif // defined(__ELF__)
|
||||
#endif // !defined(BOOST_ALL_NO_EMBEDDED_GDB_SCRIPTS)
|
||||
|
||||
#endif // !defined(BOOST_UNORDERED_UNORDERED_PRINTERS_HPP)
|
||||
#endif // !defined(BOOST_UNORDERED_DETAIL_UNORDERED_PRINTERS_HPP)
|
||||
@@ -1,6 +1,6 @@
|
||||
/* Hash function characterization.
|
||||
*
|
||||
* Copyright 2022-2024 Joaquin M Lopez Munoz.
|
||||
* Copyright 2022-2025 Joaquin M Lopez Munoz.
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -11,58 +11,15 @@
|
||||
#ifndef BOOST_UNORDERED_HASH_TRAITS_HPP
|
||||
#define BOOST_UNORDERED_HASH_TRAITS_HPP
|
||||
|
||||
#include <boost/unordered/detail/type_traits.hpp>
|
||||
#include <boost/config/header_deprecated.hpp>
|
||||
#include <boost/container_hash/hash_is_avalanching.hpp>
|
||||
|
||||
BOOST_HEADER_DEPRECATED("<boost/container_hash/hash_is_avalanching.hpp>")
|
||||
|
||||
namespace boost{
|
||||
namespace unordered{
|
||||
|
||||
namespace detail{
|
||||
|
||||
template<typename Hash,typename=void>
|
||||
struct hash_is_avalanching_impl:std::false_type{};
|
||||
|
||||
template<typename IsAvalanching>
|
||||
struct avalanching_value
|
||||
{
|
||||
static constexpr bool value=IsAvalanching::value;
|
||||
};
|
||||
|
||||
/* may be explicitly marked as BOOST_DEPRECATED in the future */
|
||||
template<> struct avalanching_value<void>
|
||||
{
|
||||
static constexpr bool value=true;
|
||||
};
|
||||
|
||||
template<typename Hash>
|
||||
struct hash_is_avalanching_impl<
|
||||
Hash,
|
||||
boost::unordered::detail::void_t<typename Hash::is_avalanching>
|
||||
>:std::integral_constant<
|
||||
bool,
|
||||
avalanching_value<typename Hash::is_avalanching>::value
|
||||
>{};
|
||||
|
||||
template<typename Hash>
|
||||
struct hash_is_avalanching_impl<
|
||||
Hash,
|
||||
typename std::enable_if<((void)Hash::is_avalanching,true)>::type
|
||||
>{}; /* Hash::is_avalanching is not a type: compile error downstream */
|
||||
|
||||
} /* namespace detail */
|
||||
|
||||
/* Each trait can be partially specialized by users for concrete hash functions
|
||||
* when actual characterization differs from default.
|
||||
*/
|
||||
|
||||
/* hash_is_avalanching<Hash>::value is:
|
||||
* - false if Hash::is_avalanching is not present.
|
||||
* - Hash::is_avalanching::value if this is present and constexpr-convertible
|
||||
* to a bool.
|
||||
* - true if Hash::is_avalanching is void (deprecated).
|
||||
* - ill-formed otherwise.
|
||||
*/
|
||||
template<typename Hash>
|
||||
struct hash_is_avalanching: detail::hash_is_avalanching_impl<Hash>::type{};
|
||||
using boost::hash_is_avalanching;
|
||||
|
||||
} /* namespace unordered */
|
||||
} /* namespace boost */
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// Copyright (C) 2022-2023 Christian Mazakas
|
||||
// Copyright (C) 2024 Joaquin M Lopez Munoz
|
||||
// Copyright (C) 2024-2025 Joaquin M Lopez Munoz
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
@@ -438,6 +438,11 @@ namespace boost {
|
||||
return table_.erase(key);
|
||||
}
|
||||
|
||||
BOOST_FORCEINLINE init_type pull(const_iterator pos)
|
||||
{
|
||||
return table_.pull(pos);
|
||||
}
|
||||
|
||||
void swap(unordered_flat_map& rhs) noexcept(
|
||||
noexcept(std::declval<table_type&>().swap(std::declval<table_type&>())))
|
||||
{
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// Copyright (C) 2022-2023 Christian Mazakas
|
||||
// Copyright (C) 2024 Joaquin M Lopez Munoz
|
||||
// Copyright (C) 2024-2025 Joaquin M Lopez Munoz
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
@@ -332,6 +332,11 @@ namespace boost {
|
||||
return table_.erase(key);
|
||||
}
|
||||
|
||||
BOOST_FORCEINLINE init_type pull(const_iterator pos)
|
||||
{
|
||||
return table_.pull(pos);
|
||||
}
|
||||
|
||||
void swap(unordered_flat_set& rhs) noexcept(
|
||||
noexcept(std::declval<table_type&>().swap(std::declval<table_type&>())))
|
||||
{
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// Copyright (C) 2022-2023 Christian Mazakas
|
||||
// Copyright (C) 2024 Joaquin M Lopez Munoz
|
||||
// Copyright (C) 2024-2025 Joaquin M Lopez Munoz
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
@@ -483,6 +483,11 @@ namespace boost {
|
||||
return table_.erase(key);
|
||||
}
|
||||
|
||||
BOOST_FORCEINLINE init_type pull(const_iterator pos)
|
||||
{
|
||||
return table_.pull(pos);
|
||||
}
|
||||
|
||||
void swap(unordered_node_map& rhs) noexcept(
|
||||
noexcept(std::declval<table_type&>().swap(std::declval<table_type&>())))
|
||||
{
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// Copyright (C) 2022-2023 Christian Mazakas
|
||||
// Copyright (C) 2024 Joaquin M Lopez Munoz
|
||||
// Copyright (C) 2024-2025 Joaquin M Lopez Munoz
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
@@ -379,6 +379,11 @@ namespace boost {
|
||||
return table_.erase(key);
|
||||
}
|
||||
|
||||
BOOST_FORCEINLINE init_type pull(const_iterator pos)
|
||||
{
|
||||
return table_.pull(pos);
|
||||
}
|
||||
|
||||
void swap(unordered_node_set& rhs) noexcept(
|
||||
noexcept(std::declval<table_type&>().swap(std::declval<table_type&>())))
|
||||
{
|
||||
|
||||
@@ -123,6 +123,7 @@ foa_tests(SOURCES unordered/uses_allocator.cpp)
|
||||
foa_tests(SOURCES unordered/link_test_1.cpp unordered/link_test_2.cpp )
|
||||
foa_tests(SOURCES unordered/scoped_allocator.cpp)
|
||||
foa_tests(SOURCES unordered/hash_is_avalanching_test.cpp)
|
||||
foa_tests(SOURCES unordered/pull_tests.cpp)
|
||||
foa_tests(SOURCES exception/constructor_exception_tests.cpp)
|
||||
foa_tests(SOURCES exception/copy_exception_tests.cpp)
|
||||
foa_tests(SOURCES exception/assign_exception_tests.cpp)
|
||||
|
||||
+12
-2
@@ -1,7 +1,7 @@
|
||||
|
||||
# Copyright 2006-2008 Daniel James.
|
||||
# Copyright 2022-2023 Christian Mazakas
|
||||
# Copyright 2024 Joaquin M Lopez Munoz
|
||||
# Copyright 2024-2025 Joaquin M Lopez Munoz
|
||||
# Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
@@ -156,7 +156,9 @@ run unordered/serialization_tests.cpp
|
||||
<toolset>gcc:<optimization>space
|
||||
<toolset>clang:<inlining>on
|
||||
<toolset>clang:<optimization>space
|
||||
<library>/boost/serialization//boost_serialization/<warnings>off ;
|
||||
<library>/boost/serialization//boost_serialization/<warnings>off
|
||||
<library>/boost/container//boost_container/<warnings-as-errors>off
|
||||
<toolset>gcc,<target-os>windows:<build>no ; # Boost.Atomic no longer supports MinGW
|
||||
|
||||
compile-fail unordered/insert_node_type_fail.cpp : <define>UNORDERED_TEST_MAP : insert_node_type_fail_map ;
|
||||
compile-fail unordered/insert_node_type_fail.cpp : <define>UNORDERED_TEST_MULTIMAP : insert_node_type_fail_multimap ;
|
||||
@@ -241,6 +243,7 @@ local FOA_TESTS =
|
||||
hash_is_avalanching_test
|
||||
fancy_pointer_noleak
|
||||
pmr_allocator_tests
|
||||
pull_tests
|
||||
stats_tests
|
||||
node_handle_allocator_tests
|
||||
;
|
||||
@@ -265,6 +268,8 @@ run unordered/serialization_tests.cpp
|
||||
<toolset>clang:<inlining>on
|
||||
<toolset>clang:<optimization>space
|
||||
<library>/boost/serialization//boost_serialization/<warnings>off
|
||||
<library>/boost/container//boost_container/<warnings-as-errors>off
|
||||
<toolset>gcc,<target-os>windows:<build>no # Boost.Atomic no longer supports MinGW
|
||||
: foa_serialization_tests ;
|
||||
|
||||
local FOA_EXCEPTION_TESTS =
|
||||
@@ -357,6 +362,7 @@ local CFOA_TESTS =
|
||||
pmr_allocator_tests
|
||||
stats_tests
|
||||
node_handle_allocator_tests
|
||||
incomplete_tests
|
||||
;
|
||||
|
||||
for local test in $(CFOA_TESTS)
|
||||
@@ -401,6 +407,10 @@ run cfoa/serialization_tests.cpp
|
||||
<toolset>clang:<inlining>on
|
||||
<toolset>clang:<optimization>space
|
||||
<library>/boost/serialization//boost_serialization/<warnings>off
|
||||
<library>/boost/container//boost_container/<warnings-as-errors>off
|
||||
<toolset>gcc,<target-os>windows:<build>no # Boost.Atomic no longer supports MinGW
|
||||
<toolset>gcc,<thread-sanitizer>norecover:<build>no # TSAN does not support atomic_thread_fence
|
||||
<toolset>clang,<thread-sanitizer>norecover:<build>no # idem
|
||||
: cfoa_serialization_tests ;
|
||||
|
||||
rule make_cfoa_interprocess_concurrency_tests ( name : defines ? )
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
// Copyright 2025 Joaquin M Lopez Munoz.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#define BOOST_UNORDERED_CFOA_TESTS
|
||||
#include "../unordered/incomplete_test.cpp"
|
||||
+31
-2
@@ -11,6 +11,7 @@
|
||||
#ifndef BOOST_NO_CXX17_HDR_MEMORY_RESOURCE
|
||||
|
||||
#include <memory_resource>
|
||||
#include <new>
|
||||
|
||||
namespace test {
|
||||
class counted_new_delete_resource : public std::pmr::memory_resource
|
||||
@@ -25,17 +26,45 @@ namespace test {
|
||||
void* do_allocate(std::size_t bytes, std::size_t alignment) override
|
||||
{
|
||||
_count += bytes;
|
||||
|
||||
#if defined(__cpp_aligned_new) && __cpp_aligned_new >= 201606L
|
||||
|
||||
return ::operator new(bytes, std::align_val_t(alignment));
|
||||
|
||||
#else
|
||||
|
||||
return ::operator new(bytes);
|
||||
(void)alignment;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
void do_deallocate(
|
||||
void* p, std::size_t bytes, std::size_t alignment) override
|
||||
{
|
||||
_count -= bytes;
|
||||
#if __cpp_sized_deallocation
|
||||
|
||||
#if defined(__cpp_aligned_new) && __cpp_aligned_new >= 201606L
|
||||
# if defined(__cpp_sized_deallocation) && __cpp_sized_deallocation >= 201309L
|
||||
|
||||
::operator delete(p, bytes, std::align_val_t(alignment));
|
||||
#else
|
||||
|
||||
# else
|
||||
|
||||
::operator delete(p, std::align_val_t(alignment));
|
||||
|
||||
# endif
|
||||
#else
|
||||
# if defined(__cpp_sized_deallocation) && __cpp_sized_deallocation >= 201309L
|
||||
|
||||
::operator delete(p, bytes);
|
||||
|
||||
# else
|
||||
|
||||
::operator delete(p);
|
||||
(void)alignment;
|
||||
|
||||
# endif
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
// Copyright 2021-2022 Christian Mazakas.
|
||||
// Copyright 2025 Joaquin M Lopez Munoz.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
@@ -42,8 +43,35 @@ namespace test {
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct non_const_pred;
|
||||
|
||||
template<class T, class U>
|
||||
struct non_const_pred<std::pair<const T, U> >
|
||||
{
|
||||
bool operator()(std::pair<const T, U>& x) const
|
||||
{
|
||||
U u = std::move(x.second);
|
||||
(void)u;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace test
|
||||
|
||||
template <class UnorderedMap> void test_map_nonconst_erase_if()
|
||||
{
|
||||
typedef UnorderedMap map_type;
|
||||
typedef typename map_type::value_type value_type;
|
||||
typedef typename map_type::size_type size_type;
|
||||
|
||||
map_type m;
|
||||
m.insert(value_type());
|
||||
size_type num_erased = erase_if(m, test::non_const_pred<value_type>());
|
||||
BOOST_TEST(m.empty());
|
||||
BOOST_TEST_EQ(num_erased, 1u);
|
||||
}
|
||||
|
||||
template <class UnorderedMap> void test_map_erase_if()
|
||||
{
|
||||
typedef UnorderedMap map_type;
|
||||
@@ -71,6 +99,8 @@ template <class UnorderedMap> void test_map_erase_if()
|
||||
num_erased = erase_if(map, test::is_even());
|
||||
BOOST_TEST_EQ(map.size(), 2u);
|
||||
BOOST_TEST_EQ(num_erased, size - map.size());
|
||||
|
||||
test_map_nonconst_erase_if<map_type>();
|
||||
}
|
||||
|
||||
template <class UnorderedSet> void test_set_erase_if()
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
// Copyright 2022 Peter Dimov
|
||||
// Copyright 2024 Joaquin M Lopez Munoz
|
||||
// Copyright 2024-2025 Joaquin M Lopez Munoz
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
// an imitation of a third-party header specializing hash_is_avalanching
|
||||
// (boost/container_hash/hash.hpp is an example doing that)
|
||||
|
||||
#include <boost/type_traits/integral_constant.hpp>
|
||||
|
||||
@@ -13,14 +12,11 @@ struct X3
|
||||
};
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace unordered
|
||||
{
|
||||
|
||||
template<class T> struct hash_is_avalanching;
|
||||
template<> struct hash_is_avalanching< ::X3 >: boost::true_type {};
|
||||
|
||||
} // namespace unordered
|
||||
} // namespace boost
|
||||
|
||||
//
|
||||
|
||||
@@ -1,17 +1,28 @@
|
||||
|
||||
// Copyright 2009 Daniel James.
|
||||
// Copyright 2022-2023 Christian Mazakas.
|
||||
// Copyright 2025 Joaquin M Lopez Munoz
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include "../helpers/unordered.hpp"
|
||||
#ifdef BOOST_UNORDERED_CFOA_TESTS
|
||||
#include <boost/unordered/concurrent_flat_set.hpp>
|
||||
#include <boost/unordered/concurrent_flat_map.hpp>
|
||||
#include <boost/unordered/concurrent_node_map.hpp>
|
||||
#include <boost/unordered/concurrent_node_set.hpp>
|
||||
#endif
|
||||
|
||||
|
||||
#include <utility>
|
||||
|
||||
namespace x {
|
||||
struct D
|
||||
{
|
||||
#ifdef BOOST_UNORDERED_FOA_TESTS
|
||||
#if defined(BOOST_UNORDERED_CFOA_TESTS)
|
||||
boost::concurrent_flat_map<D, D> x;
|
||||
boost::concurrent_node_map<D, D> y;
|
||||
#elif defined(BOOST_UNORDERED_FOA_TESTS)
|
||||
boost::unordered_flat_map<D, D> x;
|
||||
boost::unordered_node_map<D, D> y;
|
||||
#else
|
||||
@@ -30,26 +41,36 @@ namespace incomplete_test {
|
||||
|
||||
// Declare some instances
|
||||
|
||||
#ifdef BOOST_UNORDERED_FOA_TESTS
|
||||
#if defined(BOOST_UNORDERED_CFOA_TESTS)
|
||||
typedef boost::concurrent_flat_map<value, value, hash, equals,
|
||||
allocator<std::pair<value const, value> > >
|
||||
map1;
|
||||
typedef boost::concurrent_flat_set<value, hash, equals, allocator<value> > set1;
|
||||
typedef boost::concurrent_node_map<value, value, hash, equals,
|
||||
allocator<std::pair<value const, value> > >
|
||||
map2;
|
||||
typedef boost::concurrent_node_set<value, hash, equals, allocator<value> >
|
||||
set2;
|
||||
#elif defined(BOOST_UNORDERED_FOA_TESTS)
|
||||
typedef boost::unordered_flat_map<value, value, hash, equals,
|
||||
allocator<std::pair<value const, value> > >
|
||||
map;
|
||||
typedef boost::unordered_flat_set<value, hash, equals, allocator<value> > set;
|
||||
map1;
|
||||
typedef boost::unordered_flat_set<value, hash, equals, allocator<value> > set1;
|
||||
typedef boost::unordered_node_map<value, value, hash, equals,
|
||||
allocator<std::pair<value const, value> > >
|
||||
multimap;
|
||||
map2;
|
||||
typedef boost::unordered_node_set<value, hash, equals, allocator<value> >
|
||||
multiset;
|
||||
set2;
|
||||
#else
|
||||
typedef boost::unordered_map<value, value, hash, equals,
|
||||
allocator<std::pair<value const, value> > >
|
||||
map;
|
||||
map1;
|
||||
typedef boost::unordered_multimap<value, value, hash, equals,
|
||||
allocator<std::pair<value const, value> > >
|
||||
multimap;
|
||||
typedef boost::unordered_set<value, hash, equals, allocator<value> > set;
|
||||
map2;
|
||||
typedef boost::unordered_set<value, hash, equals, allocator<value> > set1;
|
||||
typedef boost::unordered_multiset<value, hash, equals, allocator<value> >
|
||||
multiset;
|
||||
set2;
|
||||
#endif
|
||||
|
||||
// Now define the types which are stored as members, as they are needed for
|
||||
@@ -132,24 +153,60 @@ namespace incomplete_test {
|
||||
boost::unordered_multiset<struct4, hash, equals, allocator<struct4> > x;
|
||||
};
|
||||
#endif
|
||||
// Now define the value type.
|
||||
|
||||
struct value
|
||||
{
|
||||
};
|
||||
|
||||
// Create some instances.
|
||||
|
||||
incomplete_test::map m1;
|
||||
incomplete_test::multimap m2;
|
||||
incomplete_test::set s1;
|
||||
incomplete_test::multiset s2;
|
||||
incomplete_test::map1 m1;
|
||||
#ifndef BOOST_UNORDERED_CFOA_TESTS
|
||||
incomplete_test::map1::iterator itm1;
|
||||
incomplete_test::map1::const_iterator citm1;
|
||||
#ifndef BOOST_UNORDERED_FOA_TESTS
|
||||
incomplete_test::map1::local_iterator litm1;
|
||||
incomplete_test::map1::const_local_iterator clitm1;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
incomplete_test::map2 m2;
|
||||
#ifndef BOOST_UNORDERED_CFOA_TESTS
|
||||
incomplete_test::map2::iterator itm2;
|
||||
incomplete_test::map2::const_iterator citm2;
|
||||
#ifndef BOOST_UNORDERED_FOA_TESTS
|
||||
incomplete_test::map2::local_iterator litm2;
|
||||
incomplete_test::map2::const_local_iterator clitm2;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
incomplete_test::set1 s1;
|
||||
#ifndef BOOST_UNORDERED_CFOA_TESTS
|
||||
incomplete_test::set1::iterator its1;
|
||||
incomplete_test::set1::const_iterator cits1;
|
||||
#ifndef BOOST_UNORDERED_FOA_TESTS
|
||||
incomplete_test::set1::local_iterator lits1;
|
||||
incomplete_test::set1::const_local_iterator clits1;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
incomplete_test::set2 s2;
|
||||
#ifndef BOOST_UNORDERED_CFOA_TESTS
|
||||
incomplete_test::set2::iterator its2;
|
||||
incomplete_test::set2::const_iterator cits2;
|
||||
#ifndef BOOST_UNORDERED_FOA_TESTS
|
||||
incomplete_test::set2::local_iterator lits2;
|
||||
incomplete_test::set2::const_local_iterator clits2;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
incomplete_test::struct1 c1;
|
||||
incomplete_test::struct2 c2;
|
||||
incomplete_test::struct3 c3;
|
||||
incomplete_test::struct4 c4;
|
||||
|
||||
// Now define the value type.
|
||||
|
||||
struct value
|
||||
{
|
||||
};
|
||||
|
||||
// Now declare, but don't define, the operators required for comparing
|
||||
// elements.
|
||||
|
||||
@@ -171,11 +228,45 @@ namespace incomplete_test {
|
||||
void use_types()
|
||||
{
|
||||
incomplete_test::value x;
|
||||
m1[x] = x;
|
||||
m2.insert(std::make_pair(x, x));
|
||||
s1.insert(x);
|
||||
s2.insert(x);
|
||||
m1.insert(std::make_pair(x, x));
|
||||
#ifndef BOOST_UNORDERED_CFOA_TESTS
|
||||
itm1 = m1.begin();
|
||||
citm1 = m1.cbegin();
|
||||
#ifndef BOOST_UNORDERED_FOA_TESTS
|
||||
litm1 = m1.begin(0);
|
||||
clitm1 = m1.cbegin(0);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
m2.insert(std::make_pair(x, x));
|
||||
#ifndef BOOST_UNORDERED_CFOA_TESTS
|
||||
itm2 = m2.begin();
|
||||
citm2 = m2.cbegin();
|
||||
#ifndef BOOST_UNORDERED_FOA_TESTS
|
||||
litm2 = m2.begin(0);
|
||||
clitm2 = m2.cbegin(0);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
s1.insert(x);
|
||||
#ifndef BOOST_UNORDERED_CFOA_TESTS
|
||||
its1 = s1.begin();
|
||||
cits1 = s1.cbegin();
|
||||
#ifndef BOOST_UNORDERED_FOA_TESTS
|
||||
lits1 = s1.begin(0);
|
||||
clits1 = s1.cbegin(0);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
s2.insert(x);
|
||||
#ifndef BOOST_UNORDERED_CFOA_TESTS
|
||||
its2 = s2.begin();
|
||||
cits2 = s2.cbegin();
|
||||
#ifndef BOOST_UNORDERED_FOA_TESTS
|
||||
lits2 = s2.begin(0);
|
||||
clits2 = s2.cbegin(0);
|
||||
#endif
|
||||
#endif
|
||||
c1.x.insert(std::make_pair(c1, c1));
|
||||
c2.x.insert(std::make_pair(c2, c2));
|
||||
c3.x.insert(c3);
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
// Copyright 2025 Joaquin M Lopez Munoz.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
|
||||
#include "../helpers/test.hpp"
|
||||
#include "../helpers/unordered.hpp"
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
|
||||
struct move_only_type
|
||||
{
|
||||
move_only_type(int n_): n{n_} {}
|
||||
move_only_type(move_only_type&&) = default;
|
||||
move_only_type(const move_only_type&) = delete;
|
||||
|
||||
move_only_type& operator=(move_only_type&&) = default;
|
||||
|
||||
int n;
|
||||
};
|
||||
|
||||
bool operator==(const move_only_type& x, const move_only_type& y)
|
||||
{
|
||||
return x.n == y.n;
|
||||
}
|
||||
|
||||
bool operator<(const move_only_type& x, const move_only_type& y)
|
||||
{
|
||||
return x.n < y.n;
|
||||
}
|
||||
|
||||
std::size_t hash_value(const move_only_type& x)
|
||||
{
|
||||
return boost::hash<int>()(x.n);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
struct from_int
|
||||
{
|
||||
T operator()(int n) const { return T(n); }
|
||||
};
|
||||
|
||||
template<typename T, typename U>
|
||||
struct from_int<std::pair<T, U> >
|
||||
{
|
||||
std::pair<T, U> operator()(int n) const { return {n, -n}; }
|
||||
};
|
||||
|
||||
template <class Container> void test_pull()
|
||||
{
|
||||
Container c;
|
||||
using init_type = typename Container::init_type;
|
||||
|
||||
std::vector<init_type> l1;
|
||||
from_int<init_type> fi;
|
||||
for(int i = 0; i < 1000; ++i ){
|
||||
l1.push_back(fi(i));
|
||||
c.insert(fi(i));
|
||||
}
|
||||
|
||||
std::vector<init_type> l2;
|
||||
for(auto first = c.cbegin(), last = c.cend(); first != last; )
|
||||
{
|
||||
l2.push_back(c.pull(first++));
|
||||
}
|
||||
BOOST_TEST(c.empty());
|
||||
|
||||
std::sort(l1.begin(), l1.end());
|
||||
std::sort(l2.begin(), l2.end());
|
||||
BOOST_TEST(l1 == l2);
|
||||
}
|
||||
|
||||
UNORDERED_AUTO_TEST (pull_) {
|
||||
#if defined(BOOST_UNORDERED_FOA_TESTS)
|
||||
test_pull<
|
||||
boost::unordered_flat_map<move_only_type, move_only_type> >();
|
||||
test_pull<
|
||||
boost::unordered_flat_set<move_only_type> >();
|
||||
test_pull<
|
||||
boost::unordered_node_map<move_only_type, move_only_type> >();
|
||||
test_pull<
|
||||
boost::unordered_node_set<move_only_type> >();
|
||||
#else
|
||||
// Closed-addressing containers do not provide pull
|
||||
#endif
|
||||
}
|
||||
|
||||
RUN_TESTS()
|
||||
@@ -1689,14 +1689,14 @@ template <class UnorderedMap> void test_map_transparent_at(UnorderedMap*)
|
||||
map.at(0) = 7331;
|
||||
BOOST_TEST_EQ(key::count_, key_count);
|
||||
|
||||
BOOST_TEST_THROWS(map.at(4), std::out_of_range)
|
||||
BOOST_TEST_THROWS(map.at(4), std::out_of_range);
|
||||
BOOST_TEST_EQ(key::count_, key_count);
|
||||
|
||||
UnorderedMap const& m = map;
|
||||
BOOST_TEST_EQ(m.at(0), 7331);
|
||||
BOOST_TEST_EQ(key::count_, key_count);
|
||||
|
||||
BOOST_TEST_THROWS(m.at(4), std::out_of_range)
|
||||
BOOST_TEST_THROWS(m.at(4), std::out_of_range);
|
||||
BOOST_TEST_EQ(key::count_, key_count);
|
||||
}
|
||||
|
||||
@@ -1719,7 +1719,7 @@ template <class UnorderedMap> void test_map_non_transparent_at(UnorderedMap*)
|
||||
BOOST_TEST_EQ(key::count_, key_count + 1);
|
||||
|
||||
key_count = key::count_;
|
||||
BOOST_TEST_THROWS(map.at(4), std::out_of_range)
|
||||
BOOST_TEST_THROWS(map.at(4), std::out_of_range);
|
||||
BOOST_TEST_EQ(key::count_, key_count + 1);
|
||||
|
||||
key_count = key::count_;
|
||||
@@ -1728,7 +1728,7 @@ template <class UnorderedMap> void test_map_non_transparent_at(UnorderedMap*)
|
||||
BOOST_TEST_EQ(key::count_, key_count + 1);
|
||||
|
||||
key_count = key::count_;
|
||||
BOOST_TEST_THROWS(m.at(4), std::out_of_range)
|
||||
BOOST_TEST_THROWS(m.at(4), std::out_of_range);
|
||||
BOOST_TEST_EQ(key::count_, key_count + 1);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user