]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
libstdc++: Avoid debug checks in uniform container erasure functions
authorJonathan Wakely <jwakely@redhat.com>
Thu, 7 Oct 2021 13:40:26 +0000 (14:40 +0100)
committerJonathan Wakely <jwakely@redhat.com>
Thu, 7 Oct 2021 16:52:04 +0000 (17:52 +0100)
In commit r12-4083 I tried to make the std::erase and std::erase_if
function avoid the unnecessary overhead of safe iterators. It didn't
work, for two reasons. Firstly, for the RB tree containers the
__niter_base function is a no-op (because the iterators aren't
random access) so the safe iterators were still used. Secondly, for the
cases where __niter_base did remove the safe iterator layer, there was
still unnecessary overhead to create a new safe iterator and link it to
the container.

This solves the problem by simply binding a reference to the non-debug
version of the conainer. For normal mode this is a no-op, and for debug
mode it binds a reference to the debug container's base class. That
means the rest of the function operates directly on the non-debug
container, and avoids all checking.

For std::basic_string there's no need to unwrap anything, because we use
std::basic_string directly in debug mode anyway.

libstdc++-v3/ChangeLog:

* include/bits/erase_if.h (__erase_nodes_if): Remove redundant
__niter_base calls.
* include/std/string (erase, erase_if): Likewise.
* include/std/deque (erase, erase_if): Access non-debug
container directly.
* include/std/map (erase, erase_if): Likewise.
* include/std/set (erase, erase_if): Likewise.
* include/std/unordered_map (erase, erase_if): Likewise.
* include/std/unordered_set (erase, erase_if): Likewise.
* include/std/vector (erase, erase_if): Likewise.
* include/experimental/deque (erase, erase_if): Likewise.
* include/experimental/map (erase, erase_if): Likewise.
* include/experimental/set (erase, erase_if): Likewise.
* include/experimental/unordered_map (erase, erase_if):
Likewise.
* include/experimental/unordered_set (erase, erase_if):
Likewise.
* include/experimental/vector (erase, erase_if): Likewise.

14 files changed:
libstdc++-v3/include/bits/erase_if.h
libstdc++-v3/include/experimental/deque
libstdc++-v3/include/experimental/map
libstdc++-v3/include/experimental/set
libstdc++-v3/include/experimental/unordered_map
libstdc++-v3/include/experimental/unordered_set
libstdc++-v3/include/experimental/vector
libstdc++-v3/include/std/deque
libstdc++-v3/include/std/map
libstdc++-v3/include/std/set
libstdc++-v3/include/std/string
libstdc++-v3/include/std/unordered_map
libstdc++-v3/include/std/unordered_set
libstdc++-v3/include/std/vector

index 7716e1a953ce0726a03452e2c5949bbadaf0ef7b..8d1d23168fa90838c6d51782d46346fb76317eb2 100644 (file)
@@ -51,8 +51,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       __erase_nodes_if(_Container& __cont, _Predicate __pred)
       {
        typename _Container::size_type __num = 0;
-       for (auto __iter = std::__niter_base(__cont.begin()),
-            __last = std::__niter_base(__cont.end());
+       for (auto __iter = __cont.begin(), __last = __cont.end();
             __iter != __last;)
          {
            if (__pred(*__iter))
index a76fb659bbf67f2064ed508f0790d127fdbebd24..710833ebcaded99b557ad800e7d6121f003229a2 100644 (file)
@@ -50,16 +50,16 @@ inline namespace fundamentals_v2
     inline void
     erase_if(deque<_Tp, _Alloc>& __cont, _Predicate __pred)
     {
-      __cont.erase(std::remove_if(__cont.begin(), __cont.end(), __pred),
-                  __cont.end());
+      _GLIBCXX_STD_C::deque<_Tp, _Alloc>& __c = __cont;
+      __c.erase(std::remove_if(__c.begin(), __c.end(), __pred), __c.end());
     }
 
   template<typename _Tp, typename _Alloc, typename _Up>
     inline void
     erase(deque<_Tp, _Alloc>& __cont, const _Up& __value)
     {
-      __cont.erase(std::remove(__cont.begin(), __cont.end(), __value),
-                  __cont.end());
+      _GLIBCXX_STD_C::deque<_Tp, _Alloc>& __c = __cont;
+      __c.erase(std::remove(__c.begin(), __c.end(), __value), __c.end());
     }
 
   namespace pmr {
index 0c0f42222f5697f392bd94ae6aec623fb667b453..ef69fadf9441ac0332ab227c1135572cf5262035 100644 (file)
@@ -50,13 +50,19 @@ inline namespace fundamentals_v2
           typename _Predicate>
     inline void
     erase_if(map<_Key, _Tp, _Compare, _Alloc>& __cont, _Predicate __pred)
-    { std::__detail::__erase_nodes_if(__cont, __pred); }
+    {
+      _GLIBCXX_STD_C::map<_Key, _Tp, _Compare, _Alloc>& __c = __cont;
+      std::__detail::__erase_nodes_if(__c, __pred);
+    }
 
   template<typename _Key, typename _Tp, typename _Compare, typename _Alloc,
           typename _Predicate>
     inline void
     erase_if(multimap<_Key, _Tp, _Compare, _Alloc>& __cont, _Predicate __pred)
-    { std::__detail::__erase_nodes_if(__cont, __pred); }
+    {
+      _GLIBCXX_STD_C::multimap<_Key, _Tp, _Compare, _Alloc>& __c = __cont;
+      std::__detail::__erase_nodes_if(__c, __pred);
+    }
 
   namespace pmr {
     template<typename _Key, typename _Tp, typename _Compare = less<_Key>>
index c3f5433e995c3c62cb7966a0f4181e7142818831..7a5986aec0e9b03b5f46b6be2ff21590fe816ca1 100644 (file)
@@ -50,13 +50,19 @@ inline namespace fundamentals_v2
           typename _Predicate>
     inline void
     erase_if(set<_Key, _Compare, _Alloc>& __cont, _Predicate __pred)
-    { std::__detail::__erase_nodes_if(__cont, __pred); }
+    {
+      _GLIBCXX_STD_C::set<_Key, _Compare, _Alloc>& __c = __cont;
+      std::__detail::__erase_nodes_if(__c, __pred);
+    }
 
   template<typename _Key, typename _Compare, typename _Alloc,
           typename _Predicate>
     inline void
     erase_if(multiset<_Key, _Compare, _Alloc>& __cont, _Predicate __pred)
-    { std::__detail::__erase_nodes_if(__cont, __pred); }
+    {
+      _GLIBCXX_STD_C::multiset<_Key, _Compare, _Alloc>& __c = __cont;
+      std::__detail::__erase_nodes_if(__c, __pred);
+    }
 
   namespace pmr {
     template<typename _Key, typename _Compare = less<_Key>>
index 0b915ab13e5bd148f6b93fcd6beba8eb7abf59ec..eba989713fa096601ed6ec1bda067187284fd865 100644 (file)
@@ -51,14 +51,22 @@ inline namespace fundamentals_v2
     inline void
     erase_if(unordered_map<_Key, _Tp, _Hash, _CPred, _Alloc>& __cont,
             _Predicate __pred)
-    { std::__detail::__erase_nodes_if(__cont, __pred); }
+    {
+      _GLIBCXX_STD_C::unordered_map<_Key, _Tp, _Hash, _CPred, _Alloc>& __c
+       = __cont;
+      std::__detail::__erase_nodes_if(__c, __pred);
+    }
 
   template<typename _Key, typename _Tp, typename _Hash, typename _CPred,
           typename _Alloc, typename _Predicate>
     inline void
     erase_if(unordered_multimap<_Key, _Tp, _Hash, _CPred, _Alloc>& __cont,
             _Predicate __pred)
-    { std::__detail::__erase_nodes_if(__cont, __pred); }
+    {
+      _GLIBCXX_STD_C::unordered_multimap<_Key, _Tp, _Hash, _CPred, _Alloc>& __c
+       = __cont;
+      std::__detail::__erase_nodes_if(__c, __pred);
+    }
 
   namespace pmr {
     template<typename _Key, typename _Tp, typename _Hash = hash<_Key>,
index 87db4464401eb1407f283d566a2a6797069a2f23..bc5cc11419e091e0da772a54fbd2e9282c8868c5 100644 (file)
@@ -51,14 +51,21 @@ inline namespace fundamentals_v2
     inline void
     erase_if(unordered_set<_Key, _Hash, _CPred, _Alloc>& __cont,
             _Predicate __pred)
-    { std::__detail::__erase_nodes_if(__cont, __pred); }
+    {
+      _GLIBCXX_STD_C::unordered_set<_Key, _Hash, _CPred, _Alloc>& __c = __cont;
+      std::__detail::__erase_nodes_if(__c, __pred);
+    }
 
   template<typename _Key, typename _Hash, typename _CPred, typename _Alloc,
           typename _Predicate>
     inline void
     erase_if(unordered_multiset<_Key, _Hash, _CPred, _Alloc>& __cont,
             _Predicate __pred)
-    { std::__detail::__erase_nodes_if(__cont, __pred); }
+    {
+      _GLIBCXX_STD_C::unordered_multiset<_Key, _Hash, _CPred, _Alloc>& __c
+       = __cont;
+      std::__detail::__erase_nodes_if(__c, __pred);
+    }
 
   namespace pmr {
     template<typename _Key, typename _Hash = hash<_Key>,
index a14aedf33640889f433de21eb9c4dd4e55bb8d12..c45a500ef5e676990f5101a516d0e5ad8676a230 100644 (file)
@@ -52,16 +52,16 @@ inline namespace fundamentals_v2
     inline void
     erase_if(vector<_Tp, _Alloc>& __cont, _Predicate __pred)
     {
-      __cont.erase(std::remove_if(__cont.begin(), __cont.end(), __pred),
-                  __cont.end());
+      _GLIBCXX_STD_C::vector<_Tp, _Alloc>& __c = __cont;
+      __c.erase(std::remove_if(__c.begin(), __c.end(), __pred), __c.end());
     }
 
   template<typename _Tp, typename _Alloc, typename _Up>
     inline void
     erase(vector<_Tp, _Alloc>& __cont, const _Up& __value)
     {
-      __cont.erase(std::remove(__cont.begin(), __cont.end(), __value),
-                  __cont.end());
+      _GLIBCXX_STD_C::vector<_Tp, _Alloc>& __c = __cont;
+      __c.erase(std::remove(__c.begin(), __c.end(), __value), __c.end());
     }
 
   namespace pmr {
index b2a7cee483aabdd3cfb9b83135623b730bfaa689..71993e757a516ad2c12de8602d5ac876093e5830 100644 (file)
@@ -95,28 +95,28 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     inline typename deque<_Tp, _Alloc>::size_type
     erase_if(deque<_Tp, _Alloc>& __cont, _Predicate __pred)
     {
+      _GLIBCXX_STD_C::deque<_Tp, _Alloc>& __c = __cont;
       using namespace __gnu_cxx;
-      const auto __osz = __cont.size();
-      const auto __end = __cont.end();
-      auto __removed(std::__remove_if(std::__niter_base(__cont.begin()),
-                                     std::__niter_base(__end),
-                                     __ops::__pred_iter(std::ref(__pred))));
-      __cont.erase(std::__niter_wrap(__end, __removed), __end);
-      return __osz - __cont.size();
+      const auto __osz = __c.size();
+      const auto __end = __c.end();
+      auto __removed = std::__remove_if(__c.begin(), __end,
+                                       __ops::__pred_iter(std::ref(__pred)));
+      __c.erase(__removed, __end);
+      return __osz - __c.size();
     }
 
   template<typename _Tp, typename _Alloc, typename _Up>
     inline typename deque<_Tp, _Alloc>::size_type
     erase(deque<_Tp, _Alloc>& __cont, const _Up& __value)
     {
+      _GLIBCXX_STD_C::deque<_Tp, _Alloc>& __c = __cont;
       using namespace __gnu_cxx;
-      const auto __osz = __cont.size();
-      const auto __end = __cont.end();
-      auto __removed(std::__remove_if(std::__niter_base(__cont.begin()),
-                                     std::__niter_base(__end),
-                                     __ops::__iter_equals_val(__value)));
-      __cont.erase(std::__niter_wrap(__end, __removed), __end);
-      return __osz - __cont.size();
+      const auto __osz = __c.size();
+      const auto __end = __c.end();
+      auto __removed = std::__remove_if(__c.begin(), __end,
+                                       __ops::__iter_equals_val(__value));
+      __c.erase(__removed, __end);
+      return __osz - __c.size();
     }
 _GLIBCXX_END_NAMESPACE_VERSION
 } // namespace std
index 44bd44b5922a44cd4e1c971ee8633578ad878c6a..29265580995f6636e23a8be5cec0962c5a178bc9 100644 (file)
@@ -95,13 +95,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
           typename _Predicate>
     inline typename map<_Key, _Tp, _Compare, _Alloc>::size_type
     erase_if(map<_Key, _Tp, _Compare, _Alloc>& __cont, _Predicate __pred)
-    { return __detail::__erase_nodes_if(__cont, __pred); }
+    {
+      _GLIBCXX_STD_C::map<_Key, _Tp, _Compare, _Alloc>& __c = __cont;
+      return __detail::__erase_nodes_if(__c, __pred);
+    }
 
   template<typename _Key, typename _Tp, typename _Compare, typename _Alloc,
           typename _Predicate>
     inline typename multimap<_Key, _Tp, _Compare, _Alloc>::size_type
     erase_if(multimap<_Key, _Tp, _Compare, _Alloc>& __cont, _Predicate __pred)
-    { return __detail::__erase_nodes_if(__cont, __pred); }
+    {
+      _GLIBCXX_STD_C::multimap<_Key, _Tp, _Compare, _Alloc>& __c = __cont;
+      return __detail::__erase_nodes_if(__c, __pred);
+    }
 _GLIBCXX_END_NAMESPACE_VERSION
 } // namespace std
 #endif // C++20
index f1e1864937a0b4b8cf5d5a60878d9c4090ed4064..24e6e6336248383e50ec668a4075393d3cff6dd4 100644 (file)
@@ -91,13 +91,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
           typename _Predicate>
     inline typename set<_Key, _Compare, _Alloc>::size_type
     erase_if(set<_Key, _Compare, _Alloc>& __cont, _Predicate __pred)
-    { return __detail::__erase_nodes_if(__cont, __pred); }
+    {
+      _GLIBCXX_STD_C::set<_Key, _Compare, _Alloc>& __c = __cont;
+      return __detail::__erase_nodes_if(__c, __pred);
+    }
 
   template<typename _Key, typename _Compare, typename _Alloc,
           typename _Predicate>
     inline typename multiset<_Key, _Compare, _Alloc>::size_type
     erase_if(multiset<_Key, _Compare, _Alloc>& __cont, _Predicate __pred)
-    { return __detail::__erase_nodes_if(__cont, __pred); }
+    {
+      _GLIBCXX_STD_C::multiset<_Key, _Compare, _Alloc>& __c = __cont;
+      return __detail::__erase_nodes_if(__c, __pred);
+    }
 _GLIBCXX_END_NAMESPACE_VERSION
 } // namespace std
 #endif // C++20
index 7f994147a330fcd1bc33e1567a0abf75bf6693ee..95412b6f7a3fb1010b77784a32902895366644ae 100644 (file)
@@ -124,12 +124,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     erase_if(basic_string<_CharT, _Traits, _Alloc>& __cont, _Predicate __pred)
     {
       using namespace __gnu_cxx;
-      using _It = typename basic_string<_CharT, _Traits, _Alloc>::iterator;
       const auto __osz = __cont.size();
-      _It __removed(std::__remove_if(std::__niter_base(__cont.begin()),
-                                     std::__niter_base(__cont.end()),
-                                     __ops::__pred_iter(std::ref(__pred))));
-      __cont.erase(__removed, __cont.end());
+      const auto __end = __cont.end();
+      auto __removed = std::__remove_if(__cont.begin(), __end,
+                                       __ops::__pred_iter(std::ref(__pred)));
+      __cont.erase(__removed, __end);
       return __osz - __cont.size();
     }
 
@@ -138,12 +137,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     erase(basic_string<_CharT, _Traits, _Alloc>& __cont, const _Up& __value)
     {
       using namespace __gnu_cxx;
-      using _It = typename basic_string<_CharT, _Traits, _Alloc>::iterator;
       const auto __osz = __cont.size();
-      _It __removed(std::__remove_if(std::__niter_base(__cont.begin()),
-                                     std::__niter_base(__cont.end()),
-                                     __ops::__iter_equals_val(__value)));
-      __cont.erase(__removed, __cont.end());
+      const auto __end = __cont.end();
+      auto __removed = std::__remove_if(__cont.begin(), __end,
+                                       __ops::__iter_equals_val(__value));
+      __cont.erase(__removed, __end);
       return __osz - __cont.size();
     }
 _GLIBCXX_END_NAMESPACE_VERSION
index e6715069362d700ff9138e24de0fddae911a117a..774c21fc28b207d9e7465b136891b8b3b763b69f 100644 (file)
@@ -83,7 +83,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     inline typename unordered_map<_Key, _Tp, _Hash, _CPred, _Alloc>::size_type
     erase_if(unordered_map<_Key, _Tp, _Hash, _CPred, _Alloc>& __cont,
             _Predicate __pred)
-    { return __detail::__erase_nodes_if(__cont, __pred); }
+    {
+      _GLIBCXX_STD_C::unordered_map<_Key, _Tp, _Hash, _CPred, _Alloc>& __c
+       = __cont;
+      return __detail::__erase_nodes_if(__c, __pred);
+    }
 
   template<typename _Key, typename _Tp, typename _Hash, typename _CPred,
           typename _Alloc, typename _Predicate>
@@ -91,7 +95,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
                    size_type
     erase_if(unordered_multimap<_Key, _Tp, _Hash, _CPred, _Alloc>& __cont,
             _Predicate __pred)
-    { return __detail::__erase_nodes_if(__cont, __pred); }
+    {
+      _GLIBCXX_STD_C::unordered_multimap<_Key, _Tp, _Hash, _CPred, _Alloc>& __c
+       = __cont;
+      return __detail::__erase_nodes_if(__c, __pred);
+    }
 _GLIBCXX_END_NAMESPACE_VERSION
 } // namespace std
 #endif // C++20
index 1ad93d0031b2c6a84077846549356559e3da757a..3859eeaebd09732a579c4d218b38799cb9498695 100644 (file)
@@ -83,14 +83,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     inline typename unordered_set<_Key, _Hash, _CPred, _Alloc>::size_type
     erase_if(unordered_set<_Key, _Hash, _CPred, _Alloc>& __cont,
             _Predicate __pred)
-    { return __detail::__erase_nodes_if(__cont, __pred); }
+    {
+      _GLIBCXX_STD_C::unordered_set<_Key, _Hash, _CPred, _Alloc>& __c = __cont;
+      return __detail::__erase_nodes_if(__c, __pred);
+    }
 
   template<typename _Key, typename _Hash, typename _CPred, typename _Alloc,
           typename _Predicate>
     inline typename unordered_multiset<_Key, _Hash, _CPred, _Alloc>::size_type
     erase_if(unordered_multiset<_Key, _Hash, _CPred, _Alloc>& __cont,
             _Predicate __pred)
-    { return __detail::__erase_nodes_if(__cont, __pred); }
+    {
+      _GLIBCXX_STD_C::unordered_multiset<_Key, _Hash, _CPred, _Alloc>& __c
+       = __cont;
+      return __detail::__erase_nodes_if(__c, __pred);
+    }
 _GLIBCXX_END_NAMESPACE_VERSION
 } // namespace std
 #endif // C++20
index 3b275e249fc6220e159dffdf7fd1654536ee088f..835fa8aeb691f28ebbb41545ba07ee21727ba853 100644 (file)
@@ -105,28 +105,28 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     inline typename vector<_Tp, _Alloc>::size_type
     erase_if(vector<_Tp, _Alloc>& __cont, _Predicate __pred)
     {
+      _GLIBCXX_STD_C::vector<_Tp, _Alloc>& __c = __cont;
       using namespace __gnu_cxx;
-      const auto __osz = __cont.size();
-      const auto __end = __cont.end();
-      auto __removed(std::__remove_if(std::__niter_base(__cont.begin()),
-                                     std::__niter_base(__end),
+      const auto __osz = __c.size();
+      const auto __end = __c.end();
+      auto __removed(std::__remove_if(__c.begin(), __end,
                                      __ops::__pred_iter(std::ref(__pred))));
-      __cont.erase(std::__niter_wrap(__end, __removed), __end);
-      return __osz - __cont.size();
+      __c.erase(__removed, __end);
+      return __osz - __c.size();
     }
 
   template<typename _Tp, typename _Alloc, typename _Up>
     inline typename vector<_Tp, _Alloc>::size_type
     erase(vector<_Tp, _Alloc>& __cont, const _Up& __value)
     {
+      _GLIBCXX_STD_C::vector<_Tp, _Alloc>& __c = __cont;
       using namespace __gnu_cxx;
-      const auto __osz = __cont.size();
-      const auto __end = __cont.end();
-      auto __removed(std::__remove_if(std::__niter_base(__cont.begin()),
-                                     std::__niter_base(__end),
-                                     __ops::__iter_equals_val(__value)));
-      __cont.erase(std::__niter_wrap(__end, __removed), __end);
-      return __osz - __cont.size();
+      const auto __osz = __c.size();
+      const auto __end = __c.end();
+      auto __removed = std::__remove_if(__c.begin(), __end,
+                                       __ops::__iter_equals_val(__value));
+      __c.erase(__removed, __end);
+      return __osz - __c.size();
     }
 _GLIBCXX_END_NAMESPACE_VERSION
 } // namespace std