]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
libstdc++: Optimize removal from unique assoc containers [PR112934]
authorBarnabás Pőcze <pobrn@protonmail.com>
Mon, 11 Mar 2024 23:35:50 +0000 (23:35 +0000)
committerJonathan Wakely <redi@gcc.gnu.org>
Tue, 29 Apr 2025 14:08:53 +0000 (15:08 +0100)
Previously, calling erase(key) on both std::map and std::set
would execute that same code that std::multi{map,set} would.
However, doing that is unnecessary because std::{map,set}
guarantee that all elements are unique.

It is reasonable to expect that erase(key) is equivalent
or better than:

  auto it = m.find(key);
  if (it != m.end())
    m.erase(it);

However, this was not the case. Fix that by adding a new
function _Rb_tree<>::_M_erase_unique() that is essentially
equivalent to the above snippet, and use this from both
std::map and std::set.

libstdc++-v3/ChangeLog:

PR libstdc++/112934
* include/bits/stl_map.h (map::erase): Use _M_erase_unique.
* include/bits/stl_set.h (set::erase): Likewise.
* include/bits/stl_tree.h (_Rb_tree::_M_erase_unique): Add.

libstdc++-v3/include/bits/stl_map.h
libstdc++-v3/include/bits/stl_set.h
libstdc++-v3/include/bits/stl_tree.h

index 006ff46dfb5df88be51ff10c6275a08a32c4ffb1..68c23b8e3e71a4e3ae669fa736f65382f0878563 100644 (file)
@@ -1156,7 +1156,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
        */
       size_type
       erase(const key_type& __x)
-      { return _M_t.erase(__x); }
+      { return _M_t._M_erase_unique(__x); }
 
 #if __cplusplus >= 201103L
       // _GLIBCXX_RESOLVE_LIB_DEFECTS
index 0799fd0918a3b167f3f5b4fa0b6ffbf4061177dc..b65d63195aa23aaaace59d245929b6029ebc038f 100644 (file)
@@ -728,7 +728,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
        */
       size_type
       erase(const key_type& __x)
-      { return _M_t.erase(__x); }
+      { return _M_t._M_erase_unique(__x); }
 
 #if __cplusplus >= 201103L
       // _GLIBCXX_RESOLVE_LIB_DEFECTS
index 6c12c41bba7b32717df30bcb0468d4e9b39b9269..4b7f482e794c804ed6b02dd61d81d17d45a2f835 100644 (file)
@@ -1850,6 +1850,9 @@ namespace __rb_tree
       size_type
       erase(const key_type& __x);
 
+      size_type
+      _M_erase_unique(const key_type& __x);
+
 #if __cplusplus >= 201103L
       // _GLIBCXX_RESOLVE_LIB_DEFECTS
       // DR 130. Associative erase should return an iterator.
@@ -3139,6 +3142,20 @@ namespace __rb_tree
       return __old_size - size();
     }
 
+  template<typename _Key, typename _Val, typename _KeyOfValue,
+          typename _Compare, typename _Alloc>
+    typename _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::size_type
+    _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
+    _M_erase_unique(const _Key& __x)
+    {
+      iterator __it = find(__x);
+      if (__it == end())
+       return 0;
+
+      _M_erase_aux(__it);
+      return 1;
+    }
+
   template<typename _Key, typename _Val, typename _KeyOfValue,
           typename _Compare, typename _Alloc>
     typename _Rb_tree<_Key, _Val, _KeyOfValue,