aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonathan Wakely <jwakely@redhat.com>2021-10-07 14:40:26 +0100
committerJonathan Wakely <jwakely@redhat.com>2021-10-07 17:52:04 +0100
commit561078480ffb5adb68577276c6b23e4ee7b39272 (patch)
tree0b8d2e4bfc2da06b79c03be3e05a28e01dac546e
parent5c1838c01652a403498e27024cb0e5ea66376353 (diff)
downloadgcc-561078480ffb5adb68577276c6b23e4ee7b39272.zip
gcc-561078480ffb5adb68577276c6b23e4ee7b39272.tar.gz
gcc-561078480ffb5adb68577276c6b23e4ee7b39272.tar.bz2
libstdc++: Avoid debug checks in uniform container erasure functions
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.
-rw-r--r--libstdc++-v3/include/bits/erase_if.h3
-rw-r--r--libstdc++-v3/include/experimental/deque8
-rw-r--r--libstdc++-v3/include/experimental/map10
-rw-r--r--libstdc++-v3/include/experimental/set10
-rw-r--r--libstdc++-v3/include/experimental/unordered_map12
-rw-r--r--libstdc++-v3/include/experimental/unordered_set11
-rw-r--r--libstdc++-v3/include/experimental/vector8
-rw-r--r--libstdc++-v3/include/std/deque28
-rw-r--r--libstdc++-v3/include/std/map10
-rw-r--r--libstdc++-v3/include/std/set10
-rw-r--r--libstdc++-v3/include/std/string18
-rw-r--r--libstdc++-v3/include/std/unordered_map12
-rw-r--r--libstdc++-v3/include/std/unordered_set11
-rw-r--r--libstdc++-v3/include/std/vector26
14 files changed, 114 insertions, 63 deletions
diff --git a/libstdc++-v3/include/bits/erase_if.h b/libstdc++-v3/include/bits/erase_if.h
index 7716e1a..8d1d231 100644
--- a/libstdc++-v3/include/bits/erase_if.h
+++ b/libstdc++-v3/include/bits/erase_if.h
@@ -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))
diff --git a/libstdc++-v3/include/experimental/deque b/libstdc++-v3/include/experimental/deque
index a76fb65..710833e 100644
--- a/libstdc++-v3/include/experimental/deque
+++ b/libstdc++-v3/include/experimental/deque
@@ -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 {
diff --git a/libstdc++-v3/include/experimental/map b/libstdc++-v3/include/experimental/map
index 0c0f422..ef69fad 100644
--- a/libstdc++-v3/include/experimental/map
+++ b/libstdc++-v3/include/experimental/map
@@ -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>>
diff --git a/libstdc++-v3/include/experimental/set b/libstdc++-v3/include/experimental/set
index c3f5433..7a5986a 100644
--- a/libstdc++-v3/include/experimental/set
+++ b/libstdc++-v3/include/experimental/set
@@ -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>>
diff --git a/libstdc++-v3/include/experimental/unordered_map b/libstdc++-v3/include/experimental/unordered_map
index 0b915ab..eba9897 100644
--- a/libstdc++-v3/include/experimental/unordered_map
+++ b/libstdc++-v3/include/experimental/unordered_map
@@ -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>,
diff --git a/libstdc++-v3/include/experimental/unordered_set b/libstdc++-v3/include/experimental/unordered_set
index 87db446..bc5cc11 100644
--- a/libstdc++-v3/include/experimental/unordered_set
+++ b/libstdc++-v3/include/experimental/unordered_set
@@ -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>,
diff --git a/libstdc++-v3/include/experimental/vector b/libstdc++-v3/include/experimental/vector
index a14aedf..c45a500 100644
--- a/libstdc++-v3/include/experimental/vector
+++ b/libstdc++-v3/include/experimental/vector
@@ -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 {
diff --git a/libstdc++-v3/include/std/deque b/libstdc++-v3/include/std/deque
index b2a7cee..71993e7 100644
--- a/libstdc++-v3/include/std/deque
+++ b/libstdc++-v3/include/std/deque
@@ -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
diff --git a/libstdc++-v3/include/std/map b/libstdc++-v3/include/std/map
index 44bd44b..2926558 100644
--- a/libstdc++-v3/include/std/map
+++ b/libstdc++-v3/include/std/map
@@ -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
diff --git a/libstdc++-v3/include/std/set b/libstdc++-v3/include/std/set
index f1e1864..24e6e63 100644
--- a/libstdc++-v3/include/std/set
+++ b/libstdc++-v3/include/std/set
@@ -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
diff --git a/libstdc++-v3/include/std/string b/libstdc++-v3/include/std/string
index 7f99414..95412b6 100644
--- a/libstdc++-v3/include/std/string
+++ b/libstdc++-v3/include/std/string
@@ -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
diff --git a/libstdc++-v3/include/std/unordered_map b/libstdc++-v3/include/std/unordered_map
index e671506..774c21f 100644
--- a/libstdc++-v3/include/std/unordered_map
+++ b/libstdc++-v3/include/std/unordered_map
@@ -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
diff --git a/libstdc++-v3/include/std/unordered_set b/libstdc++-v3/include/std/unordered_set
index 1ad93d0..3859eea 100644
--- a/libstdc++-v3/include/std/unordered_set
+++ b/libstdc++-v3/include/std/unordered_set
@@ -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
diff --git a/libstdc++-v3/include/std/vector b/libstdc++-v3/include/std/vector
index 3b275e2..835fa8a 100644
--- a/libstdc++-v3/include/std/vector
+++ b/libstdc++-v3/include/std/vector
@@ -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