diff --git a/doc/container.qbk b/doc/container.qbk index 582476f..9bf5e04 100644 --- a/doc/container.qbk +++ b/doc/container.qbk @@ -1341,6 +1341,7 @@ use [*Boost.Container]? There are several reasons for that: [section:release_notes_boost_1_78_00 Boost 1.78 Release] * Fixed bugs/issues: + * [@https://github.com/boostorg/container/issues/187 GitHub #187: ['"flat_map::erase and unique keys"]]. * [@https://github.com/boostorg/container/issues/188 GitHub #188: ['"Build fails when RTTI is disabled"]]. [endsect] diff --git a/include/boost/container/detail/flat_tree.hpp b/include/boost/container/detail/flat_tree.hpp index eaeb04e..2b16b54 100644 --- a/include/boost/container/detail/flat_tree.hpp +++ b/include/boost/container/detail/flat_tree.hpp @@ -1124,6 +1124,15 @@ class flat_tree return ret; } + size_type erase_unique(const key_type& k) + { + iterator i = this->find(k); + size_type ret = static_cast(i != this->end()); + if (ret) + this->erase(i); + return ret; + } + BOOST_CONTAINER_FORCEINLINE iterator erase(const_iterator first, const_iterator last) { return this->m_data.m_seq.erase(first, last); } diff --git a/include/boost/container/detail/tree.hpp b/include/boost/container/detail/tree.hpp index 14a1f15..cfb4436 100644 --- a/include/boost/container/detail/tree.hpp +++ b/include/boost/container/detail/tree.hpp @@ -1260,6 +1260,15 @@ class tree BOOST_CONTAINER_FORCEINLINE size_type erase(const key_type& k) { return AllocHolder::erase_key(k, KeyNodeCompare(key_comp()), alloc_version()); } + size_type erase_unique(const key_type& k) + { + iterator i = this->find(k); + size_type ret = static_cast(i != this->end()); + if (ret) + this->erase(i); + return ret; + } + iterator erase(const_iterator first, const_iterator last) { BOOST_ASSERT(first == last || (first != this->cend() && (priv_is_linked)(first))); diff --git a/include/boost/container/flat_map.hpp b/include/boost/container/flat_map.hpp index c4cbb5c..00b0350 100644 --- a/include/boost/container/flat_map.hpp +++ b/include/boost/container/flat_map.hpp @@ -1265,14 +1265,14 @@ class flat_map (m_flat_tree.erase(dtl::force_copy(p))); } - //! Effects: Erases all elements in the container with key equivalent to x. + //! Effects: If present, erases the element in the container with key equivalent to x. //! - //! Returns: Returns the number of erased elements. + //! Returns: Returns the number of erased elements (0/1). //! //! Complexity: Logarithmic search time plus erasure time //! linear to the elements with bigger keys. BOOST_CONTAINER_FORCEINLINE size_type erase(const key_type& x) - { return m_flat_tree.erase(x); } + { return m_flat_tree.erase_unique(x); } //! Effects: Erases all the elements in the range [first, last). //! diff --git a/include/boost/container/flat_set.hpp b/include/boost/container/flat_set.hpp index 1d77e42..8d66f3e 100644 --- a/include/boost/container/flat_set.hpp +++ b/include/boost/container/flat_set.hpp @@ -767,6 +767,15 @@ class flat_set BOOST_CONTAINER_FORCEINLINE void merge(BOOST_RV_REF_BEG flat_multiset BOOST_RV_REF_END source) { return this->merge(static_cast&>(source)); } + //! Effects: If present, erases the element in the container with key equivalent to x. + //! + //! Returns: Returns the number of erased elements (0/1). + //! + //! Complexity: Logarithmic search time plus erasure time + //! linear to the elements with bigger keys. + BOOST_CONTAINER_FORCEINLINE size_type erase(const key_type& x) + { return this->tree_t::erase_unique(x); } + #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED) //! Effects: Erases the element pointed to by p. @@ -781,14 +790,6 @@ class flat_set //! not less than the erased element. iterator erase(const_iterator p); - //! Effects: Erases all elements in the container with key equivalent to x. - //! - //! Returns: Returns the number of erased elements. - //! - //! Complexity: Logarithmic search time plus erasure time - //! linear to the elements with bigger keys. - size_type erase(const key_type& x); - //! Effects: Erases all the elements in the range [first, last). //! //! Returns: Returns last. @@ -909,6 +910,8 @@ class flat_set //! Note: Non-standard extension size_type index_of(const_iterator p) const BOOST_NOEXCEPT_OR_NOTHROW; + #else + using tree_t::erase; #endif // #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED) //! Returns: The number of elements with key equivalent to x. diff --git a/include/boost/container/map.hpp b/include/boost/container/map.hpp index e1003bc..30c7b83 100644 --- a/include/boost/container/map.hpp +++ b/include/boost/container/map.hpp @@ -964,6 +964,14 @@ class map #endif // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + //! Effects: If present, erases the element in the container with key equivalent to x. + //! + //! Returns: Returns the number of erased elements (0/1). + //! + //! Complexity: log(size()) + count(k) + BOOST_CONTAINER_FORCEINLINE size_type erase(const key_type& x) + { return this->base_t::erase_unique(x); } + #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED) //! Effects: Erases the element pointed to by p. @@ -975,13 +983,6 @@ class map //! Complexity: Amortized constant time iterator erase(const_iterator p) BOOST_NOEXCEPT_OR_NOTHROW; - //! Effects: Erases all elements in the container with key equivalent to x. - //! - //! Returns: Returns the number of erased elements. - //! - //! Complexity: log(size()) + count(k) - size_type erase(const key_type& x) BOOST_NOEXCEPT_OR_NOTHROW; - //! Effects: Erases all the elements in the range [first, last). //! //! Returns: Returns last. @@ -989,7 +990,9 @@ class map //! Complexity: log(size())+N where N is the distance from first to last. iterator erase(const_iterator first, const_iterator last) BOOST_NOEXCEPT_OR_NOTHROW; - #endif + #else + using base_t::erase; + #endif // #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED) //! Effects: Removes the first element in the container with key equivalent to k. //! diff --git a/include/boost/container/set.hpp b/include/boost/container/set.hpp index fc5d782..f8a2efa 100644 --- a/include/boost/container/set.hpp +++ b/include/boost/container/set.hpp @@ -680,6 +680,14 @@ class set BOOST_CONTAINER_FORCEINLINE void merge(BOOST_RV_REF_BEG multiset BOOST_RV_REF_END source) { return this->merge(static_cast&>(source)); } + //! Effects: If present, erases the element in the container with key equivalent to x. + //! + //! Returns: Returns the number of erased elements (0/1). + //! + //! Complexity: log(size()) + count(k) + BOOST_CONTAINER_FORCEINLINE size_type erase(const key_type& x) + { return this->base_t::erase_unique(x); } + #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED) //! Effects: Erases the element pointed to by p. @@ -691,13 +699,6 @@ class set //! Complexity: Amortized constant time iterator erase(const_iterator p); - //! Effects: Erases all elements in the container with key equivalent to x. - //! - //! Returns: Returns the number of erased elements. - //! - //! Complexity: log(size()) + count(k) - size_type erase(const key_type& x); - //! Effects: Erases all the elements in the range [first, last). //! //! Returns: Returns last. @@ -771,7 +772,9 @@ class set template const_iterator find(const K& x) const; - #endif //#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED) + #else + using base_t::erase; + #endif // #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED) //! Returns: The number of elements with key equivalent to x. //!