mirror of
https://github.com/boostorg/unordered.git
synced 2026-07-21 13:43:30 +00:00
added interoperability with C++20 ranges (#355)
* added from_range ctors and insert_range * worked around GCC 10-11 bug when piping a temporary range * added insert_range_(or|and)_[c]visit * typo * tried to avoid MinGW32 compilation OOM in cfoa/insert_tests.cpp * s/<debug-symbols>off/<cxxflags>-g0 * tested CTAD deduction guides * typo * updated docs * Justified std::from_range_t detection trick * reduced parallel build jobs in MINGW32 to try to avoid OOM during compilation * tried to avoid compilation OOM by tweaking GC * relaxed GCC parameters somewhat * applied same changes to test/CMakeLists.txt * fixed CMake syntax error * fixed GCC commandline syntax error
This commit is contained in:
@@ -347,7 +347,7 @@ jobs:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- { sys: MINGW32, compiler: gcc, cxxstd: '11,17,20', variant: 'release' }
|
||||
- { sys: MINGW32, compiler: gcc, cxxstd: '11,17,20', variant: 'release', cxxflags: '--param ggc-min-expand=10 --param ggc-min-heapsize=16384' }
|
||||
- { sys: MINGW64, compiler: gcc, cxxstd: '11,17,20', variant: 'debug,release' }
|
||||
|
||||
needs: [runner-selection]
|
||||
@@ -383,6 +383,7 @@ jobs:
|
||||
B2_SANITIZE: ${{matrix.sanitize}}
|
||||
B2_STDLIB: ${{matrix.stdlib}}
|
||||
B2_VARIANT: ${{matrix.variant}}
|
||||
B2_CXXFLAGS: ${{ matrix.cxxflags }}
|
||||
run: ci/github/install.sh
|
||||
|
||||
- name: Run tests
|
||||
|
||||
@@ -6,6 +6,14 @@
|
||||
:github-pr-url: https://github.com/boostorg/unordered/pull
|
||||
:cpp: C++
|
||||
|
||||
== Release 1.92.0
|
||||
|
||||
* Added interoperability with pass:[C++20] ranges to all the containers in the library:
|
||||
`insert_range` (plus `insert_range_(or|and)_[c]visit` for concurrent containers),
|
||||
`std::from_range` construction and associated CTAD deduction guides.
|
||||
The `boost::unordered::from_range` construction tag is provided
|
||||
as an alternative to pass:[C++23] `std::from_range` or when this is not available.
|
||||
|
||||
== Release 1.91.0
|
||||
|
||||
* Fixed the returned value of range insertion in concurrent containers
|
||||
|
||||
@@ -77,6 +77,12 @@ namespace unordered {
|
||||
xref:#concurrent_flat_map_copy_constructor_with_allocator[concurrent_flat_map](const concurrent_flat_map& other, const Allocator& a);
|
||||
xref:#concurrent_flat_map_move_constructor_with_allocator[concurrent_flat_map](concurrent_flat_map&& other, const Allocator& a);
|
||||
xref:#concurrent_flat_map_move_constructor_from_unordered_flat_map[concurrent_flat_map](unordered_flat_map<Key, T, Hash, Pred, Allocator>&& other);
|
||||
template<class FromRangeT, xref:#concurrent_flat_map_container_compatible_range[__container-compatible-range__]<value_type> R>
|
||||
xref:#concurrent_flat_map_range_constructor[concurrent_flat_map](FromRangeT&&, R&& rg,
|
||||
size_type n = _implementation-defined_,
|
||||
const hasher& hf = hasher(),
|
||||
const key_equal& eql = key_equal(),
|
||||
const allocator_type& a = allocator_type());
|
||||
xref:#concurrent_flat_map_initializer_list_constructor[concurrent_flat_map](std::initializer_list<value_type> il,
|
||||
size_type n = _implementation-defined_
|
||||
const hasher& hf = hasher(),
|
||||
@@ -90,6 +96,13 @@ namespace unordered {
|
||||
template<class InputIterator>
|
||||
xref:#concurrent_flat_map_iterator_range_constructor_with_bucket_count_and_hasher[concurrent_flat_map](InputIterator f, InputIterator l, size_type n, const hasher& hf,
|
||||
const allocator_type& a);
|
||||
template<class FromRangeT, xref:#concurrent_flat_map_container_compatible_range[__container-compatible-range__]<value_type> R>
|
||||
xref:#concurrent_flat_map_range_constructor_with_allocator[concurrent_flat_map](FromRangeT&&, R&& rg, const allocator_type& a);
|
||||
template<class FromRangeT, xref:#concurrent_flat_map_container_compatible_range[__container-compatible-range__]<value_type> R>
|
||||
xref:#concurrent_flat_map_range_constructor_with_bucket_count_and_allocator[concurrent_flat_map](FromRangeT&&, R&& rg, size_type n, const allocator_type& a);
|
||||
template<class FromRangeT, xref:#concurrent_flat_map_container_compatible_range[__container-compatible-range__]<value_type> R>
|
||||
xref:#concurrent_flat_map_range_constructor_with_bucket_count_and_hasher_and_allocator[concurrent_flat_map](FromRangeT&&, R&& rg, size_type n, const hasher& hf,
|
||||
const allocator_type& a);
|
||||
xref:#concurrent_flat_map_initializer_list_constructor_with_allocator[concurrent_flat_map](std::initializer_list<value_type> il, const allocator_type& a);
|
||||
xref:#concurrent_flat_map_initializer_list_constructor_with_bucket_count_and_allocator[concurrent_flat_map](std::initializer_list<value_type> il, size_type n,
|
||||
const allocator_type& a);
|
||||
@@ -152,6 +165,8 @@ namespace unordered {
|
||||
bool xref:#concurrent_flat_map_move_insert[insert](value_type&& obj);
|
||||
bool xref:#concurrent_flat_map_move_insert[insert](init_type&& obj);
|
||||
template<class InputIterator> size_type xref:#concurrent_flat_map_insert_iterator_range[insert](InputIterator first, InputIterator last);
|
||||
template<xref:#concurrent_flat_map_container_compatible_range[__container-compatible-range__]<value_type> R>
|
||||
size_type xref:#concurrent_flat_map_insert_range[insert_range](R&& rg);
|
||||
size_type xref:#concurrent_flat_map_insert_initializer_list[insert](std::initializer_list<value_type> il);
|
||||
|
||||
template<class... Args, class F> bool xref:#concurrent_flat_map_emplace_or_cvisit[emplace_or_visit](Args&&... args, F&& f);
|
||||
@@ -168,6 +183,10 @@ namespace unordered {
|
||||
size_type xref:#concurrent_flat_map_insert_iterator_range_or_visit[insert_or_visit](InputIterator first, InputIterator last, F f);
|
||||
template<class InputIterator,class F>
|
||||
size_type xref:#concurrent_flat_map_insert_iterator_range_or_visit[insert_or_cvisit](InputIterator first, InputIterator last, F f);
|
||||
template<xref:#concurrent_flat_map_container_compatible_range[__container-compatible-range__]<value_type> R, class F>
|
||||
size_type xref:#concurrent_flat_map_insert_range_or_visit[insert_range_or_visit](R&& rg, F f);
|
||||
template<xref:#concurrent_flat_map_container_compatible_range[__container-compatible-range__]<value_type> R, class F>
|
||||
size_type xref:#concurrent_flat_map_insert_range_or_visit[insert_range_or_cvisit](R&& rg, F f);
|
||||
template<class F> size_type xref:#concurrent_flat_map_insert_initializer_list_or_visit[insert_or_visit](std::initializer_list<value_type> il, F f);
|
||||
template<class F> size_type xref:#concurrent_flat_map_insert_initializer_list_or_visit[insert_or_cvisit](std::initializer_list<value_type> il, F f);
|
||||
|
||||
@@ -187,6 +206,10 @@ namespace unordered {
|
||||
size_type xref:#concurrent_flat_map_insert_iterator_range_and_visit[insert_and_visit](InputIterator first, InputIterator last, F1 f1, F2 f2);
|
||||
template<class InputIterator,class F1, class F2>
|
||||
size_type xref:#concurrent_flat_map_insert_iterator_range_and_visit[insert_and_cvisit](InputIterator first, InputIterator last, F1 f1, F2 f2);
|
||||
template<xref:#concurrent_flat_map_container_compatible_range[__container-compatible-range__]<value_type> R, class F1, class F2>
|
||||
size_type xref:#concurrent_flat_map_insert_range_and_visit[insert_range_and_visit](R&& rg, F1 f1, F2 f2);
|
||||
template<xref:#concurrent_flat_map_container_compatible_range[__container-compatible-range__]<value_type> R, class F1, class F2>
|
||||
size_type xref:#concurrent_flat_map_insert_range_and_visit[insert_range_and_cvisit](R&& rg, F1 f1, F2 f2);
|
||||
template<class F1, class F2>
|
||||
size_type xref:#concurrent_flat_map_insert_initializer_list_and_visit[insert_and_visit](std::initializer_list<value_type> il, F1 f1, F2 f2);
|
||||
template<class F1, class F2>
|
||||
@@ -282,6 +305,17 @@ namespace unordered {
|
||||
-> concurrent_flat_map<xref:#concurrent_flat_map_iter_key_type[__iter-key-type__]<InputIterator>, xref:#concurrent_flat_map_iter_mapped_type[__iter-mapped-type__]<InputIterator>, Hash,
|
||||
Pred, Allocator>;
|
||||
|
||||
template<xref:#concurrent_flat_map_convertible_to_from_range_t[__convertible-to-from-range_t__] FromRangeT,
|
||||
std::ranges::input_range R,
|
||||
class Hash = boost::hash<xref:#concurrent_flat_map_range_key_type[__range-key-type__]<R>>,
|
||||
class Pred = std::equal_to<xref:#concurrent_flat_map_range_key_type[__range-key-type__]<R>>,
|
||||
class Allocator = std::allocator<xref:#concurrent_flat_map_range_to_alloc_type[__range-to-alloc-type__]<R>>>
|
||||
concurrent_flat_map(FromRangeT&&, R&&,
|
||||
typename xref:#concurrent_flat_map_deduction_guides[__see below__]::size_type = xref:#concurrent_flat_map_deduction_guides[__see below__], Hash = Hash(),
|
||||
Pred = Pred(), Allocator = Allocator())
|
||||
-> concurrent_flat_map<xref:#concurrent_flat_map_range_key_type[__range-key-type__]<R>, xref:#concurrent_flat_map_range_mapped_type[__range-mapped-type__]<R>,
|
||||
Hash, Pred,Allocator>;
|
||||
|
||||
template<class Key, class T, class Hash = boost::hash<Key>,
|
||||
class Pred = std::equal_to<Key>,
|
||||
class Allocator = std::allocator<std::pair<const Key, T>>>
|
||||
@@ -308,6 +342,27 @@ namespace unordered {
|
||||
-> concurrent_flat_map<xref:#concurrent_flat_map_iter_key_type[__iter-key-type__]<InputIterator>, xref:#concurrent_flat_map_iter_mapped_type[__iter-mapped-type__]<InputIterator>, Hash,
|
||||
std::equal_to<xref:#concurrent_flat_map_iter_key_type[__iter-key-type__]<InputIterator>>, Allocator>;
|
||||
|
||||
template<xref:#concurrent_flat_map_convertible_to_from_range_t[__convertible-to-from-range_t__] FromRangeT,
|
||||
std::ranges::input_range R, class Allocator>
|
||||
concurrent_flat_map(FromRangeT&&, R&&, typename xref:#concurrent_flat_map_deduction_guides[__see below__]::size_type, Allocator)
|
||||
-> concurrent_flat_map<xref:#concurrent_flat_map_range_key_type[__range-key-type__]<R>, xref:#concurrent_flat_map_range_mapped_type[__range-mapped-type__]<R>,
|
||||
boost::hash<xref:#concurrent_flat_map_range_key_type[__range-key-type__]<R>>,
|
||||
std::equal_to<xref:#concurrent_flat_map_range_key_type[__range-key-type__]<R>>, Allocator>;
|
||||
|
||||
template<xref:#concurrent_flat_map_convertible_to_from_range_t[__convertible-to-from-range_t__] FromRangeT,
|
||||
std::ranges::input_range R, class Allocator>
|
||||
concurrent_flat_map(FromRangeT&&, R&&, Allocator)
|
||||
-> concurrent_flat_map<xref:#concurrent_flat_map_range_key_type[__range-key-type__]<R>, xref:#concurrent_flat_map_range_mapped_type[__range-mapped-type__]<R>,
|
||||
boost::hash<xref:#concurrent_flat_map_range_key_type[__range-key-type__]<R>>,
|
||||
std::equal_to<xref:#concurrent_flat_map_range_key_type[__range-key-type__]<R>>, Allocator>;
|
||||
|
||||
template<xref:#concurrent_flat_map_convertible_to_from_range_t[__convertible-to-from-range_t__] FromRangeT,
|
||||
std::ranges::input_range R, class Hash, class Allocator>
|
||||
concurrent_flat_map(FromRangeT&&, R&&, typename xref:#concurrent_flat_map_deduction_guides[__see below__]::size_type, Hash,
|
||||
Allocator)
|
||||
-> concurrent_flat_map<xref:#concurrent_flat_map_range_key_type[__range-key-type__]<R>, xref:#concurrent_flat_map_range_mapped_type[__range-mapped-type__]<R>,
|
||||
Hash, std::equal_to<xref:#concurrent_flat_map_range_key_type[__range-key-type__]<R>>, Allocator>;
|
||||
|
||||
template<class Key, class T, class Allocator>
|
||||
concurrent_flat_map(std::initializer_list<std::pair<Key, T>>, typename xref:#concurrent_flat_map_deduction_guides[__see below__]::size_type,
|
||||
Allocator)
|
||||
@@ -444,6 +499,15 @@ Chunk size internally used in xref:concurrent_flat_map_bulk_visit[bulk visit] op
|
||||
|
||||
=== Constructors
|
||||
|
||||
==== __container-compatible-range__
|
||||
[listings,subs="+macros,+quotes"]
|
||||
-----
|
||||
template<class R, class T>
|
||||
concept container_compatible_range =
|
||||
std::ranges::input_range<R> &&
|
||||
std::convertible_to<std::ranges::range_reference_t<R>, T>; // exposition only
|
||||
-----
|
||||
|
||||
==== Default Constructor
|
||||
```c++
|
||||
concurrent_flat_map();
|
||||
@@ -591,6 +655,27 @@ Complexity:;; O(`bucket_count()`)
|
||||
|
||||
---
|
||||
|
||||
==== Range Constructor
|
||||
[source,c++,subs="+macros,+quotes"]
|
||||
----
|
||||
template<class FromRangeT, xref:#concurrent_flat_map_container_compatible_range[__container-compatible-range__]<value_type> R>
|
||||
concurrent_flat_map(FromRangeT&&, R&& rg,
|
||||
size_type n = _implementation-defined_,
|
||||
const hasher& hf = hasher(),
|
||||
const key_equal& eql = key_equal(),
|
||||
const allocator_type& a = allocator_type());
|
||||
----
|
||||
|
||||
Constructs an empty table with at least `n` buckets, using `hf` as the hash function, `eql` as the key equality predicate and `a` as the allocator, and inserts the elements from `rg` into it.
|
||||
|
||||
Only participates in overload resolution if `FromRangeT` is convertible to `std::from_range_t` or `boost::concurrent::from_range_t`.
|
||||
|
||||
|
||||
[horizontal]
|
||||
Requires:;; If the defaults are used, `hasher`, `key_equal` and `allocator_type` need to be https://en.cppreference.com/w/cpp/named_req/DefaultConstructible[DefaultConstructible^].
|
||||
|
||||
---
|
||||
|
||||
==== Initializer List Constructor
|
||||
[source,c++,subs="+quotes"]
|
||||
----
|
||||
@@ -663,6 +748,58 @@ Requires:;; `key_equal` needs to be https://en.cppreference.com/w/cpp/named_req/
|
||||
|
||||
---
|
||||
|
||||
==== Range Constructor with Allocator
|
||||
|
||||
[source,c++,subs="+macros,+quotes"]
|
||||
----
|
||||
template<class FromRangeT, xref:#concurrent_flat_map_container_compatible_range[__container-compatible-range__]<value_type> R>
|
||||
concurrent_flat_map(FromRangeT&&, R&& rg, const allocator_type& a);
|
||||
----
|
||||
|
||||
Constructs an empty table using `a` and default hash function and key equality predicate, and inserts the elements from `rg` into it.
|
||||
|
||||
Only participates in overload resolution if `FromRangeT` is convertible to `std::from_range_t` or `boost::concurrent::from_range_t`.
|
||||
|
||||
[horizontal]
|
||||
Requires:;; `hasher` and `key_equal` need to be https://en.cppreference.com/w/cpp/named_req/DefaultConstructible[DefaultConstructible^].
|
||||
|
||||
---
|
||||
|
||||
==== Range Constructor with Bucket Count and Allocator
|
||||
|
||||
[source,c++,subs="+macros,+quotes"]
|
||||
----
|
||||
template<class FromRangeT, xref:#concurrent_flat_map_container_compatible_range[__container-compatible-range__]<value_type> R>
|
||||
concurrent_flat_map(FromRangeT&&, R&& rg, size_type n, const allocator_type& a);
|
||||
----
|
||||
|
||||
Constructs an empty table with at least `n` buckets, using `a` and default hash function and key equality predicate, and inserts the elements from `rg` into it.
|
||||
|
||||
Only participates in overload resolution if `FromRangeT` is convertible to `std::from_range_t` or `boost::concurrent::from_range_t`.
|
||||
|
||||
[horizontal]
|
||||
Requires:;; `hasher` and `key_equal` need to be https://en.cppreference.com/w/cpp/named_req/DefaultConstructible[DefaultConstructible^].
|
||||
|
||||
---
|
||||
|
||||
==== Range Constructor with Bucket Count and Hasher and Allocator
|
||||
|
||||
[source,c++,subs="+macros,+quotes"]
|
||||
----
|
||||
template<class FromRangeT, xref:#concurrent_flat_map_container_compatible_range[__container-compatible-range__]<value_type> R>
|
||||
concurrent_flat_map(FromRangeT&&, R&& rg, size_type n, const hasher& hf,
|
||||
const allocator_type& a);
|
||||
----
|
||||
|
||||
Constructs an empty table with at least `n` buckets, using `hf` as the hash function, `a` as the allocator and default key equality predicate, and inserts the elements from `rg` into it.
|
||||
|
||||
Only participates in overload resolution if `FromRangeT` is convertible to `std::from_range_t` or `boost::concurrent::from_range_t`.
|
||||
|
||||
[horizontal]
|
||||
Requires:;; `key_equal` needs to be https://en.cppreference.com/w/cpp/named_req/DefaultConstructible[DefaultConstructible^].
|
||||
|
||||
---
|
||||
|
||||
==== initializer_list Constructor with Allocator
|
||||
|
||||
```c++
|
||||
@@ -696,7 +833,7 @@ concurrent_flat_map(std::initializer_list<value_type> il, size_type n, const has
|
||||
const allocator_type& a);
|
||||
```
|
||||
|
||||
Constructs an empty table with at least `n` buckets, using `hf` as the hash function, `a` as the allocator and default key equality predicate,and inserts the elements from `il` into it.
|
||||
Constructs an empty table with at least `n` buckets, using `hf` as the hash function, `a` as the allocator and default key equality predicate, and inserts the elements from `il` into it.
|
||||
|
||||
[horizontal]
|
||||
Requires:;; `key_equal` needs to be https://en.cppreference.com/w/cpp/named_req/DefaultConstructible[DefaultConstructible^].
|
||||
@@ -1013,6 +1150,24 @@ Returns:;; The number of elements inserted.
|
||||
|
||||
---
|
||||
|
||||
==== Insert Range
|
||||
[source,c++,subs="+macros,+quotes"]
|
||||
----
|
||||
template<xref:#concurrent_flat_map_container_compatible_range[__container-compatible-range__]<value_type> R>
|
||||
void insert_range(R&& rg);
|
||||
----
|
||||
|
||||
Equivalent to
|
||||
[listing,subs="+macros,+quotes"]
|
||||
-----
|
||||
for(auto&& x: rg) this->xref:#concurrent_flat_map_emplace[emplace](std::forward<decltype(x)>(x));
|
||||
-----
|
||||
|
||||
[horizontal]
|
||||
Returns:;; The number of elements inserted.
|
||||
|
||||
---
|
||||
|
||||
==== Insert Initializer List
|
||||
```c++
|
||||
size_type insert(std::initializer_list<value_type> il);
|
||||
@@ -1095,9 +1250,9 @@ only if `std::remove_reference<decltype(obj)>::type` is `value_type`.
|
||||
==== Insert Iterator Range or Visit
|
||||
```c++
|
||||
template<class InputIterator,class F>
|
||||
size_type insert_or_visit(InputIterator first, InputIterator last, F f);
|
||||
size_type insert_or_visit(InputIterator first, InputIterator last, F f);
|
||||
template<class InputIterator,class F>
|
||||
size_type insert_or_cvisit(InputIterator first, InputIterator last, F f);
|
||||
size_type insert_or_cvisit(InputIterator first, InputIterator last, F f);
|
||||
```
|
||||
|
||||
Equivalent to
|
||||
@@ -1111,6 +1266,27 @@ Returns:;; The number of elements inserted.
|
||||
|
||||
---
|
||||
|
||||
==== Insert Range or Visit
|
||||
[source,c++,subs="+macros,+quotes"]
|
||||
----
|
||||
template<xref:#concurrent_flat_map_container_compatible_range[__container-compatible-range__]<value_type> R, class F>
|
||||
size_type insert_range_or_visit(R&& rg, F f);
|
||||
template<xref:#concurrent_flat_map_container_compatible_range[__container-compatible-range__]<value_type> R, class F>
|
||||
size_type insert_range_or_visit(R&& rg, F f);
|
||||
----
|
||||
|
||||
Equivalent to
|
||||
[listing,subs="+macros,+quotes"]
|
||||
-----
|
||||
for(auto&& x: rg)
|
||||
this->xref:#concurrent_flat_map_emplace_or_cvisit[emplace_or_[c\]visit](std::forward<decltype(x)>(x), std::ref(f));
|
||||
-----
|
||||
|
||||
[horizontal]
|
||||
Returns:;; The number of elements inserted.
|
||||
|
||||
---
|
||||
|
||||
==== Insert Initializer List or Visit
|
||||
```c++
|
||||
template<class F> size_type insert_or_visit(std::initializer_list<value_type> il, F f);
|
||||
@@ -1215,6 +1391,28 @@ Returns:;; The number of elements inserted.
|
||||
|
||||
---
|
||||
|
||||
==== Insert Range and Visit
|
||||
[source,c++,subs="+macros,+quotes"]
|
||||
----
|
||||
template<xref:#concurrent_flat_map_container_compatible_range[__container-compatible-range__]<value_type> R, class F1, class F2>
|
||||
size_type insert_range_and_visit(R&& rg, F1 f1, F2 f2);
|
||||
template<xref:#concurrent_flat_map_container_compatible_range[__container-compatible-range__]<value_type> R, class F1, class F2>
|
||||
size_type insert_range_and_cvisit(R&& rg, F1 f1, F2 f2);
|
||||
----
|
||||
|
||||
Equivalent to
|
||||
[listing,subs="+macros,+quotes"]
|
||||
-----
|
||||
for(auto&& x: rg)
|
||||
this->xref:#concurrent_flat_map_emplace_and_cvisit[emplace_and_[c\]visit](
|
||||
std::forward<decltype(x)>(x), std::ref(f1), std::ref(f2));
|
||||
-----
|
||||
|
||||
[horizontal]
|
||||
Returns:;; The number of elements inserted.
|
||||
|
||||
---
|
||||
|
||||
==== Insert Initializer List and Visit
|
||||
```c++
|
||||
template<class F1, class F2>
|
||||
@@ -1742,6 +1940,42 @@ template<class InputIterator>
|
||||
std::tuple_element_t<1, xref:#concurrent_flat_map_iter_value_type[__iter-value-type__]<InputIterator>>>; // exposition only
|
||||
-----
|
||||
|
||||
==== __convertible-to-from-range_t__
|
||||
[listings,subs="+macros,+quotes"]
|
||||
-----
|
||||
template<typename FromRangeT>
|
||||
concept __convertible-to-from_range_t__ =
|
||||
// first clause not present if std::from_range_t does not exist
|
||||
std::is_convertible_v<FromRangeT, std::from_range_t> ||
|
||||
std::is_convertible_v<FromRangeT, boost::unordered::from_range_t>; // exposition only
|
||||
-----
|
||||
|
||||
==== __range-key-type__
|
||||
[listings,subs="+macros,+quotes"]
|
||||
-----
|
||||
template<std::ranges::input_range R>
|
||||
using __range-key-type__ =
|
||||
std::remove_cvref_t<
|
||||
std::tuple_element_t<0, std::ranges::range_value_t<R>>>; // exposition only
|
||||
-----
|
||||
|
||||
==== __range-mapped-type__
|
||||
[listings,subs="+macros,+quotes"]
|
||||
-----
|
||||
template<std::ranges::input_range R>
|
||||
using __range-mapped-type__ =
|
||||
std::remove_cvref_t<
|
||||
std::tuple_element_t<1, std::ranges::range_value_t<R>>>; // exposition only
|
||||
-----
|
||||
|
||||
==== __range-to-alloc-type__
|
||||
[listings,subs="+macros,+quotes"]
|
||||
-----
|
||||
template<std::ranges::input_range R>
|
||||
using __range-to-alloc-type__ =
|
||||
std::pair<const xref:#concurrent_flat_map_range_key_type[__range-key-type__]<R>, xref:#concurrent_flat_map_range_mapped_type[__range-mapped-type__]<R>>; // exposition only
|
||||
-----
|
||||
|
||||
=== Equality Comparisons
|
||||
|
||||
==== operator==
|
||||
|
||||
@@ -72,6 +72,12 @@ namespace unordered {
|
||||
xref:#concurrent_flat_set_copy_constructor_with_allocator[concurrent_flat_set](const concurrent_flat_set& other, const Allocator& a);
|
||||
xref:#concurrent_flat_set_move_constructor_with_allocator[concurrent_flat_set](concurrent_flat_set&& other, const Allocator& a);
|
||||
xref:#concurrent_flat_set_move_constructor_from_unordered_flat_set[concurrent_flat_set](unordered_flat_set<Key, Hash, Pred, Allocator>&& other);
|
||||
template<class FromRangeT, xref:#concurrent_flat_set_container_compatible_range[__container-compatible-range__]<value_type> R>
|
||||
xref:#concurrent_flat_set_range_constructor[concurrent_flat_set](FromRangeT&&, R&& rg,
|
||||
size_type n = _implementation-defined_,
|
||||
const hasher& hf = hasher(),
|
||||
const key_equal& eql = key_equal(),
|
||||
const allocator_type& a = allocator_type());
|
||||
xref:#concurrent_flat_set_initializer_list_constructor[concurrent_flat_set](std::initializer_list<value_type> il,
|
||||
size_type n = _implementation-defined_
|
||||
const hasher& hf = hasher(),
|
||||
@@ -85,6 +91,13 @@ namespace unordered {
|
||||
template<class InputIterator>
|
||||
xref:#concurrent_flat_set_iterator_range_constructor_with_bucket_count_and_hasher[concurrent_flat_set](InputIterator f, InputIterator l, size_type n, const hasher& hf,
|
||||
const allocator_type& a);
|
||||
template<class FromRangeT, xref:#concurrent_flat_set_container_compatible_range[__container-compatible-range__]<value_type> R>
|
||||
xref:#concurrent_flat_set_range_constructor_with_allocator[concurrent_flat_set](FromRangeT&&, R&& rg, const allocator_type& a);
|
||||
template<class FromRangeT, xref:#concurrent_flat_set_container_compatible_range[__container-compatible-range__]<value_type> R>
|
||||
xref:#concurrent_flat_set_range_constructor_with_bucket_count_and_allocator[concurrent_flat_set](FromRangeT&&, R&& rg, size_type n, const allocator_type& a);
|
||||
template<class FromRangeT, xref:#concurrent_flat_set_container_compatible_range[__container-compatible-range__]<value_type> R>
|
||||
xref:#concurrent_flat_set_range_constructor_with_bucket_count_and_hasher_and_allocator[concurrent_flat_set](FromRangeT&&, R&& rg, size_type n, const hasher& hf,
|
||||
const allocator_type& a);
|
||||
xref:#concurrent_flat_set_initializer_list_constructor_with_allocator[concurrent_flat_set](std::initializer_list<value_type> il, const allocator_type& a);
|
||||
xref:#concurrent_flat_set_initializer_list_constructor_with_bucket_count_and_allocator[concurrent_flat_set](std::initializer_list<value_type> il, size_type n,
|
||||
const allocator_type& a);
|
||||
@@ -145,6 +158,8 @@ namespace unordered {
|
||||
bool xref:#concurrent_flat_set_move_insert[insert](value_type&& obj);
|
||||
template<class K> bool xref:#concurrent_flat_set_transparent_insert[insert](K&& k);
|
||||
template<class InputIterator> size_type xref:#concurrent_flat_set_insert_iterator_range[insert](InputIterator first, InputIterator last);
|
||||
template<xref:#concurrent_flat_set_container_compatible_range[__container-compatible-range__]<value_type> R>
|
||||
size_type xref:#concurrent_flat_set_insert_range[insert_range](R&& rg);
|
||||
size_type xref:#concurrent_flat_set_insert_initializer_list[insert](std::initializer_list<value_type> il);
|
||||
|
||||
template<class... Args, class F> bool xref:#concurrent_flat_set_emplace_or_cvisit[emplace_or_visit](Args&&... args, F&& f);
|
||||
@@ -159,6 +174,10 @@ namespace unordered {
|
||||
size_type xref:#concurrent_flat_set_insert_iterator_range_or_visit[insert_or_visit](InputIterator first, InputIterator last, F f);
|
||||
template<class InputIterator,class F>
|
||||
size_type xref:#concurrent_flat_set_insert_iterator_range_or_visit[insert_or_cvisit](InputIterator first, InputIterator last, F f);
|
||||
template<xref:#concurrent_flat_set_container_compatible_range[__container-compatible-range__]<value_type> R, class F>
|
||||
size_type xref:#concurrent_flat_set_insert_range_or_visit[insert_range_or_visit](R&& rg, F f);
|
||||
template<xref:#concurrent_flat_set_container_compatible_range[__container-compatible-range__]<value_type> R, class F>
|
||||
size_type xref:#concurrent_flat_set_insert_range_or_visit[insert_range_or_cvisit](R&& rg, F f);
|
||||
template<class F> size_type xref:#concurrent_flat_set_insert_initializer_list_or_visit[insert_or_visit](std::initializer_list<value_type> il, F f);
|
||||
template<class F> size_type xref:#concurrent_flat_set_insert_initializer_list_or_visit[insert_or_cvisit](std::initializer_list<value_type> il, F f);
|
||||
|
||||
@@ -176,6 +195,10 @@ namespace unordered {
|
||||
size_type xref:#concurrent_flat_set_insert_iterator_range_and_visit[insert_and_visit](InputIterator first, InputIterator last, F1 f1, F2 f2);
|
||||
template<class InputIterator,class F1, class F2>
|
||||
size_type xref:#concurrent_flat_set_insert_iterator_range_and_visit[insert_and_cvisit](InputIterator first, InputIterator last, F1 f1, F2 f2);
|
||||
template<xref:#concurrent_flat_set_container_compatible_range[__container-compatible-range__]<value_type> R, class F1, class F2>
|
||||
size_type xref:#concurrent_flat_set_insert_range_and_visit[insert_range_and_visit](R&& rg, F1 f1, F2 f2);
|
||||
template<xref:#concurrent_flat_set_container_compatible_range[__container-compatible-range__]<value_type> R, class F1, class F2>
|
||||
size_type xref:#concurrent_flat_set_insert_range_and_visit[insert_range_and_cvisit](R&& rg, F1 f1, F2 f2);
|
||||
template<class F1, class F2>
|
||||
size_type xref:#concurrent_flat_set_insert_initializer_list_and_visit[insert_and_visit](std::initializer_list<value_type> il, F1 f1, F2 f2);
|
||||
template<class F1, class F2>
|
||||
@@ -236,6 +259,16 @@ namespace unordered {
|
||||
Hash = Hash(), Pred = Pred(), Allocator = Allocator())
|
||||
-> concurrent_flat_set<xref:#concurrent_flat_set_iter_value_type[__iter-value-type__]<InputIterator>, Hash, Pred, Allocator>;
|
||||
|
||||
template<xref:#concurrent_flat_set_convertible_to_from_range_t[__convertible-to-from-range_t__] FromRangeT,
|
||||
std::ranges::input_range R,
|
||||
class Hash = boost::hash<std::ranges::range_value_t<R>>,
|
||||
class Pred = std::equal_to<std::ranges::range_value_t<R>>,
|
||||
class Allocator = std::allocator<std::ranges::range_value_t<R>>
|
||||
concurrent_flat_set(FromRangeT&&, R&&,
|
||||
typename xref:#concurrent_flat_set_deduction_guides[__see below__]::size_type = xref:#concurrent_flat_set_deduction_guides[__see below__], Hash = Hash(),
|
||||
Pred = Pred(), Allocator = Allocator())
|
||||
-> concurrent_flat_set<std::ranges::range_value_t<R>, Hash, Pred,Allocator>;
|
||||
|
||||
template<class T, class Hash = boost::hash<T>, class Pred = std::equal_to<T>,
|
||||
class Allocator = std::allocator<T>>
|
||||
concurrent_flat_set(std::initializer_list<T>, typename xref:#concurrent_flat_set_deduction_guides[__see below__]::size_type = xref:#concurrent_flat_set_deduction_guides[__see below__],
|
||||
@@ -260,6 +293,27 @@ namespace unordered {
|
||||
-> concurrent_flat_set<xref:#concurrent_flat_set_iter_value_type[__iter-value-type__]<InputIterator>, Hash,
|
||||
std::equal_to<xref:#concurrent_flat_set_iter_value_type[__iter-value-type__]<InputIterator>>, Allocator>;
|
||||
|
||||
template<xref:#concurrent_flat_set_convertible_to_from_range_t[__convertible-to-from-range_t__] FromRangeT,
|
||||
std::ranges::input_range R, class Allocator>
|
||||
concurrent_flat_set(FromRangeT&&, R&&, typename xref:#concurrent_flat_set_deduction_guides[__see below__]::size_type, Allocator)
|
||||
-> concurrent_flat_set<std::ranges::range_value_t<R>,
|
||||
boost::hash<std::ranges::range_value_t<R>>,
|
||||
std::equal_to<std::ranges::range_value_t<R>>, Allocator>;
|
||||
|
||||
template<xref:#concurrent_flat_set_convertible_to_from_range_t[__convertible-to-from-range_t__] FromRangeT,
|
||||
std::ranges::input_range R, class Allocator>
|
||||
concurrent_flat_set(FromRangeT&&, R&&, Allocator)
|
||||
-> concurrent_flat_set<std::ranges::range_value_t<R>,
|
||||
boost::hash<std::ranges::range_value_t<R>>,
|
||||
std::equal_to<std::ranges::range_value_t<R>>, Allocator>;
|
||||
|
||||
template<xref:#concurrent_flat_set_convertible_to_from_range_t[__convertible-to-from-range_t__] FromRangeT,
|
||||
std::ranges::input_range R, class Hash, class Allocator>
|
||||
concurrent_flat_set(FromRangeT&&, R&&, typename xref:#concurrent_flat_set_deduction_guides[__see below__]::size_type, Hash,
|
||||
Allocator)
|
||||
-> concurrent_flat_set<std::ranges::range_value_t<R>,
|
||||
Hash, std::equal_to<std::ranges::range_value_t<R>>, Allocator>;
|
||||
|
||||
template<class T, class Allocator>
|
||||
concurrent_flat_set(std::initializer_list<T>, typename xref:#concurrent_flat_set_deduction_guides[__see below__]::size_type, Allocator)
|
||||
-> concurrent_flat_set<T, boost::hash<T>, std::equal_to<T>, Allocator>;
|
||||
@@ -391,6 +445,15 @@ Chunk size internally used in xref:concurrent_flat_set_bulk_visit[bulk visit] op
|
||||
|
||||
=== Constructors
|
||||
|
||||
==== __container-compatible-range__
|
||||
[listings,subs="+macros,+quotes"]
|
||||
-----
|
||||
template<class R, class T>
|
||||
concept container_compatible_range =
|
||||
std::ranges::input_range<R> &&
|
||||
std::convertible_to<std::ranges::range_reference_t<R>, T>; // exposition only
|
||||
-----
|
||||
|
||||
==== Default Constructor
|
||||
```c++
|
||||
concurrent_flat_set();
|
||||
@@ -538,6 +601,27 @@ Complexity:;; O(`bucket_count()`)
|
||||
|
||||
---
|
||||
|
||||
==== Range Constructor
|
||||
[source,c++,subs="+macros,+quotes"]
|
||||
----
|
||||
template<class FromRangeT, xref:#concurrent_flat_set_container_compatible_range[__container-compatible-range__]<value_type> R>
|
||||
concurrent_flat_set(FromRangeT&&, R&& rg,
|
||||
size_type n = _implementation-defined_,
|
||||
const hasher& hf = hasher(),
|
||||
const key_equal& eql = key_equal(),
|
||||
const allocator_type& a = allocator_type());
|
||||
----
|
||||
|
||||
Constructs an empty table with at least `n` buckets, using `hf` as the hash function, `eql` as the key equality predicate and `a` as the allocator, and inserts the elements from `rg` into it.
|
||||
|
||||
Only participates in overload resolution if `FromRangeT` is convertible to `std::from_range_t` or `boost::concurrent::from_range_t`.
|
||||
|
||||
|
||||
[horizontal]
|
||||
Requires:;; If the defaults are used, `hasher`, `key_equal` and `allocator_type` need to be https://en.cppreference.com/w/cpp/named_req/DefaultConstructible[DefaultConstructible^].
|
||||
|
||||
---
|
||||
|
||||
==== Initializer List Constructor
|
||||
[source,c++,subs="+quotes"]
|
||||
----
|
||||
@@ -610,6 +694,58 @@ Requires:;; `key_equal` needs to be https://en.cppreference.com/w/cpp/named_req/
|
||||
|
||||
---
|
||||
|
||||
==== Range Constructor with Allocator
|
||||
|
||||
[source,c++,subs="+macros,+quotes"]
|
||||
----
|
||||
template<class FromRangeT, xref:#concurrent_flat_set_container_compatible_range[__container-compatible-range__]<value_type> R>
|
||||
concurrent_flat_set(FromRangeT&&, R&& rg, const allocator_type& a);
|
||||
----
|
||||
|
||||
Constructs an empty table using `a` and default hash function and key equality predicate, and inserts the elements from `rg` into it.
|
||||
|
||||
Only participates in overload resolution if `FromRangeT` is convertible to `std::from_range_t` or `boost::concurrent::from_range_t`.
|
||||
|
||||
[horizontal]
|
||||
Requires:;; `hasher` and `key_equal` need to be https://en.cppreference.com/w/cpp/named_req/DefaultConstructible[DefaultConstructible^].
|
||||
|
||||
---
|
||||
|
||||
==== Range Constructor with Bucket Count and Allocator
|
||||
|
||||
[source,c++,subs="+macros,+quotes"]
|
||||
----
|
||||
template<class FromRangeT, xref:#concurrent_flat_set_container_compatible_range[__container-compatible-range__]<value_type> R>
|
||||
concurrent_flat_set(FromRangeT&&, R&& rg, size_type n, const allocator_type& a);
|
||||
----
|
||||
|
||||
Constructs an empty table with at least `n` buckets, using `a` and default hash function and key equality predicate, and inserts the elements from `rg` into it.
|
||||
|
||||
Only participates in overload resolution if `FromRangeT` is convertible to `std::from_range_t` or `boost::concurrent::from_range_t`.
|
||||
|
||||
[horizontal]
|
||||
Requires:;; `hasher` and `key_equal` need to be https://en.cppreference.com/w/cpp/named_req/DefaultConstructible[DefaultConstructible^].
|
||||
|
||||
---
|
||||
|
||||
==== Range Constructor with Bucket Count and Hasher and Allocator
|
||||
|
||||
[source,c++,subs="+macros,+quotes"]
|
||||
----
|
||||
template<class FromRangeT, xref:#concurrent_flat_set_container_compatible_range[__container-compatible-range__]<value_type> R>
|
||||
concurrent_flat_set(FromRangeT&&, R&& rg, size_type n, const hasher& hf,
|
||||
const allocator_type& a);
|
||||
----
|
||||
|
||||
Constructs an empty table with at least `n` buckets, using `hf` as the hash function, `a` as the allocator and default key equality predicate, and inserts the elements from `rg` into it.
|
||||
|
||||
Only participates in overload resolution if `FromRangeT` is convertible to `std::from_range_t` or `boost::concurrent::from_range_t`.
|
||||
|
||||
[horizontal]
|
||||
Requires:;; `key_equal` needs to be https://en.cppreference.com/w/cpp/named_req/DefaultConstructible[DefaultConstructible^].
|
||||
|
||||
---
|
||||
|
||||
==== initializer_list Constructor with Allocator
|
||||
|
||||
```c++
|
||||
@@ -643,7 +779,7 @@ concurrent_flat_set(std::initializer_list<value_type> il, size_type n, const has
|
||||
const allocator_type& a);
|
||||
```
|
||||
|
||||
Constructs an empty table with at least `n` buckets, using `hf` as the hash function, `a` as the allocator and default key equality predicate,and inserts the elements from `il` into it.
|
||||
Constructs an empty table with at least `n` buckets, using `hf` as the hash function, `a` as the allocator and default key equality predicate, and inserts the elements from `il` into it.
|
||||
|
||||
[horizontal]
|
||||
Requires:;; `key_equal` needs to be https://en.cppreference.com/w/cpp/named_req/DefaultConstructible[DefaultConstructible^].
|
||||
@@ -963,6 +1099,24 @@ Returns:;; The number of elements inserted.
|
||||
|
||||
---
|
||||
|
||||
==== Insert Range
|
||||
[source,c++,subs="+macros,+quotes"]
|
||||
----
|
||||
template<xref:#concurrent_flat_set_container_compatible_range[__container-compatible-range__]<value_type> R>
|
||||
void insert_range(R&& rg);
|
||||
----
|
||||
|
||||
Equivalent to
|
||||
[listing,subs="+macros,+quotes"]
|
||||
-----
|
||||
for(auto&& x: rg) this->xref:#concurrent_flat_set_emplace[emplace](std::forward<decltype(x)>(x));
|
||||
-----
|
||||
|
||||
[horizontal]
|
||||
Returns:;; The number of elements inserted.
|
||||
|
||||
---
|
||||
|
||||
==== Insert Initializer List
|
||||
```c++
|
||||
size_type insert(std::initializer_list<value_type> il);
|
||||
@@ -1070,6 +1224,27 @@ Returns:;; The number of elements inserted.
|
||||
|
||||
---
|
||||
|
||||
==== Insert Range or Visit
|
||||
[source,c++,subs="+macros,+quotes"]
|
||||
----
|
||||
template<xref:#concurrent_flat_set_container_compatible_range[__container-compatible-range__]<value_type> R, class F>
|
||||
size_type insert_range_or_visit(R&& rg, F f);
|
||||
template<xref:#concurrent_flat_set_container_compatible_range[__container-compatible-range__]<value_type> R, class F>
|
||||
size_type insert_range_or_visit(R&& rg, F f);
|
||||
----
|
||||
|
||||
Equivalent to
|
||||
[listing,subs="+macros,+quotes"]
|
||||
-----
|
||||
for(auto&& x: rg)
|
||||
this->xref:#concurrent_flat_set_emplace_or_cvisit[emplace_or_[c\]visit](std::forward<decltype(x)>(x), std::ref(f));
|
||||
-----
|
||||
|
||||
[horizontal]
|
||||
Returns:;; The number of elements inserted.
|
||||
|
||||
---
|
||||
|
||||
==== Insert Initializer List or Visit
|
||||
```c++
|
||||
template<class F> size_type insert_or_visit(std::initializer_list<value_type> il, F f);
|
||||
@@ -1184,6 +1359,28 @@ Returns:;; The number of elements inserted.
|
||||
|
||||
---
|
||||
|
||||
==== Insert Range and Visit
|
||||
[source,c++,subs="+macros,+quotes"]
|
||||
----
|
||||
template<xref:#concurrent_flat_set_container_compatible_range[__container-compatible-range__]<value_type> R, class F1, class F2>
|
||||
size_type insert_range_and_visit(R&& rg, F1 f1, F2 f2);
|
||||
template<xref:#concurrent_flat_set_container_compatible_range[__container-compatible-range__]<value_type> R, class F1, class F2>
|
||||
size_type insert_range_and_cvisit(R&& rg, F1 f1, F2 f2);
|
||||
----
|
||||
|
||||
Equivalent to
|
||||
[listing,subs="+macros,+quotes"]
|
||||
-----
|
||||
for(auto&& x: rg)
|
||||
this->xref:#concurrent_flat_set_emplace_and_cvisit[emplace_and_[c\]visit](
|
||||
std::forward<decltype(x)>(x), std::ref(f1), std::ref(f2));
|
||||
-----
|
||||
|
||||
[horizontal]
|
||||
Returns:;; The number of elements inserted.
|
||||
|
||||
---
|
||||
|
||||
==== Insert Initializer List and Visit
|
||||
```c++
|
||||
template<class F1, class F2>
|
||||
@@ -1516,6 +1713,16 @@ template<class InputIterator>
|
||||
typename std::iterator_traits<InputIterator>::value_type; // exposition only
|
||||
-----
|
||||
|
||||
==== __convertible-to-from-range_t__
|
||||
[listings,subs="+macros,+quotes"]
|
||||
-----
|
||||
template<typename FromRangeT>
|
||||
concept __convertible-to-from_range_t__ =
|
||||
// first clause not present if std::from_range_t does not exist
|
||||
std::is_convertible_v<FromRangeT, std::from_range_t> ||
|
||||
std::is_convertible_v<FromRangeT, boost::unordered::from_range_t>; // exposition only
|
||||
-----
|
||||
|
||||
=== Equality Comparisons
|
||||
|
||||
==== operator==
|
||||
|
||||
@@ -80,6 +80,12 @@ namespace unordered {
|
||||
xref:#concurrent_node_map_copy_constructor_with_allocator[concurrent_node_map](const concurrent_node_map& other, const Allocator& a);
|
||||
xref:#concurrent_node_map_move_constructor_with_allocator[concurrent_node_map](concurrent_node_map&& other, const Allocator& a);
|
||||
xref:#concurrent_node_map_move_constructor_from_unordered_node_map[concurrent_node_map](unordered_node_map<Key, T, Hash, Pred, Allocator>&& other);
|
||||
template<class FromRangeT, xref:#concurrent_node_map_container_compatible_range[__container-compatible-range__]<value_type> R>
|
||||
xref:#concurrent_node_map_range_constructor[concurrent_node_map](FromRangeT&&, R&& rg,
|
||||
size_type n = _implementation-defined_,
|
||||
const hasher& hf = hasher(),
|
||||
const key_equal& eql = key_equal(),
|
||||
const allocator_type& a = allocator_type());
|
||||
xref:#concurrent_node_map_initializer_list_constructor[concurrent_node_map](std::initializer_list<value_type> il,
|
||||
size_type n = _implementation-defined_
|
||||
const hasher& hf = hasher(),
|
||||
@@ -93,6 +99,13 @@ namespace unordered {
|
||||
template<class InputIterator>
|
||||
xref:#concurrent_node_map_iterator_range_constructor_with_bucket_count_and_hasher[concurrent_node_map](InputIterator f, InputIterator l, size_type n, const hasher& hf,
|
||||
const allocator_type& a);
|
||||
template<class FromRangeT, xref:#concurrent_node_map_container_compatible_range[__container-compatible-range__]<value_type> R>
|
||||
xref:#concurrent_node_map_range_constructor_with_allocator[concurrent_node_map](FromRangeT&&, R&& rg, const allocator_type& a);
|
||||
template<class FromRangeT, xref:#concurrent_node_map_container_compatible_range[__container-compatible-range__]<value_type> R>
|
||||
xref:#concurrent_node_map_range_constructor_with_bucket_count_and_allocator[concurrent_node_map](FromRangeT&&, R&& rg, size_type n, const allocator_type& a);
|
||||
template<class FromRangeT, xref:#concurrent_node_map_container_compatible_range[__container-compatible-range__]<value_type> R>
|
||||
xref:#concurrent_node_map_range_constructor_with_bucket_count_and_hasher_and_allocator[concurrent_node_map](FromRangeT&&, R&& rg, size_type n, const hasher& hf,
|
||||
const allocator_type& a);
|
||||
xref:#concurrent_node_map_initializer_list_constructor_with_allocator[concurrent_node_map](std::initializer_list<value_type> il, const allocator_type& a);
|
||||
xref:#concurrent_node_map_initializer_list_constructor_with_bucket_count_and_allocator[concurrent_node_map](std::initializer_list<value_type> il, size_type n,
|
||||
const allocator_type& a);
|
||||
@@ -155,6 +168,8 @@ namespace unordered {
|
||||
bool xref:#concurrent_node_map_move_insert[insert](value_type&& obj);
|
||||
bool xref:#concurrent_node_map_move_insert[insert](init_type&& obj);
|
||||
template<class InputIterator> size_type xref:#concurrent_node_map_insert_iterator_range[insert](InputIterator first, InputIterator last);
|
||||
template<xref:#concurrent_node_map_container_compatible_range[__container-compatible-range__]<value_type> R>
|
||||
size_type xref:#concurrent_node_map_insert_range[insert_range](R&& rg);
|
||||
size_type xref:#concurrent_node_map_insert_initializer_list[insert](std::initializer_list<value_type> il);
|
||||
insert_return_type xref:#concurrent_node_map_insert_node[insert](node_type&& nh);
|
||||
|
||||
@@ -172,6 +187,10 @@ namespace unordered {
|
||||
size_type xref:#concurrent_node_map_insert_iterator_range_or_visit[insert_or_visit](InputIterator first, InputIterator last, F f);
|
||||
template<class InputIterator,class F>
|
||||
size_type xref:#concurrent_node_map_insert_iterator_range_or_visit[insert_or_cvisit](InputIterator first, InputIterator last, F f);
|
||||
template<xref:#concurrent_node_map_container_compatible_range[__container-compatible-range__]<value_type> R, class F>
|
||||
size_type xref:#concurrent_node_map_insert_range_or_visit[insert_range_or_visit](R&& rg, F f);
|
||||
template<xref:#concurrent_node_map_container_compatible_range[__container-compatible-range__]<value_type> R, class F>
|
||||
size_type xref:#concurrent_node_map_insert_range_or_visit[insert_range_or_cvisit](R&& rg, F f);
|
||||
template<class F> size_type xref:#concurrent_node_map_insert_initializer_list_or_visit[insert_or_visit](std::initializer_list<value_type> il, F f);
|
||||
template<class F> size_type xref:#concurrent_node_map_insert_initializer_list_or_visit[insert_or_cvisit](std::initializer_list<value_type> il, F f);
|
||||
template<class F> insert_return_type xref:#concurrent_node_map_insert_node_or_visit[insert_or_visit](node_type&& nh, F f);
|
||||
@@ -193,6 +212,10 @@ namespace unordered {
|
||||
size_type xref:#concurrent_node_map_insert_iterator_range_and_visit[insert_and_visit](InputIterator first, InputIterator last, F1 f1, F2 f2);
|
||||
template<class InputIterator,class F1, class F2>
|
||||
size_type xref:#concurrent_node_map_insert_iterator_range_and_visit[insert_and_cvisit](InputIterator first, InputIterator last, F1 f1, F2 f2);
|
||||
template<xref:#concurrent_node_map_container_compatible_range[__container-compatible-range__]<value_type> R, class F1, class F2>
|
||||
size_type xref:#concurrent_node_map_insert_range_and_visit[insert_range_and_visit](R&& rg, F1 f1, F2 f2);
|
||||
template<xref:#concurrent_node_map_container_compatible_range[__container-compatible-range__]<value_type> R, class F1, class F2>
|
||||
size_type xref:#concurrent_node_map_insert_range_and_visit[insert_range_and_cvisit](R&& rg, F1 f1, F2 f2);
|
||||
template<class F1, class F2>
|
||||
size_type xref:#concurrent_node_map_insert_initializer_list_and_visit[insert_and_visit](std::initializer_list<value_type> il, F1 f1, F2 f2);
|
||||
template<class F1, class F2>
|
||||
@@ -300,6 +323,17 @@ namespace unordered {
|
||||
-> concurrent_node_map<xref:#concurrent_node_map_iter_key_type[__iter-key-type__]<InputIterator>, xref:#concurrent_node_map_iter_mapped_type[__iter-mapped-type__]<InputIterator>, Hash,
|
||||
Pred, Allocator>;
|
||||
|
||||
template<xref:#concurrent_node_map_convertible_to_from_range_t[__convertible-to-from-range_t__] FromRangeT,
|
||||
std::ranges::input_range R,
|
||||
class Hash = boost::hash<xref:#concurrent_node_map_range_key_type[__range-key-type__]<R>>,
|
||||
class Pred = std::equal_to<xref:#concurrent_node_map_range_key_type[__range-key-type__]<R>>,
|
||||
class Allocator = std::allocator<xref:#concurrent_node_map_range_to_alloc_type[__range-to-alloc-type__]<R>>>
|
||||
concurrent_node_map(FromRangeT&&, R&&,
|
||||
typename xref:#concurrent_node_map_deduction_guides[__see below__]::size_type = xref:#concurrent_node_map_deduction_guides[__see below__], Hash = Hash(),
|
||||
Pred = Pred(), Allocator = Allocator())
|
||||
-> concurrent_node_map<xref:#concurrent_node_map_range_key_type[__range-key-type__]<R>, xref:#concurrent_node_map_range_mapped_type[__range-mapped-type__]<R>,
|
||||
Hash, Pred,Allocator>;
|
||||
|
||||
template<class Key, class T, class Hash = boost::hash<Key>,
|
||||
class Pred = std::equal_to<Key>,
|
||||
class Allocator = std::allocator<std::pair<const Key, T>>>
|
||||
@@ -326,6 +360,27 @@ namespace unordered {
|
||||
-> concurrent_node_map<xref:#concurrent_node_map_iter_key_type[__iter-key-type__]<InputIterator>, xref:#concurrent_node_map_iter_mapped_type[__iter-mapped-type__]<InputIterator>, Hash,
|
||||
std::equal_to<xref:#concurrent_node_map_iter_key_type[__iter-key-type__]<InputIterator>>, Allocator>;
|
||||
|
||||
template<xref:#concurrent_node_map_convertible_to_from_range_t[__convertible-to-from-range_t__] FromRangeT,
|
||||
std::ranges::input_range R, class Allocator>
|
||||
concurrent_node_map(FromRangeT&&, R&&, typename xref:#concurrent_node_map_deduction_guides[__see below__]::size_type, Allocator)
|
||||
-> concurrent_node_map<xref:#concurrent_node_map_range_key_type[__range-key-type__]<R>, xref:#concurrent_node_map_range_mapped_type[__range-mapped-type__]<R>,
|
||||
boost::hash<xref:#concurrent_node_map_range_key_type[__range-key-type__]<R>>,
|
||||
std::equal_to<xref:#concurrent_node_map_range_key_type[__range-key-type__]<R>>, Allocator>;
|
||||
|
||||
template<xref:#concurrent_node_map_convertible_to_from_range_t[__convertible-to-from-range_t__] FromRangeT,
|
||||
std::ranges::input_range R, class Allocator>
|
||||
concurrent_node_map(FromRangeT&&, R&&, Allocator)
|
||||
-> concurrent_node_map<xref:#concurrent_node_map_range_key_type[__range-key-type__]<R>, xref:#concurrent_node_map_range_mapped_type[__range-mapped-type__]<R>,
|
||||
boost::hash<xref:#concurrent_node_map_range_key_type[__range-key-type__]<R>>,
|
||||
std::equal_to<xref:#concurrent_node_map_range_key_type[__range-key-type__]<R>>, Allocator>;
|
||||
|
||||
template<xref:#concurrent_node_map_convertible_to_from_range_t[__convertible-to-from-range_t__] FromRangeT,
|
||||
std::ranges::input_range R, class Hash, class Allocator>
|
||||
concurrent_node_map(FromRangeT&&, R&&, typename xref:#concurrent_node_map_deduction_guides[__see below__]::size_type, Hash,
|
||||
Allocator)
|
||||
-> concurrent_node_map<xref:#concurrent_node_map_range_key_type[__range-key-type__]<R>, xref:#concurrent_node_map_range_mapped_type[__range-mapped-type__]<R>,
|
||||
Hash, std::equal_to<xref:#concurrent_node_map_range_key_type[__range-key-type__]<R>>, Allocator>;
|
||||
|
||||
template<class Key, class T, class Allocator>
|
||||
concurrent_node_map(std::initializer_list<std::pair<Key, T>>, typename xref:#concurrent_node_map_deduction_guides[__see below__]::size_type,
|
||||
Allocator)
|
||||
@@ -496,6 +551,15 @@ Chunk size internally used in xref:concurrent_node_map_bulk_visit[bulk visit] op
|
||||
|
||||
=== Constructors
|
||||
|
||||
==== __container-compatible-range__
|
||||
[listings,subs="+macros,+quotes"]
|
||||
-----
|
||||
template<class R, class T>
|
||||
concept container_compatible_range =
|
||||
std::ranges::input_range<R> &&
|
||||
std::convertible_to<std::ranges::range_reference_t<R>, T>; // exposition only
|
||||
-----
|
||||
|
||||
==== Default Constructor
|
||||
```c++
|
||||
concurrent_node_map();
|
||||
@@ -643,6 +707,27 @@ Complexity:;; O(`bucket_count()`)
|
||||
|
||||
---
|
||||
|
||||
==== Range Constructor
|
||||
[source,c++,subs="+macros,+quotes"]
|
||||
----
|
||||
template<class FromRangeT, xref:#concurrent_node_map_container_compatible_range[__container-compatible-range__]<value_type> R>
|
||||
concurrent_node_map(FromRangeT&&, R&& rg,
|
||||
size_type n = _implementation-defined_,
|
||||
const hasher& hf = hasher(),
|
||||
const key_equal& eql = key_equal(),
|
||||
const allocator_type& a = allocator_type());
|
||||
----
|
||||
|
||||
Constructs an empty table with at least `n` buckets, using `hf` as the hash function, `eql` as the key equality predicate and `a` as the allocator, and inserts the elements from `rg` into it.
|
||||
|
||||
Only participates in overload resolution if `FromRangeT` is convertible to `std::from_range_t` or `boost::concurrent::from_range_t`.
|
||||
|
||||
|
||||
[horizontal]
|
||||
Requires:;; If the defaults are used, `hasher`, `key_equal` and `allocator_type` need to be https://en.cppreference.com/w/cpp/named_req/DefaultConstructible[DefaultConstructible^].
|
||||
|
||||
---
|
||||
|
||||
==== Initializer List Constructor
|
||||
[source,c++,subs="+quotes"]
|
||||
----
|
||||
@@ -715,6 +800,58 @@ Requires:;; `key_equal` needs to be https://en.cppreference.com/w/cpp/named_req/
|
||||
|
||||
---
|
||||
|
||||
==== Range Constructor with Allocator
|
||||
|
||||
[source,c++,subs="+macros,+quotes"]
|
||||
----
|
||||
template<class FromRangeT, xref:#concurrent_node_map_container_compatible_range[__container-compatible-range__]<value_type> R>
|
||||
concurrent_node_map(FromRangeT&&, R&& rg, const allocator_type& a);
|
||||
----
|
||||
|
||||
Constructs an empty table using `a` and default hash function and key equality predicate, and inserts the elements from `rg` into it.
|
||||
|
||||
Only participates in overload resolution if `FromRangeT` is convertible to `std::from_range_t` or `boost::concurrent::from_range_t`.
|
||||
|
||||
[horizontal]
|
||||
Requires:;; `hasher` and `key_equal` need to be https://en.cppreference.com/w/cpp/named_req/DefaultConstructible[DefaultConstructible^].
|
||||
|
||||
---
|
||||
|
||||
==== Range Constructor with Bucket Count and Allocator
|
||||
|
||||
[source,c++,subs="+macros,+quotes"]
|
||||
----
|
||||
template<class FromRangeT, xref:#concurrent_node_map_container_compatible_range[__container-compatible-range__]<value_type> R>
|
||||
concurrent_node_map(FromRangeT&&, R&& rg, size_type n, const allocator_type& a);
|
||||
----
|
||||
|
||||
Constructs an empty table with at least `n` buckets, using `a` and default hash function and key equality predicate, and inserts the elements from `rg` into it.
|
||||
|
||||
Only participates in overload resolution if `FromRangeT` is convertible to `std::from_range_t` or `boost::concurrent::from_range_t`.
|
||||
|
||||
[horizontal]
|
||||
Requires:;; `hasher` and `key_equal` need to be https://en.cppreference.com/w/cpp/named_req/DefaultConstructible[DefaultConstructible^].
|
||||
|
||||
---
|
||||
|
||||
==== Range Constructor with Bucket Count and Hasher and Allocator
|
||||
|
||||
[source,c++,subs="+macros,+quotes"]
|
||||
----
|
||||
template<class FromRangeT, xref:#concurrent_node_map_container_compatible_range[__container-compatible-range__]<value_type> R>
|
||||
concurrent_node_map(FromRangeT&&, R&& rg, size_type n, const hasher& hf,
|
||||
const allocator_type& a);
|
||||
----
|
||||
|
||||
Constructs an empty table with at least `n` buckets, using `hf` as the hash function, `a` as the allocator and default key equality predicate, and inserts the elements from `rg` into it.
|
||||
|
||||
Only participates in overload resolution if `FromRangeT` is convertible to `std::from_range_t` or `boost::concurrent::from_range_t`.
|
||||
|
||||
[horizontal]
|
||||
Requires:;; `key_equal` needs to be https://en.cppreference.com/w/cpp/named_req/DefaultConstructible[DefaultConstructible^].
|
||||
|
||||
---
|
||||
|
||||
==== initializer_list Constructor with Allocator
|
||||
|
||||
```c++
|
||||
@@ -1059,6 +1196,24 @@ Returns:;; The number of elements inserted.
|
||||
|
||||
---
|
||||
|
||||
==== Insert Range
|
||||
[source,c++,subs="+macros,+quotes"]
|
||||
----
|
||||
template<xref:#concurrent_node_map_container_compatible_range[__container-compatible-range__]<value_type> R>
|
||||
void insert_range(R&& rg);
|
||||
----
|
||||
|
||||
Equivalent to
|
||||
[listing,subs="+macros,+quotes"]
|
||||
-----
|
||||
for(auto&& x: rg) this->xref:#concurrent_node_map_emplace[emplace](std::forward<decltype(x)>(x));
|
||||
-----
|
||||
|
||||
[horizontal]
|
||||
Returns:;; The number of elements inserted.
|
||||
|
||||
---
|
||||
|
||||
==== Insert Initializer List
|
||||
```c++
|
||||
size_type insert(std::initializer_list<value_type> il);
|
||||
@@ -1170,6 +1325,27 @@ Returns:;; The number of elements inserted.
|
||||
|
||||
---
|
||||
|
||||
==== Insert Range or Visit
|
||||
[source,c++,subs="+macros,+quotes"]
|
||||
----
|
||||
template<xref:#concurrent_node_map_container_compatible_range[__container-compatible-range__]<value_type> R, class F>
|
||||
size_type insert_range_or_visit(R&& rg, F f);
|
||||
template<xref:#concurrent_node_map_container_compatible_range[__container-compatible-range__]<value_type> R, class F>
|
||||
size_type insert_range_or_visit(R&& rg, F f);
|
||||
----
|
||||
|
||||
Equivalent to
|
||||
[listing,subs="+macros,+quotes"]
|
||||
-----
|
||||
for(auto&& x: rg)
|
||||
this->xref:#concurrent_node_map_emplace_or_cvisit[emplace_or_[c\]visit](std::forward<decltype(x)>(x), std::ref(f));
|
||||
-----
|
||||
|
||||
[horizontal]
|
||||
Returns:;; The number of elements inserted.
|
||||
|
||||
---
|
||||
|
||||
==== Insert Initializer List or Visit
|
||||
```c++
|
||||
template<class F> size_type insert_or_visit(std::initializer_list<value_type> il, F f);
|
||||
@@ -1289,6 +1465,28 @@ Returns:;; The number of elements inserted.
|
||||
|
||||
---
|
||||
|
||||
==== Insert Range and Visit
|
||||
[source,c++,subs="+macros,+quotes"]
|
||||
----
|
||||
template<xref:#concurrent_node_map_container_compatible_range[__container-compatible-range__]<value_type> R, class F1, class F2>
|
||||
size_type insert_range_and_visit(R&& rg, F1 f1, F2 f2);
|
||||
template<xref:#concurrent_node_map_container_compatible_range[__container-compatible-range__]<value_type> R, class F1, class F2>
|
||||
size_type insert_range_and_cvisit(R&& rg, F1 f1, F2 f2);
|
||||
----
|
||||
|
||||
Equivalent to
|
||||
[listing,subs="+macros,+quotes"]
|
||||
-----
|
||||
for(auto&& x: rg)
|
||||
this->xref:#concurrent_node_map_emplace_and_cvisit[emplace_and_[c\]visit](
|
||||
std::forward<decltype(x)>(x), std::ref(f1), std::ref(f2));
|
||||
-----
|
||||
|
||||
[horizontal]
|
||||
Returns:;; The number of elements inserted.
|
||||
|
||||
---
|
||||
|
||||
==== Insert Initializer List and Visit
|
||||
```c++
|
||||
template<class F1, class F2>
|
||||
@@ -1858,6 +2056,42 @@ template<class InputIterator>
|
||||
std::tuple_element_t<1, xref:#concurrent_node_map_iter_value_type[__iter-value-type__]<InputIterator>>>; // exposition only
|
||||
-----
|
||||
|
||||
==== __convertible-to-from-range_t__
|
||||
[listings,subs="+macros,+quotes"]
|
||||
-----
|
||||
template<typename FromRangeT>
|
||||
concept __convertible-to-from_range_t__ =
|
||||
// first clause not present if std::from_range_t does not exist
|
||||
std::is_convertible_v<FromRangeT, std::from_range_t> ||
|
||||
std::is_convertible_v<FromRangeT, boost::unordered::from_range_t>; // exposition only
|
||||
-----
|
||||
|
||||
==== __range-key-type__
|
||||
[listings,subs="+macros,+quotes"]
|
||||
-----
|
||||
template<std::ranges::input_range R>
|
||||
using __range-key-type__ =
|
||||
std::remove_cvref_t<
|
||||
std::tuple_element_t<0, std::ranges::range_value_t<R>>>; // exposition only
|
||||
-----
|
||||
|
||||
==== __range-mapped-type__
|
||||
[listings,subs="+macros,+quotes"]
|
||||
-----
|
||||
template<std::ranges::input_range R>
|
||||
using __range-mapped-type__ =
|
||||
std::remove_cvref_t<
|
||||
std::tuple_element_t<1, std::ranges::range_value_t<R>>>; // exposition only
|
||||
-----
|
||||
|
||||
==== __range-to-alloc-type__
|
||||
[listings,subs="+macros,+quotes"]
|
||||
-----
|
||||
template<std::ranges::input_range R>
|
||||
using __range-to-alloc-type__ =
|
||||
std::pair<const xref:#concurrent_node_map_range_key_type[__range-key-type__]<R>, xref:#concurrent_node_map_range_mapped_type[__range-mapped-type__]<R>>; // exposition only
|
||||
-----
|
||||
|
||||
=== Equality Comparisons
|
||||
|
||||
==== operator==
|
||||
|
||||
@@ -75,6 +75,12 @@ namespace unordered {
|
||||
xref:#concurrent_node_set_copy_constructor_with_allocator[concurrent_node_set](const concurrent_node_set& other, const Allocator& a);
|
||||
xref:#concurrent_node_set_move_constructor_with_allocator[concurrent_node_set](concurrent_node_set&& other, const Allocator& a);
|
||||
xref:#concurrent_node_set_move_constructor_from_unordered_node_set[concurrent_node_set](unordered_node_set<Key, Hash, Pred, Allocator>&& other);
|
||||
template<class FromRangeT, xref:#concurrent_node_set_container_compatible_range[__container-compatible-range__]<value_type> R>
|
||||
xref:#concurrent_node_set_range_constructor[concurrent_node_set](FromRangeT&&, R&& rg,
|
||||
size_type n = _implementation-defined_,
|
||||
const hasher& hf = hasher(),
|
||||
const key_equal& eql = key_equal(),
|
||||
const allocator_type& a = allocator_type());
|
||||
xref:#concurrent_node_set_initializer_list_constructor[concurrent_node_set](std::initializer_list<value_type> il,
|
||||
size_type n = _implementation-defined_
|
||||
const hasher& hf = hasher(),
|
||||
@@ -88,6 +94,13 @@ namespace unordered {
|
||||
template<class InputIterator>
|
||||
xref:#concurrent_node_set_iterator_range_constructor_with_bucket_count_and_hasher[concurrent_node_set](InputIterator f, InputIterator l, size_type n, const hasher& hf,
|
||||
const allocator_type& a);
|
||||
template<class FromRangeT, xref:#concurrent_node_set_container_compatible_range[__container-compatible-range__]<value_type> R>
|
||||
xref:#concurrent_node_set_range_constructor_with_allocator[concurrent_node_set](FromRangeT&&, R&& rg, const allocator_type& a);
|
||||
template<class FromRangeT, xref:#concurrent_node_set_container_compatible_range[__container-compatible-range__]<value_type> R>
|
||||
xref:#concurrent_node_set_range_constructor_with_bucket_count_and_allocator[concurrent_node_set](FromRangeT&&, R&& rg, size_type n, const allocator_type& a);
|
||||
template<class FromRangeT, xref:#concurrent_node_set_container_compatible_range[__container-compatible-range__]<value_type> R>
|
||||
xref:#concurrent_node_set_range_constructor_with_bucket_count_and_hasher_and_allocator[concurrent_node_set](FromRangeT&&, R&& rg, size_type n, const hasher& hf,
|
||||
const allocator_type& a);
|
||||
xref:#concurrent_node_set_initializer_list_constructor_with_allocator[concurrent_node_set](std::initializer_list<value_type> il, const allocator_type& a);
|
||||
xref:#concurrent_node_set_initializer_list_constructor_with_bucket_count_and_allocator[concurrent_node_set](std::initializer_list<value_type> il, size_type n,
|
||||
const allocator_type& a);
|
||||
@@ -148,6 +161,8 @@ namespace unordered {
|
||||
bool xref:#concurrent_node_set_move_insert[insert](value_type&& obj);
|
||||
template<class K> bool xref:#concurrent_node_set_transparent_insert[insert](K&& k);
|
||||
template<class InputIterator> size_type xref:#concurrent_node_set_insert_iterator_range[insert](InputIterator first, InputIterator last);
|
||||
template<xref:#concurrent_node_set_container_compatible_range[__container-compatible-range__]<value_type> R>
|
||||
size_type xref:#concurrent_node_set_insert_range[insert_range](R&& rg);
|
||||
size_type xref:#concurrent_node_set_insert_initializer_list[insert](std::initializer_list<value_type> il);
|
||||
insert_return_type xref:#concurrent_node_set_insert_node[insert](node_type&& nh);
|
||||
|
||||
@@ -163,6 +178,10 @@ namespace unordered {
|
||||
size_type xref:#concurrent_node_set_insert_iterator_range_or_visit[insert_or_visit](InputIterator first, InputIterator last, F f);
|
||||
template<class InputIterator,class F>
|
||||
size_type xref:#concurrent_node_set_insert_iterator_range_or_visit[insert_or_cvisit](InputIterator first, InputIterator last, F f);
|
||||
template<xref:#concurrent_node_set_container_compatible_range[__container-compatible-range__]<value_type> R, class F>
|
||||
size_type xref:#concurrent_node_set_insert_range_or_visit[insert_range_or_visit](R&& rg, F f);
|
||||
template<xref:#concurrent_node_set_container_compatible_range[__container-compatible-range__]<value_type> R, class F>
|
||||
size_type xref:#concurrent_node_set_insert_range_or_visit[insert_range_or_cvisit](R&& rg, F f);
|
||||
template<class F> size_type xref:#concurrent_node_set_insert_initializer_list_or_visit[insert_or_visit](std::initializer_list<value_type> il, F f);
|
||||
template<class F> size_type xref:#concurrent_node_set_insert_initializer_list_or_visit[insert_or_cvisit](std::initializer_list<value_type> il, F f);
|
||||
template<class F> insert_return_type xref:#concurrent_node_set_insert_node_or_visit[insert_or_visit](node_type&& nh, F f);
|
||||
@@ -182,6 +201,10 @@ namespace unordered {
|
||||
size_type xref:#concurrent_node_set_insert_iterator_range_and_visit[insert_and_visit](InputIterator first, InputIterator last, F1 f1, F2 f2);
|
||||
template<class InputIterator,class F1, class F2>
|
||||
size_type xref:#concurrent_node_set_insert_iterator_range_and_visit[insert_and_cvisit](InputIterator first, InputIterator last, F1 f1, F2 f2);
|
||||
template<xref:#concurrent_node_set_container_compatible_range[__container-compatible-range__]<value_type> R, class F1, class F2>
|
||||
size_type xref:#concurrent_node_set_insert_range_and_visit[insert_range_and_visit](R&& rg, F1 f1, F2 f2);
|
||||
template<xref:#concurrent_node_set_container_compatible_range[__container-compatible-range__]<value_type> R, class F1, class F2>
|
||||
size_type xref:#concurrent_node_set_insert_range_and_visit[insert_range_and_cvisit](R&& rg, F1 f1, F2 f2);
|
||||
template<class F1, class F2>
|
||||
size_type xref:#concurrent_node_set_insert_initializer_list_and_visit[insert_and_visit](std::initializer_list<value_type> il, F1 f1, F2 f2);
|
||||
template<class F1, class F2>
|
||||
@@ -253,6 +276,16 @@ namespace unordered {
|
||||
Hash = Hash(), Pred = Pred(), Allocator = Allocator())
|
||||
-> concurrent_node_set<xref:#concurrent_node_set_iter_value_type[__iter-value-type__]<InputIterator>, Hash, Pred, Allocator>;
|
||||
|
||||
template<xref:#concurrent_node_set_convertible_to_from_range_t[__convertible-to-from-range_t__] FromRangeT,
|
||||
std::ranges::input_range R,
|
||||
class Hash = boost::hash<std::ranges::range_value_t<R>>,
|
||||
class Pred = std::equal_to<std::ranges::range_value_t<R>>,
|
||||
class Allocator = std::allocator<std::ranges::range_value_t<R>>
|
||||
concurrent_node_set(FromRangeT&&, R&&,
|
||||
typename xref:#concurrent_node_set_deduction_guides[__see below__]::size_type = xref:#concurrent_node_set_deduction_guides[__see below__], Hash = Hash(),
|
||||
Pred = Pred(), Allocator = Allocator())
|
||||
-> concurrent_node_set<std::ranges::range_value_t<R>, Hash, Pred,Allocator>;
|
||||
|
||||
template<class T, class Hash = boost::hash<T>, class Pred = std::equal_to<T>,
|
||||
class Allocator = std::allocator<T>>
|
||||
concurrent_node_set(std::initializer_list<T>, typename xref:#concurrent_node_set_deduction_guides[__see below__]::size_type = xref:#concurrent_node_set_deduction_guides[__see below__],
|
||||
@@ -277,6 +310,26 @@ namespace unordered {
|
||||
-> concurrent_node_set<xref:#concurrent_node_set_iter_value_type[__iter-value-type__]<InputIterator>, Hash,
|
||||
std::equal_to<xref:#concurrent_node_set_iter_value_type[__iter-value-type__]<InputIterator>>, Allocator>;
|
||||
|
||||
template<xref:#concurrent_node_set_convertible_to_from_range_t[__convertible-to-from-range_t__] FromRangeT,
|
||||
std::ranges::input_range R, class Allocator>
|
||||
concurrent_node_set(FromRangeT&&, R&&, typename xref:#concurrent_node_set_deduction_guides[__see below__]::size_type, Allocator)
|
||||
-> concurrent_node_set<std::ranges::range_value_t<R>,
|
||||
boost::hash<std::ranges::range_value_t<R>>,
|
||||
std::equal_to<std::ranges::range_value_t<R>>, Allocator>;
|
||||
|
||||
template<xref:#concurrent_node_set_convertible_to_from_range_t[__convertible-to-from-range_t__] FromRangeT,
|
||||
std::ranges::input_range R, class Allocator>
|
||||
concurrent_node_set(FromRangeT&&, R&&, Allocator)
|
||||
-> concurrent_node_set<std::ranges::range_value_t<R>,
|
||||
boost::hash<std::ranges::range_value_t<R>>,
|
||||
std::equal_to<std::ranges::range_value_t<R>>, Allocator>;
|
||||
|
||||
template<xref:#concurrent_node_set_convertible_to_from_range_t[__convertible-to-from-range_t__] FromRangeT,
|
||||
std::ranges::input_range R, class Hash, class Allocator>
|
||||
concurrent_node_set(FromRangeT&&, R&&, typename xref:#concurrent_node_set_deduction_guides[__see below__]::size_type, Hash,
|
||||
Allocator)
|
||||
-> concurrent_node_set<std::ranges::range_value_t<R>,
|
||||
Hash, std::equal_to<std::ranges::range_value_t<R>>, Allocator>;
|
||||
template<class T, class Allocator>
|
||||
concurrent_node_set(std::initializer_list<T>, typename xref:#concurrent_node_set_deduction_guides[__see below__]::size_type, Allocator)
|
||||
-> concurrent_node_set<T, boost::hash<T>, std::equal_to<T>, Allocator>;
|
||||
@@ -441,6 +494,15 @@ Chunk size internally used in xref:concurrent_node_set_bulk_visit[bulk visit] op
|
||||
|
||||
=== Constructors
|
||||
|
||||
==== __container-compatible-range__
|
||||
[listings,subs="+macros,+quotes"]
|
||||
-----
|
||||
template<class R, class T>
|
||||
concept container_compatible_range =
|
||||
std::ranges::input_range<R> &&
|
||||
std::convertible_to<std::ranges::range_reference_t<R>, T>; // exposition only
|
||||
-----
|
||||
|
||||
==== Default Constructor
|
||||
```c++
|
||||
concurrent_node_set();
|
||||
@@ -588,6 +650,27 @@ Complexity:;; O(`bucket_count()`)
|
||||
|
||||
---
|
||||
|
||||
==== Range Constructor
|
||||
[source,c++,subs="+macros,+quotes"]
|
||||
----
|
||||
template<class FromRangeT, xref:#concurrent_node_set_container_compatible_range[__container-compatible-range__]<value_type> R>
|
||||
concurrent_node_set(FromRangeT&&, R&& rg,
|
||||
size_type n = _implementation-defined_,
|
||||
const hasher& hf = hasher(),
|
||||
const key_equal& eql = key_equal(),
|
||||
const allocator_type& a = allocator_type());
|
||||
----
|
||||
|
||||
Constructs an empty table with at least `n` buckets, using `hf` as the hash function, `eql` as the key equality predicate and `a` as the allocator, and inserts the elements from `rg` into it.
|
||||
|
||||
Only participates in overload resolution if `FromRangeT` is convertible to `std::from_range_t` or `boost::concurrent::from_range_t`.
|
||||
|
||||
|
||||
[horizontal]
|
||||
Requires:;; If the defaults are used, `hasher`, `key_equal` and `allocator_type` need to be https://en.cppreference.com/w/cpp/named_req/DefaultConstructible[DefaultConstructible^].
|
||||
|
||||
---
|
||||
|
||||
==== Initializer List Constructor
|
||||
[source,c++,subs="+quotes"]
|
||||
----
|
||||
@@ -660,6 +743,58 @@ Requires:;; `key_equal` needs to be https://en.cppreference.com/w/cpp/named_req/
|
||||
|
||||
---
|
||||
|
||||
==== Range Constructor with Allocator
|
||||
|
||||
[source,c++,subs="+macros,+quotes"]
|
||||
----
|
||||
template<class FromRangeT, xref:#concurrent_node_set_container_compatible_range[__container-compatible-range__]<value_type> R>
|
||||
concurrent_node_set(FromRangeT&&, R&& rg, const allocator_type& a);
|
||||
----
|
||||
|
||||
Constructs an empty table using `a` and default hash function and key equality predicate, and inserts the elements from `rg` into it.
|
||||
|
||||
Only participates in overload resolution if `FromRangeT` is convertible to `std::from_range_t` or `boost::concurrent::from_range_t`.
|
||||
|
||||
[horizontal]
|
||||
Requires:;; `hasher` and `key_equal` need to be https://en.cppreference.com/w/cpp/named_req/DefaultConstructible[DefaultConstructible^].
|
||||
|
||||
---
|
||||
|
||||
==== Range Constructor with Bucket Count and Allocator
|
||||
|
||||
[source,c++,subs="+macros,+quotes"]
|
||||
----
|
||||
template<class FromRangeT, xref:#concurrent_node_set_container_compatible_range[__container-compatible-range__]<value_type> R>
|
||||
concurrent_node_set(FromRangeT&&, R&& rg, size_type n, const allocator_type& a);
|
||||
----
|
||||
|
||||
Constructs an empty table with at least `n` buckets, using `a` and default hash function and key equality predicate, and inserts the elements from `rg` into it.
|
||||
|
||||
Only participates in overload resolution if `FromRangeT` is convertible to `std::from_range_t` or `boost::concurrent::from_range_t`.
|
||||
|
||||
[horizontal]
|
||||
Requires:;; `hasher` and `key_equal` need to be https://en.cppreference.com/w/cpp/named_req/DefaultConstructible[DefaultConstructible^].
|
||||
|
||||
---
|
||||
|
||||
==== Range Constructor with Bucket Count and Hasher and Allocator
|
||||
|
||||
[source,c++,subs="+macros,+quotes"]
|
||||
----
|
||||
template<class FromRangeT, xref:#concurrent_node_set_container_compatible_range[__container-compatible-range__]<value_type> R>
|
||||
concurrent_node_set(FromRangeT&&, R&& rg, size_type n, const hasher& hf,
|
||||
const allocator_type& a);
|
||||
----
|
||||
|
||||
Constructs an empty table with at least `n` buckets, using `hf` as the hash function, `a` as the allocator and default key equality predicate, and inserts the elements from `rg` into it.
|
||||
|
||||
Only participates in overload resolution if `FromRangeT` is convertible to `std::from_range_t` or `boost::concurrent::from_range_t`.
|
||||
|
||||
[horizontal]
|
||||
Requires:;; `key_equal` needs to be https://en.cppreference.com/w/cpp/named_req/DefaultConstructible[DefaultConstructible^].
|
||||
|
||||
---
|
||||
|
||||
==== initializer_list Constructor with Allocator
|
||||
|
||||
```c++
|
||||
@@ -1008,6 +1143,25 @@ Returns:;; The number of elements inserted.
|
||||
|
||||
---
|
||||
|
||||
==== Insert Range
|
||||
[source,c++,subs="+macros,+quotes"]
|
||||
----
|
||||
template<xref:#concurrent_node_set_container_compatible_range[__container-compatible-range__]<value_type> R>
|
||||
void insert_range(R&& rg);
|
||||
----
|
||||
|
||||
Equivalent to
|
||||
[listing,subs="+macros,+quotes"]
|
||||
-----
|
||||
for(auto&& x: rg) this->xref:#concurrent_node_set_emplace[emplace](std::forward<decltype(x)>(x));
|
||||
-----
|
||||
|
||||
[horizontal]
|
||||
Returns:;; The number of elements inserted.
|
||||
|
||||
---
|
||||
|
||||
|
||||
==== Insert Initializer List
|
||||
```c++
|
||||
size_type insert(std::initializer_list<value_type> il);
|
||||
@@ -1128,6 +1282,27 @@ Returns:;; The number of elements inserted.
|
||||
|
||||
---
|
||||
|
||||
==== Insert Range or Visit
|
||||
[source,c++,subs="+macros,+quotes"]
|
||||
----
|
||||
template<xref:#concurrent_node_set_container_compatible_range[__container-compatible-range__]<value_type> R, class F>
|
||||
size_type insert_range_or_visit(R&& rg, F f);
|
||||
template<xref:#concurrent_node_set_container_compatible_range[__container-compatible-range__]<value_type> R, class F>
|
||||
size_type insert_range_or_visit(R&& rg, F f);
|
||||
----
|
||||
|
||||
Equivalent to
|
||||
[listing,subs="+macros,+quotes"]
|
||||
-----
|
||||
for(auto&& x: rg)
|
||||
this->xref:#concurrent_node_set_emplace_or_cvisit[emplace_or_[c\]visit](std::forward<decltype(x)>(x), std::ref(f));
|
||||
-----
|
||||
|
||||
[horizontal]
|
||||
Returns:;; The number of elements inserted.
|
||||
|
||||
---
|
||||
|
||||
==== Insert Initializer List or Visit
|
||||
```c++
|
||||
template<class F> size_type insert_or_visit(std::initializer_list<value_type> il, F f);
|
||||
@@ -1257,6 +1432,28 @@ Returns:;; The number of elements inserted.
|
||||
|
||||
---
|
||||
|
||||
==== Insert Range and Visit
|
||||
[source,c++,subs="+macros,+quotes"]
|
||||
----
|
||||
template<xref:#concurrent_node_set_container_compatible_range[__container-compatible-range__]<value_type> R, class F1, class F2>
|
||||
size_type insert_range_and_visit(R&& rg, F1 f1, F2 f2);
|
||||
template<xref:#concurrent_node_set_container_compatible_range[__container-compatible-range__]<value_type> R, class F1, class F2>
|
||||
size_type insert_range_and_cvisit(R&& rg, F1 f1, F2 f2);
|
||||
----
|
||||
|
||||
Equivalent to
|
||||
[listing,subs="+macros,+quotes"]
|
||||
-----
|
||||
for(auto&& x: rg)
|
||||
this->xref:#concurrent_node_set_emplace_and_cvisit[emplace_and_[c\]visit](
|
||||
std::forward<decltype(x)>(x), std::ref(f1), std::ref(f2));
|
||||
-----
|
||||
|
||||
[horizontal]
|
||||
Returns:;; The number of elements inserted.
|
||||
|
||||
---
|
||||
|
||||
==== Insert Initializer List and Visit
|
||||
```c++
|
||||
template<class F1, class F2>
|
||||
@@ -1639,6 +1836,16 @@ template<class InputIterator>
|
||||
typename std::iterator_traits<InputIterator>::value_type; // exposition only
|
||||
-----
|
||||
|
||||
==== __convertible-to-from-range_t__
|
||||
[listings,subs="+macros,+quotes"]
|
||||
-----
|
||||
template<typename FromRangeT>
|
||||
concept __convertible-to-from_range_t__ =
|
||||
// first clause not present if std::from_range_t does not exist
|
||||
std::is_convertible_v<FromRangeT, std::from_range_t> ||
|
||||
std::is_convertible_v<FromRangeT, boost::unordered::from_range_t>; // exposition only
|
||||
-----
|
||||
|
||||
=== Equality Comparisons
|
||||
|
||||
==== operator==
|
||||
|
||||
@@ -19,6 +19,10 @@ namespace unordered {
|
||||
class Allocator = std::allocator<std::pair<const Key, T>>>
|
||||
class xref:reference/concurrent_flat_map.adoc#concurrent_flat_map[concurrent_flat_map];
|
||||
|
||||
// Tag for construction from ranges (pass:[C++20] and up)
|
||||
struct from_range_t { explicit from_range_t() = default; };
|
||||
inline constexpr from_range_t from_range{};
|
||||
|
||||
// Equality Comparisons
|
||||
template<class Key, class T, class Hash, class Pred, class Alloc>
|
||||
bool xref:reference/concurrent_flat_map.adoc#concurrent_flat_map_operator[operator++==++](const concurrent_flat_map<Key, T, Hash, Pred, Alloc>& x,
|
||||
@@ -39,7 +43,7 @@ namespace unordered {
|
||||
typename concurrent_flat_map<K, T, H, P, A>::size_type
|
||||
xref:reference/concurrent_flat_map.adoc#concurrent_flat_map_erase_if[erase_if](concurrent_flat_map<K, T, H, P, A>& c, Predicate pred);
|
||||
|
||||
// Pmr aliases (C++17 and up)
|
||||
// Pmr aliases (pass:[C++17] and up)
|
||||
namespace pmr {
|
||||
template<class Key,
|
||||
class T,
|
||||
|
||||
@@ -18,6 +18,10 @@ namespace unordered {
|
||||
class Allocator = std::allocator<Key>>
|
||||
class xref:reference/concurrent_flat_set.adoc#concurrent_flat_set[concurrent_flat_set];
|
||||
|
||||
// Tag for construction from ranges (pass:[C++20] and up)
|
||||
struct from_range_t { explicit from_range_t() = default; };
|
||||
inline constexpr from_range_t from_range{};
|
||||
|
||||
// Equality Comparisons
|
||||
template<class Key, class Hash, class Pred, class Alloc>
|
||||
bool xref:reference/concurrent_flat_set.adoc#concurrent_flat_set_operator[operator++==++](const concurrent_flat_set<Key, Hash, Pred, Alloc>& x,
|
||||
@@ -38,7 +42,7 @@ namespace unordered {
|
||||
typename concurrent_flat_set<K, H, P, A>::size_type
|
||||
xref:reference/concurrent_flat_set.adoc#concurrent_flat_set_erase_if[erase_if](concurrent_flat_set<K, H, P, A>& c, Predicate pred);
|
||||
|
||||
// Pmr aliases (C++17 and up)
|
||||
// Pmr aliases (pass:[C++17] and up)
|
||||
namespace pmr {
|
||||
template<class Key,
|
||||
class Hash = boost::hash<Key>,
|
||||
|
||||
@@ -19,6 +19,10 @@ namespace unordered {
|
||||
class Allocator = std::allocator<std::pair<const Key, T>>>
|
||||
class xref:reference/concurrent_node_map.adoc#concurrent_node_map[concurrent_node_map];
|
||||
|
||||
// Tag for construction from ranges (pass:[C++20] and up)
|
||||
struct from_range_t { explicit from_range_t() = default; };
|
||||
inline constexpr from_range_t from_range{};
|
||||
|
||||
// Equality Comparisons
|
||||
template<class Key, class T, class Hash, class Pred, class Alloc>
|
||||
bool xref:reference/concurrent_node_map.adoc#concurrent_node_map_operator[operator++==++](const concurrent_node_map<Key, T, Hash, Pred, Alloc>& x,
|
||||
@@ -39,7 +43,7 @@ namespace unordered {
|
||||
typename concurrent_node_map<K, T, H, P, A>::size_type
|
||||
xref:reference/concurrent_node_map.adoc#concurrent_node_map_erase_if[erase_if](concurrent_node_map<K, T, H, P, A>& c, Predicate pred);
|
||||
|
||||
// Pmr aliases (C++17 and up)
|
||||
// Pmr aliases (pass:[C++17] and up)
|
||||
namespace pmr {
|
||||
template<class Key,
|
||||
class T,
|
||||
|
||||
@@ -18,6 +18,10 @@ namespace unordered {
|
||||
class Allocator = std::allocator<Key>>
|
||||
class xref:reference/concurrent_node_set.adoc#concurrent_node_set[concurrent_node_set];
|
||||
|
||||
// Tag for construction from ranges (pass:[C++20] and up)
|
||||
struct from_range_t { explicit from_range_t() = default; };
|
||||
inline constexpr from_range_t from_range{};
|
||||
|
||||
// Equality Comparisons
|
||||
template<class Key, class Hash, class Pred, class Alloc>
|
||||
bool xref:reference/concurrent_node_set.adoc#concurrent_node_set_operator[operator++==++](const concurrent_node_set<Key, Hash, Pred, Alloc>& x,
|
||||
@@ -38,7 +42,7 @@ namespace unordered {
|
||||
typename concurrent_node_set<K, H, P, A>::size_type
|
||||
xref:reference/concurrent_node_set.adoc#concurrent_node_set_erase_if[erase_if](concurrent_node_set<K, H, P, A>& c, Predicate pred);
|
||||
|
||||
// Pmr aliases (C++17 and up)
|
||||
// Pmr aliases (pass:[C++17] and up)
|
||||
namespace pmr {
|
||||
template<class Key,
|
||||
class Hash = boost::hash<Key>,
|
||||
|
||||
@@ -19,6 +19,10 @@ namespace unordered {
|
||||
class Allocator = std::allocator<std::pair<const Key, T>>>
|
||||
class xref:reference/unordered_flat_map.adoc#unordered_flat_map[unordered_flat_map];
|
||||
|
||||
// Tag for construction from ranges (pass:[C++20] and up)
|
||||
struct from_range_t { explicit from_range_t() = default; };
|
||||
inline constexpr from_range_t from_range{};
|
||||
|
||||
// Equality Comparisons
|
||||
template<class Key, class T, class Hash, class Pred, class Alloc>
|
||||
bool xref:reference/unordered_flat_map.adoc#unordered_flat_map_operator_2[operator++==++](const unordered_flat_map<Key, T, Hash, Pred, Alloc>& x,
|
||||
@@ -39,7 +43,7 @@ namespace unordered {
|
||||
typename unordered_flat_map<K, T, H, P, A>::size_type
|
||||
xref:reference/unordered_flat_map.adoc#unordered_flat_map_erase_if[erase_if](unordered_flat_map<K, T, H, P, A>& c, Predicate pred);
|
||||
|
||||
// Pmr aliases (C++17 and up)
|
||||
// Pmr aliases (pass:[C++17] and up)
|
||||
namespace pmr {
|
||||
template<class Key,
|
||||
class T,
|
||||
|
||||
@@ -18,6 +18,10 @@ namespace unordered {
|
||||
class Allocator = std::allocator<Key>>
|
||||
class xref:reference/unordered_flat_set.adoc#unordered_flat_set[unordered_flat_set];
|
||||
|
||||
// Tag for construction from ranges (pass:[C++20] and up)
|
||||
struct from_range_t { explicit from_range_t() = default; };
|
||||
inline constexpr from_range_t from_range{};
|
||||
|
||||
// Equality Comparisons
|
||||
template<class Key, class Hash, class Pred, class Alloc>
|
||||
bool xref:reference/unordered_flat_set.adoc#unordered_flat_set_operator[operator++==++](const unordered_flat_set<Key, Hash, Pred, Alloc>& x,
|
||||
@@ -38,7 +42,7 @@ namespace unordered {
|
||||
typename unordered_flat_set<K, H, P, A>::size_type
|
||||
xref:reference/unordered_flat_set.adoc#unordered_flat_set_erase_if[erase_if](unordered_flat_set<K, H, P, A>& c, Predicate pred);
|
||||
|
||||
// Pmr aliases (C++17 and up)
|
||||
// Pmr aliases (pass:[C++17] and up)
|
||||
namespace pmr {
|
||||
template<class Key,
|
||||
class Hash = boost::hash<Key>,
|
||||
|
||||
@@ -20,6 +20,10 @@ namespace unordered {
|
||||
class Allocator = std::allocator<std::pair<const Key, T>>>
|
||||
class xref:reference/unordered_map.adoc#unordered_map[unordered_map];
|
||||
|
||||
// Tag for construction from ranges (pass:[C++20] and up)
|
||||
struct from_range_t { explicit from_range_t() = default; };
|
||||
inline constexpr from_range_t from_range{};
|
||||
|
||||
// Equality Comparisons
|
||||
template<class Key, class T, class Hash, class Pred, class Alloc>
|
||||
bool xref:reference/unordered_map.adoc#unordered_map_operator_2[operator++==++](const unordered_map<Key, T, Hash, Pred, Alloc>& x,
|
||||
@@ -67,7 +71,7 @@ namespace unordered {
|
||||
typename unordered_multimap<K, T, H, P, A>::size_type
|
||||
xref:reference/unordered_multimap.adoc#unordered_multimap_erase_if[erase_if](unordered_multimap<K, T, H, P, A>& c, Predicate pred);
|
||||
|
||||
// Pmr aliases (C++17 and up)
|
||||
// Pmr aliases (pass:[C++17] and up)
|
||||
namespace pmr {
|
||||
template<class Key,
|
||||
class T,
|
||||
|
||||
@@ -19,6 +19,10 @@ namespace unordered {
|
||||
class Allocator = std::allocator<std::pair<const Key, T>>>
|
||||
class xref:reference/unordered_node_map.adoc#unordered_node_map[unordered_node_map];
|
||||
|
||||
// Tag for construction from ranges (pass:[C++20] and up)
|
||||
struct from_range_t { explicit from_range_t() = default; };
|
||||
inline constexpr from_range_t from_range{};
|
||||
|
||||
// Equality Comparisons
|
||||
template<class Key, class T, class Hash, class Pred, class Alloc>
|
||||
bool xref:reference/unordered_node_map.adoc#unordered_node_map_operator_2[operator++==++](const unordered_node_map<Key, T, Hash, Pred, Alloc>& x,
|
||||
@@ -39,7 +43,7 @@ namespace unordered {
|
||||
typename unordered_node_map<K, T, H, P, A>::size_type
|
||||
xref:reference/unordered_node_map.adoc#unordered_node_map_erase_if[erase_if](unordered_node_map<K, T, H, P, A>& c, Predicate pred);
|
||||
|
||||
// Pmr aliases (C++17 and up)
|
||||
// Pmr aliases (pass:[C++17] and up)
|
||||
namespace pmr {
|
||||
template<class Key,
|
||||
class T,
|
||||
|
||||
@@ -18,6 +18,10 @@ namespace unordered {
|
||||
class Allocator = std::allocator<Key>>
|
||||
class xref:reference/unordered_node_set.adoc#unordered_node_set[unordered_node_set];
|
||||
|
||||
// Tag for construction from ranges (pass:[C++20] and up)
|
||||
struct from_range_t { explicit from_range_t() = default; };
|
||||
inline constexpr from_range_t from_range{};
|
||||
|
||||
// Equality Comparisons
|
||||
template<class Key, class Hash, class Pred, class Alloc>
|
||||
bool xref:reference/unordered_node_set.adoc#unordered_node_set_operator[operator++==++](const unordered_node_set<Key, Hash, Pred, Alloc>& x,
|
||||
@@ -38,7 +42,7 @@ namespace unordered {
|
||||
typename unordered_node_set<K, H, P, A>::size_type
|
||||
xref:reference/unordered_node_set.adoc#unordered_node_set_erase_if[erase_if](unordered_node_set<K, H, P, A>& c, Predicate pred);
|
||||
|
||||
// Pmr aliases (C++17 and up)
|
||||
// Pmr aliases (pass:[C++17] and up)
|
||||
namespace pmr {
|
||||
template<class Key,
|
||||
class Hash = boost::hash<Key>,
|
||||
|
||||
@@ -19,6 +19,10 @@ namespace unordered {
|
||||
class Allocator = std::allocator<Key>>
|
||||
class xref:reference/unordered_set.adoc#unordered_set[unordered_set];
|
||||
|
||||
// Tag for construction from ranges (pass:[C++20] and up)
|
||||
struct from_range_t { explicit from_range_t() = default; };
|
||||
inline constexpr from_range_t from_range{};
|
||||
|
||||
// Equality Comparisons
|
||||
template<class Key, class Hash, class Pred, class Alloc>
|
||||
bool xref:reference/unordered_set.adoc#unordered_set_operator[operator++==++](const unordered_set<Key, Hash, Pred, Alloc>& x,
|
||||
@@ -65,7 +69,7 @@ namespace unordered {
|
||||
typename unordered_multiset<K, H, P, A>::size_type
|
||||
xref:reference/unordered_multiset.adoc#unordered_multiset_erase_if[erase_if](unordered_multiset<K, H, P, A>& c, Predicate pred);
|
||||
|
||||
// Pmr aliases (C++17 and up)
|
||||
// Pmr aliases (pass:[C++17] and up)
|
||||
namespace pmr {
|
||||
template<class Key,
|
||||
class Hash = boost::hash<Key>,
|
||||
|
||||
@@ -82,6 +82,12 @@ namespace unordered {
|
||||
xref:#unordered_flat_map_copy_constructor_with_allocator[unordered_flat_map](const unordered_flat_map& other, const Allocator& a);
|
||||
xref:#unordered_flat_map_move_constructor_with_allocator[unordered_flat_map](unordered_flat_map&& other, const Allocator& a);
|
||||
xref:#unordered_flat_map_move_constructor_from_concurrent_flat_map[unordered_flat_map](concurrent_flat_map<Key, T, Hash, Pred, Allocator>&& other);
|
||||
template<class FromRangeT, xref:#unordered_flat_map_container_compatible_range[__container-compatible-range__]<value_type> R>
|
||||
xref:#unordered_flat_map_range_constructor[unordered_flat_map](FromRangeT&&, R&& rg,
|
||||
size_type n = _implementation-defined_,
|
||||
const hasher& hf = hasher(),
|
||||
const key_equal& eql = key_equal(),
|
||||
const allocator_type& a = allocator_type());
|
||||
xref:#unordered_flat_map_initializer_list_constructor[unordered_flat_map](std::initializer_list<value_type> il,
|
||||
size_type n = _implementation-defined_
|
||||
const hasher& hf = hasher(),
|
||||
@@ -94,6 +100,13 @@ namespace unordered {
|
||||
template<class InputIterator>
|
||||
xref:#unordered_flat_map_iterator_range_constructor_with_bucket_count_and_hasher[unordered_flat_map](InputIterator f, InputIterator l, size_type n, const hasher& hf,
|
||||
const allocator_type& a);
|
||||
template<class FromRangeT, xref:#unordered_flat_map_container_compatible_range[__container-compatible-range__]<value_type> R>
|
||||
xref:#unordered_flat_map_range_constructor_with_allocator[unordered_flat_map](FromRangeT&&, R&& rg, const allocator_type& a);
|
||||
template<class FromRangeT, xref:#unordered_flat_map_container_compatible_range[__container-compatible-range__]<value_type> R>
|
||||
xref:#unordered_flat_map_range_constructor_with_bucket_count_and_allocator[unordered_flat_map](FromRangeT&&, R&& rg, size_type n, const allocator_type& a);
|
||||
template<class FromRangeT, xref:#unordered_flat_map_container_compatible_range[__container-compatible-range__]<value_type> R>
|
||||
xref:#unordered_flat_map_range_constructor_with_bucket_count_and_hasher_and_allocator[unordered_flat_map](FromRangeT&&, R&& rg, size_type n, const hasher& hf,
|
||||
const allocator_type& a);
|
||||
xref:#unordered_flat_map_initializer_list_constructor_with_allocator[unordered_flat_map](std::initializer_list<value_type> il, const allocator_type& a);
|
||||
xref:#unordered_flat_map_initializer_list_constructor_with_bucket_count_and_allocator[unordered_flat_map](std::initializer_list<value_type> il, size_type n,
|
||||
const allocator_type& a);
|
||||
@@ -133,6 +146,8 @@ namespace unordered {
|
||||
iterator xref:#unordered_flat_map_move_insert_with_hint[insert](const_iterator hint, value_type&& obj);
|
||||
iterator xref:#unordered_flat_map_copy_insert_with_hint[insert](const_iterator hint, init_type&& obj);
|
||||
template<class InputIterator> void xref:#unordered_flat_map_insert_iterator_range[insert](InputIterator first, InputIterator last);
|
||||
template<xref:#unordered_flat_map_container_compatible_range[__container-compatible-range__]<value_type> R>
|
||||
void xref:#unordered_flat_map_insert_range[insert_range](R&& rg);
|
||||
void xref:#unordered_flat_map_insert_initializer_list[insert](std::initializer_list<value_type>);
|
||||
|
||||
template<class... Args>
|
||||
@@ -235,6 +250,17 @@ namespace unordered {
|
||||
-> unordered_flat_map<xref:#unordered_flat_map_iter_key_type[__iter-key-type__]<InputIterator>, xref:#unordered_flat_map_iter_mapped_type[__iter-mapped-type__]<InputIterator>, Hash,
|
||||
Pred, Allocator>;
|
||||
|
||||
template<xref:#unordered_flat_map_convertible_to_from_range_t[__convertible-to-from-range_t__] FromRangeT,
|
||||
std::ranges::input_range R,
|
||||
class Hash = boost::hash<xref:#unordered_flat_map_range_key_type[__range-key-type__]<R>>,
|
||||
class Pred = std::equal_to<xref:#unordered_flat_map_range_key_type[__range-key-type__]<R>>,
|
||||
class Allocator = std::allocator<xref:#unordered_flat_map_range_to_alloc_type[__range-to-alloc-type__]<R>>>
|
||||
unordered_flat_map(FromRangeT&&, R&&,
|
||||
typename xref:#unordered_flat_map_deduction_guides[__see below__]::size_type = xref:#unordered_flat_map_deduction_guides[__see below__], Hash = Hash(),
|
||||
Pred = Pred(), Allocator = Allocator())
|
||||
-> unordered_flat_map<xref:#unordered_flat_map_range_key_type[__range-key-type__]<R>, xref:#unordered_flat_map_range_mapped_type[__range-mapped-type__]<R>,
|
||||
Hash, Pred,Allocator>;
|
||||
|
||||
template<class Key, class T, class Hash = boost::hash<Key>,
|
||||
class Pred = std::equal_to<Key>,
|
||||
class Allocator = std::allocator<std::pair<const Key, T>>>
|
||||
@@ -261,6 +287,27 @@ namespace unordered {
|
||||
-> unordered_flat_map<xref:#unordered_flat_map_iter_key_type[__iter-key-type__]<InputIterator>, xref:#unordered_flat_map_iter_mapped_type[__iter-mapped-type__]<InputIterator>, Hash,
|
||||
std::equal_to<xref:#unordered_flat_map_iter_key_type[__iter-key-type__]<InputIterator>>, Allocator>;
|
||||
|
||||
template<xref:#unordered_flat_map_convertible_to_from_range_t[__convertible-to-from-range_t__] FromRangeT,
|
||||
std::ranges::input_range R, class Allocator>
|
||||
unordered_flat_map(FromRangeT&&, R&&, typename xref:#unordered_flat_map_deduction_guides[__see below__]::size_type, Allocator)
|
||||
-> unordered_flat_map<xref:#unordered_flat_map_range_key_type[__range-key-type__]<R>, xref:#unordered_flat_map_range_mapped_type[__range-mapped-type__]<R>,
|
||||
boost::hash<xref:#unordered_flat_map_range_key_type[__range-key-type__]<R>>,
|
||||
std::equal_to<xref:#unordered_flat_map_range_key_type[__range-key-type__]<R>>, Allocator>;
|
||||
|
||||
template<xref:#unordered_flat_map_convertible_to_from_range_t[__convertible-to-from-range_t__] FromRangeT,
|
||||
std::ranges::input_range R, class Allocator>
|
||||
unordered_flat_map(FromRangeT&&, R&&, Allocator)
|
||||
-> unordered_flat_map<xref:#unordered_flat_map_range_key_type[__range-key-type__]<R>, xref:#unordered_flat_map_range_mapped_type[__range-mapped-type__]<R>,
|
||||
boost::hash<xref:#unordered_flat_map_range_key_type[__range-key-type__]<R>>,
|
||||
std::equal_to<xref:#unordered_flat_map_range_key_type[__range-key-type__]<R>>, Allocator>;
|
||||
|
||||
template<xref:#unordered_flat_map_convertible_to_from_range_t[__convertible-to-from-range_t__] FromRangeT,
|
||||
std::ranges::input_range R, class Hash, class Allocator>
|
||||
unordered_flat_map(FromRangeT&&, R&&, typename xref:#unordered_flat_map_deduction_guides[__see below__]::size_type, Hash,
|
||||
Allocator)
|
||||
-> unordered_flat_map<xref:#unordered_flat_map_range_key_type[__range-key-type__]<R>, xref:#unordered_flat_map_range_mapped_type[__range-mapped-type__]<R>,
|
||||
Hash, std::equal_to<xref:#unordered_flat_map_range_key_type[__range-key-type__]<R>>, Allocator>;
|
||||
|
||||
template<class Key, class T, class Allocator>
|
||||
unordered_flat_map(std::initializer_list<std::pair<Key, T>>, typename xref:#unordered_flat_map_deduction_guides[__see below__]::size_type,
|
||||
Allocator)
|
||||
@@ -358,6 +405,15 @@ The iterator category is at least a forward iterator.
|
||||
|
||||
=== Constructors
|
||||
|
||||
==== __container-compatible-range__
|
||||
[listings,subs="+macros,+quotes"]
|
||||
-----
|
||||
template<class R, class T>
|
||||
concept container_compatible_range =
|
||||
std::ranges::input_range<R> &&
|
||||
std::convertible_to<std::ranges::range_reference_t<R>, T>; // exposition only
|
||||
-----
|
||||
|
||||
==== Default Constructor
|
||||
```c++
|
||||
unordered_flat_map();
|
||||
@@ -496,6 +552,27 @@ Concurrency:;; Blocking on `other`.
|
||||
|
||||
---
|
||||
|
||||
==== Range Constructor
|
||||
[source,c++,subs="+macros,+quotes"]
|
||||
----
|
||||
template<class FromRangeT, xref:#unordered_flat_map_container_compatible_range[__container-compatible-range__]<value_type> R>
|
||||
unordered_flat_map(FromRangeT&&, R&& rg,
|
||||
size_type n = _implementation-defined_,
|
||||
const hasher& hf = hasher(),
|
||||
const key_equal& eql = key_equal(),
|
||||
const allocator_type& a = allocator_type());
|
||||
----
|
||||
|
||||
Constructs an empty container with at least `n` buckets, using `hf` as the hash function, `eql` as the key equality predicate and `a` as the allocator, and inserts the elements from `rg` into it.
|
||||
|
||||
Only participates in overload resolution if `FromRangeT` is convertible to `std::from_range_t` or `boost::unordered::from_range_t`.
|
||||
|
||||
|
||||
[horizontal]
|
||||
Requires:;; If the defaults are used, `hasher`, `key_equal` and `allocator_type` need to be https://en.cppreference.com/w/cpp/named_req/DefaultConstructible[DefaultConstructible^].
|
||||
|
||||
---
|
||||
|
||||
==== Initializer List Constructor
|
||||
[source,c++,subs="+quotes"]
|
||||
----
|
||||
@@ -506,7 +583,7 @@ unordered_flat_map(std::initializer_list<value_type> il,
|
||||
const allocator_type& a = allocator_type());
|
||||
----
|
||||
|
||||
Constructs an empty container with at least `n` buckets, using `hf` as the hash function, `eql` as the key equality predicate and `a`, and inserts the elements from `il` into it.
|
||||
Constructs an empty container with at least `n` buckets, using `hf` as the hash function, `eql` as the key equality predicate and `a` as the allocator, and inserts the elements from `il` into it.
|
||||
|
||||
[horizontal]
|
||||
Requires:;; If the defaults are used, `hasher`, `key_equal` and `allocator_type` need to be https://en.cppreference.com/w/cpp/named_req/DefaultConstructible[DefaultConstructible^].
|
||||
@@ -568,6 +645,58 @@ Requires:;; `key_equal` needs to be https://en.cppreference.com/w/cpp/named_req/
|
||||
|
||||
---
|
||||
|
||||
==== Range Constructor with Allocator
|
||||
|
||||
[source,c++,subs="+macros,+quotes"]
|
||||
----
|
||||
template<class FromRangeT, xref:#unordered_flat_map_container_compatible_range[__container-compatible-range__]<value_type> R>
|
||||
unordered_flat_map(FromRangeT&&, R&& rg, const allocator_type& a);
|
||||
----
|
||||
|
||||
Constructs an empty container using `a` and default hash function and key equality predicate, and inserts the elements from `rg` into it.
|
||||
|
||||
Only participates in overload resolution if `FromRangeT` is convertible to `std::from_range_t` or `boost::unordered::from_range_t`.
|
||||
|
||||
[horizontal]
|
||||
Requires:;; `hasher` and `key_equal` need to be https://en.cppreference.com/w/cpp/named_req/DefaultConstructible[DefaultConstructible^].
|
||||
|
||||
---
|
||||
|
||||
==== Range Constructor with Bucket Count and Allocator
|
||||
|
||||
[source,c++,subs="+macros,+quotes"]
|
||||
----
|
||||
template<class FromRangeT, xref:#unordered_flat_map_container_compatible_range[__container-compatible-range__]<value_type> R>
|
||||
unordered_flat_map(FromRangeT&&, R&& rg, size_type n, const allocator_type& a);
|
||||
----
|
||||
|
||||
Constructs an empty container with at least `n` buckets, using `a` and default hash function and key equality predicate, and inserts the elements from `rg` into it.
|
||||
|
||||
Only participates in overload resolution if `FromRangeT` is convertible to `std::from_range_t` or `boost::unordered::from_range_t`.
|
||||
|
||||
[horizontal]
|
||||
Requires:;; `hasher` and `key_equal` need to be https://en.cppreference.com/w/cpp/named_req/DefaultConstructible[DefaultConstructible^].
|
||||
|
||||
---
|
||||
|
||||
==== Range Constructor with Bucket Count and Hasher and Allocator
|
||||
|
||||
[source,c++,subs="+macros,+quotes"]
|
||||
----
|
||||
template<class FromRangeT, xref:#unordered_flat_map_container_compatible_range[__container-compatible-range__]<value_type> R>
|
||||
unordered_flat_map(FromRangeT&&, R&& rg, size_type n, const hasher& hf,
|
||||
const allocator_type& a);
|
||||
----
|
||||
|
||||
Constructs an empty container with at least `n` buckets, using `hf` as the hash function, `a` as the allocator and default key equality predicate, and inserts the elements from `rg` into it.
|
||||
|
||||
Only participates in overload resolution if `FromRangeT` is convertible to `std::from_range_t` or `boost::unordered::from_range_t`.
|
||||
|
||||
[horizontal]
|
||||
Requires:;; `key_equal` needs to be https://en.cppreference.com/w/cpp/named_req/DefaultConstructible[DefaultConstructible^].
|
||||
|
||||
---
|
||||
|
||||
==== initializer_list Constructor with Allocator
|
||||
|
||||
```c++
|
||||
@@ -884,6 +1013,22 @@ Notes:;; Can invalidate iterators, pointers and references, but only if the inse
|
||||
|
||||
---
|
||||
|
||||
==== Insert Range
|
||||
[source,c++,subs="+macros,+quotes"]
|
||||
----
|
||||
template<xref:#unordered_flat_map_container_compatible_range[__container-compatible-range__]<value_type> R>
|
||||
void insert_range(R&& rg);
|
||||
----
|
||||
|
||||
Inserts a range of elements into the container. Elements are inserted if and only if there is no element in the container with an equivalent key.
|
||||
|
||||
[horizontal]
|
||||
Requires:;; `value_type` is https://en.cppreference.com/w/cpp/named_req/EmplaceConstructible[EmplaceConstructible^] into the container from `*std::ranges::begin(rg)`.
|
||||
Throws:;; When inserting a single element, if an exception is thrown by an operation other than a call to `hasher` the function has no effect.
|
||||
Notes:;; Can invalidate iterators, pointers and references, but only if the insert causes the load to be greater than the maximum load.
|
||||
|
||||
---
|
||||
|
||||
==== Insert Initializer List
|
||||
```c++
|
||||
void insert(std::initializer_list<value_type>);
|
||||
@@ -1445,6 +1590,42 @@ template<class InputIterator>
|
||||
std::tuple_element_t<1, xref:#unordered_flat_map_iter_value_type[__iter-value-type__]<InputIterator>>>; // exposition only
|
||||
-----
|
||||
|
||||
==== __convertible-to-from-range_t__
|
||||
[listings,subs="+macros,+quotes"]
|
||||
-----
|
||||
template<typename FromRangeT>
|
||||
concept __convertible-to-from_range_t__ =
|
||||
// first clause not present if std::from_range_t does not exist
|
||||
std::is_convertible_v<FromRangeT, std::from_range_t> ||
|
||||
std::is_convertible_v<FromRangeT, boost::unordered::from_range_t>; // exposition only
|
||||
-----
|
||||
|
||||
==== __range-key-type__
|
||||
[listings,subs="+macros,+quotes"]
|
||||
-----
|
||||
template<std::ranges::input_range R>
|
||||
using __range-key-type__ =
|
||||
std::remove_cvref_t<
|
||||
std::tuple_element_t<0, std::ranges::range_value_t<R>>>; // exposition only
|
||||
-----
|
||||
|
||||
==== __range-mapped-type__
|
||||
[listings,subs="+macros,+quotes"]
|
||||
-----
|
||||
template<std::ranges::input_range R>
|
||||
using __range-mapped-type__ =
|
||||
std::remove_cvref_t<
|
||||
std::tuple_element_t<1, std::ranges::range_value_t<R>>>; // exposition only
|
||||
-----
|
||||
|
||||
==== __range-to-alloc-type__
|
||||
[listings,subs="+macros,+quotes"]
|
||||
-----
|
||||
template<std::ranges::input_range R>
|
||||
using __range-to-alloc-type__ =
|
||||
std::pair<const xref:#unordered_flat_map_range_key_type[__range-key-type__]<R>, xref:#unordered_flat_map_range_mapped_type[__range-mapped-type__]<R>>; // exposition only
|
||||
-----
|
||||
|
||||
=== Equality Comparisons
|
||||
|
||||
==== operator==
|
||||
|
||||
@@ -76,6 +76,12 @@ namespace unordered {
|
||||
explicit xref:#unordered_flat_set_allocator_constructor[unordered_flat_set](const Allocator& a);
|
||||
xref:#unordered_flat_set_copy_constructor_with_allocator[unordered_flat_set](const unordered_flat_set& other, const Allocator& a);
|
||||
xref:#unordered_flat_set_move_constructor_from_concurrent_flat_set[unordered_flat_set](concurrent_flat_set<Key, Hash, Pred, Allocator>&& other);
|
||||
template<class FromRangeT, xref:#unordered_flat_set_container_compatible_range[__container-compatible-range__]<value_type> R>
|
||||
xref:#unordered_flat_set_range_constructor[unordered_flat_set](FromRangeT&&, R&& rg,
|
||||
size_type n = _implementation-defined_,
|
||||
const hasher& hf = hasher(),
|
||||
const key_equal& eql = key_equal(),
|
||||
const allocator_type& a = allocator_type());
|
||||
xref:#unordered_flat_set_initializer_list_constructor[unordered_flat_set](std::initializer_list<value_type> il,
|
||||
size_type n = _implementation-defined_
|
||||
const hasher& hf = hasher(),
|
||||
@@ -88,6 +94,13 @@ namespace unordered {
|
||||
template<class InputIterator>
|
||||
xref:#unordered_flat_set_iterator_range_constructor_with_bucket_count_and_hasher[unordered_flat_set](InputIterator f, InputIterator l, size_type n, const hasher& hf,
|
||||
const allocator_type& a);
|
||||
template<class FromRangeT, xref:#unordered_flat_set_container_compatible_range[__container-compatible-range__]<value_type> R>
|
||||
xref:#unordered_flat_set_range_constructor_with_allocator[unordered_flat_set](FromRangeT&&, R&& rg, const allocator_type& a);
|
||||
template<class FromRangeT, xref:#unordered_flat_set_container_compatible_range[__container-compatible-range__]<value_type> R>
|
||||
xref:#unordered_flat_set_range_constructor_with_bucket_count_and_allocator[unordered_flat_set](FromRangeT&&, R&& rg, size_type n, const allocator_type& a);
|
||||
template<class FromRangeT, xref:#unordered_flat_set_container_compatible_range[__container-compatible-range__]<value_type> R>
|
||||
xref:#unordered_flat_set_range_constructor_with_bucket_count_and_hasher_and_allocator[unordered_flat_set](FromRangeT&&, R&& rg, size_type n, const hasher& hf,
|
||||
const allocator_type& a);
|
||||
xref:#unordered_flat_set_initializer_list_constructor_with_allocator[unordered_flat_set](std::initializer_list<value_type> il, const allocator_type& a);
|
||||
xref:#unordered_flat_set_initializer_list_constructor_with_bucket_count_and_allocator[unordered_flat_set](std::initializer_list<value_type> il, size_type n,
|
||||
const allocator_type& a);
|
||||
@@ -125,6 +138,8 @@ namespace unordered {
|
||||
iterator xref:#unordered_flat_set_move_insert_with_hint[insert](const_iterator hint, value_type&& obj);
|
||||
template<class K> iterator xref:#unordered_flat_set_transparent_insert_with_hint[insert](const_iterator hint, K&& k);
|
||||
template<class InputIterator> void xref:#unordered_flat_set_insert_iterator_range[insert](InputIterator first, InputIterator last);
|
||||
template<xref:#unordered_flat_set_container_compatible_range[__container-compatible-range__]<value_type> R>
|
||||
void xref:#unordered_flat_set_insert_range[insert_range](R&& rg);
|
||||
void xref:#unordered_flat_set_insert_initializer_list[insert](std::initializer_list<value_type>);
|
||||
|
||||
_convertible-to-iterator_ xref:#unordered_flat_set_erase_by_position[erase](iterator position);
|
||||
@@ -192,6 +207,16 @@ namespace unordered {
|
||||
Hash = Hash(), Pred = Pred(), Allocator = Allocator())
|
||||
-> unordered_flat_set<xref:#unordered_flat_set_iter_value_type[__iter-value-type__]<InputIterator>, Hash, Pred, Allocator>;
|
||||
|
||||
template<xref:#unordered_flat_set_convertible_to_from_range_t[__convertible-to-from-range_t__] FromRangeT,
|
||||
std::ranges::input_range R,
|
||||
class Hash = boost::hash<std::ranges::range_value_t<R>>,
|
||||
class Pred = std::equal_to<std::ranges::range_value_t<R>>,
|
||||
class Allocator = std::allocator<std::ranges::range_value_t<R>>
|
||||
unordered_flat_set(FromRangeT&&, R&&,
|
||||
typename xref:#unordered_flat_set_deduction_guides[__see below__]::size_type = xref:#unordered_flat_set_deduction_guides[__see below__], Hash = Hash(),
|
||||
Pred = Pred(), Allocator = Allocator())
|
||||
-> unordered_flat_set<std::ranges::range_value_t<R>, Hash, Pred,Allocator>;
|
||||
|
||||
template<class T, class Hash = boost::hash<T>, class Pred = std::equal_to<T>,
|
||||
class Allocator = std::allocator<T>>
|
||||
unordered_flat_set(std::initializer_list<T>, typename xref:#unordered_flat_set_deduction_guides[__see below__]::size_type = xref:#unordered_flat_set_deduction_guides[__see below__],
|
||||
@@ -216,6 +241,27 @@ namespace unordered {
|
||||
-> unordered_flat_set<xref:#unordered_flat_set_iter_value_type[__iter-value-type__]<InputIterator>, Hash,
|
||||
std::equal_to<xref:#unordered_flat_set_iter_value_type[__iter-value-type__]<InputIterator>>, Allocator>;
|
||||
|
||||
template<xref:#unordered_flat_set_convertible_to_from_range_t[__convertible-to-from-range_t__] FromRangeT,
|
||||
std::ranges::input_range R, class Allocator>
|
||||
unordered_flat_set(FromRangeT&&, R&&, typename xref:#unordered_flat_set_deduction_guides[__see below__]::size_type, Allocator)
|
||||
-> unordered_flat_set<std::ranges::range_value_t<R>,
|
||||
boost::hash<std::ranges::range_value_t<R>>,
|
||||
std::equal_to<std::ranges::range_value_t<R>>, Allocator>;
|
||||
|
||||
template<xref:#unordered_flat_set_convertible_to_from_range_t[__convertible-to-from-range_t__] FromRangeT,
|
||||
std::ranges::input_range R, class Allocator>
|
||||
unordered_flat_set(FromRangeT&&, R&&, Allocator)
|
||||
-> unordered_flat_set<std::ranges::range_value_t<R>,
|
||||
boost::hash<std::ranges::range_value_t<R>>,
|
||||
std::equal_to<std::ranges::range_value_t<R>>, Allocator>;
|
||||
|
||||
template<xref:#unordered_flat_set_convertible_to_from_range_t[__convertible-to-from-range_t__] FromRangeT,
|
||||
std::ranges::input_range R, class Hash, class Allocator>
|
||||
unordered_flat_set(FromRangeT&&, R&&, typename xref:#unordered_flat_set_deduction_guides[__see below__]::size_type, Hash,
|
||||
Allocator)
|
||||
-> unordered_flat_set<std::ranges::range_value_t<R>,
|
||||
Hash, std::equal_to<std::ranges::range_value_t<R>>, Allocator>;
|
||||
|
||||
template<class T, class Allocator>
|
||||
unordered_flat_set(std::initializer_list<T>, typename xref:#unordered_flat_set_deduction_guides[__see below__]::size_type, Allocator)
|
||||
-> unordered_flat_set<T, boost::hash<T>, std::equal_to<T>, Allocator>;
|
||||
@@ -307,6 +353,15 @@ The iterator category is at least a forward iterator.
|
||||
|
||||
=== Constructors
|
||||
|
||||
==== __container-compatible-range__
|
||||
[listings,subs="+macros,+quotes"]
|
||||
-----
|
||||
template<class R, class T>
|
||||
concept container_compatible_range =
|
||||
std::ranges::input_range<R> &&
|
||||
std::convertible_to<std::ranges::range_reference_t<R>, T>; // exposition only
|
||||
-----
|
||||
|
||||
==== Default Constructor
|
||||
```c++
|
||||
unordered_flat_set();
|
||||
@@ -445,6 +500,27 @@ Concurrency:;; Blocking on `other`.
|
||||
|
||||
---
|
||||
|
||||
==== Range Constructor
|
||||
[source,c++,subs="+macros,+quotes"]
|
||||
----
|
||||
template<class FromRangeT, xref:#unordered_flat_set_container_compatible_range[__container-compatible-range__]<value_type> R>
|
||||
unordered_flat_set(FromRangeT&&, R&& rg,
|
||||
size_type n = _implementation-defined_,
|
||||
const hasher& hf = hasher(),
|
||||
const key_equal& eql = key_equal(),
|
||||
const allocator_type& a = allocator_type());
|
||||
----
|
||||
|
||||
Constructs an empty container with at least `n` buckets, using `hf` as the hash function, `eql` as the key equality predicate and `a` as the allocator, and inserts the elements from `rg` into it.
|
||||
|
||||
Only participates in overload resolution if `FromRangeT` is convertible to `std::from_range_t` or `boost::unordered::from_range_t`.
|
||||
|
||||
|
||||
[horizontal]
|
||||
Requires:;; If the defaults are used, `hasher`, `key_equal` and `allocator_type` need to be https://en.cppreference.com/w/cpp/named_req/DefaultConstructible[DefaultConstructible^].
|
||||
|
||||
---
|
||||
|
||||
==== Initializer List Constructor
|
||||
[source,c++,subs="+quotes"]
|
||||
----
|
||||
@@ -455,7 +531,7 @@ unordered_flat_set(std::initializer_list<value_type> il,
|
||||
const allocator_type& a = allocator_type());
|
||||
----
|
||||
|
||||
Constructs an empty container with at least `n` buckets, using `hf` as the hash function, `eql` as the key equality predicate and `a`, and inserts the elements from `il` into it.
|
||||
Constructs an empty container with at least `n` buckets, using `hf` as the hash function, `eql` as the key equality predicate and `a` as the allocator, and inserts the elements from `il` into it.
|
||||
|
||||
[horizontal]
|
||||
Requires:;; If the defaults are used, `hasher`, `key_equal` and `allocator_type` need to be https://en.cppreference.com/w/cpp/named_req/DefaultConstructible[DefaultConstructible^].
|
||||
@@ -517,6 +593,58 @@ Requires:;; `key_equal` needs to be https://en.cppreference.com/w/cpp/named_req/
|
||||
|
||||
---
|
||||
|
||||
==== Range Constructor with Allocator
|
||||
|
||||
[source,c++,subs="+macros,+quotes"]
|
||||
----
|
||||
template<class FromRangeT, xref:#unordered_flat_set_container_compatible_range[__container-compatible-range__]<value_type> R>
|
||||
unordered_flat_set(FromRangeT&&, R&& rg, const allocator_type& a);
|
||||
----
|
||||
|
||||
Constructs an empty container using `a` and default hash function and key equality predicate, and inserts the elements from `rg` into it.
|
||||
|
||||
Only participates in overload resolution if `FromRangeT` is convertible to `std::from_range_t` or `boost::unordered::from_range_t`.
|
||||
|
||||
[horizontal]
|
||||
Requires:;; `hasher` and `key_equal` need to be https://en.cppreference.com/w/cpp/named_req/DefaultConstructible[DefaultConstructible^].
|
||||
|
||||
---
|
||||
|
||||
==== Range Constructor with Bucket Count and Allocator
|
||||
|
||||
[source,c++,subs="+macros,+quotes"]
|
||||
----
|
||||
template<class FromRangeT, xref:#unordered_flat_set_container_compatible_range[__container-compatible-range__]<value_type> R>
|
||||
unordered_flat_set(FromRangeT&&, R&& rg, size_type n, const allocator_type& a);
|
||||
----
|
||||
|
||||
Constructs an empty container with at least `n` buckets, using `a` and default hash function and key equality predicate, and inserts the elements from `rg` into it.
|
||||
|
||||
Only participates in overload resolution if `FromRangeT` is convertible to `std::from_range_t` or `boost::unordered::from_range_t`.
|
||||
|
||||
[horizontal]
|
||||
Requires:;; `hasher` and `key_equal` need to be https://en.cppreference.com/w/cpp/named_req/DefaultConstructible[DefaultConstructible^].
|
||||
|
||||
---
|
||||
|
||||
==== Range Constructor with Bucket Count and Hasher and Allocator
|
||||
|
||||
[source,c++,subs="+macros,+quotes"]
|
||||
----
|
||||
template<class FromRangeT, xref:#unordered_flat_set_container_compatible_range[__container-compatible-range__]<value_type> R>
|
||||
unordered_flat_set(FromRangeT&&, R&& rg, size_type n, const hasher& hf,
|
||||
const allocator_type& a);
|
||||
----
|
||||
|
||||
Constructs an empty container with at least `n` buckets, using `hf` as the hash function, `a` as the allocator and default key equality predicate, and inserts the elements from `rg` into it.
|
||||
|
||||
Only participates in overload resolution if `FromRangeT` is convertible to `std::from_range_t` or `boost::unordered::from_range_t`.
|
||||
|
||||
[horizontal]
|
||||
Requires:;; `key_equal` needs to be https://en.cppreference.com/w/cpp/named_req/DefaultConstructible[DefaultConstructible^].
|
||||
|
||||
---
|
||||
|
||||
==== initializer_list Constructor with Allocator
|
||||
|
||||
```c++
|
||||
@@ -550,7 +678,7 @@ unordered_flat_set(std::initializer_list<value_type> il, size_type n, const hash
|
||||
const allocator_type& a);
|
||||
```
|
||||
|
||||
Constructs an empty container with at least `n` buckets, using `hf` as the hash function, `a` as the allocator and default key equality predicate,and inserts the elements from `il` into it.
|
||||
Constructs an empty container with at least `n` buckets, using `hf` as the hash function, `a` as the allocator and default key equality predicate, and inserts the elements from `il` into it.
|
||||
|
||||
[horizontal]
|
||||
Requires:;; `key_equal` needs to be https://en.cppreference.com/w/cpp/named_req/DefaultConstructible[DefaultConstructible^].
|
||||
@@ -857,6 +985,22 @@ Notes:;; Can invalidate iterators, pointers and references, but only if the inse
|
||||
|
||||
---
|
||||
|
||||
==== Insert Range
|
||||
[source,c++,subs="+macros,+quotes"]
|
||||
----
|
||||
template<xref:#unordered_flat_set_container_compatible_range[__container-compatible-range__]<value_type> R>
|
||||
void insert_range(R&& rg);
|
||||
----
|
||||
|
||||
Inserts a range of elements into the container. Elements are inserted if and only if there is no element in the container with an equivalent key.
|
||||
|
||||
[horizontal]
|
||||
Requires:;; `value_type` is https://en.cppreference.com/w/cpp/named_req/EmplaceConstructible[EmplaceConstructible^] into the container from `*std::ranges::begin(rg)`.
|
||||
Throws:;; When inserting a single element, if an exception is thrown by an operation other than a call to `hasher` the function has no effect.
|
||||
Notes:;; Can invalidate iterators, pointers and references, but only if the insert causes the load to be greater than the maximum load.
|
||||
|
||||
---
|
||||
|
||||
==== Insert Initializer List
|
||||
```c++
|
||||
void insert(std::initializer_list<value_type>);
|
||||
@@ -1194,6 +1338,16 @@ template<class InputIterator>
|
||||
typename std::iterator_traits<InputIterator>::value_type; // exposition only
|
||||
-----
|
||||
|
||||
==== __convertible-to-from-range_t__
|
||||
[listings,subs="+macros,+quotes"]
|
||||
-----
|
||||
template<typename FromRangeT>
|
||||
concept __convertible-to-from_range_t__ =
|
||||
// first clause not present if std::from_range_t does not exist
|
||||
std::is_convertible_v<FromRangeT, std::from_range_t> ||
|
||||
std::is_convertible_v<FromRangeT, boost::unordered::from_range_t>; // exposition only
|
||||
-----
|
||||
|
||||
=== Equality Comparisons
|
||||
|
||||
==== operator==
|
||||
|
||||
@@ -61,8 +61,14 @@ namespace unordered {
|
||||
explicit xref:#unordered_map_allocator_constructor[unordered_map](const Allocator& a);
|
||||
xref:#unordered_map_copy_constructor_with_allocator[unordered_map](const unordered_map& other, const Allocator& a);
|
||||
xref:#unordered_map_move_constructor_with_allocator[unordered_map](unordered_map&& other, const Allocator& a);
|
||||
template<class FromRangeT, xref:#unordered_map_container_compatible_range[__container-compatible-range__]<value_type> R>
|
||||
xref:#unordered_map_range_constructor[unordered_map](FromRangeT&&, R&& rg,
|
||||
size_type n = _implementation-defined_,
|
||||
const hasher& hf = hasher(),
|
||||
const key_equal& eql = key_equal(),
|
||||
const allocator_type& a = allocator_type());
|
||||
xref:#unordered_map_initializer_list_constructor[unordered_map](std::initializer_list<value_type> il,
|
||||
size_type n = _implementation-defined_
|
||||
size_type n = _implementation-defined_,
|
||||
const hasher& hf = hasher(),
|
||||
const key_equal& eql = key_equal(),
|
||||
const allocator_type& a = allocator_type());
|
||||
@@ -73,6 +79,13 @@ namespace unordered {
|
||||
template<class InputIterator>
|
||||
xref:#unordered_map_iterator_range_constructor_with_bucket_count_and_hasher[unordered_map](InputIterator f, InputIterator l, size_type n, const hasher& hf,
|
||||
const allocator_type& a);
|
||||
template<class FromRangeT, xref:#unordered_map_container_compatible_range[__container-compatible-range__]<value_type> R>
|
||||
xref:#unordered_map_range_constructor_with_allocator[unordered_map](FromRangeT&&, R&& rg, const allocator_type& a);
|
||||
template<class FromRangeT, xref:#unordered_map_container_compatible_range[__container-compatible-range__]<value_type> R>
|
||||
xref:#unordered_map_range_constructor_with_bucket_count_and_allocator[unordered_map](FromRangeT&&, R&& rg, size_type n, const allocator_type& a);
|
||||
template<class FromRangeT, xref:#unordered_map_container_compatible_range[__container-compatible-range__]<value_type> R>
|
||||
xref:#unordered_map_range_constructor_with_bucket_count_and_hasher_and_allocator[unordered_map](FromRangeT&&, R&& rg, size_type n, const hasher& hf,
|
||||
const allocator_type& a);
|
||||
xref:#unordered_map_initializer_list_constructor_with_allocator[unordered_map](std::initializer_list<value_type> il, const allocator_type& a);
|
||||
xref:#unordered_map_initializer_list_constructor_with_bucket_count_and_allocator[unordered_map](std::initializer_list<value_type> il, size_type n, const allocator_type& a);
|
||||
xref:#unordered_map_initializer_list_constructor_with_bucket_count_and_hasher_and_allocator[unordered_map](std::initializer_list<value_type> il, size_type n, const hasher& hf,
|
||||
@@ -109,6 +122,8 @@ namespace unordered {
|
||||
iterator xref:#unordered_map_move_insert_with_hint[insert](const_iterator hint, value_type&& obj);
|
||||
template<class P> iterator xref:#unordered_map_emplace_insert_with_hint[insert](const_iterator hint, P&& obj);
|
||||
template<class InputIterator> void xref:#unordered_map_insert_iterator_range[insert](InputIterator first, InputIterator last);
|
||||
template<xref:#unordered_map_container_compatible_range[__container-compatible-range__]<value_type> R>
|
||||
void xref:#unordered_map_insert_range[insert_range](R&& rg);
|
||||
void xref:#unordered_map_insert_initializer_list[insert](std::initializer_list<value_type>);
|
||||
|
||||
template<class... Args>
|
||||
@@ -231,8 +246,19 @@ namespace unordered {
|
||||
class Allocator = std::allocator<xref:#unordered_map_iter_to_alloc_type[__iter-to-alloc-type__]<InputIterator>>>
|
||||
unordered_map(InputIterator, InputIterator, typename xref:#unordered_map_deduction_guides[__see below__]::size_type = xref:#unordered_map_deduction_guides[__see below__],
|
||||
Hash = Hash(), Pred = Pred(), Allocator = Allocator())
|
||||
-> unordered_map<xref:#unordered_map_iter_key_type[__iter-key-type__]<InputIterator>, xref:#unordered_map_iter_mapped_type[__iter-mapped-type__]<InputIterator>, Hash, Pred,
|
||||
Allocator>;
|
||||
-> unordered_map<xref:#unordered_map_iter_key_type[__iter-key-type__]<InputIterator>, xref:#unordered_map_iter_mapped_type[__iter-mapped-type__]<InputIterator>,
|
||||
Hash, Pred, Allocator>;
|
||||
|
||||
template<xref:#unordered_map_convertible_to_from_range_t[__convertible-to-from-range_t__] FromRangeT,
|
||||
std::ranges::input_range R,
|
||||
class Hash = boost::hash<xref:#unordered_map_range_key_type[__range-key-type__]<R>>,
|
||||
class Pred = std::equal_to<xref:#unordered_map_range_key_type[__range-key-type__]<R>>,
|
||||
class Allocator = std::allocator<xref:#unordered_map_range_to_alloc_type[__range-to-alloc-type__]<R>>>
|
||||
unordered_map(FromRangeT&&, R&&,
|
||||
typename xref:#unordered_map_deduction_guides[__see below__]::size_type = xref:#unordered_map_deduction_guides[__see below__], Hash = Hash(),
|
||||
Pred = Pred(), Allocator = Allocator())
|
||||
-> unordered_map<xref:#unordered_map_range_key_type[__range-key-type__]<R>, xref:#unordered_map_range_mapped_type[__range-mapped-type__]<R>,
|
||||
Hash, Pred,Allocator>;
|
||||
|
||||
template<class Key, class T, class Hash = boost::hash<Key>,
|
||||
class Pred = std::equal_to<Key>,
|
||||
@@ -259,6 +285,27 @@ namespace unordered {
|
||||
-> unordered_map<xref:#unordered_map_iter_key_type[__iter-key-type__]<InputIterator>, xref:#unordered_map_iter_mapped_type[__iter-mapped-type__]<InputIterator>, Hash,
|
||||
std::equal_to<xref:#unordered_map_iter_key_type[__iter-key-type__]<InputIterator>>, Allocator>;
|
||||
|
||||
template<xref:#unordered_map_convertible_to_from_range_t[__convertible-to-from-range_t__] FromRangeT,
|
||||
std::ranges::input_range R, class Allocator>
|
||||
unordered_map(FromRangeT&&, R&&, typename xref:#unordered_map_deduction_guides[__see below__]::size_type, Allocator)
|
||||
-> unordered_map<xref:#unordered_map_range_key_type[__range-key-type__]<R>, xref:#unordered_map_range_mapped_type[__range-mapped-type__]<R>,
|
||||
boost::hash<xref:#unordered_map_range_key_type[__range-key-type__]<R>>,
|
||||
std::equal_to<xref:#unordered_map_range_key_type[__range-key-type__]<R>>, Allocator>;
|
||||
|
||||
template<xref:#unordered_map_convertible_to_from_range_t[__convertible-to-from-range_t__] FromRangeT,
|
||||
std::ranges::input_range R, class Allocator>
|
||||
unordered_map(FromRangeT&&, R&&, Allocator)
|
||||
-> unordered_map<xref:#unordered_map_range_key_type[__range-key-type__]<R>, xref:#unordered_map_range_mapped_type[__range-mapped-type__]<R>,
|
||||
boost::hash<xref:#unordered_map_range_key_type[__range-key-type__]<R>>,
|
||||
std::equal_to<xref:#unordered_map_range_key_type[__range-key-type__]<R>>, Allocator>;
|
||||
|
||||
template<xref:#unordered_map_convertible_to_from_range_t[__convertible-to-from-range_t__] FromRangeT,
|
||||
std::ranges::input_range R, class Hash, class Allocator>
|
||||
unordered_map(FromRangeT&&, R&&, typename xref:#unordered_map_deduction_guides[__see below__]::size_type, Hash,
|
||||
Allocator)
|
||||
-> unordered_map<xref:#unordered_map_range_key_type[__range-key-type__]<R>, xref:#unordered_map_range_mapped_type[__range-mapped-type__]<R>,
|
||||
Hash, std::equal_to<xref:#unordered_map_range_key_type[__range-key-type__]<R>>, Allocator>;
|
||||
|
||||
template<class Key, class T, class Allocator>
|
||||
unordered_map(std::initializer_list<std::pair<Key, T>>, typename xref:#unordered_map_deduction_guides[__see below__]::size_type,
|
||||
Allocator)
|
||||
@@ -397,6 +444,15 @@ with `Iterator` = `iterator` and `NodeType` = `node_type`.
|
||||
|
||||
=== Constructors
|
||||
|
||||
==== __container-compatible-range__
|
||||
[listings,subs="+macros,+quotes"]
|
||||
-----
|
||||
template<class R, class T>
|
||||
concept container_compatible_range =
|
||||
std::ranges::input_range<R> &&
|
||||
std::convertible_to<std::ranges::range_reference_t<R>, T>; // exposition only
|
||||
-----
|
||||
|
||||
==== Default Constructor
|
||||
```c++
|
||||
unordered_map();
|
||||
@@ -519,11 +575,32 @@ Requires:;; `value_type` is move insertable.
|
||||
|
||||
---
|
||||
|
||||
==== Range Constructor
|
||||
[source,c++,subs="+macros,+quotes"]
|
||||
----
|
||||
template<class FromRangeT, xref:#unordered_map_container_compatible_range[__container-compatible-range__]<value_type> R>
|
||||
unordered_map(FromRangeT&&, R&& rg,
|
||||
size_type n = _implementation-defined_,
|
||||
const hasher& hf = hasher(),
|
||||
const key_equal& eql = key_equal(),
|
||||
const allocator_type& a = allocator_type());
|
||||
----
|
||||
|
||||
Constructs an empty container with at least `n` buckets, using `hf` as the hash function, `eql` as the key equality predicate, `a` as the allocator and a maximum load factor of `1.0` and inserts the elements from `rg` into it.
|
||||
|
||||
Only participates in overload resolution if `FromRangeT` is convertible to `std::from_range_t` or `boost::unordered::from_range_t`.
|
||||
|
||||
|
||||
[horizontal]
|
||||
Requires:;; If the defaults are used, `hasher`, `key_equal` and `allocator_type` need to be https://en.cppreference.com/w/cpp/named_req/DefaultConstructible[DefaultConstructible^].
|
||||
|
||||
---
|
||||
|
||||
==== Initializer List Constructor
|
||||
[source,c++,subs="+quotes"]
|
||||
----
|
||||
unordered_map(std::initializer_list<value_type> il,
|
||||
size_type n = _implementation-defined_
|
||||
size_type n = _implementation-defined_,
|
||||
const hasher& hf = hasher(),
|
||||
const key_equal& eql = key_equal(),
|
||||
const allocator_type& a = allocator_type());
|
||||
@@ -591,6 +668,58 @@ Requires:;; `key_equal` needs to be https://en.cppreference.com/w/cpp/named_req/
|
||||
|
||||
---
|
||||
|
||||
==== Range Constructor with Allocator
|
||||
|
||||
[source,c++,subs="+macros,+quotes"]
|
||||
----
|
||||
template<class FromRangeT, xref:#unordered_map_container_compatible_range[__container-compatible-range__]<value_type> R>
|
||||
unordered_map(FromRangeT&&, R&& rg, const allocator_type& a);
|
||||
----
|
||||
|
||||
Constructs an empty container using `a` as the allocator and a maximum load factor of 1.0 and inserts the elements from `rg` into it.
|
||||
|
||||
Only participates in overload resolution if `FromRangeT` is convertible to `std::from_range_t` or `boost::unordered::from_range_t`.
|
||||
|
||||
[horizontal]
|
||||
Requires:;; `hasher` and `key_equal` need to be https://en.cppreference.com/w/cpp/named_req/DefaultConstructible[DefaultConstructible^].
|
||||
|
||||
---
|
||||
|
||||
==== Range Constructor with Bucket Count and Allocator
|
||||
|
||||
[source,c++,subs="+macros,+quotes"]
|
||||
----
|
||||
template<class FromRangeT, xref:#unordered_map_container_compatible_range[__container-compatible-range__]<value_type> R>
|
||||
unordered_map(FromRangeT&&, R&& rg, size_type n, const allocator_type& a);
|
||||
----
|
||||
|
||||
Constructs an empty container with at least `n` buckets, using `a` as the allocator and a maximum load factor of 1.0 and inserts the elements from `rg` into it.
|
||||
|
||||
Only participates in overload resolution if `FromRangeT` is convertible to `std::from_range_t` or `boost::unordered::from_range_t`.
|
||||
|
||||
[horizontal]
|
||||
Requires:;; `hasher` and `key_equal` need to be https://en.cppreference.com/w/cpp/named_req/DefaultConstructible[DefaultConstructible^].
|
||||
|
||||
---
|
||||
|
||||
==== Range Constructor with Bucket Count and Hasher and Allocator
|
||||
|
||||
[source,c++,subs="+macros,+quotes"]
|
||||
----
|
||||
template<class FromRangeT, xref:#unordered_map_container_compatible_range[__container-compatible-range__]<value_type> R>
|
||||
unordered_map(FromRangeT&&, R&& rg, size_type n, const hasher& hf,
|
||||
const allocator_type& a);
|
||||
----
|
||||
|
||||
Constructs an empty container with at least `n` buckets, using `hf` as the hash function, `a` as the allocator and a maximum load factor of 1.0 and inserts the elements from `rg` into it.
|
||||
|
||||
Only participates in overload resolution if `FromRangeT` is convertible to `std::from_range_t` or `boost::unordered::from_range_t`.
|
||||
|
||||
[horizontal]
|
||||
Requires:;; `key_equal` needs to be https://en.cppreference.com/w/cpp/named_req/DefaultConstructible[DefaultConstructible^].
|
||||
|
||||
---
|
||||
|
||||
==== initializer_list Constructor with Allocator
|
||||
|
||||
```c++
|
||||
@@ -944,6 +1073,24 @@ Pointers and references to elements are never invalidated.
|
||||
|
||||
---
|
||||
|
||||
==== Insert Range
|
||||
[source,c++,subs="+macros,+quotes"]
|
||||
----
|
||||
template<xref:#unordered_map_container_compatible_range[__container-compatible-range__]<value_type> R>
|
||||
void insert_range(R&& rg);
|
||||
----
|
||||
|
||||
Inserts a range of elements into the container. Elements are inserted if and only if there is no element in the container with an equivalent key.
|
||||
|
||||
[horizontal]
|
||||
Requires:;; `value_type` is https://en.cppreference.com/w/cpp/named_req/EmplaceConstructible[EmplaceConstructible^] into the container from `*std::ranges::begin(rg)`.
|
||||
Throws:;; When inserting a single element, if an exception is thrown by an operation other than a call to `hasher` the function has no effect.
|
||||
Notes:;; Can invalidate iterators, but only if the insert causes the load factor to be greater to or equal to the maximum load factor. +
|
||||
+
|
||||
Pointers and references to elements are never invalidated.
|
||||
|
||||
---
|
||||
|
||||
==== Insert Initializer List
|
||||
```c++
|
||||
void insert(std::initializer_list<value_type>);
|
||||
@@ -1697,6 +1844,42 @@ template<class InputIterator>
|
||||
std::tuple_element_t<1, xref:#unordered_map_iter_value_type[__iter-value-type__]<InputIterator>>>; // exposition only
|
||||
-----
|
||||
|
||||
==== __convertible-to-from-range_t__
|
||||
[listings,subs="+macros,+quotes"]
|
||||
-----
|
||||
template<typename FromRangeT>
|
||||
concept __convertible-to-from_range_t__ =
|
||||
// first clause not present if std::from_range_t does not exist
|
||||
std::is_convertible_v<FromRangeT, std::from_range_t> ||
|
||||
std::is_convertible_v<FromRangeT, boost::unordered::from_range_t>; // exposition only
|
||||
-----
|
||||
|
||||
==== __range-key-type__
|
||||
[listings,subs="+macros,+quotes"]
|
||||
-----
|
||||
template<std::ranges::input_range R>
|
||||
using __range-key-type__ =
|
||||
std::remove_cvref_t<
|
||||
std::tuple_element_t<0, std::ranges::range_value_t<R>>>; // exposition only
|
||||
-----
|
||||
|
||||
==== __range-mapped-type__
|
||||
[listings,subs="+macros,+quotes"]
|
||||
-----
|
||||
template<std::ranges::input_range R>
|
||||
using __range-mapped-type__ =
|
||||
std::remove_cvref_t<
|
||||
std::tuple_element_t<1, std::ranges::range_value_t<R>>>; // exposition only
|
||||
-----
|
||||
|
||||
==== __range-to-alloc-type__
|
||||
[listings,subs="+macros,+quotes"]
|
||||
-----
|
||||
template<std::ranges::input_range R>
|
||||
using __range-to-alloc-type__ =
|
||||
std::pair<const xref:#unordered_map_range_key_type[__range-key-type__]<R>, xref:#unordered_map_range_mapped_type[__range-mapped-type__]<R>>; // exposition only
|
||||
-----
|
||||
|
||||
=== Equality Comparisons
|
||||
|
||||
==== operator==
|
||||
|
||||
@@ -60,6 +60,12 @@ namespace unordered {
|
||||
explicit xref:#unordered_multimap_allocator_constructor[unordered_multimap](const Allocator& a);
|
||||
xref:#unordered_multimap_copy_constructor_with_allocator[unordered_multimap](const unordered_multimap& other, const Allocator& a);
|
||||
xref:#unordered_multimap_move_constructor_with_allocator[unordered_multimap](unordered_multimap&& other, const Allocator& a);
|
||||
template<class FromRangeT, xref:#unordered_multimap_container_compatible_range[__container-compatible-range__]<value_type> R>
|
||||
xref:#unordered_multimap_range_constructor[unordered_multimap](FromRangeT&&, R&& rg,
|
||||
size_type n = _implementation-defined_,
|
||||
const hasher& hf = hasher(),
|
||||
const key_equal& eql = key_equal(),
|
||||
const allocator_type& a = allocator_type());
|
||||
xref:#unordered_multimap_initializer_list_constructor[unordered_multimap](std::initializer_list<value_type> il,
|
||||
size_type n = _implementation-defined_,
|
||||
const hasher& hf = hasher(),
|
||||
@@ -72,6 +78,13 @@ namespace unordered {
|
||||
template<class InputIterator>
|
||||
xref:#unordered_multimap_iterator_range_constructor_with_bucket_count_and_hasher[unordered_multimap](InputIterator f, InputIterator l, size_type n, const hasher& hf,
|
||||
const allocator_type& a);
|
||||
template<class FromRangeT, xref:#unordered_multimap_container_compatible_range[__container-compatible-range__]<value_type> R>
|
||||
xref:#unordered_multimap_range_constructor_with_allocator[unordered_multimap](FromRangeT&&, R&& rg, const allocator_type& a);
|
||||
template<class FromRangeT, xref:#unordered_multimap_container_compatible_range[__container-compatible-range__]<value_type> R>
|
||||
xref:#unordered_multimap_range_constructor_with_bucket_count_and_allocator[unordered_multimap](FromRangeT&&, R&& rg, size_type n, const allocator_type& a);
|
||||
template<class FromRangeT, xref:#unordered_multimap_container_compatible_range[__container-compatible-range__]<value_type> R>
|
||||
xref:#unordered_multimap_range_constructor_with_bucket_count_and_hasher_and_allocator[unordered_multimap](FromRangeT&&, R&& rg, size_type n, const hasher& hf,
|
||||
const allocator_type& a);
|
||||
xref:#unordered_multimap_initializer_list_constructor_with_allocator[unordered_multimap](std::initializer_list<value_type> il, const allocator_type& a);
|
||||
xref:#unordered_multimap_initializer_list_constructor_with_bucket_count_and_allocator[unordered_multimap](std::initializer_list<value_type> il, size_type n,
|
||||
const allocator_type& a);
|
||||
@@ -109,6 +122,8 @@ namespace unordered {
|
||||
iterator xref:#unordered_multimap_move_insert_with_hint[insert](const_iterator hint, value_type&& obj);
|
||||
template<class P> iterator xref:#unordered_multimap_emplace_insert_with_hint[insert](const_iterator hint, P&& obj);
|
||||
template<class InputIterator> void xref:#unordered_multimap_insert_iterator_range[insert](InputIterator first, InputIterator last);
|
||||
template<xref:#unordered_multimap_container_compatible_range[__container-compatible-range__]<value_type> R>
|
||||
void xref:#unordered_multimap_insert_range[insert_range](R&& rg);
|
||||
void xref:#unordered_multimap_insert_initializer_list[insert](std::initializer_list<value_type> il);
|
||||
|
||||
node_type xref:#unordered_multimap_extract_by_iterator[extract](const_iterator position);
|
||||
@@ -200,6 +215,17 @@ namespace unordered {
|
||||
-> unordered_multimap<xref:#unordered_multimap_iter_key_type[__iter-key-type__]<InputIterator>, xref:#unordered_multimap_iter_mapped_type[__iter-mapped-type__]<InputIterator>, Hash,
|
||||
Pred, Allocator>;
|
||||
|
||||
template<xref:#unordered_multimap_convertible_to_from_range_t[__convertible-to-from-range_t__] FromRangeT,
|
||||
std::ranges::input_range R,
|
||||
class Hash = boost::hash<xref:#unordered_multimap_range_key_type[__range-key-type__]<R>>,
|
||||
class Pred = std::equal_to<xref:#unordered_multimap_range_key_type[__range-key-type__]<R>>,
|
||||
class Allocator = std::allocator<xref:#unordered_multimap_range_to_alloc_type[__range-to-alloc-type__]<R>>>
|
||||
unordered_multimap(FromRangeT&&, R&&,
|
||||
typename xref:#unordered_multimap_deduction_guides[__see below__]::size_type = xref:#unordered_multimap_deduction_guides[__see below__], Hash = Hash(),
|
||||
Pred = Pred(), Allocator = Allocator())
|
||||
-> unordered_multimap<xref:#unordered_multimap_range_key_type[__range-key-type__]<R>, xref:#unordered_multimap_range_mapped_type[__range-mapped-type__]<R>,
|
||||
Hash, Pred,Allocator>;
|
||||
|
||||
template<class Key, class T, class Hash = boost::hash<Key>,
|
||||
class Pred = std::equal_to<Key>,
|
||||
class Allocator = std::allocator<std::pair<const Key, T>>>
|
||||
@@ -226,6 +252,27 @@ namespace unordered {
|
||||
-> unordered_multimap<xref:#unordered_multimap_iter_key_type[__iter-key-type__]<InputIterator>, xref:#unordered_multimap_iter_mapped_type[__iter-mapped-type__]<InputIterator>, Hash,
|
||||
std::equal_to<xref:#unordered_multimap_iter_key_type[__iter-key-type__]<InputIterator>>, Allocator>;
|
||||
|
||||
template<xref:#unordered_multimap_convertible_to_from_range_t[__convertible-to-from-range_t__] FromRangeT,
|
||||
std::ranges::input_range R, class Allocator>
|
||||
unordered_multimap(FromRangeT&&, R&&, typename xref:#unordered_multimap_deduction_guides[__see below__]::size_type, Allocator)
|
||||
-> unordered_multimap<xref:#unordered_multimap_range_key_type[__range-key-type__]<R>, xref:#unordered_multimap_range_mapped_type[__range-mapped-type__]<R>,
|
||||
boost::hash<xref:#unordered_multimap_range_key_type[__range-key-type__]<R>>,
|
||||
std::equal_to<xref:#unordered_multimap_range_key_type[__range-key-type__]<R>>, Allocator>;
|
||||
|
||||
template<xref:#unordered_multimap_convertible_to_from_range_t[__convertible-to-from-range_t__] FromRangeT,
|
||||
std::ranges::input_range R, class Allocator>
|
||||
unordered_multimap(FromRangeT&&, R&&, Allocator)
|
||||
-> unordered_multimap<xref:#unordered_multimap_range_key_type[__range-key-type__]<R>, xref:#unordered_multimap_range_mapped_type[__range-mapped-type__]<R>,
|
||||
boost::hash<xref:#unordered_multimap_range_key_type[__range-key-type__]<R>>,
|
||||
std::equal_to<xref:#unordered_multimap_range_key_type[__range-key-type__]<R>>, Allocator>;
|
||||
|
||||
template<xref:#unordered_multimap_convertible_to_from_range_t[__convertible-to-from-range_t__] FromRangeT,
|
||||
std::ranges::input_range R, class Hash, class Allocator>
|
||||
unordered_multimap(FromRangeT&&, R&&, typename xref:#unordered_multimap_deduction_guides[__see below__]::size_type, Hash,
|
||||
Allocator)
|
||||
-> unordered_multimap<xref:#unordered_multimap_range_key_type[__range-key-type__]<R>, xref:#unordered_multimap_range_mapped_type[__range-mapped-type__]<R>,
|
||||
Hash, std::equal_to<xref:#unordered_multimap_range_key_type[__range-key-type__]<R>>, Allocator>;
|
||||
|
||||
template<class Key, class T, class Allocator>
|
||||
unordered_multimap(std::initializer_list<std::pair<Key, T>>, typename xref:#unordered_multimap_deduction_guides[__see below__]::size_type,
|
||||
Allocator)
|
||||
@@ -341,6 +388,15 @@ See node_handle_map for details.
|
||||
|
||||
=== Constructors
|
||||
|
||||
==== __container-compatible-range__
|
||||
[listings,subs="+macros,+quotes"]
|
||||
-----
|
||||
template<class R, class T>
|
||||
concept container_compatible_range =
|
||||
std::ranges::input_range<R> &&
|
||||
std::convertible_to<std::ranges::range_reference_t<R>, T>; // exposition only
|
||||
-----
|
||||
|
||||
==== Default Constructor
|
||||
```c++
|
||||
unordered_multimap();
|
||||
@@ -463,6 +519,27 @@ Requires:;; `value_type` is move insertable.
|
||||
|
||||
---
|
||||
|
||||
==== Range Constructor
|
||||
[source,c++,subs="+macros,+quotes"]
|
||||
----
|
||||
template<class FromRangeT, xref:#unordered_multimap_container_compatible_range[__container-compatible-range__]<value_type> R>
|
||||
unordered_multimap(FromRangeT&&, R&& rg,
|
||||
size_type n = _implementation-defined_,
|
||||
const hasher& hf = hasher(),
|
||||
const key_equal& eql = key_equal(),
|
||||
const allocator_type& a = allocator_type());
|
||||
----
|
||||
|
||||
Constructs an empty container with at least `n` buckets, using `hf` as the hash function, `eql` as the key equality predicate, `a` as the allocator and a maximum load factor of `1.0` and inserts the elements from `rg` into it.
|
||||
|
||||
Only participates in overload resolution if `FromRangeT` is convertible to `std::from_range_t` or `boost::unordered::from_range_t`.
|
||||
|
||||
|
||||
[horizontal]
|
||||
Requires:;; If the defaults are used, `hasher`, `key_equal` and `allocator_type` need to be https://en.cppreference.com/w/cpp/named_req/DefaultConstructible[DefaultConstructible^].
|
||||
|
||||
---
|
||||
|
||||
==== Initializer List Constructor
|
||||
[source,c++,subs="+quotes"]
|
||||
----
|
||||
@@ -534,6 +611,58 @@ Requires:;; `key_equal` needs to be https://en.cppreference.com/w/cpp/named_req/
|
||||
|
||||
---
|
||||
|
||||
==== Range Constructor with Allocator
|
||||
|
||||
[source,c++,subs="+macros,+quotes"]
|
||||
----
|
||||
template<class FromRangeT, xref:#unordered_multimap_container_compatible_range[__container-compatible-range__]<value_type> R>
|
||||
unordered_multimap(FromRangeT&&, R&& rg, const allocator_type& a);
|
||||
----
|
||||
|
||||
Constructs an empty container using `a` as the allocator and a maximum load factor of 1.0 and inserts the elements from `rg` into it.
|
||||
|
||||
Only participates in overload resolution if `FromRangeT` is convertible to `std::from_range_t` or `boost::unordered::from_range_t`.
|
||||
|
||||
[horizontal]
|
||||
Requires:;; `hasher` and `key_equal` need to be https://en.cppreference.com/w/cpp/named_req/DefaultConstructible[DefaultConstructible^].
|
||||
|
||||
---
|
||||
|
||||
==== Range Constructor with Bucket Count and Allocator
|
||||
|
||||
[source,c++,subs="+macros,+quotes"]
|
||||
----
|
||||
template<class FromRangeT, xref:#unordered_multimap_container_compatible_range[__container-compatible-range__]<value_type> R>
|
||||
unordered_multimap(FromRangeT&&, R&& rg, size_type n, const allocator_type& a);
|
||||
----
|
||||
|
||||
Constructs an empty container with at least `n` buckets, using `a` as the allocator and a maximum load factor of 1.0 and inserts the elements from `rg` into it.
|
||||
|
||||
Only participates in overload resolution if `FromRangeT` is convertible to `std::from_range_t` or `boost::unordered::from_range_t`.
|
||||
|
||||
[horizontal]
|
||||
Requires:;; `hasher` and `key_equal` need to be https://en.cppreference.com/w/cpp/named_req/DefaultConstructible[DefaultConstructible^].
|
||||
|
||||
---
|
||||
|
||||
==== Range Constructor with Bucket Count and Hasher and Allocator
|
||||
|
||||
[source,c++,subs="+macros,+quotes"]
|
||||
----
|
||||
template<class FromRangeT, xref:#unordered_multimap_container_compatible_range[__container-compatible-range__]<value_type> R>
|
||||
unordered_multimap(FromRangeT&&, R&& rg, size_type n, const hasher& hf,
|
||||
const allocator_type& a);
|
||||
----
|
||||
|
||||
Constructs an empty container with at least `n` buckets, using `hf` as the hash function, `a` as the allocator and a maximum load factor of 1.0 and inserts the elements from `rg` into it.
|
||||
|
||||
Only participates in overload resolution if `FromRangeT` is convertible to `std::from_range_t` or `boost::unordered::from_range_t`.
|
||||
|
||||
[horizontal]
|
||||
Requires:;; `key_equal` needs to be https://en.cppreference.com/w/cpp/named_req/DefaultConstructible[DefaultConstructible^].
|
||||
|
||||
---
|
||||
|
||||
==== initializer_list Constructor with Allocator
|
||||
|
||||
```c++
|
||||
@@ -874,6 +1003,25 @@ Pointers and references to elements are never invalidated.
|
||||
|
||||
---
|
||||
|
||||
==== Insert Range
|
||||
[source,c++,subs="+macros,+quotes"]
|
||||
----
|
||||
template<xref:#unordered_multimap_container_compatible_range[__container-compatible-range__]<value_type> R>
|
||||
void insert_range(R&& rg);
|
||||
----
|
||||
|
||||
Inserts a range of elements into the container.
|
||||
|
||||
[horizontal]
|
||||
Requires:;; `value_type` is https://en.cppreference.com/w/cpp/named_req/EmplaceConstructible[EmplaceConstructible^] into the container from `*std::ranges::begin(rg)`.
|
||||
Throws:;; When inserting a single element, if an exception is thrown by an operation other than a call to `hasher` the function has no effect.
|
||||
Notes:;; Can invalidate iterators, but only if the insert causes the load factor to be greater to or equal to the maximum load factor. +
|
||||
+
|
||||
Pointers and references to elements are never invalidated.
|
||||
|
||||
---
|
||||
|
||||
|
||||
==== Insert Initializer List
|
||||
```c++
|
||||
void insert(std::initializer_list<value_type> il);
|
||||
@@ -1414,6 +1562,42 @@ template<class InputIterator>
|
||||
std::tuple_element_t<1, xref:#unordered_multimap_iter_value_type[__iter-value-type__]<InputIterator>>>; // exposition only
|
||||
-----
|
||||
|
||||
==== __convertible-to-from-range_t__
|
||||
[listings,subs="+macros,+quotes"]
|
||||
-----
|
||||
template<typename FromRangeT>
|
||||
concept __convertible-to-from_range_t__ =
|
||||
// first clause not present if std::from_range_t does not exist
|
||||
std::is_convertible_v<FromRangeT, std::from_range_t> ||
|
||||
std::is_convertible_v<FromRangeT, boost::unordered::from_range_t>; // exposition only
|
||||
-----
|
||||
|
||||
==== __range-key-type__
|
||||
[listings,subs="+macros,+quotes"]
|
||||
-----
|
||||
template<std::ranges::input_range R>
|
||||
using __range-key-type__ =
|
||||
std::remove_cvref_t<
|
||||
std::tuple_element_t<0, std::ranges::range_value_t<R>>>; // exposition only
|
||||
-----
|
||||
|
||||
==== __range-mapped-type__
|
||||
[listings,subs="+macros,+quotes"]
|
||||
-----
|
||||
template<std::ranges::input_range R>
|
||||
using __range-mapped-type__ =
|
||||
std::remove_cvref_t<
|
||||
std::tuple_element_t<1, std::ranges::range_value_t<R>>>; // exposition only
|
||||
-----
|
||||
|
||||
==== __range-to-alloc-type__
|
||||
[listings,subs="+macros,+quotes"]
|
||||
-----
|
||||
template<std::ranges::input_range R>
|
||||
using __range-to-alloc-type__ =
|
||||
std::pair<const xref:#unordered_multimap_range_key_type[__range-key-type__]<R>, xref:#unordered_multimap_range_mapped_type[__range-mapped-type__]<R>>; // exposition only
|
||||
-----
|
||||
|
||||
=== Equality Comparisons
|
||||
|
||||
==== operator==
|
||||
|
||||
@@ -58,6 +58,12 @@ namespace unordered {
|
||||
explicit xref:#unordered_multiset_allocator_constructor[unordered_multiset](const Allocator& a);
|
||||
xref:#unordered_multiset_copy_constructor_with_allocator[unordered_multiset](const unordered_multiset& other, const Allocator& a);
|
||||
xref:#unordered_multiset_move_constructor_with_allocator[unordered_multiset](unordered_multiset&& other, const Allocator& a);
|
||||
template<class FromRangeT, xref:#unordered_multiset_container_compatible_range[__container-compatible-range__]<value_type> R>
|
||||
xref:#unordered_multiset_range_constructor[unordered_multiset](FromRangeT&&, R&& rg,
|
||||
size_type n = _implementation-defined_,
|
||||
const hasher& hf = hasher(),
|
||||
const key_equal& eql = key_equal(),
|
||||
const allocator_type& a = allocator_type());
|
||||
xref:#unordered_multiset_initializer_list_constructor[unordered_multiset](std::initializer_list<value_type> il,
|
||||
size_type n = _implementation-defined_,
|
||||
const hasher& hf = hasher(),
|
||||
@@ -70,6 +76,13 @@ namespace unordered {
|
||||
template<class InputIterator>
|
||||
xref:#unordered_multiset_iterator_range_constructor_with_bucket_count_and_hasher[unordered_multiset](InputIterator f, InputIterator l, size_type n, const hasher& hf,
|
||||
const allocator_type& a);
|
||||
template<class FromRangeT, xref:#unordered_multiset_container_compatible_range[__container-compatible-range__]<value_type> R>
|
||||
xref:#unordered_multiset_range_constructor_with_allocator[unordered_multiset](FromRangeT&&, R&& rg, const allocator_type& a);
|
||||
template<class FromRangeT, xref:#unordered_multiset_container_compatible_range[__container-compatible-range__]<value_type> R>
|
||||
xref:#unordered_multiset_range_constructor_with_bucket_count_and_allocator[unordered_multiset](FromRangeT&&, R&& rg, size_type n, const allocator_type& a);
|
||||
template<class FromRangeT, xref:#unordered_multiset_container_compatible_range[__container-compatible-range__]<value_type> R>
|
||||
xref:#unordered_multiset_range_constructor_with_bucket_count_and_hasher_and_allocator[unordered_multiset](FromRangeT&&, R&& rg, size_type n, const hasher& hf,
|
||||
const allocator_type& a);
|
||||
xref:#unordered_multiset_initializer_list_constructor_with_allocator[unordered_multiset](std::initializer_list<value_type> il, const allocator_type& a);
|
||||
xref:#unordered_multiset_initializer_list_constructor_with_bucket_count_and_allocator[unordered_multiset](std::initializer_list<value_type> il, size_type n,
|
||||
const allocator_type& a)
|
||||
@@ -105,6 +118,8 @@ namespace unordered {
|
||||
iterator xref:#unordered_multiset_copy_insert_with_hint[insert](const_iterator hint, const value_type& obj);
|
||||
iterator xref:#unordered_multiset_move_insert_with_hint[insert](const_iterator hint, value_type&& obj);
|
||||
template<class InputIterator> void xref:#unordered_multiset_insert_iterator_range[insert](InputIterator first, InputIterator last);
|
||||
template<xref:#unordered_multiset_container_compatible_range[__container-compatible-range__]<value_type> R>
|
||||
void xref:#unordered_multiset_insert_range[insert_range](R&& rg);
|
||||
void xref:#unordered_multiset_insert_initializer_list[insert](std::initializer_list<value_type> il);
|
||||
|
||||
node_type xref:#unordered_multiset_extract_by_iterator[extract](const_iterator position);
|
||||
@@ -195,6 +210,16 @@ namespace unordered {
|
||||
Hash = Hash(), Pred = Pred(), Allocator = Allocator())
|
||||
-> unordered_multiset<xref:#unordered_multiset_iter_value_type[__iter-value-type__]<InputIterator>, Hash, Pred, Allocator>;
|
||||
|
||||
template<xref:#unordered_multiset_convertible_to_from_range_t[__convertible-to-from-range_t__] FromRangeT,
|
||||
std::ranges::input_range R,
|
||||
class Hash = boost::hash<std::ranges::range_value_t<R>>,
|
||||
class Pred = std::equal_to<std::ranges::range_value_t<R>>,
|
||||
class Allocator = std::allocator<std::ranges::range_value_t<R>>
|
||||
unordered_multiset(FromRangeT&&, R&&,
|
||||
typename xref:#unordered_multiset_deduction_guides[__see below__]::size_type = xref:#unordered_multiset_deduction_guides[__see below__], Hash = Hash(),
|
||||
Pred = Pred(), Allocator = Allocator())
|
||||
-> unordered_multiset<std::ranges::range_value_t<R>, Hash, Pred,Allocator>;
|
||||
|
||||
template<class T, class Hash = boost::hash<T>, class Pred = std::equal_to<T>,
|
||||
class Allocator = std::allocator<T>>
|
||||
unordered_multiset(std::initializer_list<T>, typename xref:#unordered_multiset_deduction_guides[__see below__]::size_type = xref:#unordered_multiset_deduction_guides[__see below__],
|
||||
@@ -219,6 +244,27 @@ namespace unordered {
|
||||
-> unordered_multiset<xref:#unordered_multiset_iter_value_type[__iter-value-type__]<InputIterator>, Hash,
|
||||
std::equal_to<xref:#unordered_multiset_iter_value_type[__iter-value-type__]<InputIterator>>, Allocator>;
|
||||
|
||||
template<xref:#unordered_multiset_convertible_to_from_range_t[__convertible-to-from-range_t__] FromRangeT,
|
||||
std::ranges::input_range R, class Allocator>
|
||||
unordered_multiset(FromRangeT&&, R&&, typename xref:#unordered_multiset_deduction_guides[__see below__]::size_type, Allocator)
|
||||
-> unordered_multiset<std::ranges::range_value_t<R>,
|
||||
boost::hash<std::ranges::range_value_t<R>>,
|
||||
std::equal_to<std::ranges::range_value_t<R>>, Allocator>;
|
||||
|
||||
template<xref:#unordered_multiset_convertible_to_from_range_t[__convertible-to-from-range_t__] FromRangeT,
|
||||
std::ranges::input_range R, class Allocator>
|
||||
unordered_multiset(FromRangeT&&, R&&, Allocator)
|
||||
-> unordered_multiset<std::ranges::range_value_t<R>,
|
||||
boost::hash<std::ranges::range_value_t<R>>,
|
||||
std::equal_to<std::ranges::range_value_t<R>>, Allocator>;
|
||||
|
||||
template<xref:#unordered_multiset_convertible_to_from_range_t[__convertible-to-from-range_t__] FromRangeT,
|
||||
std::ranges::input_range R, class Hash, class Allocator>
|
||||
unordered_multiset(FromRangeT&&, R&&, typename xref:#unordered_multiset_deduction_guides[__see below__]::size_type, Hash,
|
||||
Allocator)
|
||||
-> unordered_multiset<std::ranges::range_value_t<R>,
|
||||
Hash, std::equal_to<std::ranges::range_value_t<R>>, Allocator>;
|
||||
|
||||
template<class T, class Allocator>
|
||||
unordered_multiset(std::initializer_list<T>, typename xref:#unordered_multiset_deduction_guides[__see below__]::size_type, Allocator)
|
||||
-> unordered_multiset<T, boost::hash<T>, std::equal_to<T>, Allocator>;
|
||||
@@ -329,6 +375,15 @@ See node_handle_set for details.
|
||||
|
||||
=== Constructors
|
||||
|
||||
==== __container-compatible-range__
|
||||
[listings,subs="+macros,+quotes"]
|
||||
-----
|
||||
template<class R, class T>
|
||||
concept container_compatible_range =
|
||||
std::ranges::input_range<R> &&
|
||||
std::convertible_to<std::ranges::range_reference_t<R>, T>; // exposition only
|
||||
-----
|
||||
|
||||
==== Default Constructor
|
||||
```c++
|
||||
unordered_multiset();
|
||||
@@ -451,6 +506,27 @@ Requires:;; `value_type` is move insertable.
|
||||
|
||||
---
|
||||
|
||||
==== Range Constructor
|
||||
[source,c++,subs="+macros,+quotes"]
|
||||
----
|
||||
template<class FromRangeT, xref:#unordered_multiset_container_compatible_range[__container-compatible-range__]<value_type> R>
|
||||
unordered_multiset(FromRangeT&&, R&& rg,
|
||||
size_type n = _implementation-defined_,
|
||||
const hasher& hf = hasher(),
|
||||
const key_equal& eql = key_equal(),
|
||||
const allocator_type& a = allocator_type());
|
||||
----
|
||||
|
||||
Constructs an empty container with at least `n` buckets, using `hf` as the hash function, `eql` as the key equality predicate, `a` as the allocator and a maximum load factor of `1.0` and inserts the elements from `rg` into it.
|
||||
|
||||
Only participates in overload resolution if `FromRangeT` is convertible to `std::from_range_t` or `boost::unordered::from_range_t`.
|
||||
|
||||
|
||||
[horizontal]
|
||||
Requires:;; If the defaults are used, `hasher`, `key_equal` and `allocator_type` need to be https://en.cppreference.com/w/cpp/named_req/DefaultConstructible[DefaultConstructible^].
|
||||
|
||||
---
|
||||
|
||||
==== Initializer List Constructor
|
||||
[source,c++,subs="+quotes"]
|
||||
----
|
||||
@@ -523,6 +599,58 @@ Requires:;; `key_equal` needs to be https://en.cppreference.com/w/cpp/named_req/
|
||||
|
||||
---
|
||||
|
||||
==== Range Constructor with Allocator
|
||||
|
||||
[source,c++,subs="+macros,+quotes"]
|
||||
----
|
||||
template<class FromRangeT, xref:#unordered_multiset_container_compatible_range[__container-compatible-range__]<value_type> R>
|
||||
unordered_multiset(FromRangeT&&, R&& rg, const allocator_type& a);
|
||||
----
|
||||
|
||||
Constructs an empty container using `a` as the allocator and a maximum load factor of 1.0 and inserts the elements from `rg` into it.
|
||||
|
||||
Only participates in overload resolution if `FromRangeT` is convertible to `std::from_range_t` or `boost::unordered::from_range_t`.
|
||||
|
||||
[horizontal]
|
||||
Requires:;; `hasher` and `key_equal` need to be https://en.cppreference.com/w/cpp/named_req/DefaultConstructible[DefaultConstructible^].
|
||||
|
||||
---
|
||||
|
||||
==== Range Constructor with Bucket Count and Allocator
|
||||
|
||||
[source,c++,subs="+macros,+quotes"]
|
||||
----
|
||||
template<class FromRangeT, xref:#unordered_multiset_container_compatible_range[__container-compatible-range__]<value_type> R>
|
||||
unordered_multiset(FromRangeT&&, R&& rg, size_type n, const allocator_type& a);
|
||||
----
|
||||
|
||||
Constructs an empty container with at least `n` buckets, using `a` as the allocator and a maximum load factor of 1.0 and inserts the elements from `rg` into it.
|
||||
|
||||
Only participates in overload resolution if `FromRangeT` is convertible to `std::from_range_t` or `boost::unordered::from_range_t`.
|
||||
|
||||
[horizontal]
|
||||
Requires:;; `hasher` and `key_equal` need to be https://en.cppreference.com/w/cpp/named_req/DefaultConstructible[DefaultConstructible^].
|
||||
|
||||
---
|
||||
|
||||
==== Range Constructor with Bucket Count and Hasher and Allocator
|
||||
|
||||
[source,c++,subs="+macros,+quotes"]
|
||||
----
|
||||
template<class FromRangeT, xref:#unordered_multiset_container_compatible_range[__container-compatible-range__]<value_type> R>
|
||||
unordered_multiset(FromRangeT&&, R&& rg, size_type n, const hasher& hf,
|
||||
const allocator_type& a);
|
||||
----
|
||||
|
||||
Constructs an empty container with at least `n` buckets, using `hf` as the hash function, `a` as the allocator and a maximum load factor of 1.0 and inserts the elements from `rg` into it.
|
||||
|
||||
Only participates in overload resolution if `FromRangeT` is convertible to `std::from_range_t` or `boost::unordered::from_range_t`.
|
||||
|
||||
[horizontal]
|
||||
Requires:;; `key_equal` needs to be https://en.cppreference.com/w/cpp/named_req/DefaultConstructible[DefaultConstructible^].
|
||||
|
||||
---
|
||||
|
||||
==== initializer_list Constructor with Allocator
|
||||
|
||||
```c++
|
||||
@@ -831,12 +959,30 @@ Pointers and references to elements are never invalidated.
|
||||
|
||||
---
|
||||
|
||||
==== Insert Range
|
||||
[source,c++,subs="+macros,+quotes"]
|
||||
----
|
||||
template<xref:#unordered_multiset_container_compatible_range[__container-compatible-range__]<value_type> R>
|
||||
void insert_range(R&& rg);
|
||||
----
|
||||
|
||||
Inserts a range of elements into the container.
|
||||
|
||||
[horizontal]
|
||||
Requires:;; `value_type` is https://en.cppreference.com/w/cpp/named_req/EmplaceConstructible[EmplaceConstructible^] into the container from `*std::ranges::begin(rg)`.
|
||||
Throws:;; When inserting a single element, if an exception is thrown by an operation other than a call to `hasher` the function has no effect.
|
||||
Notes:;; Can invalidate iterators, but only if the insert causes the load factor to be greater to or equal to the maximum load factor. +
|
||||
+
|
||||
Pointers and references to elements are never invalidated.
|
||||
|
||||
---
|
||||
|
||||
==== Insert Initializer List
|
||||
```c++
|
||||
void insert(std::initializer_list<value_type> il);
|
||||
```
|
||||
|
||||
Inserts a range of elements into the container. Elements are inserted if and only if there is no element in the container with an equivalent key.
|
||||
Inserts a range of elements into the container.
|
||||
|
||||
[horizontal]
|
||||
Requires:;; `value_type` is https://en.cppreference.com/w/cpp/named_req/CopyInsertable[CopyInsertable^] into the container.
|
||||
@@ -1346,6 +1492,16 @@ template<class InputIterator>
|
||||
typename std::iterator_traits<InputIterator>::value_type; // exposition only
|
||||
-----
|
||||
|
||||
==== __convertible-to-from-range_t__
|
||||
[listings,subs="+macros,+quotes"]
|
||||
-----
|
||||
template<typename FromRangeT>
|
||||
concept __convertible-to-from_range_t__ =
|
||||
// first clause not present if std::from_range_t does not exist
|
||||
std::is_convertible_v<FromRangeT, std::from_range_t> ||
|
||||
std::is_convertible_v<FromRangeT, boost::unordered::from_range_t>; // exposition only
|
||||
-----
|
||||
|
||||
=== Equality Comparisons
|
||||
|
||||
==== operator==
|
||||
|
||||
@@ -81,6 +81,12 @@ namespace unordered {
|
||||
xref:#unordered_node_map_copy_constructor_with_allocator[unordered_node_map](const unordered_node_map& other, const Allocator& a);
|
||||
xref:#unordered_node_map_move_constructor_with_allocator[unordered_node_map](unordered_node_map&& other, const Allocator& a);
|
||||
xref:#unordered_node_map_move_constructor_from_concurrent_node_map[unordered_node_map](concurrent_node_map<Key, T, Hash, Pred, Allocator>&& other);
|
||||
template<class FromRangeT, xref:#unordered_node_map_container_compatible_range[__container-compatible-range__]<value_type> R>
|
||||
xref:#unordered_node_map_range_constructor[unordered_node_map](FromRangeT&&, R&& rg,
|
||||
size_type n = _implementation-defined_,
|
||||
const hasher& hf = hasher(),
|
||||
const key_equal& eql = key_equal(),
|
||||
const allocator_type& a = allocator_type());
|
||||
xref:#unordered_node_map_initializer_list_constructor[unordered_node_map](std::initializer_list<value_type> il,
|
||||
size_type n = _implementation-defined_
|
||||
const hasher& hf = hasher(),
|
||||
@@ -93,6 +99,13 @@ namespace unordered {
|
||||
template<class InputIterator>
|
||||
xref:#unordered_node_map_iterator_range_constructor_with_bucket_count_and_hasher[unordered_node_map](InputIterator f, InputIterator l, size_type n, const hasher& hf,
|
||||
const allocator_type& a);
|
||||
template<class FromRangeT, xref:#unordered_node_map_container_compatible_range[__container-compatible-range__]<value_type> R>
|
||||
xref:#unordered_node_map_range_constructor_with_allocator[unordered_node_map](FromRangeT&&, R&& rg, const allocator_type& a);
|
||||
template<class FromRangeT, xref:#unordered_node_map_container_compatible_range[__container-compatible-range__]<value_type> R>
|
||||
xref:#unordered_node_map_range_constructor_with_bucket_count_and_allocator[unordered_node_map](FromRangeT&&, R&& rg, size_type n, const allocator_type& a);
|
||||
template<class FromRangeT, xref:#unordered_node_map_container_compatible_range[__container-compatible-range__]<value_type> R>
|
||||
xref:#unordered_node_map_range_constructor_with_bucket_count_and_hasher_and_allocator[unordered_node_map](FromRangeT&&, R&& rg, size_type n, const hasher& hf,
|
||||
const allocator_type& a);
|
||||
xref:#unordered_node_map_initializer_list_constructor_with_allocator[unordered_node_map](std::initializer_list<value_type> il, const allocator_type& a);
|
||||
xref:#unordered_node_map_initializer_list_constructor_with_bucket_count_and_allocator[unordered_node_map](std::initializer_list<value_type> il, size_type n,
|
||||
const allocator_type& a);
|
||||
@@ -132,6 +145,8 @@ namespace unordered {
|
||||
iterator xref:#unordered_node_map_move_insert_with_hint[insert](const_iterator hint, value_type&& obj);
|
||||
iterator xref:#unordered_node_map_copy_insert_with_hint[insert](const_iterator hint, init_type&& obj);
|
||||
template<class InputIterator> void xref:#unordered_node_map_insert_iterator_range[insert](InputIterator first, InputIterator last);
|
||||
template<xref:#unordered_node_map_container_compatible_range[__container-compatible-range__]<value_type> R>
|
||||
void xref:#unordered_node_map_insert_range[insert_range](R&& rg);
|
||||
void xref:#unordered_node_map_insert_initializer_list[insert](std::initializer_list<value_type>);
|
||||
insert_return_type xref:#unordered_node_map_insert_node[insert](node_type&& nh);
|
||||
iterator xref:#unordered_node_map_insert_node_with_hint[insert](const_iterator hint, node_type&& nh);
|
||||
@@ -239,6 +254,17 @@ namespace unordered {
|
||||
-> unordered_node_map<xref:#unordered_node_map_iter_key_type[__iter-key-type__]<InputIterator>, xref:#unordered_node_map_iter_mapped_type[__iter-mapped-type__]<InputIterator>, Hash,
|
||||
Pred, Allocator>;
|
||||
|
||||
template<xref:#unordered_node_map_convertible_to_from_range_t[__convertible-to-from-range_t__] FromRangeT,
|
||||
std::ranges::input_range R,
|
||||
class Hash = boost::hash<xref:#unordered_node_map_range_key_type[__range-key-type__]<R>>,
|
||||
class Pred = std::equal_to<xref:#unordered_node_map_range_key_type[__range-key-type__]<R>>,
|
||||
class Allocator = std::allocator<xref:#unordered_node_map_range_to_alloc_type[__range-to-alloc-type__]<R>>>
|
||||
unordered_node_map(FromRangeT&&, R&&,
|
||||
typename xref:#unordered_node_map_deduction_guides[__see below__]::size_type = xref:#unordered_node_map_deduction_guides[__see below__], Hash = Hash(),
|
||||
Pred = Pred(), Allocator = Allocator())
|
||||
-> unordered_node_map<xref:#unordered_node_map_range_key_type[__range-key-type__]<R>, xref:#unordered_node_map_range_mapped_type[__range-mapped-type__]<R>,
|
||||
Hash, Pred,Allocator>;
|
||||
|
||||
template<class Key, class T, class Hash = boost::hash<Key>,
|
||||
class Pred = std::equal_to<Key>,
|
||||
class Allocator = std::allocator<std::pair<const Key, T>>>
|
||||
@@ -265,6 +291,27 @@ namespace unordered {
|
||||
-> unordered_node_map<xref:#unordered_node_map_iter_key_type[__iter-key-type__]<InputIterator>, xref:#unordered_node_map_iter_mapped_type[__iter-mapped-type__]<InputIterator>, Hash,
|
||||
std::equal_to<xref:#unordered_node_map_iter_key_type[__iter-key-type__]<InputIterator>>, Allocator>;
|
||||
|
||||
template<xref:#unordered_node_map_convertible_to_from_range_t[__convertible-to-from-range_t__] FromRangeT,
|
||||
std::ranges::input_range R, class Allocator>
|
||||
unordered_node_map(FromRangeT&&, R&&, typename xref:#unordered_node_map_deduction_guides[__see below__]::size_type, Allocator)
|
||||
-> unordered_node_map<xref:#unordered_node_map_range_key_type[__range-key-type__]<R>, xref:#unordered_node_map_range_mapped_type[__range-mapped-type__]<R>,
|
||||
boost::hash<xref:#unordered_node_map_range_key_type[__range-key-type__]<R>>,
|
||||
std::equal_to<xref:#unordered_node_map_range_key_type[__range-key-type__]<R>>, Allocator>;
|
||||
|
||||
template<xref:#unordered_node_map_convertible_to_from_range_t[__convertible-to-from-range_t__] FromRangeT,
|
||||
std::ranges::input_range R, class Allocator>
|
||||
unordered_node_map(FromRangeT&&, R&&, Allocator)
|
||||
-> unordered_node_map<xref:#unordered_node_map_range_key_type[__range-key-type__]<R>, xref:#unordered_node_map_range_mapped_type[__range-mapped-type__]<R>,
|
||||
boost::hash<xref:#unordered_node_map_range_key_type[__range-key-type__]<R>>,
|
||||
std::equal_to<xref:#unordered_node_map_range_key_type[__range-key-type__]<R>>, Allocator>;
|
||||
|
||||
template<xref:#unordered_node_map_convertible_to_from_range_t[__convertible-to-from-range_t__] FromRangeT,
|
||||
std::ranges::input_range R, class Hash, class Allocator>
|
||||
unordered_node_map(FromRangeT&&, R&&, typename xref:#unordered_node_map_deduction_guides[__see below__]::size_type, Hash,
|
||||
Allocator)
|
||||
-> unordered_node_map<xref:#unordered_node_map_range_key_type[__range-key-type__]<R>, xref:#unordered_node_map_range_mapped_type[__range-mapped-type__]<R>,
|
||||
Hash, std::equal_to<xref:#unordered_node_map_range_key_type[__range-key-type__]<R>>, Allocator>;
|
||||
|
||||
template<class Key, class T, class Allocator>
|
||||
unordered_node_map(std::initializer_list<std::pair<Key, T>>, typename xref:#unordered_node_map_deduction_guides[__see below__]::size_type,
|
||||
Allocator)
|
||||
@@ -395,6 +442,15 @@ with `Iterator` = `iterator` and `NodeType` = `node_type`.
|
||||
|
||||
=== Constructors
|
||||
|
||||
==== __container-compatible-range__
|
||||
[listings,subs="+macros,+quotes"]
|
||||
-----
|
||||
template<class R, class T>
|
||||
concept container_compatible_range =
|
||||
std::ranges::input_range<R> &&
|
||||
std::convertible_to<std::ranges::range_reference_t<R>, T>; // exposition only
|
||||
-----
|
||||
|
||||
==== Default Constructor
|
||||
```c++
|
||||
unordered_node_map();
|
||||
@@ -530,6 +586,27 @@ Concurrency:;; Blocking on `other`.
|
||||
|
||||
---
|
||||
|
||||
==== Range Constructor
|
||||
[source,c++,subs="+macros,+quotes"]
|
||||
----
|
||||
template<class FromRangeT, xref:#unordered_node_map_container_compatible_range[__container-compatible-range__]<value_type> R>
|
||||
unordered_node_map(FromRangeT&&, R&& rg,
|
||||
size_type n = _implementation-defined_,
|
||||
const hasher& hf = hasher(),
|
||||
const key_equal& eql = key_equal(),
|
||||
const allocator_type& a = allocator_type());
|
||||
----
|
||||
|
||||
Constructs an empty container with at least `n` buckets, using `hf` as the hash function, `eql` as the key equality predicate and `a` as the allocator, and inserts the elements from `rg` into it.
|
||||
|
||||
Only participates in overload resolution if `FromRangeT` is convertible to `std::from_range_t` or `boost::unordered::from_range_t`.
|
||||
|
||||
|
||||
[horizontal]
|
||||
Requires:;; If the defaults are used, `hasher`, `key_equal` and `allocator_type` need to be https://en.cppreference.com/w/cpp/named_req/DefaultConstructible[DefaultConstructible^].
|
||||
|
||||
---
|
||||
|
||||
==== Initializer List Constructor
|
||||
[source,c++,subs="+quotes"]
|
||||
----
|
||||
@@ -540,7 +617,7 @@ unordered_node_map(std::initializer_list<value_type> il,
|
||||
const allocator_type& a = allocator_type());
|
||||
----
|
||||
|
||||
Constructs an empty container with at least `n` buckets, using `hf` as the hash function, `eql` as the key equality predicate and `a`, and inserts the elements from `il` into it.
|
||||
Constructs an empty container with at least `n` buckets, using `hf` as the hash function, `eql` as the key equality predicate and `a` as the allocator, and inserts the elements from `il` into it.
|
||||
|
||||
[horizontal]
|
||||
Requires:;; If the defaults are used, `hasher`, `key_equal` and `allocator_type` need to be https://en.cppreference.com/w/cpp/named_req/DefaultConstructible[DefaultConstructible^].
|
||||
@@ -602,6 +679,58 @@ Requires:;; `key_equal` needs to be https://en.cppreference.com/w/cpp/named_req/
|
||||
|
||||
---
|
||||
|
||||
==== Range Constructor with Allocator
|
||||
|
||||
[source,c++,subs="+macros,+quotes"]
|
||||
----
|
||||
template<class FromRangeT, xref:#unordered_node_map_container_compatible_range[__container-compatible-range__]<value_type> R>
|
||||
unordered_node_map(FromRangeT&&, R&& rg, const allocator_type& a);
|
||||
----
|
||||
|
||||
Constructs an empty container using `a` and default hash function and key equality predicate, and inserts the elements from `rg` into it.
|
||||
|
||||
Only participates in overload resolution if `FromRangeT` is convertible to `std::from_range_t` or `boost::unordered::from_range_t`.
|
||||
|
||||
[horizontal]
|
||||
Requires:;; `hasher` and `key_equal` need to be https://en.cppreference.com/w/cpp/named_req/DefaultConstructible[DefaultConstructible^].
|
||||
|
||||
---
|
||||
|
||||
==== Range Constructor with Bucket Count and Allocator
|
||||
|
||||
[source,c++,subs="+macros,+quotes"]
|
||||
----
|
||||
template<class FromRangeT, xref:#unordered_node_map_container_compatible_range[__container-compatible-range__]<value_type> R>
|
||||
unordered_node_map(FromRangeT&&, R&& rg, size_type n, const allocator_type& a);
|
||||
----
|
||||
|
||||
Constructs an empty container with at least `n` buckets, using `a` and default hash function and key equality predicate, and inserts the elements from `rg` into it.
|
||||
|
||||
Only participates in overload resolution if `FromRangeT` is convertible to `std::from_range_t` or `boost::unordered::from_range_t`.
|
||||
|
||||
[horizontal]
|
||||
Requires:;; `hasher` and `key_equal` need to be https://en.cppreference.com/w/cpp/named_req/DefaultConstructible[DefaultConstructible^].
|
||||
|
||||
---
|
||||
|
||||
==== Range Constructor with Bucket Count and Hasher and Allocator
|
||||
|
||||
[source,c++,subs="+macros,+quotes"]
|
||||
----
|
||||
template<class FromRangeT, xref:#unordered_node_map_container_compatible_range[__container-compatible-range__]<value_type> R>
|
||||
unordered_node_map(FromRangeT&&, R&& rg, size_type n, const hasher& hf,
|
||||
const allocator_type& a);
|
||||
----
|
||||
|
||||
Constructs an empty container with at least `n` buckets, using `hf` as the hash function, `a` as the allocator and default key equality predicate, and inserts the elements from `rg` into it.
|
||||
|
||||
Only participates in overload resolution if `FromRangeT` is convertible to `std::from_range_t` or `boost::unordered::from_range_t`.
|
||||
|
||||
[horizontal]
|
||||
Requires:;; `key_equal` needs to be https://en.cppreference.com/w/cpp/named_req/DefaultConstructible[DefaultConstructible^].
|
||||
|
||||
---
|
||||
|
||||
==== initializer_list Constructor with Allocator
|
||||
|
||||
```c++
|
||||
@@ -918,6 +1047,22 @@ Notes:;; Can invalidate iterators, but only if the insert causes the load to be
|
||||
|
||||
---
|
||||
|
||||
==== Insert Range
|
||||
[source,c++,subs="+macros,+quotes"]
|
||||
----
|
||||
template<xref:#unordered_node_map_container_compatible_range[__container-compatible-range__]<value_type> R>
|
||||
void insert_range(R&& rg);
|
||||
----
|
||||
|
||||
Inserts a range of elements into the container. Elements are inserted if and only if there is no element in the container with an equivalent key.
|
||||
|
||||
[horizontal]
|
||||
Requires:;; `value_type` is https://en.cppreference.com/w/cpp/named_req/EmplaceConstructible[EmplaceConstructible^] into the container from `*std::ranges::begin(rg)`.
|
||||
Throws:;; When inserting a single element, if an exception is thrown by an operation other than a call to `hasher` the function has no effect.
|
||||
Notes:;; Can invalidate iterators, but only if the insert causes the load to be greater than the maximum load.
|
||||
|
||||
---
|
||||
|
||||
==== Insert Initializer List
|
||||
```c++
|
||||
void insert(std::initializer_list<value_type>);
|
||||
@@ -1549,6 +1694,42 @@ template<class InputIterator>
|
||||
std::tuple_element_t<1, xref:#unordered_node_map_iter_value_type[__iter-value-type__]<InputIterator>>>; // exposition only
|
||||
-----
|
||||
|
||||
==== __convertible-to-from-range_t__
|
||||
[listings,subs="+macros,+quotes"]
|
||||
-----
|
||||
template<typename FromRangeT>
|
||||
concept __convertible-to-from_range_t__ =
|
||||
// first clause not present if std::from_range_t does not exist
|
||||
std::is_convertible_v<FromRangeT, std::from_range_t> ||
|
||||
std::is_convertible_v<FromRangeT, boost::unordered::from_range_t>; // exposition only
|
||||
-----
|
||||
|
||||
==== __range-key-type__
|
||||
[listings,subs="+macros,+quotes"]
|
||||
-----
|
||||
template<std::ranges::input_range R>
|
||||
using __range-key-type__ =
|
||||
std::remove_cvref_t<
|
||||
std::tuple_element_t<0, std::ranges::range_value_t<R>>>; // exposition only
|
||||
-----
|
||||
|
||||
==== __range-mapped-type__
|
||||
[listings,subs="+macros,+quotes"]
|
||||
-----
|
||||
template<std::ranges::input_range R>
|
||||
using __range-mapped-type__ =
|
||||
std::remove_cvref_t<
|
||||
std::tuple_element_t<1, std::ranges::range_value_t<R>>>; // exposition only
|
||||
-----
|
||||
|
||||
==== __range-to-alloc-type__
|
||||
[listings,subs="+macros,+quotes"]
|
||||
-----
|
||||
template<std::ranges::input_range R>
|
||||
using __range-to-alloc-type__ =
|
||||
std::pair<const xref:#unordered_node_map_range_key_type[__range-key-type__]<R>, xref:#unordered_node_map_range_mapped_type[__range-mapped-type__]<R>>; // exposition only
|
||||
-----
|
||||
|
||||
=== Equality Comparisons
|
||||
|
||||
==== operator==
|
||||
|
||||
@@ -76,6 +76,12 @@ namespace unordered {
|
||||
xref:#unordered_node_set_copy_constructor_with_allocator[unordered_node_set](const unordered_node_set& other, const Allocator& a);
|
||||
xref:#unordered_node_set_move_constructor_with_allocator[unordered_node_set](unordered_node_set&& other, const Allocator& a);
|
||||
xref:#unordered_node_set_move_constructor_from_concurrent_node_set[unordered_node_set](concurrent_node_set<Key, Hash, Pred, Allocator>&& other);
|
||||
template<class FromRangeT, xref:#unordered_node_set_container_compatible_range[__container-compatible-range__]<value_type> R>
|
||||
xref:#unordered_node_set_range_constructor[unordered_node_set](FromRangeT&&, R&& rg,
|
||||
size_type n = _implementation-defined_,
|
||||
const hasher& hf = hasher(),
|
||||
const key_equal& eql = key_equal(),
|
||||
const allocator_type& a = allocator_type());
|
||||
xref:#unordered_node_set_initializer_list_constructor[unordered_node_set](std::initializer_list<value_type> il,
|
||||
size_type n = _implementation-defined_
|
||||
const hasher& hf = hasher(),
|
||||
@@ -88,6 +94,13 @@ namespace unordered {
|
||||
template<class InputIterator>
|
||||
xref:#unordered_node_set_iterator_range_constructor_with_bucket_count_and_hasher[unordered_node_set](InputIterator f, InputIterator l, size_type n, const hasher& hf,
|
||||
const allocator_type& a);
|
||||
template<class FromRangeT, xref:#unordered_node_set_container_compatible_range[__container-compatible-range__]<value_type> R>
|
||||
xref:#unordered_node_set_range_constructor_with_allocator[unordered_node_set](FromRangeT&&, R&& rg, const allocator_type& a);
|
||||
template<class FromRangeT, xref:#unordered_node_set_container_compatible_range[__container-compatible-range__]<value_type> R>
|
||||
xref:#unordered_node_set_range_constructor_with_bucket_count_and_allocator[unordered_node_set](FromRangeT&&, R&& rg, size_type n, const allocator_type& a);
|
||||
template<class FromRangeT, xref:#unordered_node_set_container_compatible_range[__container-compatible-range__]<value_type> R>
|
||||
xref:#unordered_node_set_range_constructor_with_bucket_count_and_hasher_and_allocator[unordered_node_set](FromRangeT&&, R&& rg, size_type n, const hasher& hf,
|
||||
const allocator_type& a);
|
||||
xref:#unordered_node_set_initializer_list_constructor_with_allocator[unordered_node_set](std::initializer_list<value_type> il, const allocator_type& a);
|
||||
xref:#unordered_node_set_initializer_list_constructor_with_bucket_count_and_allocator[unordered_node_set](std::initializer_list<value_type> il, size_type n,
|
||||
const allocator_type& a);
|
||||
@@ -125,6 +138,8 @@ namespace unordered {
|
||||
iterator xref:#unordered_node_set_move_insert_with_hint[insert](const_iterator hint, value_type&& obj);
|
||||
template<class K> iterator xref:#unordered_node_set_transparent_insert_with_hint[insert](const_iterator hint, K&& k);
|
||||
template<class InputIterator> void xref:#unordered_node_set_insert_iterator_range[insert](InputIterator first, InputIterator last);
|
||||
template<xref:#unordered_node_set_container_compatible_range[__container-compatible-range__]<value_type> R>
|
||||
void xref:#unordered_node_set_insert_range[insert_range](R&& rg);
|
||||
void xref:#unordered_node_set_insert_initializer_list[insert](std::initializer_list<value_type>);
|
||||
insert_return_type xref:#unordered_node_set_insert_node[insert](node_type&& nh);
|
||||
iterator xref:#unordered_node_set_insert_node_with_hint[insert](const_iterator hint, node_type&& nh);
|
||||
@@ -197,6 +212,16 @@ namespace unordered {
|
||||
Hash = Hash(), Pred = Pred(), Allocator = Allocator())
|
||||
-> unordered_node_set<xref:#unordered_node_set_iter_value_type[__iter-value-type__]<InputIterator>, Hash, Pred, Allocator>;
|
||||
|
||||
template<xref:#unordered_node_set_convertible_to_from_range_t[__convertible-to-from-range_t__] FromRangeT,
|
||||
std::ranges::input_range R,
|
||||
class Hash = boost::hash<std::ranges::range_value_t<R>>,
|
||||
class Pred = std::equal_to<std::ranges::range_value_t<R>>,
|
||||
class Allocator = std::allocator<std::ranges::range_value_t<R>>
|
||||
unordered_node_set(FromRangeT&&, R&&,
|
||||
typename xref:#unordered_node_set_deduction_guides[__see below__]::size_type = xref:#unordered_node_set_deduction_guides[__see below__], Hash = Hash(),
|
||||
Pred = Pred(), Allocator = Allocator())
|
||||
-> unordered_node_set<std::ranges::range_value_t<R>, Hash, Pred,Allocator>;
|
||||
|
||||
template<class T, class Hash = boost::hash<T>, class Pred = std::equal_to<T>,
|
||||
class Allocator = std::allocator<T>>
|
||||
unordered_node_set(std::initializer_list<T>, typename xref:#unordered_node_set_deduction_guides[__see below__]::size_type = xref:#unordered_node_set_deduction_guides[__see below__],
|
||||
@@ -221,6 +246,27 @@ namespace unordered {
|
||||
-> unordered_node_set<xref:#unordered_node_set_iter_value_type[__iter-value-type__]<InputIterator>, Hash,
|
||||
std::equal_to<xref:#unordered_node_set_iter_value_type[__iter-value-type__]<InputIterator>>, Allocator>;
|
||||
|
||||
template<xref:#unordered_node_set_convertible_to_from_range_t[__convertible-to-from-range_t__] FromRangeT,
|
||||
std::ranges::input_range R, class Allocator>
|
||||
unordered_node_set(FromRangeT&&, R&&, typename xref:#unordered_node_set_deduction_guides[__see below__]::size_type, Allocator)
|
||||
-> unordered_node_set<std::ranges::range_value_t<R>,
|
||||
boost::hash<std::ranges::range_value_t<R>>,
|
||||
std::equal_to<std::ranges::range_value_t<R>>, Allocator>;
|
||||
|
||||
template<xref:#unordered_node_set_convertible_to_from_range_t[__convertible-to-from-range_t__] FromRangeT,
|
||||
std::ranges::input_range R, class Allocator>
|
||||
unordered_node_set(FromRangeT&&, R&&, Allocator)
|
||||
-> unordered_node_set<std::ranges::range_value_t<R>,
|
||||
boost::hash<std::ranges::range_value_t<R>>,
|
||||
std::equal_to<std::ranges::range_value_t<R>>, Allocator>;
|
||||
|
||||
template<xref:#unordered_node_set_convertible_to_from_range_t[__convertible-to-from-range_t__] FromRangeT,
|
||||
std::ranges::input_range R, class Hash, class Allocator>
|
||||
unordered_node_set(FromRangeT&&, R&&, typename xref:#unordered_node_set_deduction_guides[__see below__]::size_type, Hash,
|
||||
Allocator)
|
||||
-> unordered_node_set<std::ranges::range_value_t<R>,
|
||||
Hash, std::equal_to<std::ranges::range_value_t<R>>, Allocator>;
|
||||
|
||||
template<class T, class Allocator>
|
||||
unordered_node_set(std::initializer_list<T>, typename xref:#unordered_node_set_deduction_guides[__see below__]::size_type, Allocator)
|
||||
-> unordered_node_set<T, boost::hash<T>, std::equal_to<T>, Allocator>;
|
||||
@@ -345,6 +391,15 @@ with `Iterator` = `iterator` and `NodeType` = `node_type`.
|
||||
|
||||
=== Constructors
|
||||
|
||||
==== __container-compatible-range__
|
||||
[listings,subs="+macros,+quotes"]
|
||||
-----
|
||||
template<class R, class T>
|
||||
concept container_compatible_range =
|
||||
std::ranges::input_range<R> &&
|
||||
std::convertible_to<std::ranges::range_reference_t<R>, T>; // exposition only
|
||||
-----
|
||||
|
||||
==== Default Constructor
|
||||
```c++
|
||||
unordered_node_set();
|
||||
@@ -483,6 +538,27 @@ Concurrency:;; Blocking on `other`.
|
||||
|
||||
---
|
||||
|
||||
==== Range Constructor
|
||||
[source,c++,subs="+macros,+quotes"]
|
||||
----
|
||||
template<class FromRangeT, xref:#unordered_node_set_container_compatible_range[__container-compatible-range__]<value_type> R>
|
||||
unordered_node_set(FromRangeT&&, R&& rg,
|
||||
size_type n = _implementation-defined_,
|
||||
const hasher& hf = hasher(),
|
||||
const key_equal& eql = key_equal(),
|
||||
const allocator_type& a = allocator_type());
|
||||
----
|
||||
|
||||
Constructs an empty container with at least `n` buckets, using `hf` as the hash function, `eql` as the key equality predicate and `a` as the allocator, and inserts the elements from `rg` into it.
|
||||
|
||||
Only participates in overload resolution if `FromRangeT` is convertible to `std::from_range_t` or `boost::unordered::from_range_t`.
|
||||
|
||||
|
||||
[horizontal]
|
||||
Requires:;; If the defaults are used, `hasher`, `key_equal` and `allocator_type` need to be https://en.cppreference.com/w/cpp/named_req/DefaultConstructible[DefaultConstructible^].
|
||||
|
||||
---
|
||||
|
||||
==== Initializer List Constructor
|
||||
[source,c++,subs="+quotes"]
|
||||
----
|
||||
@@ -555,6 +631,58 @@ Requires:;; `key_equal` needs to be https://en.cppreference.com/w/cpp/named_req/
|
||||
|
||||
---
|
||||
|
||||
==== Range Constructor with Allocator
|
||||
|
||||
[source,c++,subs="+macros,+quotes"]
|
||||
----
|
||||
template<class FromRangeT, xref:#unordered_node_set_container_compatible_range[__container-compatible-range__]<value_type> R>
|
||||
unordered_node_set(FromRangeT&&, R&& rg, const allocator_type& a);
|
||||
----
|
||||
|
||||
Constructs an empty container using `a` and default hash function and key equality predicate, and inserts the elements from `rg` into it.
|
||||
|
||||
Only participates in overload resolution if `FromRangeT` is convertible to `std::from_range_t` or `boost::unordered::from_range_t`.
|
||||
|
||||
[horizontal]
|
||||
Requires:;; `hasher` and `key_equal` need to be https://en.cppreference.com/w/cpp/named_req/DefaultConstructible[DefaultConstructible^].
|
||||
|
||||
---
|
||||
|
||||
==== Range Constructor with Bucket Count and Allocator
|
||||
|
||||
[source,c++,subs="+macros,+quotes"]
|
||||
----
|
||||
template<class FromRangeT, xref:#unordered_node_set_container_compatible_range[__container-compatible-range__]<value_type> R>
|
||||
unordered_node_set(FromRangeT&&, R&& rg, size_type n, const allocator_type& a);
|
||||
----
|
||||
|
||||
Constructs an empty container with at least `n` buckets, using `a` and default hash function and key equality predicate, and inserts the elements from `rg` into it.
|
||||
|
||||
Only participates in overload resolution if `FromRangeT` is convertible to `std::from_range_t` or `boost::unordered::from_range_t`.
|
||||
|
||||
[horizontal]
|
||||
Requires:;; `hasher` and `key_equal` need to be https://en.cppreference.com/w/cpp/named_req/DefaultConstructible[DefaultConstructible^].
|
||||
|
||||
---
|
||||
|
||||
==== Range Constructor with Bucket Count and Hasher and Allocator
|
||||
|
||||
[source,c++,subs="+macros,+quotes"]
|
||||
----
|
||||
template<class FromRangeT, xref:#unordered_node_set_container_compatible_range[__container-compatible-range__]<value_type> R>
|
||||
unordered_node_set(FromRangeT&&, R&& rg, size_type n, const hasher& hf,
|
||||
const allocator_type& a);
|
||||
----
|
||||
|
||||
Constructs an empty container with at least `n` buckets, using `hf` as the hash function, `a` as the allocator and default key equality predicate, and inserts the elements from `rg` into it.
|
||||
|
||||
Only participates in overload resolution if `FromRangeT` is convertible to `std::from_range_t` or `boost::unordered::from_range_t`.
|
||||
|
||||
[horizontal]
|
||||
Requires:;; `key_equal` needs to be https://en.cppreference.com/w/cpp/named_req/DefaultConstructible[DefaultConstructible^].
|
||||
|
||||
---
|
||||
|
||||
==== initializer_list Constructor with Allocator
|
||||
|
||||
```c++
|
||||
@@ -588,7 +716,7 @@ unordered_node_set(std::initializer_list<value_type> il, size_type n, const hash
|
||||
const allocator_type& a);
|
||||
```
|
||||
|
||||
Constructs an empty container with at least `n` buckets, using `hf` as the hash function, `a` as the allocator and default key equality predicate,and inserts the elements from `il` into it.
|
||||
Constructs an empty container with at least `n` buckets, using `hf` as the hash function, `a` as the allocator and default key equality predicate, and inserts the elements from `il` into it.
|
||||
|
||||
[horizontal]
|
||||
Requires:;; `key_equal` needs to be https://en.cppreference.com/w/cpp/named_req/DefaultConstructible[DefaultConstructible^].
|
||||
@@ -895,6 +1023,22 @@ Notes:;; Can invalidate iterators, but only if the insert causes the load to be
|
||||
|
||||
---
|
||||
|
||||
==== Insert Range
|
||||
[source,c++,subs="+macros,+quotes"]
|
||||
----
|
||||
template<xref:#unordered_node_set_container_compatible_range[__container-compatible-range__]<value_type> R>
|
||||
void insert_range(R&& rg);
|
||||
----
|
||||
|
||||
Inserts a range of elements into the container. Elements are inserted if and only if there is no element in the container with an equivalent key.
|
||||
|
||||
[horizontal]
|
||||
Requires:;; `value_type` is https://en.cppreference.com/w/cpp/named_req/EmplaceConstructible[EmplaceConstructible^] into the container from `*std::ranges::begin(rg)`.
|
||||
Throws:;; When inserting a single element, if an exception is thrown by an operation other than a call to `hasher` the function has no effect.
|
||||
Notes:;; Can invalidate iterators, but only if the insert causes the load to be greater than the maximum load.
|
||||
|
||||
---
|
||||
|
||||
==== Insert Initializer List
|
||||
```c++
|
||||
void insert(std::initializer_list<value_type>);
|
||||
@@ -1302,6 +1446,16 @@ template<class InputIterator>
|
||||
typename std::iterator_traits<InputIterator>::value_type; // exposition only
|
||||
-----
|
||||
|
||||
==== __convertible-to-from-range_t__
|
||||
[listings,subs="+macros,+quotes"]
|
||||
-----
|
||||
template<typename FromRangeT>
|
||||
concept __convertible-to-from_range_t__ =
|
||||
// first clause not present if std::from_range_t does not exist
|
||||
std::is_convertible_v<FromRangeT, std::from_range_t> ||
|
||||
std::is_convertible_v<FromRangeT, boost::unordered::from_range_t>; // exposition only
|
||||
-----
|
||||
|
||||
=== Equality Comparisons
|
||||
|
||||
==== operator==
|
||||
|
||||
@@ -59,6 +59,12 @@ namespace unordered {
|
||||
explicit xref:#unordered_set_allocator_constructor[unordered_set](const Allocator& a);
|
||||
xref:#unordered_set_copy_constructor_with_allocator[unordered_set](const unordered_set& other, const Allocator& a);
|
||||
xref:#unordered_set_move_constructor_with_allocator[unordered_set](unordered_set&& other, const Allocator& a);
|
||||
template<class FromRangeT, xref:#unordered_set_container_compatible_range[__container-compatible-range__]<value_type> R>
|
||||
xref:#unordered_set_range_constructor[unordered_set](FromRangeT&&, R&& rg,
|
||||
size_type n = _implementation-defined_,
|
||||
const hasher& hf = hasher(),
|
||||
const key_equal& eql = key_equal(),
|
||||
const allocator_type& a = allocator_type());
|
||||
xref:#unordered_set_initializer_list_constructor[unordered_set](std::initializer_list<value_type> il,
|
||||
size_type n = _implementation-defined_,
|
||||
const hasher& hf = hasher(),
|
||||
@@ -71,6 +77,13 @@ namespace unordered {
|
||||
template<class InputIterator>
|
||||
xref:#unordered_set_iterator_range_constructor_with_bucket_count_and_hasher[unordered_set](InputIterator f, InputIterator l, size_type n, const hasher& hf,
|
||||
const allocator_type& a);
|
||||
template<class FromRangeT, xref:#unordered_set_container_compatible_range[__container-compatible-range__]<value_type> R>
|
||||
xref:#unordered_set_range_constructor_with_allocator[unordered_set](FromRangeT&&, R&& rg, const allocator_type& a);
|
||||
template<class FromRangeT, xref:#unordered_set_container_compatible_range[__container-compatible-range__]<value_type> R>
|
||||
xref:#unordered_set_range_constructor_with_bucket_count_and_allocator[unordered_set](FromRangeT&&, R&& rg, size_type n, const allocator_type& a);
|
||||
template<class FromRangeT, xref:#unordered_set_container_compatible_range[__container-compatible-range__]<value_type> R>
|
||||
xref:#unordered_set_range_constructor_with_bucket_count_and_hasher_and_allocator[unordered_set](FromRangeT&&, R&& rg, size_type n, const hasher& hf,
|
||||
const allocator_type& a);
|
||||
xref:#unordered_set_initializer_list_constructor_with_allocator[unordered_set](std::initializer_list<value_type> il, const allocator_type& a);
|
||||
xref:#unordered_set_initializer_list_constructor_with_bucket_count_and_allocator[unordered_set](std::initializer_list<value_type> il, size_type n, const allocator_type& a);
|
||||
xref:#unordered_set_initializer_list_constructor_with_bucket_count_and_hasher_and_allocator[unordered_set](std::initializer_list<value_type> il, size_type n, const hasher& hf,
|
||||
@@ -107,6 +120,8 @@ namespace unordered {
|
||||
iterator xref:#unordered_set_move_insert_with_hint[insert](const_iterator hint, value_type&& obj);
|
||||
template<class K> iterator xref:#unordered_set_transparent_insert_with_hint[insert](const_iterator hint, K&& k);
|
||||
template<class InputIterator> void xref:#unordered_set_insert_iterator_range[insert](InputIterator first, InputIterator last);
|
||||
template<xref:#unordered_set_container_compatible_range[__container-compatible-range__]<value_type> R>
|
||||
void xref:#unordered_set_insert_range[insert_range](R&& rg);
|
||||
void xref:#unordered_set_insert_initializer_list[insert](std::initializer_list<value_type>);
|
||||
|
||||
node_type xref:#unordered_set_extract_by_iterator[extract](const_iterator position);
|
||||
@@ -197,6 +212,16 @@ namespace unordered {
|
||||
Hash = Hash(), Pred = Pred(), Allocator = Allocator())
|
||||
-> unordered_set<xref:#unordered_set_iter_value_type[__iter-value-type__]<InputIterator>, Hash, Pred, Allocator>;
|
||||
|
||||
template<xref:#unordered_set_convertible_to_from_range_t[__convertible-to-from-range_t__] FromRangeT,
|
||||
std::ranges::input_range R,
|
||||
class Hash = boost::hash<std::ranges::range_value_t<R>>,
|
||||
class Pred = std::equal_to<std::ranges::range_value_t<R>>,
|
||||
class Allocator = std::allocator<std::ranges::range_value_t<R>>
|
||||
unordered_set(FromRangeT&&, R&&,
|
||||
typename xref:#unordered_set_deduction_guides[__see below__]::size_type = xref:#unordered_set_deduction_guides[__see below__], Hash = Hash(),
|
||||
Pred = Pred(), Allocator = Allocator())
|
||||
-> unordered_set<std::ranges::range_value_t<R>, Hash, Pred,Allocator>;
|
||||
|
||||
template<class T, class Hash = boost::hash<T>, class Pred = std::equal_to<T>,
|
||||
class Allocator = std::allocator<T>>
|
||||
unordered_set(std::initializer_list<T>, typename xref:#unordered_set_deduction_guides[__see below__]::size_type = xref:#unordered_set_deduction_guides[__see below__],
|
||||
@@ -220,6 +245,27 @@ namespace unordered {
|
||||
-> unordered_set<xref:#unordered_set_iter_value_type[__iter-value-type__]<InputIterator>, Hash,
|
||||
std::equal_to<xref:#unordered_set_iter_value_type[__iter-value-type__]<InputIterator>>, Allocator>;
|
||||
|
||||
template<xref:#unordered_set_convertible_to_from_range_t[__convertible-to-from-range_t__] FromRangeT,
|
||||
std::ranges::input_range R, class Allocator>
|
||||
unordered_set(FromRangeT&&, R&&, typename xref:#unordered_set_deduction_guides[__see below__]::size_type, Allocator)
|
||||
-> unordered_set<std::ranges::range_value_t<R>,
|
||||
boost::hash<std::ranges::range_value_t<R>>,
|
||||
std::equal_to<std::ranges::range_value_t<R>>, Allocator>;
|
||||
|
||||
template<xref:#unordered_set_convertible_to_from_range_t[__convertible-to-from-range_t__] FromRangeT,
|
||||
std::ranges::input_range R, class Allocator>
|
||||
unordered_set(FromRangeT&&, R&&, Allocator)
|
||||
-> unordered_set<std::ranges::range_value_t<R>,
|
||||
boost::hash<std::ranges::range_value_t<R>>,
|
||||
std::equal_to<std::ranges::range_value_t<R>>, Allocator>;
|
||||
|
||||
template<xref:#unordered_set_convertible_to_from_range_t[__convertible-to-from-range_t__] FromRangeT,
|
||||
std::ranges::input_range R, class Hash, class Allocator>
|
||||
unordered_set(FromRangeT&&, R&&, typename xref:#unordered_set_deduction_guides[__see below__]::size_type, Hash,
|
||||
Allocator)
|
||||
-> unordered_set<std::ranges::range_value_t<R>,
|
||||
Hash, std::equal_to<std::ranges::range_value_t<R>>, Allocator>;
|
||||
|
||||
template<class T, class Allocator>
|
||||
unordered_set(std::initializer_list<T>, typename xref:#unordered_set_deduction_guides[__see below__]::size_type, Allocator)
|
||||
-> unordered_set<T, boost::hash<T>, std::equal_to<T>, Allocator>;
|
||||
@@ -353,6 +399,16 @@ with `Iterator` = `iterator` and `NodeType` = `node_type`.
|
||||
|
||||
=== Constructors
|
||||
|
||||
==== __container-compatible-range__
|
||||
[listings,subs="+macros,+quotes"]
|
||||
-----
|
||||
template<class R, class T>
|
||||
concept container_compatible_range =
|
||||
std::ranges::input_range<R> &&
|
||||
std::convertible_to<std::ranges::range_reference_t<R>, T>; // exposition only
|
||||
-----
|
||||
|
||||
|
||||
==== Default Constructor
|
||||
```c++
|
||||
unordered_set();
|
||||
@@ -475,6 +531,27 @@ Requires:;; `value_type` is move insertable.
|
||||
|
||||
---
|
||||
|
||||
==== Range Constructor
|
||||
[source,c++,subs="+macros,+quotes"]
|
||||
----
|
||||
template<class FromRangeT, xref:#unordered_set_container_compatible_range[__container-compatible-range__]<value_type> R>
|
||||
unordered_set(FromRangeT&&, R&& rg,
|
||||
size_type n = _implementation-defined_,
|
||||
const hasher& hf = hasher(),
|
||||
const key_equal& eql = key_equal(),
|
||||
const allocator_type& a = allocator_type());
|
||||
----
|
||||
|
||||
Constructs an empty container with at least `n` buckets, using `hf` as the hash function, `eql` as the key equality predicate, `a` as the allocator and a maximum load factor of `1.0` and inserts the elements from `rg` into it.
|
||||
|
||||
Only participates in overload resolution if `FromRangeT` is convertible to `std::from_range_t` or `boost::unordered::from_range_t`.
|
||||
|
||||
|
||||
[horizontal]
|
||||
Requires:;; If the defaults are used, `hasher`, `key_equal` and `allocator_type` need to be https://en.cppreference.com/w/cpp/named_req/DefaultConstructible[DefaultConstructible^].
|
||||
|
||||
---
|
||||
|
||||
==== Initializer List Constructor
|
||||
[source,c++,subs="+quotes"]
|
||||
----
|
||||
@@ -547,6 +624,58 @@ Requires:;; `key_equal` needs to be https://en.cppreference.com/w/cpp/named_req/
|
||||
|
||||
---
|
||||
|
||||
==== Range Constructor with Allocator
|
||||
|
||||
[source,c++,subs="+macros,+quotes"]
|
||||
----
|
||||
template<class FromRangeT, xref:#unordered_set_container_compatible_range[__container-compatible-range__]<value_type> R>
|
||||
unordered_set(FromRangeT&&, R&& rg, const allocator_type& a);
|
||||
----
|
||||
|
||||
Constructs an empty container using `a` as the allocator and a maximum load factor of 1.0 and inserts the elements from `rg` into it.
|
||||
|
||||
Only participates in overload resolution if `FromRangeT` is convertible to `std::from_range_t` or `boost::unordered::from_range_t`.
|
||||
|
||||
[horizontal]
|
||||
Requires:;; `hasher` and `key_equal` need to be https://en.cppreference.com/w/cpp/named_req/DefaultConstructible[DefaultConstructible^].
|
||||
|
||||
---
|
||||
|
||||
==== Range Constructor with Bucket Count and Allocator
|
||||
|
||||
[source,c++,subs="+macros,+quotes"]
|
||||
----
|
||||
template<class FromRangeT, xref:#unordered_set_container_compatible_range[__container-compatible-range__]<value_type> R>
|
||||
unordered_set(FromRangeT&&, R&& rg, size_type n, const allocator_type& a);
|
||||
----
|
||||
|
||||
Constructs an empty container with at least `n` buckets, using `a` as the allocator and a maximum load factor of 1.0 and inserts the elements from `rg` into it.
|
||||
|
||||
Only participates in overload resolution if `FromRangeT` is convertible to `std::from_range_t` or `boost::unordered::from_range_t`.
|
||||
|
||||
[horizontal]
|
||||
Requires:;; `hasher` and `key_equal` need to be https://en.cppreference.com/w/cpp/named_req/DefaultConstructible[DefaultConstructible^].
|
||||
|
||||
---
|
||||
|
||||
==== Range Constructor with Bucket Count and Hasher and Allocator
|
||||
|
||||
[source,c++,subs="+macros,+quotes"]
|
||||
----
|
||||
template<class FromRangeT, xref:#unordered_set_container_compatible_range[__container-compatible-range__]<value_type> R>
|
||||
unordered_set(FromRangeT&&, R&& rg, size_type n, const hasher& hf,
|
||||
const allocator_type& a);
|
||||
----
|
||||
|
||||
Constructs an empty container with at least `n` buckets, using `hf` as the hash function, `a` as the allocator and a maximum load factor of 1.0 and inserts the elements from `rg` into it.
|
||||
|
||||
Only participates in overload resolution if `FromRangeT` is convertible to `std::from_range_t` or `boost::unordered::from_range_t`.
|
||||
|
||||
[horizontal]
|
||||
Requires:;; `key_equal` needs to be https://en.cppreference.com/w/cpp/named_req/DefaultConstructible[DefaultConstructible^].
|
||||
|
||||
---
|
||||
|
||||
==== initializer_list Constructor with Allocator
|
||||
|
||||
```c++
|
||||
@@ -904,6 +1033,24 @@ Pointers and references to elements are never invalidated.
|
||||
|
||||
---
|
||||
|
||||
==== Insert Range
|
||||
[source,c++,subs="+macros,+quotes"]
|
||||
----
|
||||
template<xref:#unordered_set_container_compatible_range[__container-compatible-range__]<value_type> R>
|
||||
void insert_range(R&& rg);
|
||||
----
|
||||
|
||||
Inserts a range of elements into the container. Elements are inserted if and only if there is no element in the container with an equivalent key.
|
||||
|
||||
[horizontal]
|
||||
Requires:;; `value_type` is https://en.cppreference.com/w/cpp/named_req/EmplaceConstructible[EmplaceConstructible^] into the container from `*std::ranges::begin(rg)`.
|
||||
Throws:;; When inserting a single element, if an exception is thrown by an operation other than a call to `hasher` the function has no effect.
|
||||
Notes:;; Can invalidate iterators, but only if the insert causes the load factor to be greater to or equal to the maximum load factor. +
|
||||
+
|
||||
Pointers and references to elements are never invalidated.
|
||||
|
||||
---
|
||||
|
||||
==== Insert Initializer List
|
||||
```c++
|
||||
void insert(std::initializer_list<value_type>);
|
||||
@@ -1424,6 +1571,16 @@ template<class InputIterator>
|
||||
typename std::iterator_traits<InputIterator>::value_type; // exposition only
|
||||
-----
|
||||
|
||||
==== __convertible-to-from-range_t__
|
||||
[listings,subs="+macros,+quotes"]
|
||||
-----
|
||||
template<typename FromRangeT>
|
||||
concept __convertible-to-from_range_t__ =
|
||||
// first clause not present if std::from_range_t does not exist
|
||||
std::is_convertible_v<FromRangeT, std::from_range_t> ||
|
||||
std::is_convertible_v<FromRangeT, boost::unordered::from_range_t>; // exposition only
|
||||
-----
|
||||
|
||||
=== Equality Comparisons
|
||||
|
||||
==== operator==
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include <boost/unordered/detail/concurrent_static_asserts.hpp>
|
||||
#include <boost/unordered/detail/foa/concurrent_table.hpp>
|
||||
#include <boost/unordered/detail/foa/flat_map_types.hpp>
|
||||
#include <boost/unordered/detail/ranges_support.hpp>
|
||||
#include <boost/unordered/detail/type_traits.hpp>
|
||||
#include <boost/unordered/unordered_flat_map_fwd.hpp>
|
||||
|
||||
@@ -102,6 +103,21 @@ namespace boost {
|
||||
this->insert(f, l);
|
||||
}
|
||||
|
||||
#if !defined(BOOST_UNORDERED_NO_RANGES)
|
||||
template<
|
||||
detail::convertible_to_from_range_t FromRangeT,
|
||||
detail::container_compatible_range<value_type> R
|
||||
>
|
||||
concurrent_flat_map(FromRangeT&&, R&& rg,
|
||||
size_type n = detail::foa::default_bucket_count,
|
||||
const hasher& hf = hasher(), const key_equal& eql = key_equal(),
|
||||
const allocator_type& a = allocator_type())
|
||||
: table_(n, hf, eql, a)
|
||||
{
|
||||
this->insert_range(std::forward<R>(rg));
|
||||
}
|
||||
#endif
|
||||
|
||||
concurrent_flat_map(concurrent_flat_map const& rhs)
|
||||
: table_(rhs.table_,
|
||||
boost::allocator_select_on_container_copy_construction(
|
||||
@@ -121,6 +137,19 @@ namespace boost {
|
||||
{
|
||||
}
|
||||
|
||||
#if !defined(BOOST_UNORDERED_NO_RANGES)
|
||||
template<
|
||||
detail::convertible_to_from_range_t FromRangeT,
|
||||
detail::container_compatible_range<value_type> R
|
||||
>
|
||||
concurrent_flat_map(
|
||||
FromRangeT&& fr, R&& rg, allocator_type const& a)
|
||||
: concurrent_flat_map(
|
||||
fr, std::forward<R>(rg), 0, hasher(), key_equal(), a)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
explicit concurrent_flat_map(allocator_type const& a)
|
||||
: table_(detail::foa::default_bucket_count, hasher(), key_equal(), a)
|
||||
{
|
||||
@@ -171,6 +200,29 @@ namespace boost {
|
||||
{
|
||||
}
|
||||
|
||||
#if !defined(BOOST_UNORDERED_NO_RANGES)
|
||||
template<
|
||||
detail::convertible_to_from_range_t FromRangeT,
|
||||
detail::container_compatible_range<value_type> R
|
||||
>
|
||||
concurrent_flat_map(
|
||||
FromRangeT&& fr, R&& rg, size_type n, const allocator_type& a)
|
||||
: concurrent_flat_map(
|
||||
fr, std::forward<R>(rg), n, hasher(), key_equal(), a)
|
||||
{
|
||||
}
|
||||
|
||||
template<
|
||||
detail::convertible_to_from_range_t FromRangeT,
|
||||
detail::container_compatible_range<value_type> R
|
||||
>
|
||||
concurrent_flat_map(FromRangeT&& fr, R&& rg, size_type n,
|
||||
const hasher& hf, const allocator_type& a)
|
||||
: concurrent_flat_map(fr, std::forward<R>(rg), n, hf, key_equal(), a)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
concurrent_flat_map(
|
||||
std::initializer_list<value_type> il, const allocator_type& a)
|
||||
: concurrent_flat_map(
|
||||
@@ -430,6 +482,20 @@ namespace boost {
|
||||
return count_elements;
|
||||
}
|
||||
|
||||
#if !defined(BOOST_UNORDERED_NO_RANGES)
|
||||
template<detail::container_compatible_range<value_type> R>
|
||||
size_type insert_range(R&& rg)
|
||||
{
|
||||
size_type count_elements = 0;
|
||||
auto first = std::ranges::begin(rg);
|
||||
auto last = std::ranges::end(rg);
|
||||
while (first != last) {
|
||||
if (table_.emplace(*first++)) ++count_elements;
|
||||
}
|
||||
return count_elements;
|
||||
}
|
||||
#endif
|
||||
|
||||
size_type insert(std::initializer_list<value_type> ilist)
|
||||
{
|
||||
return this->insert(ilist.begin(), ilist.end());
|
||||
@@ -485,6 +551,21 @@ namespace boost {
|
||||
return count_elements;
|
||||
}
|
||||
|
||||
#if !defined(BOOST_UNORDERED_NO_RANGES)
|
||||
template<detail::container_compatible_range<value_type> R, class F>
|
||||
size_type insert_range_or_visit(R&& rg, F f)
|
||||
{
|
||||
BOOST_UNORDERED_STATIC_ASSERT_INVOCABLE(F)
|
||||
size_type count_elements = 0;
|
||||
auto first = std::ranges::begin(rg);
|
||||
auto last = std::ranges::end(rg);
|
||||
for (; first != last; ++first, ++count_elements) {
|
||||
table_.emplace_or_visit(*first, f);
|
||||
}
|
||||
return count_elements;
|
||||
}
|
||||
#endif
|
||||
|
||||
template <class F>
|
||||
size_type insert_or_visit(std::initializer_list<value_type> ilist, F f)
|
||||
{
|
||||
@@ -518,6 +599,21 @@ namespace boost {
|
||||
return count_elements;
|
||||
}
|
||||
|
||||
#if !defined(BOOST_UNORDERED_NO_RANGES)
|
||||
template<detail::container_compatible_range<value_type> R, class F>
|
||||
size_type insert_range_or_cvisit(R&& rg, F f)
|
||||
{
|
||||
BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F)
|
||||
size_type count_elements = 0;
|
||||
auto first = std::ranges::begin(rg);
|
||||
auto last = std::ranges::end(rg);
|
||||
for (; first != last; ++first, ++count_elements) {
|
||||
table_.emplace_or_cvisit(*first, f);
|
||||
}
|
||||
return count_elements;
|
||||
}
|
||||
#endif
|
||||
|
||||
template <class F>
|
||||
size_type insert_or_cvisit(std::initializer_list<value_type> ilist, F f)
|
||||
{
|
||||
@@ -555,6 +651,24 @@ namespace boost {
|
||||
return count_elements;
|
||||
}
|
||||
|
||||
#if !defined(BOOST_UNORDERED_NO_RANGES)
|
||||
template<
|
||||
detail::container_compatible_range<value_type> R, class F1, class F2
|
||||
>
|
||||
size_type insert_range_and_visit(R&& rg, F1 f1, F2 f2)
|
||||
{
|
||||
BOOST_UNORDERED_STATIC_ASSERT_INVOCABLE(F1)
|
||||
BOOST_UNORDERED_STATIC_ASSERT_INVOCABLE(F2)
|
||||
size_type count_elements = 0;
|
||||
auto first = std::ranges::begin(rg);
|
||||
auto last = std::ranges::end(rg);
|
||||
for (; first != last; ++first, ++count_elements) {
|
||||
table_.emplace_and_visit(*first, f1, f2);
|
||||
}
|
||||
return count_elements;
|
||||
}
|
||||
#endif
|
||||
|
||||
template <class F1, class F2>
|
||||
size_type insert_and_visit(
|
||||
std::initializer_list<value_type> ilist, F1 f1, F2 f2)
|
||||
@@ -595,6 +709,24 @@ namespace boost {
|
||||
return count_elements;
|
||||
}
|
||||
|
||||
#if !defined(BOOST_UNORDERED_NO_RANGES)
|
||||
template<
|
||||
detail::container_compatible_range<value_type> R, class F1, class F2
|
||||
>
|
||||
size_type insert_range_and_cvisit(R&& rg, F1 f1, F2 f2)
|
||||
{
|
||||
BOOST_UNORDERED_STATIC_ASSERT_INVOCABLE(F1)
|
||||
BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F2)
|
||||
size_type count_elements = 0;
|
||||
auto first = std::ranges::begin(rg);
|
||||
auto last = std::ranges::end(rg);
|
||||
for (; first != last; ++first, ++count_elements) {
|
||||
table_.emplace_and_cvisit(*first, f1, f2);
|
||||
}
|
||||
return count_elements;
|
||||
}
|
||||
#endif
|
||||
|
||||
template <class F1, class F2>
|
||||
size_type insert_and_cvisit(
|
||||
std::initializer_list<value_type> ilist, F1 f1, F2 f2)
|
||||
@@ -980,6 +1112,27 @@ namespace boost {
|
||||
boost::unordered::detail::iter_val_t<InputIterator>, Hash, Pred,
|
||||
Allocator>;
|
||||
|
||||
#if !defined(BOOST_UNORDERED_NO_RANGES)
|
||||
template <
|
||||
boost::unordered::detail::convertible_to_from_range_t FromRangeT,
|
||||
std::ranges::input_range R,
|
||||
class Hash =
|
||||
boost::hash<boost::unordered::detail::range_key_t<R> >,
|
||||
class Pred =
|
||||
std::equal_to<boost::unordered::detail::range_key_t<R> >,
|
||||
class Allocator = std::allocator<
|
||||
boost::unordered::detail::range_to_alloc_t<R> >,
|
||||
class = std::enable_if_t<detail::is_hash_v<Hash> >,
|
||||
class = std::enable_if_t<detail::is_pred_v<Pred> >,
|
||||
class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
|
||||
concurrent_flat_map(FromRangeT&&, R&&,
|
||||
std::size_t = boost::unordered::detail::foa::default_bucket_count,
|
||||
Hash = Hash(), Pred = Pred(), Allocator = Allocator())
|
||||
-> concurrent_flat_map<boost::unordered::detail::range_key_t<R>,
|
||||
boost::unordered::detail::range_mapped_t<R>, Hash, Pred,
|
||||
Allocator>;
|
||||
#endif
|
||||
|
||||
template <class Key, class T,
|
||||
class Hash = boost::hash<std::remove_const_t<Key> >,
|
||||
class Pred = std::equal_to<std::remove_const_t<Key> >,
|
||||
@@ -1027,6 +1180,42 @@ namespace boost {
|
||||
std::equal_to<boost::unordered::detail::iter_key_t<InputIterator> >,
|
||||
Allocator>;
|
||||
|
||||
#if !defined(BOOST_UNORDERED_NO_RANGES)
|
||||
template <boost::unordered::detail::convertible_to_from_range_t FromRangeT,
|
||||
std::ranges::input_range R,
|
||||
class Allocator,
|
||||
class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
|
||||
concurrent_flat_map(FromRangeT&&, R&&, std::size_t, Allocator)
|
||||
-> concurrent_flat_map<boost::unordered::detail::range_key_t<R>,
|
||||
boost::unordered::detail::range_mapped_t<R>,
|
||||
boost::hash<boost::unordered::detail::range_key_t<R> >,
|
||||
std::equal_to<boost::unordered::detail::range_key_t<R> >,
|
||||
Allocator>;
|
||||
|
||||
template <boost::unordered::detail::convertible_to_from_range_t FromRangeT,
|
||||
std::ranges::input_range R,
|
||||
class Allocator,
|
||||
class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
|
||||
concurrent_flat_map(FromRangeT&&, R&&, Allocator)
|
||||
-> concurrent_flat_map<boost::unordered::detail::range_key_t<R>,
|
||||
boost::unordered::detail::range_mapped_t<R>,
|
||||
boost::hash<boost::unordered::detail::range_key_t<R> >,
|
||||
std::equal_to<boost::unordered::detail::range_key_t<R> >,
|
||||
Allocator>;
|
||||
|
||||
template <boost::unordered::detail::convertible_to_from_range_t FromRangeT,
|
||||
std::ranges::input_range R,
|
||||
class Hash, class Allocator,
|
||||
class = std::enable_if_t<detail::is_hash_v<Hash> >,
|
||||
class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
|
||||
concurrent_flat_map(
|
||||
FromRangeT&&, R&&, std::size_t, Hash, Allocator)
|
||||
-> concurrent_flat_map<boost::unordered::detail::range_key_t<R>,
|
||||
boost::unordered::detail::range_mapped_t<R>, Hash,
|
||||
std::equal_to<boost::unordered::detail::range_key_t<R> >,
|
||||
Allocator>;
|
||||
#endif
|
||||
|
||||
template <class Key, class T, class Allocator,
|
||||
class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
|
||||
concurrent_flat_map(std::initializer_list<std::pair<Key, T> >, std::size_t,
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include <boost/unordered/detail/concurrent_static_asserts.hpp>
|
||||
#include <boost/unordered/detail/foa/concurrent_table.hpp>
|
||||
#include <boost/unordered/detail/foa/flat_set_types.hpp>
|
||||
#include <boost/unordered/detail/ranges_support.hpp>
|
||||
#include <boost/unordered/detail/type_traits.hpp>
|
||||
#include <boost/unordered/unordered_flat_set_fwd.hpp>
|
||||
|
||||
@@ -99,6 +100,21 @@ namespace boost {
|
||||
this->insert(f, l);
|
||||
}
|
||||
|
||||
#if !defined(BOOST_UNORDERED_NO_RANGES)
|
||||
template<
|
||||
detail::convertible_to_from_range_t FromRangeT,
|
||||
detail::container_compatible_range<value_type> R
|
||||
>
|
||||
concurrent_flat_set(FromRangeT&&, R&& rg,
|
||||
size_type n = detail::foa::default_bucket_count,
|
||||
const hasher& hf = hasher(), const key_equal& eql = key_equal(),
|
||||
const allocator_type& a = allocator_type())
|
||||
: table_(n, hf, eql, a)
|
||||
{
|
||||
this->insert_range(std::forward<R>(rg));
|
||||
}
|
||||
#endif
|
||||
|
||||
concurrent_flat_set(concurrent_flat_set const& rhs)
|
||||
: table_(rhs.table_,
|
||||
boost::allocator_select_on_container_copy_construction(
|
||||
@@ -118,6 +134,19 @@ namespace boost {
|
||||
{
|
||||
}
|
||||
|
||||
#if !defined(BOOST_UNORDERED_NO_RANGES)
|
||||
template<
|
||||
detail::convertible_to_from_range_t FromRangeT,
|
||||
detail::container_compatible_range<value_type> R
|
||||
>
|
||||
concurrent_flat_set(
|
||||
FromRangeT&& fr, R&& rg, allocator_type const& a)
|
||||
: concurrent_flat_set(
|
||||
fr, std::forward<R>(rg), 0, hasher(), key_equal(), a)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
explicit concurrent_flat_set(allocator_type const& a)
|
||||
: table_(detail::foa::default_bucket_count, hasher(), key_equal(), a)
|
||||
{
|
||||
@@ -168,6 +197,29 @@ namespace boost {
|
||||
{
|
||||
}
|
||||
|
||||
#if !defined(BOOST_UNORDERED_NO_RANGES)
|
||||
template<
|
||||
detail::convertible_to_from_range_t FromRangeT,
|
||||
detail::container_compatible_range<value_type> R
|
||||
>
|
||||
concurrent_flat_set(
|
||||
FromRangeT&& fr, R&& rg, size_type n, const allocator_type& a)
|
||||
: concurrent_flat_set(
|
||||
fr, std::forward<R>(rg), n, hasher(), key_equal(), a)
|
||||
{
|
||||
}
|
||||
|
||||
template<
|
||||
detail::convertible_to_from_range_t FromRangeT,
|
||||
detail::container_compatible_range<value_type> R
|
||||
>
|
||||
concurrent_flat_set(FromRangeT&& fr, R&& rg, size_type n,
|
||||
const hasher& hf, const allocator_type& a)
|
||||
: concurrent_flat_set(fr, std::forward<R>(rg), n, hf, key_equal(), a)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
concurrent_flat_set(
|
||||
std::initializer_list<value_type> il, const allocator_type& a)
|
||||
: concurrent_flat_set(
|
||||
@@ -436,6 +488,20 @@ namespace boost {
|
||||
return count_elements;
|
||||
}
|
||||
|
||||
#if !defined(BOOST_UNORDERED_NO_RANGES)
|
||||
template<detail::container_compatible_range<value_type> R>
|
||||
size_type insert_range(R&& rg)
|
||||
{
|
||||
size_type count_elements = 0;
|
||||
auto first = std::ranges::begin(rg);
|
||||
auto last = std::ranges::end(rg);
|
||||
while (first != last) {
|
||||
if (table_.emplace(*first++)) ++count_elements;
|
||||
}
|
||||
return count_elements;
|
||||
}
|
||||
#endif
|
||||
|
||||
size_type insert(std::initializer_list<value_type> ilist)
|
||||
{
|
||||
return this->insert(ilist.begin(), ilist.end());
|
||||
@@ -476,6 +542,21 @@ namespace boost {
|
||||
return count_elements;
|
||||
}
|
||||
|
||||
#if !defined(BOOST_UNORDERED_NO_RANGES)
|
||||
template<detail::container_compatible_range<value_type> R, class F>
|
||||
size_type insert_range_or_visit(R&& rg, F f)
|
||||
{
|
||||
BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F)
|
||||
size_type count_elements = 0;
|
||||
auto first = std::ranges::begin(rg);
|
||||
auto last = std::ranges::end(rg);
|
||||
for (; first != last; ++first, ++count_elements) {
|
||||
table_.emplace_or_visit(*first, f);
|
||||
}
|
||||
return count_elements;
|
||||
}
|
||||
#endif
|
||||
|
||||
template <class F>
|
||||
size_type insert_or_visit(std::initializer_list<value_type> ilist, F f)
|
||||
{
|
||||
@@ -518,6 +599,21 @@ namespace boost {
|
||||
return count_elements;
|
||||
}
|
||||
|
||||
#if !defined(BOOST_UNORDERED_NO_RANGES)
|
||||
template<detail::container_compatible_range<value_type> R, class F>
|
||||
size_type insert_range_or_cvisit(R&& rg, F f)
|
||||
{
|
||||
BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F)
|
||||
size_type count_elements = 0;
|
||||
auto first = std::ranges::begin(rg);
|
||||
auto last = std::ranges::end(rg);
|
||||
for (; first != last; ++first, ++count_elements) {
|
||||
table_.emplace_or_cvisit(*first, f);
|
||||
}
|
||||
return count_elements;
|
||||
}
|
||||
#endif
|
||||
|
||||
template <class F>
|
||||
size_type insert_or_cvisit(std::initializer_list<value_type> ilist, F f)
|
||||
{
|
||||
@@ -566,6 +662,24 @@ namespace boost {
|
||||
return count_elements;
|
||||
}
|
||||
|
||||
#if !defined(BOOST_UNORDERED_NO_RANGES)
|
||||
template<
|
||||
detail::container_compatible_range<value_type> R, class F1, class F2
|
||||
>
|
||||
size_type insert_range_and_visit(R&& rg, F1 f1, F2 f2)
|
||||
{
|
||||
BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F1)
|
||||
BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F2)
|
||||
size_type count_elements = 0;
|
||||
auto first = std::ranges::begin(rg);
|
||||
auto last = std::ranges::end(rg);
|
||||
for (; first != last; ++first, ++count_elements) {
|
||||
table_.emplace_and_visit(*first, f1, f2);
|
||||
}
|
||||
return count_elements;
|
||||
}
|
||||
#endif
|
||||
|
||||
template <class F1, class F2>
|
||||
size_type insert_and_visit(std::initializer_list<value_type> ilist, F1 f1, F2 f2)
|
||||
{
|
||||
@@ -616,6 +730,24 @@ namespace boost {
|
||||
return count_elements;
|
||||
}
|
||||
|
||||
#if !defined(BOOST_UNORDERED_NO_RANGES)
|
||||
template<
|
||||
detail::container_compatible_range<value_type> R, class F1, class F2
|
||||
>
|
||||
size_type insert_range_and_cvisit(R&& rg, F1 f1, F2 f2)
|
||||
{
|
||||
BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F1)
|
||||
BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F2)
|
||||
size_type count_elements = 0;
|
||||
auto first = std::ranges::begin(rg);
|
||||
auto last = std::ranges::end(rg);
|
||||
for (; first != last; ++first, ++count_elements) {
|
||||
table_.emplace_and_cvisit(*first, f1, f2);
|
||||
}
|
||||
return count_elements;
|
||||
}
|
||||
#endif
|
||||
|
||||
template <class F1, class F2>
|
||||
size_type insert_and_cvisit(
|
||||
std::initializer_list<value_type> ilist, F1 f1, F2 f2)
|
||||
@@ -853,6 +985,25 @@ namespace boost {
|
||||
typename std::iterator_traits<InputIterator>::value_type, Hash, Pred,
|
||||
Allocator>;
|
||||
|
||||
#if !defined(BOOST_UNORDERED_NO_RANGES)
|
||||
template <
|
||||
boost::unordered::detail::convertible_to_from_range_t FromRangeT,
|
||||
std::ranges::input_range R,
|
||||
class Hash =
|
||||
boost::hash<std::ranges::range_value_t<R> >,
|
||||
class Pred =
|
||||
std::equal_to<std::ranges::range_value_t<R> >,
|
||||
class Allocator = std::allocator<std::ranges::range_value_t<R> >,
|
||||
class = std::enable_if_t<detail::is_hash_v<Hash> >,
|
||||
class = std::enable_if_t<detail::is_pred_v<Pred> >,
|
||||
class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
|
||||
concurrent_flat_set(FromRangeT&&, R&&,
|
||||
std::size_t = boost::unordered::detail::foa::default_bucket_count,
|
||||
Hash = Hash(), Pred = Pred(), Allocator = Allocator())
|
||||
-> concurrent_flat_set<std::ranges::range_value_t<R>,
|
||||
Hash, Pred, Allocator>;
|
||||
#endif
|
||||
|
||||
template <class T, class Hash = boost::hash<T>,
|
||||
class Pred = std::equal_to<T>, class Allocator = std::allocator<T>,
|
||||
class = std::enable_if_t<detail::is_hash_v<Hash> >,
|
||||
@@ -894,6 +1045,39 @@ namespace boost {
|
||||
std::equal_to<typename std::iterator_traits<InputIterator>::value_type>,
|
||||
Allocator>;
|
||||
|
||||
#if !defined(BOOST_UNORDERED_NO_RANGES)
|
||||
template <boost::unordered::detail::convertible_to_from_range_t FromRangeT,
|
||||
std::ranges::input_range R,
|
||||
class Allocator,
|
||||
class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
|
||||
concurrent_flat_set(FromRangeT&&, R&&, std::size_t, Allocator)
|
||||
-> concurrent_flat_set<std::ranges::range_value_t<R>,
|
||||
boost::hash<std::ranges::range_value_t<R> >,
|
||||
std::equal_to<std::ranges::range_value_t<R> >,
|
||||
Allocator>;
|
||||
|
||||
template <boost::unordered::detail::convertible_to_from_range_t FromRangeT,
|
||||
std::ranges::input_range R,
|
||||
class Hash, class Allocator,
|
||||
class = std::enable_if_t<detail::is_hash_v<Hash> >,
|
||||
class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
|
||||
concurrent_flat_set(
|
||||
FromRangeT&&, R&&, std::size_t, Hash, Allocator)
|
||||
-> concurrent_flat_set<std::ranges::range_value_t<R>,
|
||||
Hash, std::equal_to<std::ranges::range_value_t<R> >,
|
||||
Allocator>;
|
||||
|
||||
template <boost::unordered::detail::convertible_to_from_range_t FromRangeT,
|
||||
std::ranges::input_range R,
|
||||
class Allocator,
|
||||
class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
|
||||
concurrent_flat_set(FromRangeT&&, R&&, Allocator)
|
||||
-> concurrent_flat_set<std::ranges::range_value_t<R>,
|
||||
boost::hash<std::ranges::range_value_t<R> >,
|
||||
std::equal_to<std::ranges::range_value_t<R> >,
|
||||
Allocator>;
|
||||
#endif
|
||||
|
||||
template <class T, class Allocator,
|
||||
class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
|
||||
concurrent_flat_set(std::initializer_list<T>, std::size_t, Allocator)
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include <boost/unordered/detail/foa/element_type.hpp>
|
||||
#include <boost/unordered/detail/foa/node_map_handle.hpp>
|
||||
#include <boost/unordered/detail/foa/node_map_types.hpp>
|
||||
#include <boost/unordered/detail/ranges_support.hpp>
|
||||
#include <boost/unordered/detail/type_traits.hpp>
|
||||
#include <boost/unordered/unordered_node_map_fwd.hpp>
|
||||
|
||||
@@ -110,6 +111,21 @@ namespace boost {
|
||||
this->insert(f, l);
|
||||
}
|
||||
|
||||
#if !defined(BOOST_UNORDERED_NO_RANGES)
|
||||
template<
|
||||
detail::convertible_to_from_range_t FromRangeT,
|
||||
detail::container_compatible_range<value_type> R
|
||||
>
|
||||
concurrent_node_map(FromRangeT&&, R&& rg,
|
||||
size_type n = detail::foa::default_bucket_count,
|
||||
const hasher& hf = hasher(), const key_equal& eql = key_equal(),
|
||||
const allocator_type& a = allocator_type())
|
||||
: table_(n, hf, eql, a)
|
||||
{
|
||||
this->insert_range(std::forward<R>(rg));
|
||||
}
|
||||
#endif
|
||||
|
||||
concurrent_node_map(concurrent_node_map const& rhs)
|
||||
: table_(rhs.table_,
|
||||
boost::allocator_select_on_container_copy_construction(
|
||||
@@ -129,6 +145,19 @@ namespace boost {
|
||||
{
|
||||
}
|
||||
|
||||
#if !defined(BOOST_UNORDERED_NO_RANGES)
|
||||
template<
|
||||
detail::convertible_to_from_range_t FromRangeT,
|
||||
detail::container_compatible_range<value_type> R
|
||||
>
|
||||
concurrent_node_map(
|
||||
FromRangeT&& fr, R&& rg, allocator_type const& a)
|
||||
: concurrent_node_map(
|
||||
fr, std::forward<R>(rg), 0, hasher(), key_equal(), a)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
explicit concurrent_node_map(allocator_type const& a)
|
||||
: table_(detail::foa::default_bucket_count, hasher(), key_equal(), a)
|
||||
{
|
||||
@@ -179,6 +208,29 @@ namespace boost {
|
||||
{
|
||||
}
|
||||
|
||||
#if !defined(BOOST_UNORDERED_NO_RANGES)
|
||||
template<
|
||||
detail::convertible_to_from_range_t FromRangeT,
|
||||
detail::container_compatible_range<value_type> R
|
||||
>
|
||||
concurrent_node_map(
|
||||
FromRangeT&& fr, R&& rg, size_type n, const allocator_type& a)
|
||||
: concurrent_node_map(
|
||||
fr, std::forward<R>(rg), n, hasher(), key_equal(), a)
|
||||
{
|
||||
}
|
||||
|
||||
template<
|
||||
detail::convertible_to_from_range_t FromRangeT,
|
||||
detail::container_compatible_range<value_type> R
|
||||
>
|
||||
concurrent_node_map(FromRangeT&& fr, R&& rg, size_type n,
|
||||
const hasher& hf, const allocator_type& a)
|
||||
: concurrent_node_map(fr, std::forward<R>(rg), n, hf, key_equal(), a)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
concurrent_node_map(
|
||||
std::initializer_list<value_type> il, const allocator_type& a)
|
||||
: concurrent_node_map(
|
||||
@@ -438,6 +490,20 @@ namespace boost {
|
||||
return count_elements;
|
||||
}
|
||||
|
||||
#if !defined(BOOST_UNORDERED_NO_RANGES)
|
||||
template<detail::container_compatible_range<value_type> R>
|
||||
size_type insert_range(R&& rg)
|
||||
{
|
||||
size_type count_elements = 0;
|
||||
auto first = std::ranges::begin(rg);
|
||||
auto last = std::ranges::end(rg);
|
||||
while (first != last) {
|
||||
if (table_.emplace(*first++)) ++count_elements;
|
||||
}
|
||||
return count_elements;
|
||||
}
|
||||
#endif
|
||||
|
||||
size_type insert(std::initializer_list<value_type> ilist)
|
||||
{
|
||||
return this->insert(ilist.begin(), ilist.end());
|
||||
@@ -512,6 +578,21 @@ namespace boost {
|
||||
return count_elements;
|
||||
}
|
||||
|
||||
#if !defined(BOOST_UNORDERED_NO_RANGES)
|
||||
template<detail::container_compatible_range<value_type> R, class F>
|
||||
size_type insert_range_or_visit(R&& rg, F f)
|
||||
{
|
||||
BOOST_UNORDERED_STATIC_ASSERT_INVOCABLE(F)
|
||||
size_type count_elements = 0;
|
||||
auto first = std::ranges::begin(rg);
|
||||
auto last = std::ranges::end(rg);
|
||||
for (; first != last; ++first, ++count_elements) {
|
||||
table_.emplace_or_visit(*first, f);
|
||||
}
|
||||
return count_elements;
|
||||
}
|
||||
#endif
|
||||
|
||||
template <class F>
|
||||
size_type insert_or_visit(std::initializer_list<value_type> ilist, F f)
|
||||
{
|
||||
@@ -566,6 +647,21 @@ namespace boost {
|
||||
return count_elements;
|
||||
}
|
||||
|
||||
#if !defined(BOOST_UNORDERED_NO_RANGES)
|
||||
template<detail::container_compatible_range<value_type> R, class F>
|
||||
size_type insert_range_or_cvisit(R&& rg, F f)
|
||||
{
|
||||
BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F)
|
||||
size_type count_elements = 0;
|
||||
auto first = std::ranges::begin(rg);
|
||||
auto last = std::ranges::end(rg);
|
||||
for (; first != last; ++first, ++count_elements) {
|
||||
table_.emplace_or_cvisit(*first, f);
|
||||
}
|
||||
return count_elements;
|
||||
}
|
||||
#endif
|
||||
|
||||
template <class F>
|
||||
size_type insert_or_cvisit(std::initializer_list<value_type> ilist, F f)
|
||||
{
|
||||
@@ -624,6 +720,24 @@ namespace boost {
|
||||
return count_elements;
|
||||
}
|
||||
|
||||
#if !defined(BOOST_UNORDERED_NO_RANGES)
|
||||
template<
|
||||
detail::container_compatible_range<value_type> R, class F1, class F2
|
||||
>
|
||||
size_type insert_range_and_visit(R&& rg, F1 f1, F2 f2)
|
||||
{
|
||||
BOOST_UNORDERED_STATIC_ASSERT_INVOCABLE(F1)
|
||||
BOOST_UNORDERED_STATIC_ASSERT_INVOCABLE(F2)
|
||||
size_type count_elements = 0;
|
||||
auto first = std::ranges::begin(rg);
|
||||
auto last = std::ranges::end(rg);
|
||||
for (; first != last; ++first, ++count_elements) {
|
||||
table_.emplace_and_visit(*first, f1, f2);
|
||||
}
|
||||
return count_elements;
|
||||
}
|
||||
#endif
|
||||
|
||||
template <class F1, class F2>
|
||||
size_type insert_and_visit(
|
||||
std::initializer_list<value_type> ilist, F1 f1, F2 f2)
|
||||
@@ -686,6 +800,24 @@ namespace boost {
|
||||
return count_elements;
|
||||
}
|
||||
|
||||
#if !defined(BOOST_UNORDERED_NO_RANGES)
|
||||
template<
|
||||
detail::container_compatible_range<value_type> R, class F1, class F2
|
||||
>
|
||||
size_type insert_range_and_cvisit(R&& rg, F1 f1, F2 f2)
|
||||
{
|
||||
BOOST_UNORDERED_STATIC_ASSERT_INVOCABLE(F1)
|
||||
BOOST_UNORDERED_STATIC_ASSERT_INVOCABLE(F2)
|
||||
size_type count_elements = 0;
|
||||
auto first = std::ranges::begin(rg);
|
||||
auto last = std::ranges::end(rg);
|
||||
for (; first != last; ++first, ++count_elements) {
|
||||
table_.emplace_and_cvisit(*first, f1, f2);
|
||||
}
|
||||
return count_elements;
|
||||
}
|
||||
#endif
|
||||
|
||||
template <class F1, class F2>
|
||||
size_type insert_and_cvisit(
|
||||
std::initializer_list<value_type> ilist, F1 f1, F2 f2)
|
||||
@@ -1128,6 +1260,27 @@ namespace boost {
|
||||
boost::unordered::detail::iter_val_t<InputIterator>, Hash, Pred,
|
||||
Allocator>;
|
||||
|
||||
#if !defined(BOOST_UNORDERED_NO_RANGES)
|
||||
template <
|
||||
boost::unordered::detail::convertible_to_from_range_t FromRangeT,
|
||||
std::ranges::input_range R,
|
||||
class Hash =
|
||||
boost::hash<boost::unordered::detail::range_key_t<R> >,
|
||||
class Pred =
|
||||
std::equal_to<boost::unordered::detail::range_key_t<R> >,
|
||||
class Allocator = std::allocator<
|
||||
boost::unordered::detail::range_to_alloc_t<R> >,
|
||||
class = std::enable_if_t<detail::is_hash_v<Hash> >,
|
||||
class = std::enable_if_t<detail::is_pred_v<Pred> >,
|
||||
class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
|
||||
concurrent_node_map(FromRangeT&&, R&&,
|
||||
std::size_t = boost::unordered::detail::foa::default_bucket_count,
|
||||
Hash = Hash(), Pred = Pred(), Allocator = Allocator())
|
||||
-> concurrent_node_map<boost::unordered::detail::range_key_t<R>,
|
||||
boost::unordered::detail::range_mapped_t<R>, Hash, Pred,
|
||||
Allocator>;
|
||||
#endif
|
||||
|
||||
template <class Key, class T,
|
||||
class Hash = boost::hash<std::remove_const_t<Key> >,
|
||||
class Pred = std::equal_to<std::remove_const_t<Key> >,
|
||||
@@ -1175,6 +1328,42 @@ namespace boost {
|
||||
std::equal_to<boost::unordered::detail::iter_key_t<InputIterator> >,
|
||||
Allocator>;
|
||||
|
||||
#if !defined(BOOST_UNORDERED_NO_RANGES)
|
||||
template <boost::unordered::detail::convertible_to_from_range_t FromRangeT,
|
||||
std::ranges::input_range R,
|
||||
class Allocator,
|
||||
class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
|
||||
concurrent_node_map(FromRangeT&&, R&&, std::size_t, Allocator)
|
||||
-> concurrent_node_map<boost::unordered::detail::range_key_t<R>,
|
||||
boost::unordered::detail::range_mapped_t<R>,
|
||||
boost::hash<boost::unordered::detail::range_key_t<R> >,
|
||||
std::equal_to<boost::unordered::detail::range_key_t<R> >,
|
||||
Allocator>;
|
||||
|
||||
template <boost::unordered::detail::convertible_to_from_range_t FromRangeT,
|
||||
std::ranges::input_range R,
|
||||
class Allocator,
|
||||
class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
|
||||
concurrent_node_map(FromRangeT&&, R&&, Allocator)
|
||||
-> concurrent_node_map<boost::unordered::detail::range_key_t<R>,
|
||||
boost::unordered::detail::range_mapped_t<R>,
|
||||
boost::hash<boost::unordered::detail::range_key_t<R> >,
|
||||
std::equal_to<boost::unordered::detail::range_key_t<R> >,
|
||||
Allocator>;
|
||||
|
||||
template <boost::unordered::detail::convertible_to_from_range_t FromRangeT,
|
||||
std::ranges::input_range R,
|
||||
class Hash, class Allocator,
|
||||
class = std::enable_if_t<detail::is_hash_v<Hash> >,
|
||||
class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
|
||||
concurrent_node_map(
|
||||
FromRangeT&&, R&&, std::size_t, Hash, Allocator)
|
||||
-> concurrent_node_map<boost::unordered::detail::range_key_t<R>,
|
||||
boost::unordered::detail::range_mapped_t<R>, Hash,
|
||||
std::equal_to<boost::unordered::detail::range_key_t<R> >,
|
||||
Allocator>;
|
||||
#endif
|
||||
|
||||
template <class Key, class T, class Allocator,
|
||||
class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
|
||||
concurrent_node_map(std::initializer_list<std::pair<Key, T> >, std::size_t,
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include <boost/unordered/detail/foa/element_type.hpp>
|
||||
#include <boost/unordered/detail/foa/node_set_handle.hpp>
|
||||
#include <boost/unordered/detail/foa/node_set_types.hpp>
|
||||
#include <boost/unordered/detail/ranges_support.hpp>
|
||||
#include <boost/unordered/detail/type_traits.hpp>
|
||||
#include <boost/unordered/unordered_node_set_fwd.hpp>
|
||||
|
||||
@@ -107,6 +108,21 @@ namespace boost {
|
||||
this->insert(f, l);
|
||||
}
|
||||
|
||||
#if !defined(BOOST_UNORDERED_NO_RANGES)
|
||||
template<
|
||||
detail::convertible_to_from_range_t FromRangeT,
|
||||
detail::container_compatible_range<value_type> R
|
||||
>
|
||||
concurrent_node_set(FromRangeT&&, R&& rg,
|
||||
size_type n = detail::foa::default_bucket_count,
|
||||
const hasher& hf = hasher(), const key_equal& eql = key_equal(),
|
||||
const allocator_type& a = allocator_type())
|
||||
: table_(n, hf, eql, a)
|
||||
{
|
||||
this->insert_range(std::forward<R>(rg));
|
||||
}
|
||||
#endif
|
||||
|
||||
concurrent_node_set(concurrent_node_set const& rhs)
|
||||
: table_(rhs.table_,
|
||||
boost::allocator_select_on_container_copy_construction(
|
||||
@@ -126,6 +142,19 @@ namespace boost {
|
||||
{
|
||||
}
|
||||
|
||||
#if !defined(BOOST_UNORDERED_NO_RANGES)
|
||||
template<
|
||||
detail::convertible_to_from_range_t FromRangeT,
|
||||
detail::container_compatible_range<value_type> R
|
||||
>
|
||||
concurrent_node_set(
|
||||
FromRangeT&& fr, R&& rg, allocator_type const& a)
|
||||
: concurrent_node_set(
|
||||
fr, std::forward<R>(rg), 0, hasher(), key_equal(), a)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
explicit concurrent_node_set(allocator_type const& a)
|
||||
: table_(detail::foa::default_bucket_count, hasher(), key_equal(), a)
|
||||
{
|
||||
@@ -176,6 +205,29 @@ namespace boost {
|
||||
{
|
||||
}
|
||||
|
||||
#if !defined(BOOST_UNORDERED_NO_RANGES)
|
||||
template<
|
||||
detail::convertible_to_from_range_t FromRangeT,
|
||||
detail::container_compatible_range<value_type> R
|
||||
>
|
||||
concurrent_node_set(
|
||||
FromRangeT&& fr, R&& rg, size_type n, const allocator_type& a)
|
||||
: concurrent_node_set(
|
||||
fr, std::forward<R>(rg), n, hasher(), key_equal(), a)
|
||||
{
|
||||
}
|
||||
|
||||
template<
|
||||
detail::convertible_to_from_range_t FromRangeT,
|
||||
detail::container_compatible_range<value_type> R
|
||||
>
|
||||
concurrent_node_set(FromRangeT&& fr, R&& rg, size_type n,
|
||||
const hasher& hf, const allocator_type& a)
|
||||
: concurrent_node_set(fr, std::forward<R>(rg), n, hf, key_equal(), a)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
concurrent_node_set(
|
||||
std::initializer_list<value_type> il, const allocator_type& a)
|
||||
: concurrent_node_set(
|
||||
@@ -444,6 +496,20 @@ namespace boost {
|
||||
return count_elements;
|
||||
}
|
||||
|
||||
#if !defined(BOOST_UNORDERED_NO_RANGES)
|
||||
template<detail::container_compatible_range<value_type> R>
|
||||
size_type insert_range(R&& rg)
|
||||
{
|
||||
size_type count_elements = 0;
|
||||
auto first = std::ranges::begin(rg);
|
||||
auto last = std::ranges::end(rg);
|
||||
while (first != last) {
|
||||
if (table_.emplace(*first++)) ++count_elements;
|
||||
}
|
||||
return count_elements;
|
||||
}
|
||||
#endif
|
||||
|
||||
size_type insert(std::initializer_list<value_type> ilist)
|
||||
{
|
||||
return this->insert(ilist.begin(), ilist.end());
|
||||
@@ -503,6 +569,21 @@ namespace boost {
|
||||
return count_elements;
|
||||
}
|
||||
|
||||
#if !defined(BOOST_UNORDERED_NO_RANGES)
|
||||
template<detail::container_compatible_range<value_type> R, class F>
|
||||
size_type insert_range_or_visit(R&& rg, F f)
|
||||
{
|
||||
BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F)
|
||||
size_type count_elements = 0;
|
||||
auto first = std::ranges::begin(rg);
|
||||
auto last = std::ranges::end(rg);
|
||||
for (; first != last; ++first, ++count_elements) {
|
||||
table_.emplace_or_visit(*first, f);
|
||||
}
|
||||
return count_elements;
|
||||
}
|
||||
#endif
|
||||
|
||||
template <class F>
|
||||
size_type insert_or_visit(std::initializer_list<value_type> ilist, F f)
|
||||
{
|
||||
@@ -566,6 +647,21 @@ namespace boost {
|
||||
return count_elements;
|
||||
}
|
||||
|
||||
#if !defined(BOOST_UNORDERED_NO_RANGES)
|
||||
template<detail::container_compatible_range<value_type> R, class F>
|
||||
size_type insert_range_or_cvisit(R&& rg, F f)
|
||||
{
|
||||
BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F)
|
||||
size_type count_elements = 0;
|
||||
auto first = std::ranges::begin(rg);
|
||||
auto last = std::ranges::end(rg);
|
||||
for (; first != last; ++first, ++count_elements) {
|
||||
table_.emplace_or_cvisit(*first, f);
|
||||
}
|
||||
return count_elements;
|
||||
}
|
||||
#endif
|
||||
|
||||
template <class F>
|
||||
size_type insert_or_cvisit(std::initializer_list<value_type> ilist, F f)
|
||||
{
|
||||
@@ -635,6 +731,24 @@ namespace boost {
|
||||
return count_elements;
|
||||
}
|
||||
|
||||
#if !defined(BOOST_UNORDERED_NO_RANGES)
|
||||
template<
|
||||
detail::container_compatible_range<value_type> R, class F1, class F2
|
||||
>
|
||||
size_type insert_range_and_visit(R&& rg, F1 f1, F2 f2)
|
||||
{
|
||||
BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F1)
|
||||
BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F2)
|
||||
size_type count_elements = 0;
|
||||
auto first = std::ranges::begin(rg);
|
||||
auto last = std::ranges::end(rg);
|
||||
for (; first != last; ++first, ++count_elements) {
|
||||
table_.emplace_and_visit(*first, f1, f2);
|
||||
}
|
||||
return count_elements;
|
||||
}
|
||||
#endif
|
||||
|
||||
template <class F1, class F2>
|
||||
size_type insert_and_visit(
|
||||
std::initializer_list<value_type> ilist, F1 f1, F2 f2)
|
||||
@@ -708,6 +822,24 @@ namespace boost {
|
||||
return count_elements;
|
||||
}
|
||||
|
||||
#if !defined(BOOST_UNORDERED_NO_RANGES)
|
||||
template<
|
||||
detail::container_compatible_range<value_type> R, class F1, class F2
|
||||
>
|
||||
size_type insert_range_and_cvisit(R&& rg, F1 f1, F2 f2)
|
||||
{
|
||||
BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F1)
|
||||
BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F2)
|
||||
size_type count_elements = 0;
|
||||
auto first = std::ranges::begin(rg);
|
||||
auto last = std::ranges::end(rg);
|
||||
for (; first != last; ++first, ++count_elements) {
|
||||
table_.emplace_and_cvisit(*first, f1, f2);
|
||||
}
|
||||
return count_elements;
|
||||
}
|
||||
#endif
|
||||
|
||||
template <class F1, class F2>
|
||||
size_type insert_and_cvisit(
|
||||
std::initializer_list<value_type> ilist, F1 f1, F2 f2)
|
||||
@@ -1002,6 +1134,26 @@ namespace boost {
|
||||
typename std::iterator_traits<InputIterator>::value_type, Hash, Pred,
|
||||
Allocator>;
|
||||
|
||||
#if !defined(BOOST_UNORDERED_NO_RANGES)
|
||||
template <
|
||||
boost::unordered::detail::convertible_to_from_range_t FromRangeT,
|
||||
std::ranges::input_range R,
|
||||
class Hash =
|
||||
boost::hash<std::ranges::range_value_t<R> >,
|
||||
class Pred =
|
||||
std::equal_to<std::ranges::range_value_t<R> >,
|
||||
class Allocator = std::allocator<std::ranges::range_value_t<R> >,
|
||||
class = std::enable_if_t<detail::is_hash_v<Hash> >,
|
||||
class = std::enable_if_t<detail::is_pred_v<Pred> >,
|
||||
class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
|
||||
concurrent_node_set(FromRangeT&&, R&&,
|
||||
std::size_t = boost::unordered::detail::foa::default_bucket_count,
|
||||
Hash = Hash(), Pred = Pred(), Allocator = Allocator())
|
||||
-> concurrent_node_set<std::ranges::range_value_t<R>,
|
||||
Hash, Pred, Allocator>;
|
||||
#endif
|
||||
|
||||
|
||||
template <class T, class Hash = boost::hash<T>,
|
||||
class Pred = std::equal_to<T>, class Allocator = std::allocator<T>,
|
||||
class = std::enable_if_t<detail::is_hash_v<Hash> >,
|
||||
@@ -1043,6 +1195,39 @@ namespace boost {
|
||||
std::equal_to<typename std::iterator_traits<InputIterator>::value_type>,
|
||||
Allocator>;
|
||||
|
||||
#if !defined(BOOST_UNORDERED_NO_RANGES)
|
||||
template <boost::unordered::detail::convertible_to_from_range_t FromRangeT,
|
||||
std::ranges::input_range R,
|
||||
class Allocator,
|
||||
class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
|
||||
concurrent_node_set(FromRangeT&&, R&&, std::size_t, Allocator)
|
||||
-> concurrent_node_set<std::ranges::range_value_t<R>,
|
||||
boost::hash<std::ranges::range_value_t<R> >,
|
||||
std::equal_to<std::ranges::range_value_t<R> >,
|
||||
Allocator>;
|
||||
|
||||
template <boost::unordered::detail::convertible_to_from_range_t FromRangeT,
|
||||
std::ranges::input_range R,
|
||||
class Hash, class Allocator,
|
||||
class = std::enable_if_t<detail::is_hash_v<Hash> >,
|
||||
class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
|
||||
concurrent_node_set(
|
||||
FromRangeT&&, R&&, std::size_t, Hash, Allocator)
|
||||
-> concurrent_node_set<std::ranges::range_value_t<R>,
|
||||
Hash, std::equal_to<std::ranges::range_value_t<R> >,
|
||||
Allocator>;
|
||||
|
||||
template <boost::unordered::detail::convertible_to_from_range_t FromRangeT,
|
||||
std::ranges::input_range R,
|
||||
class Allocator,
|
||||
class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
|
||||
concurrent_node_set(FromRangeT&&, R&&, Allocator)
|
||||
-> concurrent_node_set<std::ranges::range_value_t<R>,
|
||||
boost::hash<std::ranges::range_value_t<R> >,
|
||||
std::equal_to<std::ranges::range_value_t<R> >,
|
||||
Allocator>;
|
||||
#endif
|
||||
|
||||
template <class T, class Allocator,
|
||||
class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
|
||||
concurrent_node_set(std::initializer_list<T>, std::size_t, Allocator)
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include <boost/unordered/detail/allocator_constructed.hpp>
|
||||
#include <boost/unordered/detail/fca.hpp>
|
||||
#include <boost/unordered/detail/opt_storage.hpp>
|
||||
#include <boost/unordered/detail/ranges_support.hpp>
|
||||
#include <boost/unordered/detail/serialize_tracked_address.hpp>
|
||||
#include <boost/unordered/detail/static_assert.hpp>
|
||||
#include <boost/unordered/detail/type_traits.hpp>
|
||||
@@ -175,6 +176,29 @@ namespace boost {
|
||||
boost::unordered::detail::insert_size(i, j), num_buckets);
|
||||
}
|
||||
|
||||
#if !defined(BOOST_UNORDERED_NO_RANGES)
|
||||
template<std::ranges::input_range R>
|
||||
inline std::size_t insert_size(R&& rg)
|
||||
{
|
||||
if constexpr (std::ranges::sized_range<R>)
|
||||
return std::ranges::size(std::forward<R>(rg));
|
||||
else if constexpr (std::ranges::forward_range<R>)
|
||||
return std::ranges::distance(std::forward<R>(rg));
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
template <std::ranges::input_range R>
|
||||
inline std::size_t initial_size(R&& rg,
|
||||
std::size_t num_buckets =
|
||||
boost::unordered::detail::default_bucket_count)
|
||||
{
|
||||
return (std::max)(
|
||||
boost::unordered::detail::insert_size(std::forward<R>(rg)),
|
||||
num_buckets);
|
||||
}
|
||||
#endif
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// compressed
|
||||
|
||||
@@ -2155,8 +2179,8 @@ namespace boost {
|
||||
// if hash function throws, or inserting > 1 element, basic exception
|
||||
// safety strong otherwise
|
||||
|
||||
template <class InputIt>
|
||||
void insert_range_unique(no_key, InputIt i, InputIt j)
|
||||
template <class InputIt, class Sentinel>
|
||||
void insert_range_unique(no_key, InputIt i, Sentinel j)
|
||||
{
|
||||
hasher const& hf = this->hash_function();
|
||||
node_allocator_type alloc = this->node_alloc();
|
||||
@@ -2543,14 +2567,20 @@ namespace boost {
|
||||
|
||||
// if hash function throws, or inserting > 1 element, basic exception
|
||||
// safety. Strong otherwise
|
||||
template <class I>
|
||||
template <class I, class S>
|
||||
typename boost::unordered::detail::enable_if_forward<I, void>::type
|
||||
insert_range_equiv(I i, I j)
|
||||
insert_range_equiv(I i, S j)
|
||||
{
|
||||
if (i == j)
|
||||
return;
|
||||
|
||||
#if !defined(BOOST_UNORDERED_NO_RANGES)
|
||||
std::size_t distance = static_cast<std::size_t>(
|
||||
std::ranges::distance(i, j));
|
||||
#else
|
||||
std::size_t distance = static_cast<std::size_t>(std::distance(i, j));
|
||||
#endif
|
||||
|
||||
if (distance == 1) {
|
||||
emplace_equiv(boost::unordered::detail::func::construct_node(
|
||||
this->node_alloc(), *i));
|
||||
@@ -2566,9 +2596,9 @@ namespace boost {
|
||||
}
|
||||
}
|
||||
|
||||
template <class I>
|
||||
template <class I, class S>
|
||||
typename boost::unordered::detail::disable_if_forward<I, void>::type
|
||||
insert_range_equiv(I i, I j)
|
||||
insert_range_equiv(I i, S j)
|
||||
{
|
||||
for (; i != j; ++i) {
|
||||
emplace_equiv(boost::unordered::detail::func::construct_node(
|
||||
|
||||
@@ -0,0 +1,104 @@
|
||||
/* Copyright 2026 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)
|
||||
*
|
||||
* See https://www.boost.org/libs/unordered for library home page.
|
||||
*/
|
||||
|
||||
#ifndef BOOST_UNORDERED_DETAIL_RANGES_SUPPORT_HPP
|
||||
#define BOOST_UNORDERED_DETAIL_RANGES_SUPPORT_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/config/workaround.hpp>
|
||||
|
||||
#if defined(BOOST_NO_CXX20_HDR_CONCEPTS) || defined(BOOST_NO_CXX20_HDR_RANGES)
|
||||
#define BOOST_UNORDERED_NO_RANGES
|
||||
#elif BOOST_WORKAROUND(BOOST_CLANG_VERSION, < 170100) && \
|
||||
defined(BOOST_LIBSTDCXX_VERSION)
|
||||
/* https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109647
|
||||
* https://github.com/llvm/llvm-project/issues/49620
|
||||
*/
|
||||
#define BOOST_UNORDERED_NO_RANGES
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_UNORDERED_NO_RANGES)
|
||||
#include <concepts>
|
||||
#include <functional>
|
||||
#include <ranges>
|
||||
#include <tuple>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
namespace boost {
|
||||
namespace unordered {
|
||||
|
||||
struct from_range_t { explicit from_range_t() = default; };
|
||||
inline constexpr from_range_t from_range{};
|
||||
|
||||
namespace detail {
|
||||
|
||||
/* Existence of std::from_range_t is governed by feature macro
|
||||
* __cpp_lib_containers_ranges, but at least one stdlib implementation
|
||||
* (GCC 14.1) does not honor it, hence the workadound below: code picks
|
||||
* std::from_range_t if it exists, boost::unordered::from_range_t otherwise.
|
||||
* Technique explained at
|
||||
https://bannalia.blogspot.com/2016/09/compile-time-checking-existence-of.html
|
||||
*/
|
||||
|
||||
struct from_range_t_hook{};
|
||||
|
||||
} /* namespace detail */
|
||||
} /* namespace unordered */
|
||||
} /* namespace boost */
|
||||
|
||||
namespace std {
|
||||
|
||||
template<> struct hash< ::boost::unordered::detail::from_range_t_hook>
|
||||
{
|
||||
using from_range_t_type = decltype([] {
|
||||
using namespace ::boost::unordered;
|
||||
return from_range_t{};
|
||||
}());
|
||||
|
||||
/* make standard happy */
|
||||
std::size_t operator()(
|
||||
const ::boost::unordered::detail::from_range_t_hook&) const;
|
||||
};
|
||||
|
||||
} /* namespace std */
|
||||
|
||||
namespace boost {
|
||||
namespace unordered {
|
||||
namespace detail {
|
||||
|
||||
template<typename T>
|
||||
concept convertible_to_from_range_t =
|
||||
std::is_convertible_v<T, boost::unordered::from_range_t> ||
|
||||
std::is_convertible_v<T, std::hash<from_range_t_hook>::from_range_t_type>;
|
||||
|
||||
template<class R, class T>
|
||||
concept container_compatible_range =
|
||||
std::ranges::input_range<R> &&
|
||||
std::convertible_to<std::ranges::range_reference_t<R>, T>;
|
||||
|
||||
template<std::ranges::input_range Range>
|
||||
using range_key_t =
|
||||
std::remove_cvref_t<
|
||||
std::tuple_element_t<0, std::ranges::range_value_t<Range>>>;
|
||||
|
||||
template<std::ranges::input_range Range>
|
||||
using range_mapped_t =
|
||||
std::remove_cvref_t<
|
||||
std::tuple_element_t<1, std::ranges::range_value_t<Range>>>;
|
||||
|
||||
template<std::ranges::input_range Range>
|
||||
using range_to_alloc_t =
|
||||
std::pair<const range_key_t<Range>, range_mapped_t<Range>>;
|
||||
|
||||
} /* namespace detail */
|
||||
} /* namespace unordered */
|
||||
} /* namespace boost */
|
||||
|
||||
#endif /* !defined(BOOST_UNORDERED_NO_RANGES) */
|
||||
#endif
|
||||
@@ -1,5 +1,5 @@
|
||||
// Copyright (C) 2022-2023 Christian Mazakas
|
||||
// Copyright (C) 2024-2025 Joaquin M Lopez Munoz
|
||||
// Copyright (C) 2024-2026 Joaquin M Lopez Munoz
|
||||
// Copyright (C) 2026 Braden Ganetsky
|
||||
// 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)
|
||||
@@ -15,6 +15,7 @@
|
||||
#include <boost/unordered/concurrent_flat_map_fwd.hpp>
|
||||
#include <boost/unordered/detail/foa/flat_map_types.hpp>
|
||||
#include <boost/unordered/detail/foa/table.hpp>
|
||||
#include <boost/unordered/detail/ranges_support.hpp>
|
||||
#include <boost/unordered/detail/serialize_container.hpp>
|
||||
#include <boost/unordered/detail/throw_exception.hpp>
|
||||
#include <boost/unordered/detail/type_traits.hpp>
|
||||
@@ -108,6 +109,19 @@ namespace boost {
|
||||
{
|
||||
}
|
||||
|
||||
#if !defined(BOOST_UNORDERED_NO_RANGES)
|
||||
template<
|
||||
detail::convertible_to_from_range_t FromRangeT,
|
||||
detail::container_compatible_range<value_type> R
|
||||
>
|
||||
unordered_flat_map(
|
||||
FromRangeT&& fr, R&& rg, allocator_type const& a)
|
||||
: unordered_flat_map(
|
||||
fr, std::forward<R>(rg), size_type(0), hasher(), key_equal(), a)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
explicit unordered_flat_map(allocator_type const& a)
|
||||
: unordered_flat_map(0, a)
|
||||
{
|
||||
@@ -136,6 +150,41 @@ namespace boost {
|
||||
{
|
||||
}
|
||||
|
||||
#if !defined(BOOST_UNORDERED_NO_RANGES)
|
||||
template<
|
||||
detail::convertible_to_from_range_t FromRangeT,
|
||||
detail::container_compatible_range<value_type> R
|
||||
>
|
||||
unordered_flat_map(FromRangeT&&, R&& rg, size_type n = 0,
|
||||
hasher const& h = hasher(), key_equal const& pred = key_equal(),
|
||||
allocator_type const& a = allocator_type())
|
||||
: unordered_flat_map(n, h, pred, a)
|
||||
{
|
||||
this->insert_range(std::forward<R>(rg));
|
||||
}
|
||||
|
||||
template<
|
||||
detail::convertible_to_from_range_t FromRangeT,
|
||||
detail::container_compatible_range<value_type> R
|
||||
>
|
||||
unordered_flat_map(
|
||||
FromRangeT&& fr, R&& rg, size_type n, allocator_type const& a)
|
||||
: unordered_flat_map(
|
||||
fr, std::forward<R>(rg), n, hasher(), key_equal(), a)
|
||||
{
|
||||
}
|
||||
|
||||
template<
|
||||
detail::convertible_to_from_range_t FromRangeT,
|
||||
detail::container_compatible_range<value_type> R
|
||||
>
|
||||
unordered_flat_map(FromRangeT&& fr, R&& rg, size_type n,
|
||||
hasher const& h, allocator_type const& a)
|
||||
: unordered_flat_map(fr, std::forward<R>(rg), n, h, key_equal(), a)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
unordered_flat_map(unordered_flat_map const& other) : table_(other.table_)
|
||||
{
|
||||
}
|
||||
@@ -278,6 +327,16 @@ namespace boost {
|
||||
}
|
||||
}
|
||||
|
||||
#if !defined(BOOST_UNORDERED_NO_RANGES)
|
||||
template<detail::container_compatible_range<value_type> R>
|
||||
BOOST_FORCEINLINE void insert_range(R&& rg)
|
||||
{
|
||||
auto first = std::ranges::begin(rg);
|
||||
auto last = std::ranges::end(rg);
|
||||
while (first != last) table_.emplace(*first++);
|
||||
}
|
||||
#endif
|
||||
|
||||
void insert(std::initializer_list<value_type> ilist)
|
||||
{
|
||||
this->insert(ilist.begin(), ilist.end());
|
||||
@@ -756,6 +815,27 @@ namespace boost {
|
||||
boost::unordered::detail::iter_val_t<InputIterator>, Hash, Pred,
|
||||
Allocator>;
|
||||
|
||||
#if !defined(BOOST_UNORDERED_NO_RANGES)
|
||||
template <
|
||||
boost::unordered::detail::convertible_to_from_range_t FromRangeT,
|
||||
std::ranges::input_range R,
|
||||
class Hash =
|
||||
boost::hash<boost::unordered::detail::range_key_t<R> >,
|
||||
class Pred =
|
||||
std::equal_to<boost::unordered::detail::range_key_t<R> >,
|
||||
class Allocator = std::allocator<
|
||||
boost::unordered::detail::range_to_alloc_t<R> >,
|
||||
class = std::enable_if_t<detail::is_hash_v<Hash> >,
|
||||
class = std::enable_if_t<detail::is_pred_v<Pred> >,
|
||||
class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
|
||||
unordered_flat_map(FromRangeT&&, R&&,
|
||||
std::size_t = boost::unordered::detail::foa::default_bucket_count,
|
||||
Hash = Hash(), Pred = Pred(), Allocator = Allocator())
|
||||
-> unordered_flat_map<boost::unordered::detail::range_key_t<R>,
|
||||
boost::unordered::detail::range_mapped_t<R>, Hash, Pred,
|
||||
Allocator>;
|
||||
#endif
|
||||
|
||||
template <class Key, class T,
|
||||
class Hash = boost::hash<std::remove_const_t<Key> >,
|
||||
class Pred = std::equal_to<std::remove_const_t<Key> >,
|
||||
@@ -800,6 +880,42 @@ namespace boost {
|
||||
std::equal_to<boost::unordered::detail::iter_key_t<InputIterator> >,
|
||||
Allocator>;
|
||||
|
||||
#if !defined(BOOST_UNORDERED_NO_RANGES)
|
||||
template <boost::unordered::detail::convertible_to_from_range_t FromRangeT,
|
||||
std::ranges::input_range R,
|
||||
class Allocator,
|
||||
class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
|
||||
unordered_flat_map(FromRangeT&&, R&&, std::size_t, Allocator)
|
||||
-> unordered_flat_map<boost::unordered::detail::range_key_t<R>,
|
||||
boost::unordered::detail::range_mapped_t<R>,
|
||||
boost::hash<boost::unordered::detail::range_key_t<R> >,
|
||||
std::equal_to<boost::unordered::detail::range_key_t<R> >,
|
||||
Allocator>;
|
||||
|
||||
template <boost::unordered::detail::convertible_to_from_range_t FromRangeT,
|
||||
std::ranges::input_range R,
|
||||
class Allocator,
|
||||
class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
|
||||
unordered_flat_map(FromRangeT&&, R&&, Allocator)
|
||||
-> unordered_flat_map<boost::unordered::detail::range_key_t<R>,
|
||||
boost::unordered::detail::range_mapped_t<R>,
|
||||
boost::hash<boost::unordered::detail::range_key_t<R> >,
|
||||
std::equal_to<boost::unordered::detail::range_key_t<R> >,
|
||||
Allocator>;
|
||||
|
||||
template <boost::unordered::detail::convertible_to_from_range_t FromRangeT,
|
||||
std::ranges::input_range R,
|
||||
class Hash, class Allocator,
|
||||
class = std::enable_if_t<detail::is_hash_v<Hash> >,
|
||||
class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
|
||||
unordered_flat_map(
|
||||
FromRangeT&&, R&&, std::size_t, Hash, Allocator)
|
||||
-> unordered_flat_map<boost::unordered::detail::range_key_t<R>,
|
||||
boost::unordered::detail::range_mapped_t<R>, Hash,
|
||||
std::equal_to<boost::unordered::detail::range_key_t<R> >,
|
||||
Allocator>;
|
||||
#endif
|
||||
|
||||
template <class Key, class T, class Allocator,
|
||||
class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
|
||||
unordered_flat_map(std::initializer_list<std::pair<Key, T> >, std::size_t,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// Copyright (C) 2022-2023 Christian Mazakas
|
||||
// Copyright (C) 2024-2025 Joaquin M Lopez Munoz
|
||||
// Copyright (C) 2024-2026 Joaquin M Lopez Munoz
|
||||
// Copyright (C) 2026 Braden Ganetsky
|
||||
// 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)
|
||||
@@ -15,6 +15,7 @@
|
||||
#include <boost/unordered/concurrent_flat_set_fwd.hpp>
|
||||
#include <boost/unordered/detail/foa/flat_set_types.hpp>
|
||||
#include <boost/unordered/detail/foa/table.hpp>
|
||||
#include <boost/unordered/detail/ranges_support.hpp>
|
||||
#include <boost/unordered/detail/serialize_container.hpp>
|
||||
#include <boost/unordered/detail/type_traits.hpp>
|
||||
#include <boost/unordered/unordered_flat_set_fwd.hpp>
|
||||
@@ -104,6 +105,19 @@ namespace boost {
|
||||
{
|
||||
}
|
||||
|
||||
#if !defined(BOOST_UNORDERED_NO_RANGES)
|
||||
template<
|
||||
detail::convertible_to_from_range_t FromRangeT,
|
||||
detail::container_compatible_range<value_type> R
|
||||
>
|
||||
unordered_flat_set(
|
||||
FromRangeT&& fr, R&& rg, allocator_type const& a)
|
||||
: unordered_flat_set(
|
||||
fr, std::forward<R>(rg), size_type(0), hasher(), key_equal(), a)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
explicit unordered_flat_set(allocator_type const& a)
|
||||
: unordered_flat_set(0, a)
|
||||
{
|
||||
@@ -132,6 +146,41 @@ namespace boost {
|
||||
{
|
||||
}
|
||||
|
||||
#if !defined(BOOST_UNORDERED_NO_RANGES)
|
||||
template<
|
||||
detail::convertible_to_from_range_t FromRangeT,
|
||||
detail::container_compatible_range<value_type> R
|
||||
>
|
||||
unordered_flat_set(FromRangeT&&, R&& rg, size_type n = 0,
|
||||
hasher const& h = hasher(), key_equal const& pred = key_equal(),
|
||||
allocator_type const& a = allocator_type())
|
||||
: unordered_flat_set(n, h, pred, a)
|
||||
{
|
||||
this->insert_range(std::forward<R>(rg));
|
||||
}
|
||||
|
||||
template<
|
||||
detail::convertible_to_from_range_t FromRangeT,
|
||||
detail::container_compatible_range<value_type> R
|
||||
>
|
||||
unordered_flat_set(
|
||||
FromRangeT&& fr, R&& rg, size_type n, allocator_type const& a)
|
||||
: unordered_flat_set(
|
||||
fr, std::forward<R>(rg), n, hasher(), key_equal(), a)
|
||||
{
|
||||
}
|
||||
|
||||
template<
|
||||
detail::convertible_to_from_range_t FromRangeT,
|
||||
detail::container_compatible_range<value_type> R
|
||||
>
|
||||
unordered_flat_set(FromRangeT&& fr, R&& rg, size_type n,
|
||||
hasher const& h, allocator_type const& a)
|
||||
: unordered_flat_set(fr, std::forward<R>(rg), n, h, key_equal(), a)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
unordered_flat_set(unordered_flat_set const& other) : table_(other.table_)
|
||||
{
|
||||
}
|
||||
@@ -289,6 +338,16 @@ namespace boost {
|
||||
}
|
||||
}
|
||||
|
||||
#if !defined(BOOST_UNORDERED_NO_RANGES)
|
||||
template<detail::container_compatible_range<value_type> R>
|
||||
void insert_range(R&& rg)
|
||||
{
|
||||
auto first = std::ranges::begin(rg);
|
||||
auto last = std::ranges::end(rg);
|
||||
while (first != last) table_.emplace(*first++);
|
||||
}
|
||||
#endif
|
||||
|
||||
void insert(std::initializer_list<value_type> ilist)
|
||||
{
|
||||
this->insert(ilist.begin(), ilist.end());
|
||||
@@ -574,6 +633,25 @@ namespace boost {
|
||||
typename std::iterator_traits<InputIterator>::value_type, Hash, Pred,
|
||||
Allocator>;
|
||||
|
||||
#if !defined(BOOST_UNORDERED_NO_RANGES)
|
||||
template <
|
||||
boost::unordered::detail::convertible_to_from_range_t FromRangeT,
|
||||
std::ranges::input_range R,
|
||||
class Hash =
|
||||
boost::hash<std::ranges::range_value_t<R> >,
|
||||
class Pred =
|
||||
std::equal_to<std::ranges::range_value_t<R> >,
|
||||
class Allocator = std::allocator<std::ranges::range_value_t<R> >,
|
||||
class = std::enable_if_t<detail::is_hash_v<Hash> >,
|
||||
class = std::enable_if_t<detail::is_pred_v<Pred> >,
|
||||
class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
|
||||
unordered_flat_set(FromRangeT&&, R&&,
|
||||
std::size_t = boost::unordered::detail::foa::default_bucket_count,
|
||||
Hash = Hash(), Pred = Pred(), Allocator = Allocator())
|
||||
-> unordered_flat_set<std::ranges::range_value_t<R>,
|
||||
Hash, Pred, Allocator>;
|
||||
#endif
|
||||
|
||||
template <class T, class Hash = boost::hash<T>,
|
||||
class Pred = std::equal_to<T>, class Allocator = std::allocator<T>,
|
||||
class = std::enable_if_t<detail::is_hash_v<Hash> >,
|
||||
@@ -605,6 +683,29 @@ namespace boost {
|
||||
std::equal_to<typename std::iterator_traits<InputIterator>::value_type>,
|
||||
Allocator>;
|
||||
|
||||
#if !defined(BOOST_UNORDERED_NO_RANGES)
|
||||
template <boost::unordered::detail::convertible_to_from_range_t FromRangeT,
|
||||
std::ranges::input_range R,
|
||||
class Allocator,
|
||||
class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
|
||||
unordered_flat_set(FromRangeT&&, R&&, std::size_t, Allocator)
|
||||
-> unordered_flat_set<std::ranges::range_value_t<R>,
|
||||
boost::hash<std::ranges::range_value_t<R> >,
|
||||
std::equal_to<std::ranges::range_value_t<R> >,
|
||||
Allocator>;
|
||||
|
||||
template <boost::unordered::detail::convertible_to_from_range_t FromRangeT,
|
||||
std::ranges::input_range R,
|
||||
class Hash, class Allocator,
|
||||
class = std::enable_if_t<detail::is_hash_v<Hash> >,
|
||||
class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
|
||||
unordered_flat_set(
|
||||
FromRangeT&&, R&&, std::size_t, Hash, Allocator)
|
||||
-> unordered_flat_set<std::ranges::range_value_t<R>,
|
||||
Hash, std::equal_to<std::ranges::range_value_t<R> >,
|
||||
Allocator>;
|
||||
#endif
|
||||
|
||||
template <class T, class Allocator,
|
||||
class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
|
||||
unordered_flat_set(std::initializer_list<T>, std::size_t, Allocator)
|
||||
@@ -626,6 +727,18 @@ namespace boost {
|
||||
std::equal_to<typename std::iterator_traits<InputIterator>::value_type>,
|
||||
Allocator>;
|
||||
|
||||
#if !defined(BOOST_UNORDERED_NO_RANGES)
|
||||
template <boost::unordered::detail::convertible_to_from_range_t FromRangeT,
|
||||
std::ranges::input_range R,
|
||||
class Allocator,
|
||||
class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
|
||||
unordered_flat_set(FromRangeT&&, R&&, Allocator)
|
||||
-> unordered_flat_set<std::ranges::range_value_t<R>,
|
||||
boost::hash<std::ranges::range_value_t<R> >,
|
||||
std::equal_to<std::ranges::range_value_t<R> >,
|
||||
Allocator>;
|
||||
#endif
|
||||
|
||||
template <class T, class Allocator,
|
||||
class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
|
||||
unordered_flat_set(std::initializer_list<T>, Allocator)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Copyright (C) 2003-2004 Jeremy B. Maitin-Shepard.
|
||||
// Copyright (C) 2005-2011 Daniel James.
|
||||
// Copyright (C) 2022-2023 Christian Mazakas
|
||||
// Copyright (C) 2024 Joaquin M Lopez Munoz.
|
||||
// Copyright (C) 2024-2026 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)
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#endif
|
||||
|
||||
#include <boost/unordered/detail/map.hpp>
|
||||
#include <boost/unordered/detail/ranges_support.hpp>
|
||||
#include <boost/unordered/detail/serialize_fca_container.hpp>
|
||||
#include <boost/unordered/detail/throw_exception.hpp>
|
||||
#include <boost/unordered/detail/type_traits.hpp>
|
||||
@@ -92,6 +93,17 @@ namespace boost {
|
||||
const hasher& = hasher(), const key_equal& = key_equal(),
|
||||
const allocator_type& = allocator_type());
|
||||
|
||||
#if !defined(BOOST_UNORDERED_NO_RANGES)
|
||||
template <
|
||||
detail::convertible_to_from_range_t FromRangeT,
|
||||
detail::container_compatible_range<std::pair<const K, T> > R
|
||||
>
|
||||
unordered_map(FromRangeT&&, R&&,
|
||||
size_type = boost::unordered::detail::default_bucket_count,
|
||||
const hasher& = hasher(), const key_equal& = key_equal(),
|
||||
const allocator_type& = allocator_type());
|
||||
#endif
|
||||
|
||||
unordered_map(unordered_map const&);
|
||||
|
||||
unordered_map(unordered_map&& other)
|
||||
@@ -126,6 +138,27 @@ namespace boost {
|
||||
unordered_map(
|
||||
InputIt, InputIt, size_type, const hasher&, const allocator_type&);
|
||||
|
||||
#if !defined(BOOST_UNORDERED_NO_RANGES)
|
||||
template <
|
||||
detail::convertible_to_from_range_t FromRangeT,
|
||||
detail::container_compatible_range<std::pair<const K, T> > R
|
||||
>
|
||||
unordered_map(FromRangeT&&, R&&, const allocator_type&);
|
||||
|
||||
template <
|
||||
detail::convertible_to_from_range_t FromRangeT,
|
||||
detail::container_compatible_range<std::pair<const K, T> > R
|
||||
>
|
||||
unordered_map(FromRangeT&&, R&&, size_type, const allocator_type&);
|
||||
|
||||
template <
|
||||
detail::convertible_to_from_range_t FromRangeT,
|
||||
detail::container_compatible_range<std::pair<const K, T> > R
|
||||
>
|
||||
unordered_map(
|
||||
FromRangeT&&, R&&, size_type, const hasher&, const allocator_type&);
|
||||
#endif
|
||||
|
||||
unordered_map(std::initializer_list<value_type>, const allocator_type&);
|
||||
|
||||
unordered_map(
|
||||
@@ -248,6 +281,11 @@ namespace boost {
|
||||
|
||||
template <class InputIt> void insert(InputIt, InputIt);
|
||||
|
||||
#if !defined(BOOST_UNORDERED_NO_RANGES)
|
||||
template <detail::container_compatible_range<std::pair<const K, T> > R>
|
||||
void insert_range(R&&);
|
||||
#endif
|
||||
|
||||
void insert(std::initializer_list<value_type>);
|
||||
|
||||
// extract
|
||||
@@ -622,6 +660,27 @@ namespace boost {
|
||||
boost::unordered::detail::iter_val_t<InputIterator>, Hash, Pred,
|
||||
Allocator>;
|
||||
|
||||
#if !defined(BOOST_UNORDERED_NO_RANGES)
|
||||
template <
|
||||
boost::unordered::detail::convertible_to_from_range_t FromRangeT,
|
||||
std::ranges::input_range R,
|
||||
class Hash =
|
||||
boost::hash<boost::unordered::detail::range_key_t<R> >,
|
||||
class Pred =
|
||||
std::equal_to<boost::unordered::detail::range_key_t<R> >,
|
||||
class Allocator = std::allocator<
|
||||
boost::unordered::detail::range_to_alloc_t<R> >,
|
||||
class = std::enable_if_t<detail::is_hash_v<Hash> >,
|
||||
class = std::enable_if_t<detail::is_pred_v<Pred> >,
|
||||
class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
|
||||
unordered_map(FromRangeT&&, R&&,
|
||||
std::size_t = boost::unordered::detail::default_bucket_count,
|
||||
Hash = Hash(), Pred = Pred(), Allocator = Allocator())
|
||||
-> unordered_map<boost::unordered::detail::range_key_t<R>,
|
||||
boost::unordered::detail::range_mapped_t<R>, Hash, Pred,
|
||||
Allocator>;
|
||||
#endif
|
||||
|
||||
template <class Key, class T,
|
||||
class Hash = boost::hash<std::remove_const_t<Key> >,
|
||||
class Pred = std::equal_to<std::remove_const_t<Key> >,
|
||||
@@ -664,6 +723,42 @@ namespace boost {
|
||||
std::equal_to<boost::unordered::detail::iter_key_t<InputIterator> >,
|
||||
Allocator>;
|
||||
|
||||
#if !defined(BOOST_UNORDERED_NO_RANGES)
|
||||
template <boost::unordered::detail::convertible_to_from_range_t FromRangeT,
|
||||
std::ranges::input_range R,
|
||||
class Allocator,
|
||||
class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
|
||||
unordered_map(FromRangeT&&, R&&, std::size_t, Allocator)
|
||||
-> unordered_map<boost::unordered::detail::range_key_t<R>,
|
||||
boost::unordered::detail::range_mapped_t<R>,
|
||||
boost::hash<boost::unordered::detail::range_key_t<R> >,
|
||||
std::equal_to<boost::unordered::detail::range_key_t<R> >,
|
||||
Allocator>;
|
||||
|
||||
template <boost::unordered::detail::convertible_to_from_range_t FromRangeT,
|
||||
std::ranges::input_range R,
|
||||
class Allocator,
|
||||
class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
|
||||
unordered_map(FromRangeT&&, R&&, Allocator)
|
||||
-> unordered_map<boost::unordered::detail::range_key_t<R>,
|
||||
boost::unordered::detail::range_mapped_t<R>,
|
||||
boost::hash<boost::unordered::detail::range_key_t<R> >,
|
||||
std::equal_to<boost::unordered::detail::range_key_t<R> >,
|
||||
Allocator>;
|
||||
|
||||
template <boost::unordered::detail::convertible_to_from_range_t FromRangeT,
|
||||
std::ranges::input_range R,
|
||||
class Hash, class Allocator,
|
||||
class = std::enable_if_t<detail::is_hash_v<Hash> >,
|
||||
class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
|
||||
unordered_map(
|
||||
FromRangeT&&, R&&, std::size_t, Hash, Allocator)
|
||||
-> unordered_map<boost::unordered::detail::range_key_t<R>,
|
||||
boost::unordered::detail::range_mapped_t<R>, Hash,
|
||||
std::equal_to<boost::unordered::detail::range_key_t<R> >,
|
||||
Allocator>;
|
||||
#endif
|
||||
|
||||
template <class Key, class T, class Allocator,
|
||||
class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
|
||||
unordered_map(std::initializer_list<std::pair<Key, T> >, std::size_t,
|
||||
@@ -742,6 +837,17 @@ namespace boost {
|
||||
const hasher& = hasher(), const key_equal& = key_equal(),
|
||||
const allocator_type& = allocator_type());
|
||||
|
||||
#if !defined(BOOST_UNORDERED_NO_RANGES)
|
||||
template <
|
||||
detail::convertible_to_from_range_t FromRangeT,
|
||||
detail::container_compatible_range<std::pair<const K, T> > R
|
||||
>
|
||||
unordered_multimap(FromRangeT&&, R&&,
|
||||
size_type = boost::unordered::detail::default_bucket_count,
|
||||
const hasher& = hasher(), const key_equal& = key_equal(),
|
||||
const allocator_type& = allocator_type());
|
||||
#endif
|
||||
|
||||
unordered_multimap(unordered_multimap const&);
|
||||
|
||||
unordered_multimap(unordered_multimap&& other)
|
||||
@@ -777,6 +883,27 @@ namespace boost {
|
||||
unordered_multimap(
|
||||
InputIt, InputIt, size_type, const hasher&, const allocator_type&);
|
||||
|
||||
#if !defined(BOOST_UNORDERED_NO_RANGES)
|
||||
template <
|
||||
detail::convertible_to_from_range_t FromRangeT,
|
||||
detail::container_compatible_range<std::pair<const K, T> > R
|
||||
>
|
||||
unordered_multimap(FromRangeT&&, R&&, const allocator_type&);
|
||||
|
||||
template <
|
||||
detail::convertible_to_from_range_t FromRangeT,
|
||||
detail::container_compatible_range<std::pair<const K, T> > R
|
||||
>
|
||||
unordered_multimap(FromRangeT&&, R&&, size_type, const allocator_type&);
|
||||
|
||||
template <
|
||||
detail::convertible_to_from_range_t FromRangeT,
|
||||
detail::container_compatible_range<std::pair<const K, T> > R
|
||||
>
|
||||
unordered_multimap(
|
||||
FromRangeT&&, R&&, size_type, const hasher&, const allocator_type&);
|
||||
#endif
|
||||
|
||||
unordered_multimap(
|
||||
std::initializer_list<value_type>, const allocator_type&);
|
||||
|
||||
@@ -894,6 +1021,11 @@ namespace boost {
|
||||
|
||||
template <class InputIt> void insert(InputIt, InputIt);
|
||||
|
||||
#if !defined(BOOST_UNORDERED_NO_RANGES)
|
||||
template <detail::container_compatible_range<std::pair<const K, T> > R>
|
||||
void insert_range(R&&);
|
||||
#endif
|
||||
|
||||
void insert(std::initializer_list<value_type>);
|
||||
|
||||
// extract
|
||||
@@ -1141,6 +1273,26 @@ namespace boost {
|
||||
boost::unordered::detail::iter_val_t<InputIterator>, Hash, Pred,
|
||||
Allocator>;
|
||||
|
||||
#if !defined(BOOST_UNORDERED_NO_RANGES)
|
||||
template <
|
||||
boost::unordered::detail::convertible_to_from_range_t FromRangeT,
|
||||
std::ranges::input_range R,
|
||||
class Hash =
|
||||
boost::hash<boost::unordered::detail::range_key_t<R> >,
|
||||
class Pred =
|
||||
std::equal_to<boost::unordered::detail::range_key_t<R> >,
|
||||
class Allocator = std::allocator<
|
||||
boost::unordered::detail::range_to_alloc_t<R> >,
|
||||
class = std::enable_if_t<detail::is_hash_v<Hash> >,
|
||||
class = std::enable_if_t<detail::is_pred_v<Pred> >,
|
||||
class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
|
||||
unordered_multimap(FromRangeT&&, R&&,
|
||||
std::size_t = boost::unordered::detail::default_bucket_count,
|
||||
Hash = Hash(), Pred = Pred(), Allocator = Allocator())
|
||||
-> unordered_multimap<boost::unordered::detail::range_key_t<R>,
|
||||
boost::unordered::detail::range_mapped_t<R>, Hash, Pred,
|
||||
Allocator>;
|
||||
#endif
|
||||
template <class Key, class T,
|
||||
class Hash = boost::hash<std::remove_const_t<Key> >,
|
||||
class Pred = std::equal_to<std::remove_const_t<Key> >,
|
||||
@@ -1184,6 +1336,42 @@ namespace boost {
|
||||
std::equal_to<boost::unordered::detail::iter_key_t<InputIterator> >,
|
||||
Allocator>;
|
||||
|
||||
#if !defined(BOOST_UNORDERED_NO_RANGES)
|
||||
template <boost::unordered::detail::convertible_to_from_range_t FromRangeT,
|
||||
std::ranges::input_range R,
|
||||
class Allocator,
|
||||
class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
|
||||
unordered_multimap(FromRangeT&&, R&&, std::size_t, Allocator)
|
||||
-> unordered_multimap<boost::unordered::detail::range_key_t<R>,
|
||||
boost::unordered::detail::range_mapped_t<R>,
|
||||
boost::hash<boost::unordered::detail::range_key_t<R> >,
|
||||
std::equal_to<boost::unordered::detail::range_key_t<R> >,
|
||||
Allocator>;
|
||||
|
||||
template <boost::unordered::detail::convertible_to_from_range_t FromRangeT,
|
||||
std::ranges::input_range R,
|
||||
class Allocator,
|
||||
class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
|
||||
unordered_multimap(FromRangeT&&, R&&, Allocator)
|
||||
-> unordered_multimap<boost::unordered::detail::range_key_t<R>,
|
||||
boost::unordered::detail::range_mapped_t<R>,
|
||||
boost::hash<boost::unordered::detail::range_key_t<R> >,
|
||||
std::equal_to<boost::unordered::detail::range_key_t<R> >,
|
||||
Allocator>;
|
||||
|
||||
template <boost::unordered::detail::convertible_to_from_range_t FromRangeT,
|
||||
std::ranges::input_range R,
|
||||
class Hash, class Allocator,
|
||||
class = std::enable_if_t<detail::is_hash_v<Hash> >,
|
||||
class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
|
||||
unordered_multimap(
|
||||
FromRangeT&&, R&&, std::size_t, Hash, Allocator)
|
||||
-> unordered_multimap<boost::unordered::detail::range_key_t<R>,
|
||||
boost::unordered::detail::range_mapped_t<R>, Hash,
|
||||
std::equal_to<boost::unordered::detail::range_key_t<R> >,
|
||||
Allocator>;
|
||||
#endif
|
||||
|
||||
template <class Key, class T, class Allocator,
|
||||
class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
|
||||
unordered_multimap(std::initializer_list<std::pair<Key, T> >, std::size_t,
|
||||
@@ -1231,6 +1419,23 @@ namespace boost {
|
||||
this->insert(f, l);
|
||||
}
|
||||
|
||||
#if !defined(BOOST_UNORDERED_NO_RANGES)
|
||||
template <class K, class T, class H, class P, class A>
|
||||
template <
|
||||
detail::convertible_to_from_range_t FromRangeT,
|
||||
detail::container_compatible_range<std::pair<const K, T> > R
|
||||
>
|
||||
unordered_map<K, T, H, P, A>::unordered_map(FromRangeT&&, R&& rg,
|
||||
size_type n, const hasher& hf, const key_equal& eql,
|
||||
const allocator_type& a)
|
||||
: table_(
|
||||
boost::unordered::detail::initial_size(std::forward<R>(rg), n),
|
||||
hf, eql, a)
|
||||
{
|
||||
this->insert_range(std::forward<R>(rg));
|
||||
}
|
||||
#endif
|
||||
|
||||
template <class K, class T, class H, class P, class A>
|
||||
unordered_map<K, T, H, P, A>::unordered_map(unordered_map const& other)
|
||||
: table_(other.table_,
|
||||
@@ -1303,6 +1508,7 @@ namespace boost {
|
||||
this->insert(f, l);
|
||||
}
|
||||
|
||||
|
||||
template <class K, class T, class H, class P, class A>
|
||||
template <class InputIt>
|
||||
unordered_map<K, T, H, P, A>::unordered_map(
|
||||
@@ -1323,6 +1529,51 @@ namespace boost {
|
||||
this->insert(f, l);
|
||||
}
|
||||
|
||||
#if !defined(BOOST_UNORDERED_NO_RANGES)
|
||||
template <class K, class T, class H, class P, class A>
|
||||
template <
|
||||
detail::convertible_to_from_range_t FromRangeT,
|
||||
detail::container_compatible_range<std::pair<const K, T> > R
|
||||
>
|
||||
unordered_map<K, T, H, P, A>::unordered_map(
|
||||
FromRangeT&&, R&& rg, const allocator_type& a)
|
||||
: table_(
|
||||
boost::unordered::detail::initial_size(
|
||||
std::forward<R>(rg), detail::default_bucket_count),
|
||||
hasher(), key_equal(), a)
|
||||
{
|
||||
this->insert_range(std::forward<R>(rg));
|
||||
}
|
||||
|
||||
template <class K, class T, class H, class P, class A>
|
||||
template <
|
||||
detail::convertible_to_from_range_t FromRangeT,
|
||||
detail::container_compatible_range<std::pair<const K, T> > R
|
||||
>
|
||||
unordered_map<K, T, H, P, A>::unordered_map(
|
||||
FromRangeT&&, R&& rg, size_type n, const allocator_type& a)
|
||||
: table_(
|
||||
boost::unordered::detail::initial_size(std::forward<R>(rg), n),
|
||||
hasher(), key_equal(), a)
|
||||
{
|
||||
this->insert_range(std::forward<R>(rg));
|
||||
}
|
||||
|
||||
template <class K, class T, class H, class P, class A>
|
||||
template <
|
||||
detail::convertible_to_from_range_t FromRangeT,
|
||||
detail::container_compatible_range<std::pair<const K, T> > R
|
||||
>
|
||||
unordered_map<K, T, H, P, A>::unordered_map(FromRangeT&&, R&& rg,
|
||||
size_type n, const hasher& hf, const allocator_type& a)
|
||||
: table_(
|
||||
boost::unordered::detail::initial_size(std::forward<R>(rg), n),
|
||||
hf, key_equal(), a)
|
||||
{
|
||||
this->insert_range(std::forward<R>(rg));
|
||||
}
|
||||
#endif
|
||||
|
||||
template <class K, class T, class H, class P, class A>
|
||||
unordered_map<K, T, H, P, A>::unordered_map(
|
||||
std::initializer_list<value_type> list, const allocator_type& a)
|
||||
@@ -1395,6 +1646,20 @@ namespace boost {
|
||||
}
|
||||
}
|
||||
|
||||
#if !defined(BOOST_UNORDERED_NO_RANGES)
|
||||
template <class K, class T, class H, class P, class A>
|
||||
template <detail::container_compatible_range<std::pair<const K, T> > R>
|
||||
void unordered_map<K, T, H, P, A>::insert_range(R&& rg)
|
||||
{
|
||||
auto first = std::ranges::begin(rg);
|
||||
auto last = std::ranges::end(rg);
|
||||
if (first != last) {
|
||||
table_.insert_range_unique(
|
||||
table::extractor::extract(*first), first, last);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
template <class K, class T, class H, class P, class A>
|
||||
void unordered_map<K, T, H, P, A>::insert(
|
||||
std::initializer_list<value_type> list)
|
||||
@@ -1757,6 +2022,23 @@ namespace boost {
|
||||
this->insert(f, l);
|
||||
}
|
||||
|
||||
#if !defined(BOOST_UNORDERED_NO_RANGES)
|
||||
template <class K, class T, class H, class P, class A>
|
||||
template <
|
||||
detail::convertible_to_from_range_t FromRangeT,
|
||||
detail::container_compatible_range<std::pair<const K, T> > R
|
||||
>
|
||||
unordered_multimap<K, T, H, P, A>::unordered_multimap(FromRangeT&&, R&& rg,
|
||||
size_type n, const hasher& hf, const key_equal& eql,
|
||||
const allocator_type& a)
|
||||
: table_(
|
||||
boost::unordered::detail::initial_size(std::forward<R>(rg), n),
|
||||
hf, eql, a)
|
||||
{
|
||||
this->insert_range(std::forward<R>(rg));
|
||||
}
|
||||
#endif
|
||||
|
||||
template <class K, class T, class H, class P, class A>
|
||||
unordered_multimap<K, T, H, P, A>::unordered_multimap(
|
||||
unordered_multimap const& other)
|
||||
@@ -1851,6 +2133,51 @@ namespace boost {
|
||||
this->insert(f, l);
|
||||
}
|
||||
|
||||
#if !defined(BOOST_UNORDERED_NO_RANGES)
|
||||
template <class K, class T, class H, class P, class A>
|
||||
template <
|
||||
detail::convertible_to_from_range_t FromRangeT,
|
||||
detail::container_compatible_range<std::pair<const K, T> > R
|
||||
>
|
||||
unordered_multimap<K, T, H, P, A>::unordered_multimap(
|
||||
FromRangeT&&, R&& rg, const allocator_type& a)
|
||||
: table_(
|
||||
boost::unordered::detail::initial_size(
|
||||
std::forward<R>(rg), detail::default_bucket_count),
|
||||
hasher(), key_equal(), a)
|
||||
{
|
||||
this->insert_range(std::forward<R>(rg));
|
||||
}
|
||||
|
||||
template <class K, class T, class H, class P, class A>
|
||||
template <
|
||||
detail::convertible_to_from_range_t FromRangeT,
|
||||
detail::container_compatible_range<std::pair<const K, T> > R
|
||||
>
|
||||
unordered_multimap<K, T, H, P, A>::unordered_multimap(
|
||||
FromRangeT&&, R&& rg, size_type n, const allocator_type& a)
|
||||
: table_(
|
||||
boost::unordered::detail::initial_size(std::forward<R>(rg), n),
|
||||
hasher(), key_equal(), a)
|
||||
{
|
||||
this->insert_range(std::forward<R>(rg));
|
||||
}
|
||||
|
||||
template <class K, class T, class H, class P, class A>
|
||||
template <
|
||||
detail::convertible_to_from_range_t FromRangeT,
|
||||
detail::container_compatible_range<std::pair<const K, T> > R
|
||||
>
|
||||
unordered_multimap<K, T, H, P, A>::unordered_multimap(FromRangeT&&, R&& rg,
|
||||
size_type n, const hasher& hf, const allocator_type& a)
|
||||
: table_(
|
||||
boost::unordered::detail::initial_size(std::forward<R>(rg), n),
|
||||
hf, key_equal(), a)
|
||||
{
|
||||
this->insert_range(std::forward<R>(rg));
|
||||
}
|
||||
#endif
|
||||
|
||||
template <class K, class T, class H, class P, class A>
|
||||
unordered_multimap<K, T, H, P, A>::unordered_multimap(
|
||||
std::initializer_list<value_type> list, const allocator_type& a)
|
||||
@@ -1921,6 +2248,16 @@ namespace boost {
|
||||
table_.insert_range_equiv(first, last);
|
||||
}
|
||||
|
||||
#if !defined(BOOST_UNORDERED_NO_RANGES)
|
||||
template <class K, class T, class H, class P, class A>
|
||||
template <detail::container_compatible_range<std::pair<const K, T> > R>
|
||||
void unordered_multimap<K, T, H, P, A>::insert_range(R&& rg)
|
||||
{
|
||||
table_.insert_range_equiv(std::ranges::begin(rg), std::ranges::end(rg));
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
template <class K, class T, class H, class P, class A>
|
||||
void unordered_multimap<K, T, H, P, A>::insert(
|
||||
std::initializer_list<value_type> list)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// Copyright (C) 2022-2023 Christian Mazakas
|
||||
// Copyright (C) 2024-2025 Joaquin M Lopez Munoz
|
||||
// Copyright (C) 2024-2026 Joaquin M Lopez Munoz
|
||||
// Copyright (C) 2026 Braden Ganetsky
|
||||
// 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)
|
||||
@@ -16,6 +16,7 @@
|
||||
#include <boost/unordered/detail/foa/node_map_handle.hpp>
|
||||
#include <boost/unordered/detail/foa/node_map_types.hpp>
|
||||
#include <boost/unordered/detail/foa/table.hpp>
|
||||
#include <boost/unordered/detail/ranges_support.hpp>
|
||||
#include <boost/unordered/detail/serialize_container.hpp>
|
||||
#include <boost/unordered/detail/throw_exception.hpp>
|
||||
#include <boost/unordered/detail/type_traits.hpp>
|
||||
@@ -115,6 +116,19 @@ namespace boost {
|
||||
{
|
||||
}
|
||||
|
||||
#if !defined(BOOST_UNORDERED_NO_RANGES)
|
||||
template<
|
||||
detail::convertible_to_from_range_t FromRangeT,
|
||||
detail::container_compatible_range<value_type> R
|
||||
>
|
||||
unordered_node_map(
|
||||
FromRangeT&& fr, R&& rg, allocator_type const& a)
|
||||
: unordered_node_map(
|
||||
fr, std::forward<R>(rg), size_type(0), hasher(), key_equal(), a)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
explicit unordered_node_map(allocator_type const& a)
|
||||
: unordered_node_map(0, a)
|
||||
{
|
||||
@@ -143,6 +157,41 @@ namespace boost {
|
||||
{
|
||||
}
|
||||
|
||||
#if !defined(BOOST_UNORDERED_NO_RANGES)
|
||||
template<
|
||||
detail::convertible_to_from_range_t FromRangeT,
|
||||
detail::container_compatible_range<value_type> R
|
||||
>
|
||||
unordered_node_map(FromRangeT&&, R&& rg, size_type n = 0,
|
||||
hasher const& h = hasher(), key_equal const& pred = key_equal(),
|
||||
allocator_type const& a = allocator_type())
|
||||
: unordered_node_map(n, h, pred, a)
|
||||
{
|
||||
this->insert_range(std::forward<R>(rg));
|
||||
}
|
||||
|
||||
template<
|
||||
detail::convertible_to_from_range_t FromRangeT,
|
||||
detail::container_compatible_range<value_type> R
|
||||
>
|
||||
unordered_node_map(
|
||||
FromRangeT&& fr, R&& rg, size_type n, allocator_type const& a)
|
||||
: unordered_node_map(
|
||||
fr, std::forward<R>(rg), n, hasher(), key_equal(), a)
|
||||
{
|
||||
}
|
||||
|
||||
template<
|
||||
detail::convertible_to_from_range_t FromRangeT,
|
||||
detail::container_compatible_range<value_type> R
|
||||
>
|
||||
unordered_node_map(FromRangeT&& fr, R&& rg, size_type n,
|
||||
hasher const& h, allocator_type const& a)
|
||||
: unordered_node_map(fr, std::forward<R>(rg), n, h, key_equal(), a)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
unordered_node_map(unordered_node_map const& other) : table_(other.table_)
|
||||
{
|
||||
}
|
||||
@@ -285,6 +334,16 @@ namespace boost {
|
||||
}
|
||||
}
|
||||
|
||||
#if !defined(BOOST_UNORDERED_NO_RANGES)
|
||||
template<detail::container_compatible_range<value_type> R>
|
||||
BOOST_FORCEINLINE void insert_range(R&& rg)
|
||||
{
|
||||
auto first = std::ranges::begin(rg);
|
||||
auto last = std::ranges::end(rg);
|
||||
while (first != last) table_.emplace(*first++);
|
||||
}
|
||||
#endif
|
||||
|
||||
void insert(std::initializer_list<value_type> ilist)
|
||||
{
|
||||
this->insert(ilist.begin(), ilist.end());
|
||||
@@ -830,6 +889,27 @@ namespace boost {
|
||||
boost::unordered::detail::iter_val_t<InputIterator>, Hash, Pred,
|
||||
Allocator>;
|
||||
|
||||
#if !defined(BOOST_UNORDERED_NO_RANGES)
|
||||
template <
|
||||
boost::unordered::detail::convertible_to_from_range_t FromRangeT,
|
||||
std::ranges::input_range R,
|
||||
class Hash =
|
||||
boost::hash<boost::unordered::detail::range_key_t<R> >,
|
||||
class Pred =
|
||||
std::equal_to<boost::unordered::detail::range_key_t<R> >,
|
||||
class Allocator = std::allocator<
|
||||
boost::unordered::detail::range_to_alloc_t<R> >,
|
||||
class = std::enable_if_t<detail::is_hash_v<Hash> >,
|
||||
class = std::enable_if_t<detail::is_pred_v<Pred> >,
|
||||
class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
|
||||
unordered_node_map(FromRangeT&&, R&&,
|
||||
std::size_t = boost::unordered::detail::foa::default_bucket_count,
|
||||
Hash = Hash(), Pred = Pred(), Allocator = Allocator())
|
||||
-> unordered_node_map<boost::unordered::detail::range_key_t<R>,
|
||||
boost::unordered::detail::range_mapped_t<R>, Hash, Pred,
|
||||
Allocator>;
|
||||
#endif
|
||||
|
||||
template <class Key, class T,
|
||||
class Hash = boost::hash<std::remove_const_t<Key> >,
|
||||
class Pred = std::equal_to<std::remove_const_t<Key> >,
|
||||
@@ -874,6 +954,42 @@ namespace boost {
|
||||
std::equal_to<boost::unordered::detail::iter_key_t<InputIterator> >,
|
||||
Allocator>;
|
||||
|
||||
#if !defined(BOOST_UNORDERED_NO_RANGES)
|
||||
template <boost::unordered::detail::convertible_to_from_range_t FromRangeT,
|
||||
std::ranges::input_range R,
|
||||
class Allocator,
|
||||
class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
|
||||
unordered_node_map(FromRangeT&&, R&&, std::size_t, Allocator)
|
||||
-> unordered_node_map<boost::unordered::detail::range_key_t<R>,
|
||||
boost::unordered::detail::range_mapped_t<R>,
|
||||
boost::hash<boost::unordered::detail::range_key_t<R> >,
|
||||
std::equal_to<boost::unordered::detail::range_key_t<R> >,
|
||||
Allocator>;
|
||||
|
||||
template <boost::unordered::detail::convertible_to_from_range_t FromRangeT,
|
||||
std::ranges::input_range R,
|
||||
class Allocator,
|
||||
class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
|
||||
unordered_node_map(FromRangeT&&, R&&, Allocator)
|
||||
-> unordered_node_map<boost::unordered::detail::range_key_t<R>,
|
||||
boost::unordered::detail::range_mapped_t<R>,
|
||||
boost::hash<boost::unordered::detail::range_key_t<R> >,
|
||||
std::equal_to<boost::unordered::detail::range_key_t<R> >,
|
||||
Allocator>;
|
||||
|
||||
template <boost::unordered::detail::convertible_to_from_range_t FromRangeT,
|
||||
std::ranges::input_range R,
|
||||
class Hash, class Allocator,
|
||||
class = std::enable_if_t<detail::is_hash_v<Hash> >,
|
||||
class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
|
||||
unordered_node_map(
|
||||
FromRangeT&&, R&&, std::size_t, Hash, Allocator)
|
||||
-> unordered_node_map<boost::unordered::detail::range_key_t<R>,
|
||||
boost::unordered::detail::range_mapped_t<R>, Hash,
|
||||
std::equal_to<boost::unordered::detail::range_key_t<R> >,
|
||||
Allocator>;
|
||||
#endif
|
||||
|
||||
template <class Key, class T, class Allocator,
|
||||
class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
|
||||
unordered_node_map(std::initializer_list<std::pair<Key, T> >, std::size_t,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// Copyright (C) 2022-2023 Christian Mazakas
|
||||
// Copyright (C) 2024-2025 Joaquin M Lopez Munoz
|
||||
// Copyright (C) 2024-2026 Joaquin M Lopez Munoz
|
||||
// Copyright (C) 2026 Braden Ganetsky
|
||||
// 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)
|
||||
@@ -17,6 +17,7 @@
|
||||
#include <boost/unordered/detail/foa/node_set_handle.hpp>
|
||||
#include <boost/unordered/detail/foa/node_set_types.hpp>
|
||||
#include <boost/unordered/detail/foa/table.hpp>
|
||||
#include <boost/unordered/detail/ranges_support.hpp>
|
||||
#include <boost/unordered/detail/serialize_container.hpp>
|
||||
#include <boost/unordered/detail/type_traits.hpp>
|
||||
#include <boost/unordered/unordered_node_set_fwd.hpp>
|
||||
@@ -113,6 +114,19 @@ namespace boost {
|
||||
{
|
||||
}
|
||||
|
||||
#if !defined(BOOST_UNORDERED_NO_RANGES)
|
||||
template<
|
||||
detail::convertible_to_from_range_t FromRangeT,
|
||||
detail::container_compatible_range<value_type> R
|
||||
>
|
||||
unordered_node_set(
|
||||
FromRangeT&& fr, R&& rg, allocator_type const& a)
|
||||
: unordered_node_set(
|
||||
fr, std::forward<R>(rg), size_type(0), hasher(), key_equal(), a)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
explicit unordered_node_set(allocator_type const& a)
|
||||
: unordered_node_set(0, a)
|
||||
{
|
||||
@@ -141,6 +155,41 @@ namespace boost {
|
||||
{
|
||||
}
|
||||
|
||||
#if !defined(BOOST_UNORDERED_NO_RANGES)
|
||||
template<
|
||||
detail::convertible_to_from_range_t FromRangeT,
|
||||
detail::container_compatible_range<value_type> R
|
||||
>
|
||||
unordered_node_set(FromRangeT&&, R&& rg, size_type n = 0,
|
||||
hasher const& h = hasher(), key_equal const& pred = key_equal(),
|
||||
allocator_type const& a = allocator_type())
|
||||
: unordered_node_set(n, h, pred, a)
|
||||
{
|
||||
this->insert_range(std::forward<R>(rg));
|
||||
}
|
||||
|
||||
template<
|
||||
detail::convertible_to_from_range_t FromRangeT,
|
||||
detail::container_compatible_range<value_type> R
|
||||
>
|
||||
unordered_node_set(
|
||||
FromRangeT&& fr, R&& rg, size_type n, allocator_type const& a)
|
||||
: unordered_node_set(
|
||||
fr, std::forward<R>(rg), n, hasher(), key_equal(), a)
|
||||
{
|
||||
}
|
||||
|
||||
template<
|
||||
detail::convertible_to_from_range_t FromRangeT,
|
||||
detail::container_compatible_range<value_type> R
|
||||
>
|
||||
unordered_node_set(FromRangeT&& fr, R&& rg, size_type n,
|
||||
hasher const& h, allocator_type const& a)
|
||||
: unordered_node_set(fr, std::forward<R>(rg), n, h, key_equal(), a)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
unordered_node_set(unordered_node_set const& other) : table_(other.table_)
|
||||
{
|
||||
}
|
||||
@@ -298,6 +347,16 @@ namespace boost {
|
||||
}
|
||||
}
|
||||
|
||||
#if !defined(BOOST_UNORDERED_NO_RANGES)
|
||||
template<detail::container_compatible_range<value_type> R>
|
||||
void insert_range(R&& rg)
|
||||
{
|
||||
auto first = std::ranges::begin(rg);
|
||||
auto last = std::ranges::end(rg);
|
||||
while (first != last) table_.emplace(*first++);
|
||||
}
|
||||
#endif
|
||||
|
||||
void insert(std::initializer_list<value_type> ilist)
|
||||
{
|
||||
this->insert(ilist.begin(), ilist.end());
|
||||
@@ -650,6 +709,25 @@ namespace boost {
|
||||
typename std::iterator_traits<InputIterator>::value_type, Hash, Pred,
|
||||
Allocator>;
|
||||
|
||||
#if !defined(BOOST_UNORDERED_NO_RANGES)
|
||||
template <
|
||||
boost::unordered::detail::convertible_to_from_range_t FromRangeT,
|
||||
std::ranges::input_range R,
|
||||
class Hash =
|
||||
boost::hash<std::ranges::range_value_t<R> >,
|
||||
class Pred =
|
||||
std::equal_to<std::ranges::range_value_t<R> >,
|
||||
class Allocator = std::allocator<std::ranges::range_value_t<R> >,
|
||||
class = std::enable_if_t<detail::is_hash_v<Hash> >,
|
||||
class = std::enable_if_t<detail::is_pred_v<Pred> >,
|
||||
class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
|
||||
unordered_node_set(FromRangeT&&, R&&,
|
||||
std::size_t = boost::unordered::detail::foa::default_bucket_count,
|
||||
Hash = Hash(), Pred = Pred(), Allocator = Allocator())
|
||||
-> unordered_node_set<std::ranges::range_value_t<R>,
|
||||
Hash, Pred, Allocator>;
|
||||
#endif
|
||||
|
||||
template <class T, class Hash = boost::hash<T>,
|
||||
class Pred = std::equal_to<T>, class Allocator = std::allocator<T>,
|
||||
class = std::enable_if_t<detail::is_hash_v<Hash> >,
|
||||
@@ -681,6 +759,29 @@ namespace boost {
|
||||
std::equal_to<typename std::iterator_traits<InputIterator>::value_type>,
|
||||
Allocator>;
|
||||
|
||||
#if !defined(BOOST_UNORDERED_NO_RANGES)
|
||||
template <boost::unordered::detail::convertible_to_from_range_t FromRangeT,
|
||||
std::ranges::input_range R,
|
||||
class Allocator,
|
||||
class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
|
||||
unordered_node_set(FromRangeT&&, R&&, std::size_t, Allocator)
|
||||
-> unordered_node_set<std::ranges::range_value_t<R>,
|
||||
boost::hash<std::ranges::range_value_t<R> >,
|
||||
std::equal_to<std::ranges::range_value_t<R> >,
|
||||
Allocator>;
|
||||
|
||||
template <boost::unordered::detail::convertible_to_from_range_t FromRangeT,
|
||||
std::ranges::input_range R,
|
||||
class Hash, class Allocator,
|
||||
class = std::enable_if_t<detail::is_hash_v<Hash> >,
|
||||
class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
|
||||
unordered_node_set(
|
||||
FromRangeT&&, R&&, std::size_t, Hash, Allocator)
|
||||
-> unordered_node_set<std::ranges::range_value_t<R>,
|
||||
Hash, std::equal_to<std::ranges::range_value_t<R> >,
|
||||
Allocator>;
|
||||
#endif
|
||||
|
||||
template <class T, class Allocator,
|
||||
class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
|
||||
unordered_node_set(std::initializer_list<T>, std::size_t, Allocator)
|
||||
@@ -702,6 +803,18 @@ namespace boost {
|
||||
std::equal_to<typename std::iterator_traits<InputIterator>::value_type>,
|
||||
Allocator>;
|
||||
|
||||
#if !defined(BOOST_UNORDERED_NO_RANGES)
|
||||
template <boost::unordered::detail::convertible_to_from_range_t FromRangeT,
|
||||
std::ranges::input_range R,
|
||||
class Allocator,
|
||||
class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
|
||||
unordered_node_set(FromRangeT&&, R&&, Allocator)
|
||||
-> unordered_node_set<std::ranges::range_value_t<R>,
|
||||
boost::hash<std::ranges::range_value_t<R> >,
|
||||
std::equal_to<std::ranges::range_value_t<R> >,
|
||||
Allocator>;
|
||||
#endif
|
||||
|
||||
template <class T, class Allocator,
|
||||
class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
|
||||
unordered_node_set(std::initializer_list<T>, Allocator)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Copyright (C) 2003-2004 Jeremy B. Maitin-Shepard.
|
||||
// Copyright (C) 2005-2011 Daniel James.
|
||||
// Copyright (C) 2022-2023 Christian Mazakas
|
||||
// Copyright (C) 2024 Joaquin M Lopez Munoz.
|
||||
// Copyright (C) 2024-2026 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)
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/unordered/detail/ranges_support.hpp>
|
||||
#include <boost/unordered/detail/serialize_fca_container.hpp>
|
||||
#include <boost/unordered/detail/set.hpp>
|
||||
#include <boost/unordered/detail/type_traits.hpp>
|
||||
@@ -88,6 +89,17 @@ namespace boost {
|
||||
const hasher& = hasher(), const key_equal& = key_equal(),
|
||||
const allocator_type& = allocator_type());
|
||||
|
||||
#if !defined(BOOST_UNORDERED_NO_RANGES)
|
||||
template<
|
||||
detail::convertible_to_from_range_t FromRangeT,
|
||||
detail::container_compatible_range<T> R
|
||||
>
|
||||
unordered_set(FromRangeT&&, R&&,
|
||||
size_type = boost::unordered::detail::default_bucket_count,
|
||||
const hasher& = hasher(), const key_equal& = key_equal(),
|
||||
const allocator_type& = allocator_type());
|
||||
#endif
|
||||
|
||||
unordered_set(unordered_set const&);
|
||||
|
||||
unordered_set(unordered_set&& other)
|
||||
@@ -122,6 +134,27 @@ namespace boost {
|
||||
unordered_set(
|
||||
InputIt, InputIt, size_type, const hasher&, const allocator_type&);
|
||||
|
||||
#if !defined(BOOST_UNORDERED_NO_RANGES)
|
||||
template <
|
||||
detail::convertible_to_from_range_t FromRangeT,
|
||||
detail::container_compatible_range<T> R
|
||||
>
|
||||
unordered_set(FromRangeT&&, R&&, const allocator_type&);
|
||||
|
||||
template <
|
||||
detail::convertible_to_from_range_t FromRangeT,
|
||||
detail::container_compatible_range<T> R
|
||||
>
|
||||
unordered_set(FromRangeT&&, R&&, size_type, const allocator_type&);
|
||||
|
||||
template <
|
||||
detail::convertible_to_from_range_t FromRangeT,
|
||||
detail::container_compatible_range<T> R
|
||||
>
|
||||
unordered_set(
|
||||
FromRangeT&&, R&&, size_type, const hasher&, const allocator_type&);
|
||||
#endif
|
||||
|
||||
unordered_set(std::initializer_list<value_type>, const allocator_type&);
|
||||
|
||||
unordered_set(
|
||||
@@ -246,6 +279,11 @@ namespace boost {
|
||||
|
||||
template <class InputIt> void insert(InputIt, InputIt);
|
||||
|
||||
#if !defined(BOOST_UNORDERED_NO_RANGES)
|
||||
template <detail::container_compatible_range<T> R>
|
||||
void insert_range(R&&);
|
||||
#endif
|
||||
|
||||
void insert(std::initializer_list<value_type>);
|
||||
|
||||
// extract
|
||||
@@ -478,6 +516,25 @@ namespace boost {
|
||||
-> unordered_set<typename std::iterator_traits<InputIterator>::value_type,
|
||||
Hash, Pred, Allocator>;
|
||||
|
||||
#if !defined(BOOST_UNORDERED_NO_RANGES)
|
||||
template <
|
||||
boost::unordered::detail::convertible_to_from_range_t FromRangeT,
|
||||
std::ranges::input_range R,
|
||||
class Hash =
|
||||
boost::hash<std::ranges::range_value_t<R> >,
|
||||
class Pred =
|
||||
std::equal_to<std::ranges::range_value_t<R> >,
|
||||
class Allocator = std::allocator<std::ranges::range_value_t<R> >,
|
||||
class = std::enable_if_t<detail::is_hash_v<Hash> >,
|
||||
class = std::enable_if_t<detail::is_pred_v<Pred> >,
|
||||
class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
|
||||
unordered_set(FromRangeT&&, R&&,
|
||||
std::size_t = boost::unordered::detail::default_bucket_count,
|
||||
Hash = Hash(), Pred = Pred(), Allocator = Allocator())
|
||||
-> unordered_set<std::ranges::range_value_t<R>,
|
||||
Hash, Pred, Allocator>;
|
||||
#endif
|
||||
|
||||
template <class T, class Hash = boost::hash<T>,
|
||||
class Pred = std::equal_to<T>, class Allocator = std::allocator<T>,
|
||||
class = std::enable_if_t<detail::is_hash_v<Hash> >,
|
||||
@@ -507,6 +564,29 @@ namespace boost {
|
||||
std::equal_to<typename std::iterator_traits<InputIterator>::value_type>,
|
||||
Allocator>;
|
||||
|
||||
#if !defined(BOOST_UNORDERED_NO_RANGES)
|
||||
template <boost::unordered::detail::convertible_to_from_range_t FromRangeT,
|
||||
std::ranges::input_range R,
|
||||
class Allocator,
|
||||
class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
|
||||
unordered_set(FromRangeT&&, R&&, std::size_t, Allocator)
|
||||
-> unordered_set<std::ranges::range_value_t<R>,
|
||||
boost::hash<std::ranges::range_value_t<R> >,
|
||||
std::equal_to<std::ranges::range_value_t<R> >,
|
||||
Allocator>;
|
||||
|
||||
template <boost::unordered::detail::convertible_to_from_range_t FromRangeT,
|
||||
std::ranges::input_range R,
|
||||
class Hash, class Allocator,
|
||||
class = std::enable_if_t<detail::is_hash_v<Hash> >,
|
||||
class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
|
||||
unordered_set(
|
||||
FromRangeT&&, R&&, std::size_t, Hash, Allocator)
|
||||
-> unordered_set<std::ranges::range_value_t<R>,
|
||||
Hash, std::equal_to<std::ranges::range_value_t<R> >,
|
||||
Allocator>;
|
||||
#endif
|
||||
|
||||
template <class T, class Allocator,
|
||||
class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
|
||||
unordered_set(std::initializer_list<T>, std::size_t, Allocator)
|
||||
@@ -527,6 +607,18 @@ namespace boost {
|
||||
std::equal_to<typename std::iterator_traits<InputIterator>::value_type>,
|
||||
Allocator>;
|
||||
|
||||
#if !defined(BOOST_UNORDERED_NO_RANGES)
|
||||
template <boost::unordered::detail::convertible_to_from_range_t FromRangeT,
|
||||
std::ranges::input_range R,
|
||||
class Allocator,
|
||||
class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
|
||||
unordered_set(FromRangeT&&, R&&, Allocator)
|
||||
-> unordered_set<std::ranges::range_value_t<R>,
|
||||
boost::hash<std::ranges::range_value_t<R> >,
|
||||
std::equal_to<std::ranges::range_value_t<R> >,
|
||||
Allocator>;
|
||||
#endif
|
||||
|
||||
template <class T, class Allocator,
|
||||
class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
|
||||
unordered_set(std::initializer_list<T>, Allocator)
|
||||
@@ -585,6 +677,18 @@ namespace boost {
|
||||
const hasher& = hasher(), const key_equal& = key_equal(),
|
||||
const allocator_type& = allocator_type());
|
||||
|
||||
#if !defined(BOOST_UNORDERED_NO_RANGES)
|
||||
template<
|
||||
detail::convertible_to_from_range_t FromRangeT,
|
||||
detail::container_compatible_range<T> R
|
||||
>
|
||||
unordered_multiset(FromRangeT&&, R&&,
|
||||
size_type = boost::unordered::detail::default_bucket_count,
|
||||
const hasher& = hasher(), const key_equal& = key_equal(),
|
||||
const allocator_type& = allocator_type());
|
||||
#endif
|
||||
|
||||
|
||||
unordered_multiset(unordered_multiset const&);
|
||||
|
||||
unordered_multiset(unordered_multiset&& other)
|
||||
@@ -620,6 +724,27 @@ namespace boost {
|
||||
unordered_multiset(
|
||||
InputIt, InputIt, size_type, const hasher&, const allocator_type&);
|
||||
|
||||
#if !defined(BOOST_UNORDERED_NO_RANGES)
|
||||
template <
|
||||
detail::convertible_to_from_range_t FromRangeT,
|
||||
detail::container_compatible_range<T> R
|
||||
>
|
||||
unordered_multiset(FromRangeT&&, R&&, const allocator_type&);
|
||||
|
||||
template <
|
||||
detail::convertible_to_from_range_t FromRangeT,
|
||||
detail::container_compatible_range<T> R
|
||||
>
|
||||
unordered_multiset(FromRangeT&&, R&&, size_type, const allocator_type&);
|
||||
|
||||
template <
|
||||
detail::convertible_to_from_range_t FromRangeT,
|
||||
detail::container_compatible_range<T> R
|
||||
>
|
||||
unordered_multiset(
|
||||
FromRangeT&&, R&&, size_type, const hasher&, const allocator_type&);
|
||||
#endif
|
||||
|
||||
unordered_multiset(
|
||||
std::initializer_list<value_type>, const allocator_type&);
|
||||
|
||||
@@ -720,6 +845,11 @@ namespace boost {
|
||||
|
||||
template <class InputIt> void insert(InputIt, InputIt);
|
||||
|
||||
#if !defined(BOOST_UNORDERED_NO_RANGES)
|
||||
template <detail::container_compatible_range<T> R>
|
||||
void insert_range(R&&);
|
||||
#endif
|
||||
|
||||
void insert(std::initializer_list<value_type>);
|
||||
|
||||
// extract
|
||||
@@ -942,6 +1072,25 @@ namespace boost {
|
||||
typename std::iterator_traits<InputIterator>::value_type, Hash, Pred,
|
||||
Allocator>;
|
||||
|
||||
#if !defined(BOOST_UNORDERED_NO_RANGES)
|
||||
template <
|
||||
boost::unordered::detail::convertible_to_from_range_t FromRangeT,
|
||||
std::ranges::input_range R,
|
||||
class Hash =
|
||||
boost::hash<std::ranges::range_value_t<R> >,
|
||||
class Pred =
|
||||
std::equal_to<std::ranges::range_value_t<R> >,
|
||||
class Allocator = std::allocator<std::ranges::range_value_t<R> >,
|
||||
class = std::enable_if_t<detail::is_hash_v<Hash> >,
|
||||
class = std::enable_if_t<detail::is_pred_v<Pred> >,
|
||||
class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
|
||||
unordered_multiset(FromRangeT&&, R&&,
|
||||
std::size_t = boost::unordered::detail::default_bucket_count,
|
||||
Hash = Hash(), Pred = Pred(), Allocator = Allocator())
|
||||
-> unordered_multiset<std::ranges::range_value_t<R>,
|
||||
Hash, Pred, Allocator>;
|
||||
#endif
|
||||
|
||||
template <class T, class Hash = boost::hash<T>,
|
||||
class Pred = std::equal_to<T>, class Allocator = std::allocator<T>,
|
||||
class = std::enable_if_t<detail::is_hash_v<Hash> >,
|
||||
@@ -973,6 +1122,29 @@ namespace boost {
|
||||
std::equal_to<typename std::iterator_traits<InputIterator>::value_type>,
|
||||
Allocator>;
|
||||
|
||||
#if !defined(BOOST_UNORDERED_NO_RANGES)
|
||||
template <boost::unordered::detail::convertible_to_from_range_t FromRangeT,
|
||||
std::ranges::input_range R,
|
||||
class Allocator,
|
||||
class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
|
||||
unordered_multiset(FromRangeT&&, R&&, std::size_t, Allocator)
|
||||
-> unordered_multiset<std::ranges::range_value_t<R>,
|
||||
boost::hash<std::ranges::range_value_t<R> >,
|
||||
std::equal_to<std::ranges::range_value_t<R> >,
|
||||
Allocator>;
|
||||
|
||||
template <boost::unordered::detail::convertible_to_from_range_t FromRangeT,
|
||||
std::ranges::input_range R,
|
||||
class Hash, class Allocator,
|
||||
class = std::enable_if_t<detail::is_hash_v<Hash> >,
|
||||
class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
|
||||
unordered_multiset(
|
||||
FromRangeT&&, R&&, std::size_t, Hash, Allocator)
|
||||
-> unordered_multiset<std::ranges::range_value_t<R>,
|
||||
Hash, std::equal_to<std::ranges::range_value_t<R> >,
|
||||
Allocator>;
|
||||
#endif
|
||||
|
||||
template <class T, class Allocator,
|
||||
class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
|
||||
unordered_multiset(std::initializer_list<T>, std::size_t, Allocator)
|
||||
@@ -994,6 +1166,18 @@ namespace boost {
|
||||
std::equal_to<typename std::iterator_traits<InputIterator>::value_type>,
|
||||
Allocator>;
|
||||
|
||||
#if !defined(BOOST_UNORDERED_NO_RANGES)
|
||||
template <boost::unordered::detail::convertible_to_from_range_t FromRangeT,
|
||||
std::ranges::input_range R,
|
||||
class Allocator,
|
||||
class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
|
||||
unordered_multiset(FromRangeT&&, R&&, Allocator)
|
||||
-> unordered_multiset<std::ranges::range_value_t<R>,
|
||||
boost::hash<std::ranges::range_value_t<R> >,
|
||||
std::equal_to<std::ranges::range_value_t<R> >,
|
||||
Allocator>;
|
||||
#endif
|
||||
|
||||
template <class T, class Allocator,
|
||||
class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
|
||||
unordered_multiset(std::initializer_list<T>, Allocator)
|
||||
@@ -1023,6 +1207,23 @@ namespace boost {
|
||||
this->insert(f, l);
|
||||
}
|
||||
|
||||
#if !defined(BOOST_UNORDERED_NO_RANGES)
|
||||
template <class T, class H, class P, class A>
|
||||
template <
|
||||
detail::convertible_to_from_range_t FromRangeT,
|
||||
detail::container_compatible_range<T> R
|
||||
>
|
||||
unordered_set<T, H, P, A>::unordered_set(FromRangeT&&, R&& rg,
|
||||
size_type n, const hasher& hf, const key_equal& eql,
|
||||
const allocator_type& a)
|
||||
: table_(
|
||||
boost::unordered::detail::initial_size(std::forward<R>(rg), n),
|
||||
hf, eql, a)
|
||||
{
|
||||
this->insert_range(std::forward<R>(rg));
|
||||
}
|
||||
#endif
|
||||
|
||||
template <class T, class H, class P, class A>
|
||||
unordered_set<T, H, P, A>::unordered_set(unordered_set const& other)
|
||||
: table_(other.table_,
|
||||
@@ -1115,6 +1316,51 @@ namespace boost {
|
||||
this->insert(f, l);
|
||||
}
|
||||
|
||||
#if !defined(BOOST_UNORDERED_NO_RANGES)
|
||||
template <class T, class H, class P, class A>
|
||||
template <
|
||||
detail::convertible_to_from_range_t FromRangeT,
|
||||
detail::container_compatible_range<T> R
|
||||
>
|
||||
unordered_set<T, H, P, A>::unordered_set(
|
||||
FromRangeT&&, R&& rg, const allocator_type& a)
|
||||
: table_(
|
||||
boost::unordered::detail::initial_size(
|
||||
std::forward<R>(rg), detail::default_bucket_count),
|
||||
hasher(), key_equal(), a)
|
||||
{
|
||||
this->insert_range(std::forward<R>(rg));
|
||||
}
|
||||
|
||||
template <class T, class H, class P, class A>
|
||||
template <
|
||||
detail::convertible_to_from_range_t FromRangeT,
|
||||
detail::container_compatible_range<T> R
|
||||
>
|
||||
unordered_set<T, H, P, A>::unordered_set(
|
||||
FromRangeT&&, R&& rg, size_type n, const allocator_type& a)
|
||||
: table_(
|
||||
boost::unordered::detail::initial_size(std::forward<R>(rg), n),
|
||||
hasher(), key_equal(), a)
|
||||
{
|
||||
this->insert_range(std::forward<R>(rg));
|
||||
}
|
||||
|
||||
template <class T, class H, class P, class A>
|
||||
template <
|
||||
detail::convertible_to_from_range_t FromRangeT,
|
||||
detail::container_compatible_range<T> R
|
||||
>
|
||||
unordered_set<T, H, P, A>::unordered_set(FromRangeT&&, R&& rg,
|
||||
size_type n, const hasher& hf, const allocator_type& a)
|
||||
: table_(
|
||||
boost::unordered::detail::initial_size(std::forward<R>(rg), n),
|
||||
hf, key_equal(), a)
|
||||
{
|
||||
this->insert_range(std::forward<R>(rg));
|
||||
}
|
||||
#endif
|
||||
|
||||
template <class T, class H, class P, class A>
|
||||
unordered_set<T, H, P, A>::unordered_set(
|
||||
std::initializer_list<value_type> list, const allocator_type& a)
|
||||
@@ -1187,6 +1433,20 @@ namespace boost {
|
||||
}
|
||||
}
|
||||
|
||||
#if !defined(BOOST_UNORDERED_NO_RANGES)
|
||||
template <class T, class H, class P, class A>
|
||||
template <detail::container_compatible_range<T> R>
|
||||
void unordered_set<T, H, P, A>::insert_range(R&& rg)
|
||||
{
|
||||
auto first = std::ranges::begin(rg);
|
||||
auto last = std::ranges::end(rg);
|
||||
if (first != last) {
|
||||
table_.insert_range_unique(
|
||||
table::extractor::extract(*first), first, last);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
template <class T, class H, class P, class A>
|
||||
void unordered_set<T, H, P, A>::insert(
|
||||
std::initializer_list<value_type> list)
|
||||
@@ -1420,6 +1680,23 @@ namespace boost {
|
||||
this->insert(f, l);
|
||||
}
|
||||
|
||||
#if !defined(BOOST_UNORDERED_NO_RANGES)
|
||||
template <class T, class H, class P, class A>
|
||||
template <
|
||||
detail::convertible_to_from_range_t FromRangeT,
|
||||
detail::container_compatible_range<T> R
|
||||
>
|
||||
unordered_multiset<T, H, P, A>::unordered_multiset(FromRangeT&&, R&& rg,
|
||||
size_type n, const hasher& hf, const key_equal& eql,
|
||||
const allocator_type& a)
|
||||
: table_(
|
||||
boost::unordered::detail::initial_size(std::forward<R>(rg), n),
|
||||
hf, eql, a)
|
||||
{
|
||||
this->insert_range(std::forward<R>(rg));
|
||||
}
|
||||
#endif
|
||||
|
||||
template <class T, class H, class P, class A>
|
||||
unordered_multiset<T, H, P, A>::unordered_multiset(
|
||||
unordered_multiset const& other)
|
||||
@@ -1513,6 +1790,51 @@ namespace boost {
|
||||
this->insert(f, l);
|
||||
}
|
||||
|
||||
#if !defined(BOOST_UNORDERED_NO_RANGES)
|
||||
template <class T, class H, class P, class A>
|
||||
template <
|
||||
detail::convertible_to_from_range_t FromRangeT,
|
||||
detail::container_compatible_range<T> R
|
||||
>
|
||||
unordered_multiset<T, H, P, A>::unordered_multiset(
|
||||
FromRangeT&&, R&& rg, const allocator_type& a)
|
||||
: table_(
|
||||
boost::unordered::detail::initial_size(
|
||||
std::forward<R>(rg), detail::default_bucket_count),
|
||||
hasher(), key_equal(), a)
|
||||
{
|
||||
this->insert_range(std::forward<R>(rg));
|
||||
}
|
||||
|
||||
template <class T, class H, class P, class A>
|
||||
template <
|
||||
detail::convertible_to_from_range_t FromRangeT,
|
||||
detail::container_compatible_range<T> R
|
||||
>
|
||||
unordered_multiset<T, H, P, A>::unordered_multiset(
|
||||
FromRangeT&&, R&& rg, size_type n, const allocator_type& a)
|
||||
: table_(
|
||||
boost::unordered::detail::initial_size(std::forward<R>(rg), n),
|
||||
hasher(), key_equal(), a)
|
||||
{
|
||||
this->insert_range(std::forward<R>(rg));
|
||||
}
|
||||
|
||||
template <class T, class H, class P, class A>
|
||||
template <
|
||||
detail::convertible_to_from_range_t FromRangeT,
|
||||
detail::container_compatible_range<T> R
|
||||
>
|
||||
unordered_multiset<T, H, P, A>::unordered_multiset(FromRangeT&&, R&& rg,
|
||||
size_type n, const hasher& hf, const allocator_type& a)
|
||||
: table_(
|
||||
boost::unordered::detail::initial_size(std::forward<R>(rg), n),
|
||||
hf, key_equal(), a)
|
||||
{
|
||||
this->insert_range(std::forward<R>(rg));
|
||||
}
|
||||
#endif
|
||||
|
||||
template <class T, class H, class P, class A>
|
||||
unordered_multiset<T, H, P, A>::unordered_multiset(
|
||||
std::initializer_list<value_type> list, const allocator_type& a)
|
||||
@@ -1582,6 +1904,16 @@ namespace boost {
|
||||
table_.insert_range_equiv(first, last);
|
||||
}
|
||||
|
||||
#if !defined(BOOST_UNORDERED_NO_RANGES)
|
||||
template <class T, class H, class P, class A>
|
||||
template <detail::container_compatible_range<T> R>
|
||||
void unordered_multiset<T, H, P, A>::insert_range(R&& rg)
|
||||
{
|
||||
table_.insert_range_equiv(
|
||||
std::ranges::begin(rg), std::ranges::end(rg));
|
||||
}
|
||||
#endif
|
||||
|
||||
template <class T, class H, class P, class A>
|
||||
void unordered_multiset<T, H, P, A>::insert(
|
||||
std::initializer_list<value_type> list)
|
||||
|
||||
+5
-1
@@ -139,7 +139,11 @@ foa_tests(SOURCES exception/merge_exception_tests.cpp)
|
||||
set(cfoa_insert_test_options $<$<CXX_COMPILER_ID:MSVC>:/bigobj>)
|
||||
|
||||
if(MINGW AND CMAKE_SIZEOF_VOID_P EQUAL 4)
|
||||
list(APPEND cfoa_insert_test_options -O0 -g0) # GCC MinGW32 OOMs otherwise
|
||||
list(APPEND cfoa_insert_test_options
|
||||
-O0 -g0
|
||||
--param=ggc-min-expand=10
|
||||
--param=ggc-min-heapsize=16384
|
||||
) # GCC MinGW32 OOMs otherwise
|
||||
endif()
|
||||
|
||||
cfoa_tests(SOURCES cfoa/insert_tests.cpp COMPILE_OPTIONS ${cfoa_insert_test_options})
|
||||
|
||||
+2
-1
@@ -379,7 +379,8 @@ run cfoa/insert_tests.cpp
|
||||
: $(CPP11) <threading>multi
|
||||
<toolset>msvc:<cxxflags>/bigobj
|
||||
<toolset>gcc:<inlining>on
|
||||
<toolset>gcc:<optimization>space
|
||||
<toolset>gcc:<optimization>off
|
||||
<toolset>gcc:<cxxflags>-g0
|
||||
<toolset>clang:<inlining>on
|
||||
<toolset>clang:<optimization>space
|
||||
: cfoa_insert_tests ;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// Copyright (C) 2023 Christian Mazakas
|
||||
// Copyright (C) 2023-2024 Joaquin M Lopez Munoz
|
||||
// Copyright (C) 2023-2026 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)
|
||||
|
||||
@@ -10,6 +10,8 @@
|
||||
#include <boost/unordered/concurrent_node_map.hpp>
|
||||
#include <boost/unordered/concurrent_node_set.hpp>
|
||||
|
||||
#include <list>
|
||||
|
||||
test::seed_t initialize_seed(4122023);
|
||||
|
||||
using test::default_generator;
|
||||
@@ -702,6 +704,97 @@ namespace {
|
||||
}
|
||||
}
|
||||
|
||||
#if !defined(BOOST_UNORDERED_NO_RANGES)
|
||||
template <class X, class IL>
|
||||
void range_with_all_params(std::pair<X*, IL> p)
|
||||
{
|
||||
using value_type = typename X::value_type;
|
||||
static constexpr auto value_type_cardinality =
|
||||
value_cardinality<value_type>::value;
|
||||
using allocator_type = typename X::allocator_type;
|
||||
|
||||
auto init_list = p.second;
|
||||
auto init_std_list = std::list<value_type>{init_list};
|
||||
auto sentineled_rg = init_std_list | std::views::take(init_list.size());
|
||||
|
||||
{
|
||||
raii::reset_counts();
|
||||
|
||||
X x(
|
||||
boost::unordered::from_range,
|
||||
init_list, 0, hasher(1), key_equal(2), allocator_type(3));
|
||||
|
||||
BOOST_TEST_EQ(x.size(), 11u);
|
||||
BOOST_TEST_EQ(x.hash_function(), hasher(1));
|
||||
BOOST_TEST_EQ(x.key_eq(), key_equal(2));
|
||||
BOOST_TEST(x.get_allocator() == allocator_type(3));
|
||||
|
||||
BOOST_TEST_EQ(raii::default_constructor, 0u);
|
||||
BOOST_TEST_EQ(
|
||||
raii::copy_constructor, value_type_cardinality * init_list.size() / 2u);
|
||||
BOOST_TEST_EQ(
|
||||
raii::move_constructor, 0u);
|
||||
}
|
||||
check_raii_counts();
|
||||
|
||||
{
|
||||
raii::reset_counts();
|
||||
|
||||
X x(boost::unordered::from_range, sentineled_rg, allocator_type(3));
|
||||
|
||||
BOOST_TEST_EQ(x.size(), 11u);
|
||||
BOOST_TEST_EQ(x.hash_function(), hasher());
|
||||
BOOST_TEST_EQ(x.key_eq(), key_equal());
|
||||
BOOST_TEST(x.get_allocator() == allocator_type(3));
|
||||
|
||||
BOOST_TEST_EQ(raii::default_constructor, 0u);
|
||||
BOOST_TEST_EQ(
|
||||
raii::copy_constructor, value_type_cardinality * init_list.size() / 2u);
|
||||
BOOST_TEST_EQ(
|
||||
raii::move_constructor, 0u);
|
||||
}
|
||||
check_raii_counts();
|
||||
|
||||
{
|
||||
raii::reset_counts();
|
||||
|
||||
X x(boost::unordered::from_range, init_list, 0, allocator_type(3));
|
||||
|
||||
BOOST_TEST_EQ(x.size(), 11u);
|
||||
BOOST_TEST_EQ(x.hash_function(), hasher());
|
||||
BOOST_TEST_EQ(x.key_eq(), key_equal());
|
||||
BOOST_TEST(x.get_allocator() == allocator_type(3));
|
||||
|
||||
BOOST_TEST_EQ(raii::default_constructor, 0u);
|
||||
BOOST_TEST_EQ(
|
||||
raii::copy_constructor, value_type_cardinality * init_list.size() / 2u);
|
||||
BOOST_TEST_EQ(
|
||||
raii::move_constructor, 0u);
|
||||
}
|
||||
check_raii_counts();
|
||||
|
||||
{
|
||||
raii::reset_counts();
|
||||
|
||||
X x(
|
||||
boost::unordered::from_range,
|
||||
sentineled_rg, 0, hasher(1), allocator_type(3));
|
||||
|
||||
BOOST_TEST_EQ(x.size(), 11u);
|
||||
BOOST_TEST_EQ(x.hash_function(), hasher(1));
|
||||
BOOST_TEST_EQ(x.key_eq(), key_equal());
|
||||
BOOST_TEST(x.get_allocator() == allocator_type(3));
|
||||
|
||||
BOOST_TEST_EQ(raii::default_constructor, 0u);
|
||||
BOOST_TEST_EQ(
|
||||
raii::copy_constructor, value_type_cardinality * init_list.size() / 2u);
|
||||
BOOST_TEST_EQ(
|
||||
raii::move_constructor, 0u);
|
||||
}
|
||||
check_raii_counts();
|
||||
}
|
||||
#endif
|
||||
|
||||
template <class X, class IL>
|
||||
void initializer_list_with_all_params(std::pair<X*, IL> p)
|
||||
{
|
||||
@@ -1040,6 +1133,13 @@ UNORDERED_TEST(
|
||||
explicit_allocator,
|
||||
((test_map)(test_node_map)(test_set)(test_node_set)))
|
||||
|
||||
#if !defined(BOOST_UNORDERED_NO_RANGES)
|
||||
UNORDERED_TEST(
|
||||
range_with_all_params,
|
||||
((test_map_and_init_list)(test_node_map_and_init_list)
|
||||
(test_set_and_init_list)(test_node_set_and_init_list)))
|
||||
#endif
|
||||
|
||||
UNORDERED_TEST(
|
||||
initializer_list_with_all_params,
|
||||
((test_map_and_init_list)(test_node_map_and_init_list)
|
||||
|
||||
+227
-3
@@ -175,6 +175,39 @@ namespace {
|
||||
}
|
||||
} iterator_range_inserter;
|
||||
|
||||
#if !defined(BOOST_UNORDERED_NO_RANGES)
|
||||
struct range_inserter_type
|
||||
{
|
||||
template <class T, class X> void operator()(std::vector<T>& values, X& x)
|
||||
{
|
||||
static constexpr auto value_type_cardinality =
|
||||
value_cardinality<typename X::value_type>::value;
|
||||
|
||||
std::vector<raii_convertible> values2;
|
||||
values2.reserve(values.size());
|
||||
for (auto const& v : values) {
|
||||
values2.push_back(raii_convertible(v));
|
||||
}
|
||||
|
||||
auto sz = x.size();
|
||||
std::atomic<std::uint64_t> num_inserts{0};
|
||||
std::atomic<std::uint64_t> num_attempted_inserts{0};
|
||||
thread_runner(values2, [&x, &num_inserts, &num_attempted_inserts](boost::span<raii_convertible> s) {
|
||||
num_inserts += x.insert_range(s | std::views::take(s.size() / 2));
|
||||
num_inserts += x.insert_range(s);
|
||||
num_attempted_inserts += s.size() + s.size() / 2;
|
||||
});
|
||||
BOOST_TEST_EQ(x.size(), sz + num_inserts);
|
||||
|
||||
BOOST_TEST_EQ(
|
||||
raii::default_constructor, value_type_cardinality * num_attempted_inserts);
|
||||
BOOST_TEST_EQ(raii::copy_constructor, 0u);
|
||||
BOOST_TEST_EQ(raii::copy_assignment, 0u);
|
||||
BOOST_TEST_EQ(raii::move_assignment, 0u);
|
||||
}
|
||||
} range_inserter;
|
||||
#endif
|
||||
|
||||
struct lvalue_insert_or_assign_copy_assign_type
|
||||
{
|
||||
template <class T, class X> void operator()(std::vector<T>& values, X& x)
|
||||
@@ -798,6 +831,41 @@ namespace {
|
||||
}
|
||||
} iterator_range_insert_or_cvisit;
|
||||
|
||||
#if !defined(BOOST_UNORDERED_NO_RANGES)
|
||||
struct insert_range_or_cvisit_type
|
||||
{
|
||||
template <class T, class X> void operator()(std::vector<T>& values, X& x)
|
||||
{
|
||||
static constexpr auto value_type_cardinality =
|
||||
value_cardinality<typename X::value_type>::value;
|
||||
|
||||
std::vector<raii_convertible> values2;
|
||||
values2.reserve(values.size());
|
||||
for (auto const& v : values) {
|
||||
values2.push_back(raii_convertible(v));
|
||||
}
|
||||
|
||||
std::atomic<std::uint64_t> num_invokes{0};
|
||||
thread_runner(
|
||||
values2, [&x, &num_invokes](boost::span<raii_convertible> s) {
|
||||
BOOST_TEST_EQ(x.insert_range_or_cvisit(s,
|
||||
[&num_invokes](typename X::value_type const& v) {
|
||||
(void)v;
|
||||
++num_invokes;
|
||||
}),
|
||||
s.size());
|
||||
});
|
||||
|
||||
BOOST_TEST_EQ(num_invokes, values.size() - x.size());
|
||||
|
||||
BOOST_TEST_EQ(
|
||||
raii::default_constructor, value_type_cardinality * values2.size());
|
||||
BOOST_TEST_EQ(raii::copy_constructor, 0u);
|
||||
BOOST_TEST_GT(raii::move_constructor, 0u);
|
||||
}
|
||||
} insert_range_or_cvisit;
|
||||
#endif
|
||||
|
||||
struct iterator_range_insert_and_cvisit_type
|
||||
{
|
||||
template <class T, class X> void operator()(std::vector<T>& values, X& x)
|
||||
@@ -852,6 +920,55 @@ namespace {
|
||||
}
|
||||
} iterator_range_insert_and_cvisit;
|
||||
|
||||
#if !defined(BOOST_UNORDERED_NO_RANGES)
|
||||
struct insert_range_and_cvisit_type
|
||||
{
|
||||
template <class T, class X> void operator()(std::vector<T>& values, X& x)
|
||||
{
|
||||
static constexpr auto value_type_cardinality =
|
||||
value_cardinality<typename X::value_type>::value;
|
||||
|
||||
// concurrent_flat_set visit is always const access
|
||||
using arg_type = typename std::conditional<
|
||||
std::is_same<typename X::key_type, typename X::value_type>::value,
|
||||
typename X::value_type const,
|
||||
typename X::value_type
|
||||
>::type;
|
||||
|
||||
std::vector<raii_convertible> values2;
|
||||
values2.reserve(values.size());
|
||||
for (auto const& v : values) {
|
||||
values2.push_back(raii_convertible(v));
|
||||
}
|
||||
|
||||
std::atomic<std::uint64_t> num_inserts{0};
|
||||
std::atomic<std::uint64_t> num_invokes{0};
|
||||
thread_runner(values2,
|
||||
[&x, &num_inserts, &num_invokes](boost::span<raii_convertible> s) {
|
||||
BOOST_TEST_EQ(x.insert_range_and_cvisit(
|
||||
s,
|
||||
[&num_inserts](arg_type& v) {
|
||||
(void)v;
|
||||
++num_inserts;
|
||||
},
|
||||
[&num_invokes](typename X::value_type const& v) {
|
||||
(void)v;
|
||||
++num_invokes;
|
||||
}),
|
||||
s.size());
|
||||
});
|
||||
|
||||
BOOST_TEST_EQ(num_inserts, x.size());
|
||||
BOOST_TEST_EQ(num_invokes, values.size() - x.size());
|
||||
|
||||
BOOST_TEST_EQ(
|
||||
raii::default_constructor, value_type_cardinality * values2.size());
|
||||
BOOST_TEST_EQ(raii::copy_constructor, 0u);
|
||||
BOOST_TEST_GT(raii::move_constructor, 0u);
|
||||
}
|
||||
} insert_range_and_cvisit;
|
||||
#endif
|
||||
|
||||
struct iterator_range_insert_or_visit_type
|
||||
{
|
||||
template <class T, class X> void operator()(std::vector<T>& values, X& x)
|
||||
@@ -899,6 +1016,48 @@ namespace {
|
||||
}
|
||||
} iterator_range_insert_or_visit;
|
||||
|
||||
#if !defined(BOOST_UNORDERED_NO_RANGES)
|
||||
struct insert_range_or_visit_type
|
||||
{
|
||||
template <class T, class X> void operator()(std::vector<T>& values, X& x)
|
||||
{
|
||||
static constexpr auto value_type_cardinality =
|
||||
value_cardinality<typename X::value_type>::value;
|
||||
|
||||
// concurrent_flat_set visit is always const access
|
||||
using arg_type = typename std::conditional<
|
||||
std::is_same<typename X::key_type, typename X::value_type>::value,
|
||||
typename X::value_type const,
|
||||
typename X::value_type
|
||||
>::type;
|
||||
|
||||
std::vector<raii_convertible> values2;
|
||||
values2.reserve(values.size());
|
||||
for (auto const& v : values) {
|
||||
values2.push_back(raii_convertible(v));
|
||||
}
|
||||
|
||||
std::atomic<std::uint64_t> num_invokes{0};
|
||||
thread_runner(
|
||||
values2, [&x, &num_invokes](boost::span<raii_convertible> s) {
|
||||
BOOST_TEST_EQ(x.insert_range_or_visit(s,
|
||||
[&num_invokes](arg_type& v) {
|
||||
(void)v;
|
||||
++num_invokes;
|
||||
}),
|
||||
s.size());
|
||||
});
|
||||
|
||||
BOOST_TEST_EQ(num_invokes, values.size() - x.size());
|
||||
|
||||
BOOST_TEST_EQ(
|
||||
raii::default_constructor, value_type_cardinality * values2.size());
|
||||
BOOST_TEST_EQ(raii::copy_constructor, 0u);
|
||||
BOOST_TEST_GT(raii::move_constructor, 0u);
|
||||
}
|
||||
} insert_range_or_visit;
|
||||
#endif
|
||||
|
||||
struct iterator_range_insert_and_visit_type
|
||||
{
|
||||
template <class T, class X> void operator()(std::vector<T>& values, X& x)
|
||||
@@ -953,6 +1112,55 @@ namespace {
|
||||
}
|
||||
} iterator_range_insert_and_visit;
|
||||
|
||||
#if !defined(BOOST_UNORDERED_NO_RANGES)
|
||||
struct insert_range_and_visit_type
|
||||
{
|
||||
template <class T, class X> void operator()(std::vector<T>& values, X& x)
|
||||
{
|
||||
static constexpr auto value_type_cardinality =
|
||||
value_cardinality<typename X::value_type>::value;
|
||||
|
||||
// concurrent_flat_set visit is always const access
|
||||
using arg_type = typename std::conditional<
|
||||
std::is_same<typename X::key_type, typename X::value_type>::value,
|
||||
typename X::value_type const,
|
||||
typename X::value_type
|
||||
>::type;
|
||||
|
||||
std::vector<raii_convertible> values2;
|
||||
values2.reserve(values.size());
|
||||
for (auto const& v : values) {
|
||||
values2.push_back(raii_convertible(v));
|
||||
}
|
||||
|
||||
std::atomic<std::uint64_t> num_inserts{0};
|
||||
std::atomic<std::uint64_t> num_invokes{0};
|
||||
thread_runner(values2,
|
||||
[&x, &num_inserts, &num_invokes](boost::span<raii_convertible> s) {
|
||||
BOOST_TEST_EQ(x.insert_range_and_visit(
|
||||
s,
|
||||
[&num_inserts](arg_type& v) {
|
||||
(void)v;
|
||||
++num_inserts;
|
||||
},
|
||||
[&num_invokes](typename X::value_type const& v) {
|
||||
(void)v;
|
||||
++num_invokes;
|
||||
}),
|
||||
s.size());
|
||||
});
|
||||
|
||||
BOOST_TEST_EQ(num_inserts, x.size());
|
||||
BOOST_TEST_EQ(num_invokes, values.size() - x.size());
|
||||
|
||||
BOOST_TEST_EQ(
|
||||
raii::default_constructor, value_type_cardinality * values2.size());
|
||||
BOOST_TEST_EQ(raii::copy_constructor, 0u);
|
||||
BOOST_TEST_GT(raii::move_constructor, 0u);
|
||||
}
|
||||
} insert_range_and_visit;
|
||||
#endif
|
||||
|
||||
struct non_copyable_function
|
||||
{
|
||||
non_copyable_function() = default;
|
||||
@@ -1265,16 +1473,31 @@ UNORDERED_TEST(
|
||||
((map_and_init_list)(node_map_and_init_list)
|
||||
(set_and_init_list)(node_set_and_init_list)))
|
||||
|
||||
#if !defined(BOOST_UNORDERED_NO_RANGES)
|
||||
#define RANGE_INSERTER (range_inserter)
|
||||
#define INSERT_RANGE_OR_CVISIT (insert_range_or_cvisit)
|
||||
#define INSERT_RANGE_OR_VISIT (insert_range_or_visit)
|
||||
#define INSERT_RANGE_AND_CVISIT (insert_range_and_cvisit)
|
||||
#define INSERT_RANGE_AND_VISIT (insert_range_and_visit)
|
||||
#else
|
||||
#define RANGE_INSERTER
|
||||
#define INSERT_RANGE_OR_CVISIT
|
||||
#define INSERT_RANGE_OR_VISIT
|
||||
#define INSERT_RANGE_AND_CVISIT
|
||||
#define INSERT_RANGE_AND_VISIT
|
||||
#endif
|
||||
|
||||
UNORDERED_TEST(
|
||||
insert,
|
||||
((map)(fancy_map)(node_map)(fancy_node_map)
|
||||
(set)(fancy_set)(node_set)(fancy_node_set))
|
||||
((value_type_generator_factory)(init_type_generator_factory))
|
||||
((lvalue_inserter)(rvalue_inserter)(iterator_range_inserter)
|
||||
(norehash_lvalue_inserter)(norehash_rvalue_inserter)
|
||||
RANGE_INSERTER (norehash_lvalue_inserter)(norehash_rvalue_inserter)
|
||||
(lvalue_insert_or_cvisit)(lvalue_insert_or_visit)
|
||||
(rvalue_insert_or_cvisit)(rvalue_insert_or_visit)
|
||||
(iterator_range_insert_or_cvisit)(iterator_range_insert_or_visit))
|
||||
(iterator_range_insert_or_cvisit)(iterator_range_insert_or_visit)
|
||||
INSERT_RANGE_OR_CVISIT INSERT_RANGE_OR_VISIT )
|
||||
((default_generator)(sequential)(limited_range)))
|
||||
|
||||
UNORDERED_TEST(
|
||||
@@ -1284,7 +1507,8 @@ UNORDERED_TEST(
|
||||
((value_type_generator_factory)(init_type_generator_factory))
|
||||
((lvalue_insert_and_cvisit)(lvalue_insert_and_visit)
|
||||
(rvalue_insert_and_cvisit)(rvalue_insert_and_visit)
|
||||
(iterator_range_insert_and_cvisit)(iterator_range_insert_and_visit))
|
||||
(iterator_range_insert_and_cvisit)(iterator_range_insert_and_visit)
|
||||
INSERT_RANGE_AND_CVISIT INSERT_RANGE_AND_VISIT )
|
||||
((default_generator)(sequential)(limited_range)))
|
||||
|
||||
UNORDERED_TEST(
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
|
||||
// Copyright 2006-2010 Daniel James.
|
||||
// Copyright (C) 2022-2023 Christian Mazakas
|
||||
// Copyright (C) 2026 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)
|
||||
|
||||
@@ -14,6 +15,7 @@
|
||||
#include "../helpers/tracker.hpp"
|
||||
#include "../objects/test.hpp"
|
||||
|
||||
#include <list>
|
||||
#include <vector>
|
||||
|
||||
namespace constructor_tests {
|
||||
@@ -337,6 +339,205 @@ namespace constructor_tests {
|
||||
//
|
||||
std::vector<value_type> expected(vec.begin(), vec.begin() + 3);
|
||||
|
||||
#if !defined(BOOST_UNORDERED_NO_RANGES)
|
||||
auto std_list = std::list{vec[0], vec[1], vec[2]};
|
||||
auto sentineled_rg = std_list | std::views::take(3);
|
||||
|
||||
UNORDERED_SUB_TEST("Range construct 1")
|
||||
{
|
||||
test::check_instances check_;
|
||||
|
||||
{
|
||||
T x(boost::unordered::from_range, list);
|
||||
BOOST_TEST(x.empty());
|
||||
BOOST_TEST(test::equivalent(x.hash_function(), hf));
|
||||
BOOST_TEST(test::equivalent(x.key_eq(), eq));
|
||||
BOOST_TEST(test::equivalent(x.get_allocator(), al));
|
||||
}
|
||||
|
||||
{
|
||||
T x(boost::unordered::from_range, std::vector{vec[0], vec[1], vec[2]});
|
||||
BOOST_TEST_NOT(x.empty());
|
||||
BOOST_TEST_GT(x.bucket_count(), 0u);
|
||||
BOOST_TEST(test::equivalent(x.hash_function(), hf));
|
||||
BOOST_TEST(test::equivalent(x.key_eq(), eq));
|
||||
BOOST_TEST(test::equivalent(x.get_allocator(), al));
|
||||
test::check_container(x, expected);
|
||||
}
|
||||
}
|
||||
|
||||
UNORDERED_SUB_TEST("Range construct 2")
|
||||
{
|
||||
test::check_instances check_;
|
||||
|
||||
{
|
||||
T x(boost::unordered::from_range, list, 1000);
|
||||
BOOST_TEST(x.empty());
|
||||
BOOST_TEST(x.bucket_count() >= 1000);
|
||||
BOOST_TEST(test::equivalent(x.hash_function(), hf));
|
||||
BOOST_TEST(test::equivalent(x.key_eq(), eq));
|
||||
BOOST_TEST(test::equivalent(x.get_allocator(), al));
|
||||
}
|
||||
|
||||
{
|
||||
T x(boost::unordered::from_range, sentineled_rg, 1000);
|
||||
BOOST_TEST_NOT(x.empty());
|
||||
BOOST_TEST(x.bucket_count() >= 1000);
|
||||
BOOST_TEST(test::equivalent(x.hash_function(), hf));
|
||||
BOOST_TEST(test::equivalent(x.key_eq(), eq));
|
||||
BOOST_TEST(test::equivalent(x.get_allocator(), al));
|
||||
test::check_container(x, expected);
|
||||
}
|
||||
}
|
||||
|
||||
UNORDERED_SUB_TEST("Range construct 3")
|
||||
{
|
||||
{
|
||||
test::check_instances check_;
|
||||
|
||||
T x(boost::unordered::from_range, list, 10, hf1);
|
||||
BOOST_TEST(x.empty());
|
||||
BOOST_TEST(x.bucket_count() >= 10);
|
||||
BOOST_TEST(test::equivalent(x.hash_function(), hf1));
|
||||
BOOST_TEST(test::equivalent(x.key_eq(), eq));
|
||||
BOOST_TEST(test::equivalent(x.get_allocator(), al));
|
||||
}
|
||||
|
||||
{
|
||||
test::check_instances check_;
|
||||
|
||||
T x(
|
||||
boost::unordered::from_range, std::vector{vec[0], vec[1], vec[2]},
|
||||
10, hf1);
|
||||
BOOST_TEST_NOT(x.empty());
|
||||
BOOST_TEST(x.bucket_count() >= 10);
|
||||
BOOST_TEST(test::equivalent(x.hash_function(), hf1));
|
||||
BOOST_TEST(test::equivalent(x.key_eq(), eq));
|
||||
BOOST_TEST(test::equivalent(x.get_allocator(), al));
|
||||
test::check_container(x, expected);
|
||||
}
|
||||
}
|
||||
|
||||
UNORDERED_SUB_TEST("Range construct 4")
|
||||
{
|
||||
{
|
||||
test::check_instances check_;
|
||||
|
||||
T x(boost::unordered::from_range, list, 10, hf1, eq1);
|
||||
BOOST_TEST(x.empty());
|
||||
BOOST_TEST(x.bucket_count() >= 10);
|
||||
BOOST_TEST(test::equivalent(x.hash_function(), hf1));
|
||||
BOOST_TEST(test::equivalent(x.key_eq(), eq1));
|
||||
BOOST_TEST(test::equivalent(x.get_allocator(), al));
|
||||
}
|
||||
|
||||
{
|
||||
test::check_instances check_;
|
||||
|
||||
T x(boost::unordered::from_range, sentineled_rg, 10, hf1, eq1);
|
||||
BOOST_TEST_NOT(x.empty());
|
||||
BOOST_TEST(x.bucket_count() >= 10);
|
||||
BOOST_TEST(test::equivalent(x.hash_function(), hf1));
|
||||
BOOST_TEST(test::equivalent(x.key_eq(), eq1));
|
||||
BOOST_TEST(test::equivalent(x.get_allocator(), al));
|
||||
test::check_container(x, expected);
|
||||
}
|
||||
}
|
||||
|
||||
UNORDERED_SUB_TEST("Range construct 5")
|
||||
{
|
||||
{
|
||||
test::check_instances check_;
|
||||
|
||||
T x(boost::unordered::from_range, list, 10, hf1, eq1, al1);
|
||||
BOOST_TEST(x.empty());
|
||||
BOOST_TEST(x.bucket_count() >= 10);
|
||||
BOOST_TEST(test::equivalent(x.hash_function(), hf1));
|
||||
BOOST_TEST(test::equivalent(x.key_eq(), eq1));
|
||||
BOOST_TEST(test::equivalent(x.get_allocator(), al1));
|
||||
}
|
||||
|
||||
{
|
||||
test::check_instances check_;
|
||||
|
||||
T x(
|
||||
boost::unordered::from_range,
|
||||
std::vector{vec[0], vec[1], vec[2]}, 10, hf1, eq1, al1);
|
||||
BOOST_TEST_NOT(x.empty());
|
||||
BOOST_TEST(x.bucket_count() >= 10);
|
||||
BOOST_TEST(test::equivalent(x.hash_function(), hf1));
|
||||
BOOST_TEST(test::equivalent(x.key_eq(), eq1));
|
||||
BOOST_TEST(test::equivalent(x.get_allocator(), al1));
|
||||
test::check_container(x, expected);
|
||||
}
|
||||
}
|
||||
|
||||
UNORDERED_SUB_TEST("Range construct 6")
|
||||
{
|
||||
{
|
||||
test::check_instances check_;
|
||||
|
||||
T x(boost::unordered::from_range, list, 10, al1);
|
||||
BOOST_TEST(x.empty());
|
||||
BOOST_TEST(x.bucket_count() >= 10);
|
||||
BOOST_TEST(test::equivalent(x.get_allocator(), al1));
|
||||
}
|
||||
|
||||
{
|
||||
test::check_instances check_;
|
||||
|
||||
T x(boost::unordered::from_range, sentineled_rg, 10, al1);
|
||||
BOOST_TEST_NOT(x.empty());
|
||||
BOOST_TEST(x.bucket_count() >= 10);
|
||||
BOOST_TEST(test::equivalent(x.get_allocator(), al1));
|
||||
test::check_container(x, expected);
|
||||
}
|
||||
}
|
||||
|
||||
UNORDERED_SUB_TEST("Range construct 7")
|
||||
{
|
||||
{
|
||||
test::check_instances check_;
|
||||
|
||||
T x(boost::unordered::from_range, list, 10, hf1, al1);
|
||||
BOOST_TEST(x.empty());
|
||||
BOOST_TEST(x.bucket_count() >= 10);
|
||||
BOOST_TEST(test::equivalent(x.hash_function(), hf1));
|
||||
BOOST_TEST(test::equivalent(x.get_allocator(), al1));
|
||||
}
|
||||
|
||||
{
|
||||
test::check_instances check_;
|
||||
|
||||
T x(
|
||||
boost::unordered::from_range,
|
||||
std::vector{vec[0], vec[1], vec[2]}, 10, hf1, al1);
|
||||
BOOST_TEST_NOT(x.empty());
|
||||
BOOST_TEST(x.bucket_count() >= 10);
|
||||
BOOST_TEST(test::equivalent(x.hash_function(), hf1));
|
||||
BOOST_TEST(test::equivalent(x.get_allocator(), al1));
|
||||
test::check_container(x, expected);
|
||||
}
|
||||
}
|
||||
|
||||
UNORDERED_SUB_TEST("Range construct 8")
|
||||
{
|
||||
test::check_instances check_;
|
||||
|
||||
{
|
||||
T x(boost::unordered::from_range, list, al1);
|
||||
BOOST_TEST(x.empty());
|
||||
BOOST_TEST(test::equivalent(x.get_allocator(), al1));
|
||||
}
|
||||
|
||||
{
|
||||
T x(boost::unordered::from_range, sentineled_rg, al1);
|
||||
BOOST_TEST(test::equivalent(x.get_allocator(), al1));
|
||||
test::check_container(x, expected);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
UNORDERED_SUB_TEST("Initializer list construct 1")
|
||||
{
|
||||
test::check_instances check_;
|
||||
|
||||
@@ -1,19 +1,26 @@
|
||||
|
||||
// Copyright 2017-2018 Daniel James.
|
||||
// Copyright 2026 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 <boost/unordered_map.hpp>
|
||||
#include <iostream>
|
||||
|
||||
#if BOOST_UNORDERED_TEMPLATE_DEDUCTION_GUIDES
|
||||
|
||||
#include <boost/core/lightweight_test_trait.hpp>
|
||||
#include <boost/unordered_map.hpp>
|
||||
#include <boost/unordered_set.hpp>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
#if BOOST_UNORDERED_TEMPLATE_DEDUCTION_GUIDES
|
||||
|
||||
#include <boost/unordered/unordered_flat_map.hpp>
|
||||
#include <boost/unordered/unordered_flat_set.hpp>
|
||||
#include <boost/unordered/unordered_node_map.hpp>
|
||||
#include <boost/unordered/unordered_node_set.hpp>
|
||||
#include <boost/unordered/concurrent_flat_map.hpp>
|
||||
#include <boost/unordered/concurrent_flat_set.hpp>
|
||||
#include <boost/unordered/concurrent_node_map.hpp>
|
||||
#include <boost/unordered/concurrent_node_set.hpp>
|
||||
#include <vector>
|
||||
|
||||
struct hash_equals
|
||||
{
|
||||
@@ -87,6 +94,44 @@ template <template <class...> class UnorderedMap> void map_tests()
|
||||
test_allocator<std::pair<const int, int> > >);
|
||||
}
|
||||
|
||||
#if !defined(BOOST_UNORDERED_NO_RANGES)
|
||||
/*
|
||||
template<ranges::input_range R, class Hash = hash<range-key-type<R>>,
|
||||
class Pred = equal_to<range-key-type<R>>,
|
||||
class Allocator = allocator<range-to-alloc-type<R>>>
|
||||
unordered_map(from_range_t, R&&,
|
||||
typename see below::size_type = see below,
|
||||
Hash = Hash(), Pred = Pred(), Allocator = Allocator())
|
||||
-> unordered_map<
|
||||
range-key-type<R>, range-mapped-type<R>, Hash, Pred, Allocator>;
|
||||
*/
|
||||
|
||||
{
|
||||
UnorderedMap m(boost::unordered::from_range, x);
|
||||
BOOST_TEST_TRAIT_SAME(decltype(m), UnorderedMap<int, int>);
|
||||
}
|
||||
|
||||
{
|
||||
UnorderedMap m(boost::unordered::from_range, x, 0, std::hash<int>());
|
||||
BOOST_TEST_TRAIT_SAME(decltype(m), UnorderedMap<int, int, std::hash<int> >);
|
||||
}
|
||||
|
||||
{
|
||||
UnorderedMap m(
|
||||
boost::unordered::from_range, x, 0, std::hash<int>(), std::equal_to<int>());
|
||||
BOOST_TEST_TRAIT_SAME(
|
||||
decltype(m), UnorderedMap<int, int, std::hash<int>, std::equal_to<int> >);
|
||||
}
|
||||
|
||||
{
|
||||
UnorderedMap m(boost::unordered::from_range, x, 0, std::hash<int>(),
|
||||
std::equal_to<int>(), pair_allocator);
|
||||
BOOST_TEST_TRAIT_SAME(
|
||||
decltype(m), UnorderedMap<int, int, std::hash<int>, std::equal_to<int>,
|
||||
test_allocator<std::pair<const int, int> > >);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
template<class Key, class T, class Hash = hash<Key>,
|
||||
class Pred = equal_to<Key>, class Allocator = allocator<pair<const
|
||||
@@ -162,6 +207,24 @@ template <template <class...> class UnorderedMap> void map_tests()
|
||||
test_allocator<std::pair<const int, int> > >);
|
||||
}
|
||||
|
||||
#if !defined(BOOST_UNORDERED_NO_RANGES)
|
||||
/*
|
||||
template<ranges::input_range R, class Allocator>
|
||||
unordered_map(
|
||||
from_range_t, R&&, typename see below::size_type, Allocator)
|
||||
-> unordered_map<
|
||||
range-key-type<R>, range-mapped-type<R>, hash<range-key-type<R>>,
|
||||
equal_to<range-key-type<R>>, Allocator>;
|
||||
*/
|
||||
|
||||
{
|
||||
UnorderedMap m(boost::unordered::from_range, x, 0u, pair_allocator);
|
||||
BOOST_TEST_TRAIT_SAME(
|
||||
decltype(m), UnorderedMap<int, int, boost::hash<int>, std::equal_to<int>,
|
||||
test_allocator<std::pair<const int, int> > >);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
template<class InputIterator, class Allocator>
|
||||
unordered_map(InputIterator, InputIterator, Allocator)
|
||||
@@ -178,6 +241,23 @@ template <template <class...> class UnorderedMap> void map_tests()
|
||||
test_allocator<std::pair<const int, int> > >);
|
||||
}
|
||||
|
||||
#if !defined(BOOST_UNORDERED_NO_RANGES)
|
||||
/*
|
||||
template<ranges::input_range R, class Allocator>
|
||||
unordered_map(from_range_t, R&&, Allocator)
|
||||
-> unordered_map<
|
||||
range-key-type<R>, range-mapped-type<R>, hash<range-key-type<R>>,
|
||||
equal_to<range-key-type<R>>, Allocator>;
|
||||
*/
|
||||
|
||||
{
|
||||
UnorderedMap m(boost::unordered::from_range, x, pair_allocator);
|
||||
BOOST_TEST_TRAIT_SAME(
|
||||
decltype(m), UnorderedMap<int, int, boost::hash<int>, std::equal_to<int>,
|
||||
test_allocator<std::pair<const int, int> > >);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
template<class InputIterator, class Hash, class Allocator>
|
||||
unordered_map(InputIterator, InputIterator, typename see below::size_type,
|
||||
@@ -194,6 +274,23 @@ template <template <class...> class UnorderedMap> void map_tests()
|
||||
test_allocator<std::pair<const int, int> > >);
|
||||
}
|
||||
|
||||
#if !defined(BOOST_UNORDERED_NO_RANGES)
|
||||
/*
|
||||
template<ranges::input_range R, class Hash, class Allocator>
|
||||
unordered_map(
|
||||
from_range_t, R&&, typename see below::size_type, Hash, Allocator)
|
||||
-> unordered_map<range-key-type<R>, range-mapped-type<R>, Hash,
|
||||
equal_to<range-key-type<R>>, Allocator>;
|
||||
*/
|
||||
|
||||
{
|
||||
UnorderedMap m(boost::unordered::from_range, x, 0u, f, pair_allocator);
|
||||
BOOST_TEST_TRAIT_SAME(
|
||||
decltype(m), UnorderedMap<int, int, hash_equals, std::equal_to<int>,
|
||||
test_allocator<std::pair<const int, int> > >);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
template<class Key, class T, typename Allocator>
|
||||
unordered_map(initializer_list<pair<const Key, T>>, typename see
|
||||
@@ -305,6 +402,45 @@ template <template <class...> class UnorderedSet> void set_tests()
|
||||
test_allocator<int> >);
|
||||
}
|
||||
|
||||
#if !defined(BOOST_UNORDERED_NO_RANGES)
|
||||
/*
|
||||
template<ranges::input_range R,
|
||||
class Hash = hash<ranges::range_value_t<R>>,
|
||||
class Pred = equal_to<ranges::range_value_t<R>>,
|
||||
class Allocator = allocator<ranges::range_value_t<R>>>
|
||||
unordered_set(from_range_t, R&&,
|
||||
typename see below::size_type = see below,
|
||||
Hash = Hash(), Pred = Pred(), Allocator = Allocator())
|
||||
-> unordered_set<ranges::range_value_t<R>, Hash, Pred, Allocator>;
|
||||
*/
|
||||
|
||||
{
|
||||
UnorderedSet s(boost::unordered::from_range, y);
|
||||
BOOST_TEST_TRAIT_SAME(decltype(s), UnorderedSet<int>);
|
||||
}
|
||||
|
||||
{
|
||||
UnorderedSet s(boost::unordered::from_range, y, 0, std::hash<int>());
|
||||
BOOST_TEST_TRAIT_SAME(decltype(s), UnorderedSet<int, std::hash<int> >);
|
||||
}
|
||||
|
||||
{
|
||||
UnorderedSet s(
|
||||
boost::unordered::from_range, y, 0, std::hash<int>(),
|
||||
std::equal_to<int>());
|
||||
BOOST_TEST_TRAIT_SAME(
|
||||
decltype(s), UnorderedSet<int, std::hash<int>, std::equal_to<int> >);
|
||||
}
|
||||
|
||||
{
|
||||
UnorderedSet s(boost::unordered::from_range, y, 0, std::hash<int>(),
|
||||
std::equal_to<int>(), int_allocator);
|
||||
BOOST_TEST_TRAIT_SAME(
|
||||
decltype(s), UnorderedSet<int, std::hash<int>, std::equal_to<int>,
|
||||
test_allocator<int> >);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* template<class T,
|
||||
class Hash = std::hash<T>,
|
||||
class Pred = std::equal_to<T>,
|
||||
@@ -358,6 +494,24 @@ template <template <class...> class UnorderedSet> void set_tests()
|
||||
test_allocator<int> >);
|
||||
}
|
||||
|
||||
#if !defined(BOOST_UNORDERED_NO_RANGES)
|
||||
/*
|
||||
template<ranges::input_range R, class Allocator>
|
||||
unordered_set(from_range_t, R&&,
|
||||
typename see below::size_type, Allocator)
|
||||
-> unordered_set<ranges::range_value_t<R>,
|
||||
hash<ranges::range_value_t<R>>,
|
||||
equal_to<ranges::range_value_t<R>>, Allocator>;
|
||||
*/
|
||||
|
||||
{
|
||||
UnorderedSet s(boost::unordered::from_range, y, 0u, int_allocator);
|
||||
BOOST_TEST_TRAIT_SAME(
|
||||
decltype(s), UnorderedSet<int, boost::hash<int>, std::equal_to<int>,
|
||||
test_allocator<int> >);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* template<class InputIt, class Hash, class Alloc>
|
||||
unordered_set(InputIt, InputIt, typename see below::size_type, Hash, Alloc)
|
||||
-> unordered_set<typename std::iterator_traits<InputIt>::value_type, Hash,
|
||||
@@ -370,6 +524,22 @@ template <template <class...> class UnorderedSet> void set_tests()
|
||||
UnorderedSet<int, hash_equals, std::equal_to<int>, test_allocator<int> >);
|
||||
}
|
||||
|
||||
#if !defined(BOOST_UNORDERED_NO_RANGES)
|
||||
/*
|
||||
template<ranges::input_range R, class Hash, class Allocator>
|
||||
unordered_set(from_range_t, R&&, typename see below::size_type,
|
||||
Hash, Allocator)
|
||||
-> unordered_set<ranges::range_value_t<R>, Hash,
|
||||
equal_to<ranges::range_value_t<R>>, Allocator>;
|
||||
*/
|
||||
|
||||
{
|
||||
UnorderedSet s(boost::unordered::from_range, y, 0u, f, int_allocator);
|
||||
BOOST_TEST_TRAIT_SAME(decltype(s),
|
||||
UnorderedSet<int, hash_equals, std::equal_to<int>, test_allocator<int> >);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* template<class T, class Allocator>
|
||||
unordered_set(std::initializer_list<T>, typename see below::size_type,
|
||||
Allocator)
|
||||
@@ -408,6 +578,23 @@ template <template <class...> class UnorderedSet> void set_tests()
|
||||
test_allocator<int> >);
|
||||
}
|
||||
|
||||
#if !defined(BOOST_UNORDERED_NO_RANGES)
|
||||
/*
|
||||
template<ranges::input_range R, class Allocator>
|
||||
unordered_set(from_range_t, R&&, Allocator)
|
||||
-> unordered_set<ranges::range_value_t<R>,
|
||||
hash<ranges::range_value_t<R>>,
|
||||
equal_to<ranges::range_value_t<R>>, Allocator>;
|
||||
*/
|
||||
|
||||
{
|
||||
UnorderedSet s(boost::unordered::from_range, y, int_allocator);
|
||||
BOOST_TEST_TRAIT_SAME(
|
||||
decltype(s), UnorderedSet<int, boost::hash<int>, std::equal_to<int>,
|
||||
test_allocator<int> >);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
template<class T, class Allocator>
|
||||
unordered_set(initializer_list<T>, Allocator)
|
||||
@@ -433,10 +620,15 @@ int main()
|
||||
map_tests<boost::unordered_map>();
|
||||
map_tests<boost::unordered_multimap>();
|
||||
map_tests<boost::unordered_flat_map>();
|
||||
map_tests<boost::unordered_node_map>();
|
||||
map_tests<boost::concurrent_flat_map>();
|
||||
map_tests<boost::concurrent_node_map>();
|
||||
set_tests<boost::unordered_set>();
|
||||
set_tests<boost::unordered_multiset>();
|
||||
set_tests<boost::unordered_flat_set>();
|
||||
set_tests<boost::unordered_node_set>();
|
||||
set_tests<boost::concurrent_flat_set>();
|
||||
set_tests<boost::concurrent_node_set>();
|
||||
|
||||
return boost::report_errors();
|
||||
#endif
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
|
||||
// Copyright 2006-2010 Daniel James.
|
||||
// Copyright (C) 2022-2023 Christian Mazakas
|
||||
// Copyright (C) 2026 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)
|
||||
|
||||
@@ -405,6 +406,27 @@ namespace insert_tests {
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
}
|
||||
|
||||
#if !defined(BOOST_UNORDERED_NO_RANGES)
|
||||
UNORDERED_SUB_TEST("insert_range tests")
|
||||
{
|
||||
test::check_instances check_;
|
||||
|
||||
X x;
|
||||
|
||||
test::random_values<X> v(1000, generator);
|
||||
x.insert_range(v);
|
||||
|
||||
test::check_container(x, v);
|
||||
test::check_equivalent_keys(x);
|
||||
|
||||
x.clear();
|
||||
x.insert_range(v | std::views::take(v.size()));
|
||||
|
||||
test::check_container(x, v);
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
template <class X>
|
||||
|
||||
Reference in New Issue
Block a user