From 2b6cfe4f3cd8d7cf4a605fb42018841dc3e234ea Mon Sep 17 00:00:00 2001 From: joaquintides Date: Thu, 15 Jun 2023 14:42:56 +0200 Subject: [PATCH] documented proxy erase(iterator) --- doc/unordered/changes.adoc | 4 ++++ doc/unordered/compliance.adoc | 4 +++- doc/unordered/unordered_flat_map.adoc | 19 +++++++++++-------- doc/unordered/unordered_flat_set.adoc | 19 +++++++++++-------- doc/unordered/unordered_node_map.adoc | 19 +++++++++++-------- doc/unordered/unordered_node_set.adoc | 19 +++++++++++-------- 6 files changed, 51 insertions(+), 33 deletions(-) diff --git a/doc/unordered/changes.adoc b/doc/unordered/changes.adoc index 04f0bc44..5679a9ea 100644 --- a/doc/unordered/changes.adoc +++ b/doc/unordered/changes.adoc @@ -10,6 +10,10 @@ * Added `boost::concurrent_flat_map`, a fast, thread-safe hashmap based on open addressing. * Sped up iteration of open-addressing containers. +* In open-addressing containers, `erase(iterator)`, which previously returned nothing, now +returns a proxy object convertible to an iterator to the next element. +This enables the typical `it = c.erase(it)` idiom without incurring any performance penalty +when the returned proxy is not used. == Release 1.82.0 - Major update diff --git a/doc/unordered/compliance.adoc b/doc/unordered/compliance.adoc index d5d84e9c..eb91ac4f 100644 --- a/doc/unordered/compliance.adoc +++ b/doc/unordered/compliance.adoc @@ -135,7 +135,9 @@ The main differences with C++ unordered associative containers are: * In general: ** `begin()` is not constant-time. - ** `erase(iterator)` returns `void` instead of an iterator to the following element. + ** `erase(iterator)` does not return an iterator to the following element, but + a proxy object that converts to that iterator if requested; this avoids + a potentially costly iterator increment operation when not needed. ** There is no API for bucket handling (except `bucket_count`). ** The maximum load factor of the container is managed internally and can't be set by the user. The maximum load, exposed through the public function `max_load`, may decrease on erasure under high-load conditions. diff --git a/doc/unordered/unordered_flat_map.adoc b/doc/unordered/unordered_flat_map.adoc index ba95eb73..03f6d892 100644 --- a/doc/unordered/unordered_flat_map.adoc +++ b/doc/unordered/unordered_flat_map.adoc @@ -17,7 +17,6 @@ a number of aspects from that of `boost::unordered_flat_map`/`std::unordered_fla - `value_type` must be move-constructible. - Pointer stability is not kept under rehashing. - `begin()` is not constant-time. - - `erase(iterator)` returns `void`. - There is no API for bucket handling (except `bucket_count`) or node extraction/insertion. - The maximum load factor of the container is managed internally and can't be set by the user. @@ -155,9 +154,9 @@ namespace boost { template iterator xref:#unordered_flat_map_insert_or_assign_with_hint[insert_or_assign](const_iterator hint, K&& k, M&& obj); - void xref:#unordered_flat_map_erase_by_position[erase](iterator position); - void xref:#unordered_flat_map_erase_by_position[erase](const_iterator position); - size_type xref:#unordered_flat_map_erase_by_key[erase](const key_type& k); + _implementation-defined_ xref:#unordered_flat_map_erase_by_position[erase](iterator position); + _implementation-defined_ xref:#unordered_flat_map_erase_by_position[erase](const_iterator position); + size_type xref:#unordered_flat_map_erase_by_key[erase](const key_type& k); template size_type xref:#unordered_flat_map_erase_by_key[erase](K&& k); iterator xref:#unordered_flat_map_erase_range[erase](const_iterator first, const_iterator last); void xref:#unordered_flat_map_swap[swap](unordered_flat_map& other) @@ -1035,15 +1034,19 @@ The `template` only participates in overload resolution if `Ha ==== Erase by Position -```c++ -void erase(iterator position); -void erase(const_iterator position); -``` +[source,c++,subs=+quotes] +---- +_implementation-defined_ erase(iterator position); +_implementation-defined_ erase(const_iterator position); +---- Erase the element pointed to by `position`. [horizontal] +Returns:;; An opaque object implicitly convertible to the `iterator` or `const_iterator` +immediately following `position` prior to the erasure. Throws:;; Nothing. +Notes:;; The opaque object returned must only be discarded or immediately converted to `iterator` or `const_iterator`. --- diff --git a/doc/unordered/unordered_flat_set.adoc b/doc/unordered/unordered_flat_set.adoc index 770ce797..7853978a 100644 --- a/doc/unordered/unordered_flat_set.adoc +++ b/doc/unordered/unordered_flat_set.adoc @@ -17,7 +17,6 @@ a number of aspects from that of `boost::unordered_flat_set`/`std::unordered_fla - `value_type` must be move-constructible. - Pointer stability is not kept under rehashing. - `begin()` is not constant-time. - - `erase(iterator)` returns `void`. - There is no API for bucket handling (except `bucket_count`) or node extraction/insertion. - The maximum load factor of the container is managed internally and can't be set by the user. @@ -123,9 +122,9 @@ namespace boost { template void xref:#unordered_flat_set_insert_iterator_range[insert](InputIterator first, InputIterator last); void xref:#unordered_flat_set_insert_initializer_list[insert](std::initializer_list); - void xref:#unordered_flat_set_erase_by_position[erase](iterator position); - void xref:#unordered_flat_set_erase_by_position[erase](const_iterator position); - size_type xref:#unordered_flat_set_erase_by_key[erase](const key_type& k); + _implementation-defined_ xref:#unordered_flat_set_erase_by_position[erase](iterator position); + _implementation-defined_ xref:#unordered_flat_set_erase_by_position[erase](const_iterator position); + size_type xref:#unordered_flat_set_erase_by_key[erase](const key_type& k); template size_type xref:#unordered_flat_set_erase_by_key[erase](K&& k); iterator xref:#unordered_flat_set_erase_range[erase](const_iterator first, const_iterator last); void xref:#unordered_flat_set_swap[swap](unordered_flat_set& other) @@ -846,15 +845,19 @@ Notes:;; Can invalidate iterators, pointers and references, but only if the inse ==== Erase by Position -```c++ -void erase(iterator position); -void erase(const_iterator position); -``` +[source,c++,subs=+quotes] +---- +_implementation-defined_ erase(iterator position); +_implementation-defined_ erase(const_iterator position); +---- Erase the element pointed to by `position`. [horizontal] +Returns:;; An opaque object implicitly convertible to the `iterator` or `const_iterator` +immediately following `position` prior to the erasure. Throws:;; Nothing. +Notes:;; The opaque object returned must only be discarded or immediately converted to `iterator` or `const_iterator`. --- diff --git a/doc/unordered/unordered_node_map.adoc b/doc/unordered/unordered_node_map.adoc index 4821414a..bc362786 100644 --- a/doc/unordered/unordered_node_map.adoc +++ b/doc/unordered/unordered_node_map.adoc @@ -13,7 +13,6 @@ As a result of its using open addressing, the interface of `boost::unordered_nod a number of aspects from that of `boost::unordered_map`/`std::unordered_map`: - `begin()` is not constant-time. - - `erase(iterator)` returns `void`. - There is no API for bucket handling (except `bucket_count`). - The maximum load factor of the container is managed internally and can't be set by the user. @@ -156,9 +155,9 @@ namespace boost { template iterator xref:#unordered_node_map_insert_or_assign_with_hint[insert_or_assign](const_iterator hint, K&& k, M&& obj); - void xref:#unordered_node_map_erase_by_position[erase](iterator position); - void xref:#unordered_node_map_erase_by_position[erase](const_iterator position); - size_type xref:#unordered_node_map_erase_by_key[erase](const key_type& k); + _implementation-defined_ xref:#unordered_node_map_erase_by_position[erase](iterator position); + _implementation-defined_ xref:#unordered_node_map_erase_by_position[erase](const_iterator position); + size_type xref:#unordered_node_map_erase_by_key[erase](const key_type& k); template size_type xref:#unordered_node_map_erase_by_key[erase](K&& k); iterator xref:#unordered_node_map_erase_range[erase](const_iterator first, const_iterator last); void xref:#unordered_node_map_swap[swap](unordered_node_map& other) @@ -1105,15 +1104,19 @@ The `template` only participates in overload resolution if `Ha ==== Erase by Position -```c++ -void erase(iterator position); -void erase(const_iterator position); -``` +[source,c++,subs=+quotes] +---- +_implementation-defined_ erase(iterator position); +_implementation-defined_ erase(const_iterator position); +---- Erase the element pointed to by `position`. [horizontal] +Returns:;; An opaque object implicitly convertible to the `iterator` or `const_iterator` +immediately following `position` prior to the erasure. Throws:;; Nothing. +Notes:;; The opaque object returned must only be discarded or immediately converted to `iterator` or `const_iterator`. --- diff --git a/doc/unordered/unordered_node_set.adoc b/doc/unordered/unordered_node_set.adoc index b5a5ff97..dc25a79f 100644 --- a/doc/unordered/unordered_node_set.adoc +++ b/doc/unordered/unordered_node_set.adoc @@ -13,7 +13,6 @@ As a result of its using open addressing, the interface of `boost::unordered_nod a number of aspects from that of `boost::unordered_set`/`std::unordered_set`: - `begin()` is not constant-time. - - `erase(iterator)` returns `void`. - There is no API for bucket handling (except `bucket_count`). - The maximum load factor of the container is managed internally and can't be set by the user. @@ -124,9 +123,9 @@ namespace boost { 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); - void xref:#unordered_node_set_erase_by_position[erase](iterator position); - void xref:#unordered_node_set_erase_by_position[erase](const_iterator position); - size_type xref:#unordered_node_set_erase_by_key[erase](const key_type& k); + _implementation-defined_ xref:#unordered_node_set_erase_by_position[erase](iterator position); + _implementation-defined_ xref:#unordered_node_set_erase_by_position[erase](const_iterator position); + size_type xref:#unordered_node_set_erase_by_key[erase](const key_type& k); template size_type xref:#unordered_node_set_erase_by_key[erase](K&& k); iterator xref:#unordered_node_set_erase_range[erase](const_iterator first, const_iterator last); void xref:#unordered_node_set_swap[swap](unordered_node_set& other) @@ -919,15 +918,19 @@ Notes:;; Behavior is undefined if `nh` is not empty and the allocators of `nh` a ==== Erase by Position -```c++ -void erase(iterator position); -void erase(const_iterator position); -``` +[source,c++,subs=+quotes] +---- +_implementation-defined_ erase(iterator position); +_implementation-defined_ erase(const_iterator position); +---- Erase the element pointed to by `position`. [horizontal] +Returns:;; An opaque object implicitly convertible to the `iterator` or `const_iterator` +immediately following `position` prior to the erasure. Throws:;; Nothing. +Notes:;; The opaque object returned must only be discarded or immediately converted to `iterator` or `const_iterator`. ---