Bypass the _GLIBCXX_DEBUG additional checks in std::__detail::__erase_node_if used
by all implementations of std::erase_if for node based containers.
libstdc++-v3/ChangeLog:
* include/bits/erase_if.h (__erase_nodes_if): Add _UnsafeContainer template
parameter. Use it to get iterators to work with.
* include/debug/macros.h (__glibcxx_check_erase2): New.
* include/debug/map.h (map<>::erase(_Base_const_iterator)): New.
(map<>::erase(const_iterator)): Use latter.
* include/debug/multimap.h (multimap<>::erase(_Base_const_iterator)): New.
(multimap<>::erase(const_iterator)): Use latter.
* include/debug/multiset.h (multiset<>::erase(_Base_const_iterator)): New.
(multiset<>::erase(const_iterator)): Use latter.
* include/debug/set.h (set<>::erase(_Base_const_iterator)): New.
(set<>::erase(const_iterator)): Use latter.
* include/debug/unordered_map (unordered_map<>::erase(_Base_const_iterator)): New.
(unordered_multimap<>::erase(const_iterator)): New.
* include/debug/unordered_set (unordered_set<>::erase(_Base_const_iterator)): New.
(unordered_multiset<>::erase(const_iterator)): New.
* include/experimental/map (erase_if): Adapt.
* include/experimental/set (erase_if): Adapt.
* include/experimental/unordered_map (erase_if): Adapt.
* include/experimental/unordered_set (erase_if): Adapt.
* include/std/map (erase_if): Adapt.
* include/std/set (erase_if): Adapt.
* include/std/unordered_map (erase_if): Adapt.
* include/std/unordered_set (erase_if): Adapt.
namespace __detail
{
- template<typename _Container, typename _Predicate>
+ template<typename _Container, typename _UnsafeContainer,
+ typename _Predicate>
typename _Container::size_type
- __erase_nodes_if(_Container& __cont, _Predicate __pred)
+ __erase_nodes_if(_Container& __cont, const _UnsafeContainer& __ucont,
+ _Predicate __pred)
{
typename _Container::size_type __num = 0;
- for (auto __iter = __cont.begin(), __last = __cont.end();
+ for (auto __iter = __ucont.begin(), __last = __ucont.end();
__iter != __last;)
{
if (__pred(*__iter))
*/
#define __glibcxx_check_erase(_Position) \
_GLIBCXX_DEBUG_VERIFY(_Position._M_dereferenceable(), \
- _M_message(__gnu_debug::__msg_erase_bad) \
- ._M_sequence(*this, "this") \
+ _M_message(__gnu_debug::__msg_erase_bad) \
+ ._M_sequence(*this, "this") \
._M_iterator(_Position, #_Position)); \
_GLIBCXX_DEBUG_VERIFY(_Position._M_attached_to(this), \
_M_message(__gnu_debug::__msg_erase_different) \
._M_sequence(*this, "this") \
._M_iterator(_Position, #_Position))
+#if __cplusplus >= 201103L
+# define __glibcxx_check_erase2(_CPosition) \
+_GLIBCXX_DEBUG_VERIFY(_CPosition != _M_base().cend(), \
+ _M_message(__gnu_debug::__msg_erase_bad) \
+ ._M_sequence(*this, "this") \
+ ._M_iterator(_CPosition, #_CPosition));
+#endif
+
/** Verify that we can erase the element after the iterator
* _Position. We can erase the element if the _Position iterator is
* before a dereferenceable one and references this sequence.
__glibcxx_check_valid_range(_First,_Last); \
_GLIBCXX_DEBUG_VERIFY(_First._M_attached_to(this), \
_M_message(__gnu_debug::__msg_erase_different) \
- ._M_sequence(*this, "this") \
+ ._M_sequence(*this, "this") \
._M_iterator(_First, #_First) \
._M_iterator(_Last, #_Last))
#define __glibcxx_check_subscript(_N) \
_GLIBCXX_DEBUG_VERIFY(_N < this->size(), \
_M_message(__gnu_debug::__msg_subscript_oob) \
- ._M_sequence(*this, "this") \
+ ._M_sequence(*this, "this") \
._M_integer(_N, #_N) \
._M_integer(this->size(), "size"))
#define __glibcxx_check_bucket_index(_N) \
_GLIBCXX_DEBUG_VERIFY(_N < this->bucket_count(), \
_M_message(__gnu_debug::__msg_bucket_index_oob) \
- ._M_sequence(*this, "this") \
+ ._M_sequence(*this, "this") \
._M_integer(_N, #_N) \
._M_integer(this->bucket_count(), "size"))
// Verify that the container is nonempty
#define __glibcxx_check_nonempty() \
_GLIBCXX_DEBUG_VERIFY(! this->empty(), \
- _M_message(__gnu_debug::__msg_empty) \
- ._M_sequence(*this, "this"))
+ _M_message(__gnu_debug::__msg_empty) \
+ ._M_sequence(*this, "this"))
// Verify that a predicate is irreflexive
#define __glibcxx_check_irreflexive(_First,_Last) \
_GLIBCXX_DEBUG_VERIFY(__gnu_debug::__check_sorted( \
__gnu_debug::__base(_First), \
__gnu_debug::__base(_Last)), \
- _M_message(__gnu_debug::__msg_unsorted) \
- ._M_iterator(_First, #_First) \
+ _M_message(__gnu_debug::__msg_unsorted) \
+ ._M_iterator(_First, #_First) \
._M_iterator(_Last, #_Last))
/** Verify that the iterator range [_First, _Last) is sorted by the
__gnu_debug::__base(_First), \
__gnu_debug::__base(_Last), _Pred), \
_M_message(__gnu_debug::__msg_unsorted_pred) \
- ._M_iterator(_First, #_First) \
+ ._M_iterator(_First, #_First) \
._M_iterator(_Last, #_Last) \
._M_string(#_Pred))
// Special variant for std::merge, std::includes, std::set_*
#define __glibcxx_check_sorted_set(_First1,_Last1,_First2) \
__glibcxx_check_valid_range(_First1,_Last1); \
-_GLIBCXX_DEBUG_VERIFY( \
+_GLIBCXX_DEBUG_VERIFY( \
__gnu_debug::__check_sorted_set(__gnu_debug::__base(_First1), \
__gnu_debug::__base(_Last1), _First2),\
_M_message(__gnu_debug::__msg_unsorted) \
// Likewise with a _Pred.
#define __glibcxx_check_sorted_set_pred(_First1,_Last1,_First2,_Pred) \
-__glibcxx_check_valid_range(_First1,_Last1); \
+__glibcxx_check_valid_range(_First1,_Last1); \
_GLIBCXX_DEBUG_VERIFY( \
__gnu_debug::__check_sorted_set(__gnu_debug::__base(_First1), \
__gnu_debug::__base(_Last1), \
._M_iterator(_First, #_First) \
._M_iterator(_Last, #_Last) \
._M_string(#_Pred) \
- ._M_string(#_Value))
+ ._M_string(#_Value))
/** Verify that the iterator range [_First, _Last) is partitioned
w.r.t. the value _Value and predicate _Pred. */
._M_iterator(_First, #_First) \
._M_iterator(_Last, #_Last) \
._M_string(#_Pred) \
- ._M_string(#_Value))
+ ._M_string(#_Value))
// Verify that the iterator range [_First, _Last) is a heap
#define __glibcxx_check_heap(_First,_Last) \
_GLIBCXX_DEBUG_VERIFY(std::__is_heap(__gnu_debug::__base(_First), \
__gnu_debug::__base(_Last)), \
- _M_message(__gnu_debug::__msg_not_heap) \
+ _M_message(__gnu_debug::__msg_not_heap) \
._M_iterator(_First, #_First) \
._M_iterator(_Last, #_Last))
__gnu_debug::__base(_Last), \
_Pred), \
_M_message(__gnu_debug::__msg_not_heap_pred) \
- ._M_iterator(_First, #_First) \
+ ._M_iterator(_First, #_First) \
._M_iterator(_Last, #_Last) \
._M_string(#_Pred))
#define __glibcxx_check_max_load_factor(_F) \
_GLIBCXX_DEBUG_VERIFY(_F > 0.0f, \
_M_message(__gnu_debug::__msg_valid_load_factor) \
- ._M_sequence(*this, "this"))
+ ._M_sequence(*this, "this"))
#define __glibcxx_check_equal_allocs(_This, _Other) \
_GLIBCXX_DEBUG_VERIFY(_This.get_allocator() == _Other.get_allocator(), \
erase(const_iterator __position)
{
__glibcxx_check_erase(__position);
- this->_M_invalidate_if(_Equal(__position.base()));
- return { _Base::erase(__position.base()), this };
+ return { erase(__position.base()), this };
+ }
+
+ _Base_iterator
+ erase(_Base_const_iterator __position)
+ {
+ __glibcxx_check_erase2(__position);
+ this->_M_invalidate_if(_Equal(__position));
+ return _Base::erase(__position);
}
_GLIBCXX_ABI_TAG_CXX11
erase(const_iterator __position)
{
__glibcxx_check_erase(__position);
- this->_M_invalidate_if(_Equal(__position.base()));
- return { _Base::erase(__position.base()), this };
+ return { erase(__position.base()), this };
+ }
+
+ _Base_iterator
+ erase(_Base_const_iterator __position)
+ {
+ __glibcxx_check_erase2(__position);
+ this->_M_invalidate_if(_Equal(__position));
+ return _Base::erase(__position);
}
_GLIBCXX_ABI_TAG_CXX11
erase(const_iterator __position)
{
__glibcxx_check_erase(__position);
- this->_M_invalidate_if(_Equal(__position.base()));
- return { _Base::erase(__position.base()), this };
+ return { erase(__position.base()), this };
+ }
+
+ _Base_iterator
+ erase(_Base_const_iterator __position)
+ {
+ __glibcxx_check_erase2(__position);
+ this->_M_invalidate_if(_Equal(__position));
+ return _Base::erase(__position);
}
#else
void
erase(const_iterator __position)
{
__glibcxx_check_erase(__position);
- this->_M_invalidate_if(_Equal(__position.base()));
- return { _Base::erase(__position.base()), this };
+ return { erase(__position.base()), this };
+ }
+
+ _Base_iterator
+ erase(_Base_const_iterator __position)
+ {
+ __glibcxx_check_erase2(__position);
+ this->_M_invalidate_if(_Equal(__position));
+ return _Base::erase(__position);
}
#else
void
return { _M_erase(__it.base()), this };
}
+ _Base_iterator
+ erase(_Base_const_iterator __it)
+ {
+ __glibcxx_check_erase2(__it);
+ return _M_erase(__it);
+ }
+
iterator
erase(iterator __it)
{
return { _M_erase(__it.base()), this };
}
+ _Base_iterator
+ erase(_Base_const_iterator __it)
+ {
+ __glibcxx_check_erase2(__it);
+ return _M_erase(__it);
+ }
+
iterator
erase(iterator __it)
{
return { _M_erase(__it.base()), this };
}
+ _Base_iterator
+ erase(_Base_const_iterator __it)
+ {
+ __glibcxx_check_erase2(__it);
+ return _M_erase(__it);
+ }
+
iterator
erase(iterator __it)
{
return { _M_erase(__it.base()), this };
}
+ _Base_iterator
+ erase(_Base_const_iterator __it)
+ {
+ __glibcxx_check_erase2(__it);
+ return _M_erase(__it);
+ }
+
iterator
erase(iterator __it)
{
typename _Predicate>
inline void
erase_if(map<_Key, _Tp, _Compare, _Alloc>& __cont, _Predicate __pred)
- { std::__detail::__erase_nodes_if(__cont, __pred); }
+ {
+ const _GLIBCXX_STD_C::map<_Key, _Tp, _Compare, _Alloc>&
+ __ucont = __cont;
+ std::__detail::__erase_nodes_if(__cont, __ucont, __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); }
+ {
+ const _GLIBCXX_STD_C::multimap<_Key, _Tp, _Compare, _Alloc>&
+ __ucont = __cont;
+ std::__detail::__erase_nodes_if(__cont, __ucont, __pred);
+ }
namespace pmr {
template<typename _Key, typename _Tp, typename _Compare = less<_Key>>
typename _Predicate>
inline void
erase_if(set<_Key, _Compare, _Alloc>& __cont, _Predicate __pred)
- { std::__detail::__erase_nodes_if(__cont, __pred); }
+ {
+ const _GLIBCXX_STD_C::set<_Key, _Compare, _Alloc>& __ucont = __cont;
+ std::__detail::__erase_nodes_if(__cont, __ucont, __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); }
+ {
+ const _GLIBCXX_STD_C::multiset<_Key, _Compare, _Alloc>& __ucont = __cont;
+ std::__detail::__erase_nodes_if(__cont, __ucont, __pred);
+ }
namespace pmr {
template<typename _Key, typename _Compare = less<_Key>>
inline void
erase_if(unordered_map<_Key, _Tp, _Hash, _CPred, _Alloc>& __cont,
_Predicate __pred)
- { std::__detail::__erase_nodes_if(__cont, __pred); }
+ {
+ const _GLIBCXX_STD_C::unordered_map<_Key, _Tp, _Hash, _CPred, _Alloc>&
+ __ucont = __cont;
+ std::__detail::__erase_nodes_if(__cont, __ucont, __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); }
+ {
+ const _GLIBCXX_STD_C::unordered_multimap<_Key, _Tp, _Hash, _CPred, _Alloc>&
+ __ucont = __cont;
+ std::__detail::__erase_nodes_if(__cont, __ucont, __pred);
+ }
namespace pmr {
template<typename _Key, typename _Tp, typename _Hash = hash<_Key>,
inline void
erase_if(unordered_set<_Key, _Hash, _CPred, _Alloc>& __cont,
_Predicate __pred)
- { std::__detail::__erase_nodes_if(__cont, __pred); }
+ {
+ const _GLIBCXX_STD_C::unordered_set<_Key, _Hash, _CPred, _Alloc>&
+ __ucont = __cont;
+ std::__detail::__erase_nodes_if(__cont, __ucont, __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); }
+ {
+ const _GLIBCXX_STD_C::unordered_multiset<_Key, _Hash, _CPred, _Alloc>&
+ __ucont = __cont;
+ std::__detail::__erase_nodes_if(__cont, __ucont, __pred);
+ }
namespace pmr {
template<typename _Key, typename _Hash = hash<_Key>,
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); }
+ {
+ const _GLIBCXX_STD_C::map<_Key, _Tp, _Compare, _Alloc>&
+ __ucont = __cont;
+ return __detail::__erase_nodes_if(__cont, __ucont, __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); }
+ {
+ const _GLIBCXX_STD_C::multimap<_Key, _Tp, _Compare, _Alloc>&
+ __ucont = __cont;
+ return __detail::__erase_nodes_if(__cont, __ucont, __pred);
+ }
_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
#endif // C++20
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); }
+ {
+ const _GLIBCXX_STD_C::set<_Key, _Compare, _Alloc>& __ucont = __cont;
+ return __detail::__erase_nodes_if(__cont, __ucont, __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); }
+ {
+ const _GLIBCXX_STD_C::multiset<_Key, _Compare, _Alloc>& __ucont = __cont;
+ return __detail::__erase_nodes_if(__cont, __ucont, __pred);
+ }
_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
#endif // C++20
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); }
+ {
+ const _GLIBCXX_STD_C::unordered_map<_Key, _Tp, _Hash, _CPred, _Alloc>&
+ __ucont = __cont;
+ return __detail::__erase_nodes_if(__cont, __ucont, __pred);
+ }
template<typename _Key, typename _Tp, typename _Hash, typename _CPred,
typename _Alloc, typename _Predicate>
size_type
erase_if(unordered_multimap<_Key, _Tp, _Hash, _CPred, _Alloc>& __cont,
_Predicate __pred)
- { return __detail::__erase_nodes_if(__cont, __pred); }
+ {
+ const _GLIBCXX_STD_C::unordered_multimap<_Key, _Tp, _Hash, _CPred, _Alloc>&
+ __ucont = __cont;
+ return __detail::__erase_nodes_if(__cont, __ucont, __pred);
+ }
_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
#endif // C++20
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); }
+ {
+ const _GLIBCXX_STD_C::unordered_set<_Key, _Hash, _CPred, _Alloc>&
+ __ucont = __cont;
+ return __detail::__erase_nodes_if(__cont, __ucont, __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); }
+ {
+ const _GLIBCXX_STD_C::unordered_multiset<_Key, _Hash, _CPred, _Alloc>&
+ __ucont = __cont;
+ return __detail::__erase_nodes_if(__cont, __ucont, __pred);
+ }
_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
#endif // C++20