Compare commits

...

8 Commits

Author SHA1 Message Date
joaquintides 59e2a562ed deprecated boost::unordered::hash_is_avalanching in favor of boost::hash_is_avalanching (#313)
* deprecated boost::unordered::hash_is_avalanching in favor of boost::hash_is_avalanching

* replaced deprecation message with simpler BOOST_HEADER_DEPRECATED
2025-06-02 12:43:45 +02:00
joaquintides 164cbe4e0f documented non-const reference passing to erase_if (#312)
* documented non-const reference passing to erase_if

* prevented warning as error in Boost.Container build

* skipped tests for MinGW (https://github.com/boostorg/atomic/pull/70)

* correct reference link for previous commit is https://github.com/boostorg/atomic/issues/73

* commented previous disabled cases

* disabled cfoa_serialization_tests with TSAN

* fixed previous

* fixed previous

* fixed previous
2025-05-31 18:08:37 +02:00
joaquintides a64d81a378 editorial s/mulx/mul (mulx properly refers to multiplication and xoring) 2025-04-26 10:48:47 +02:00
Sam Darwin 628c8c445e GHA: windows-2025 (#306) 2025-04-16 13:04:11 +02:00
joaquintides 3dde65b2ef added pull to open-addressing containers (#309)
* added pull to open-addressing containers

* added pull_tests.cpp

* guarded pull against exceptions in mid init_type construction
2025-04-14 21:47:30 +02:00
joaquintides 2907fe8c98 trimmed AppVeyor jobs (#311)
* removed jobs redundant with Drone or GHA

* added 32-bit jobs removed from AppVeyor
2025-04-14 18:51:18 +02:00
joaquintides 28663ad5ce [skip ci] fixed AppVeyor badge link 2025-04-13 13:03:17 +02:00
joaquintides 5417494fae removed debug info in mingw-w64 32 bit to reduce compiler memory consumption (#310)
* removed debug info in mingw-w64 32.bit to reduce compiler memory consumption

* documented previous
2025-04-13 09:17:20 +02:00
31 changed files with 277 additions and 230 deletions
+4 -119
View File
@@ -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
+1 -1
View File
@@ -475,7 +475,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(
+2
View File
@@ -285,6 +285,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 -1
View File
@@ -1,7 +1,7 @@
# Boost.Unordered
[![Branch](https://img.shields.io/badge/branch-master-brightgreen.svg)](https://github.com/boostorg/unordered/tree/master) [![CI](https://github.com/boostorg/unordered/actions/workflows/ci.yml/badge.svg?branch=master)](https://github.com/boostorg/unordered/actions/workflows/ci.yml) [![Drone status](https://img.shields.io/drone/build/boostorg/unordered/master?server=https%3A%2F%2Fdrone.cpp.al&logo=drone&logoColor=%23CCCCCC&label=CI)](https://drone.cpp.al/boostorg/unordered) [![Build status](https://img.shields.io/appveyor/build/cppalliance/unordered/master?logo=appveyor&label=CI)](https://ci.appveyor.com/project/cppalliance/unordered/branch/master) [![codecov](https://codecov.io/gh/boostorg/unordered/branch/master/graph/badge.svg)](https://codecov.io/gh/boostorg/unordered/branch/master) [![Deps](https://img.shields.io/badge/deps-master-brightgreen.svg)](https://pdimov.github.io/boostdep-report/master/unordered.html) [![Documentation](https://img.shields.io/badge/docs-master-brightgreen.svg)](https://www.boost.org/doc/libs/master/libs/unordered/index.html) [![Enter the Matrix](https://img.shields.io/badge/matrix-master-brightgreen.svg)](http://www.boost.org/development/tests/master/developer/unordered.html)<br/>
[![Branch](https://img.shields.io/badge/branch-develop-brightgreen.svg)](https://github.com/boostorg/unordered/tree/develop) [![CI](https://github.com/boostorg/unordered/actions/workflows/ci.yml/badge.svg?branch=develop)](https://github.com/boostorg/unordered/actions/workflows/ci.yml) [![Drone status](https://img.shields.io/drone/build/boostorg/unordered/develop?server=https%3A%2F%2Fdrone.cpp.al&logo=drone&logoColor=%23CCCCCC&label=CI)](https://drone.cpp.al/boostorg/unordered) [![Build status](https://img.shields.io/appveyor/build/cppalliance/unordered/master?logo=appveyor&label=CI)](https://ci.appveyor.com/project/cppalliance/unordered/branch/develop) [![codecov](https://codecov.io/gh/boostorg/unordered/branch/develop/graph/badge.svg)](https://codecov.io/gh/boostorg/unordered/branch/develop) [![Deps](https://img.shields.io/badge/deps-develop-brightgreen.svg)](https://pdimov.github.io/boostdep-report/develop/unordered.html) [![Documentation](https://img.shields.io/badge/docs-develop-brightgreen.svg)](https://www.boost.org/doc/libs/develop/libs/unordered/index.html) [![Enter the Matrix](https://img.shields.io/badge/matrix-develop-brightgreen.svg)](http://www.boost.org/development/tests/develop/developer/unordered.html)<br/>
[![Branch](https://img.shields.io/badge/branch-develop-brightgreen.svg)](https://github.com/boostorg/unordered/tree/develop) [![CI](https://github.com/boostorg/unordered/actions/workflows/ci.yml/badge.svg?branch=develop)](https://github.com/boostorg/unordered/actions/workflows/ci.yml) [![Drone status](https://img.shields.io/drone/build/boostorg/unordered/develop?server=https%3A%2F%2Fdrone.cpp.al&logo=drone&logoColor=%23CCCCCC&label=CI)](https://drone.cpp.al/boostorg/unordered) [![Build status](https://img.shields.io/appveyor/build/cppalliance/unordered/develop?logo=appveyor&label=CI)](https://ci.appveyor.com/project/cppalliance/unordered/branch/develop) [![codecov](https://codecov.io/gh/boostorg/unordered/branch/develop/graph/badge.svg)](https://codecov.io/gh/boostorg/unordered/branch/develop) [![Deps](https://img.shields.io/badge/deps-develop-brightgreen.svg)](https://pdimov.github.io/boostdep-report/develop/unordered.html) [![Documentation](https://img.shields.io/badge/docs-develop-brightgreen.svg)](https://www.boost.org/doc/libs/develop/libs/unordered/index.html) [![Enter the Matrix](https://img.shields.io/badge/matrix-develop-brightgreen.svg)](http://www.boost.org/development/tests/develop/developer/unordered.html)<br/>
[![BSL 1.0](https://img.shields.io/badge/license-BSL_1.0-blue.svg)](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:
+9
View File
@@ -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.
+2 -1
View File
@@ -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.
+4 -3
View File
@@ -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^&#8725;https://en.wikipedia.org/wiki/Golden_ratio[_&phi;_],
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 &#8212;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
+2 -1
View File
@@ -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;
+3 -3
View File
@@ -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,7 +29,6 @@
#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 <climits>
#include <cmath>
@@ -1426,7 +1426,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;
+9 -1
View File
@@ -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&>())))
{
+6 -49
View File
@@ -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&>())))
{
+1
View File
@@ -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)
+11 -2
View File
@@ -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 =
@@ -401,6 +406,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 ? )
+30
View File
@@ -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 -5
View File
@@ -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
//
+88
View File
@@ -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()