https://gcc.gnu.org/g:e84da9c1d45cb13de9727d7e1efc3c1997dde88d
commit r16-7701-ge84da9c1d45cb13de9727d7e1efc3c1997dde88d Author: Nathan Myers <[email protected]> Date: Fri Feb 6 16:57:07 2026 -0500 libstdc++: debug impls for heterogeneous erasure overloads (P2077) [PR117404] Implement the debug versions of new overloads from P2077. libstdc++-v3/ChangeLog: PR libstdc++/117404 * include/debug/map.h (extract, erase): Define overloads. * include/debug/multimap.h: Same. * include/debug/multiset.h: Same. * include/debug/set.h: Same. * include/debug/unordered_map: Same (2x). * include/debug/unordered_set: Same (2x), rename some locals. Diff: --- libstdc++-v3/include/debug/map.h | 32 ++++++++++++++++ libstdc++-v3/include/debug/multimap.h | 29 +++++++++++++++ libstdc++-v3/include/debug/multiset.h | 29 +++++++++++++++ libstdc++-v3/include/debug/set.h | 32 ++++++++++++++++ libstdc++-v3/include/debug/unordered_map | 53 +++++++++++++++++++++++++++ libstdc++-v3/include/debug/unordered_set | 63 +++++++++++++++++++++++++++++--- 6 files changed, 232 insertions(+), 6 deletions(-) diff --git a/libstdc++-v3/include/debug/map.h b/libstdc++-v3/include/debug/map.h index 0fc7afae385b..47d1fe6b3efe 100644 --- a/libstdc++-v3/include/debug/map.h +++ b/libstdc++-v3/include/debug/map.h @@ -476,6 +476,18 @@ namespace __debug return {}; } +# ifdef __glibcxx_associative_heterogeneous_erasure + template <__heterogeneous_tree_key<map> _Kt> + node_type + extract(_Kt&& __key) + { + const auto __position = find(__key); + if (__position != end()) + return extract(__position); + return {}; + } +# endif + insert_return_type insert(node_type&& __nh) { @@ -538,6 +550,26 @@ namespace __debug } } +# ifdef __glibcxx_associative_heterogeneous_erasure + // Note that for some types _Kt this may erase more than + // one element, such as if _Kt::operator< checks only part + // of the key. + template <__heterogeneous_tree_key<map> _Kt> + size_type + erase(_Kt&& __x) + { + auto __victims = _Base::equal_range(__x); + size_type __count = 0; + for (auto __victim = __victims.first; __victim != __victims.second;) + { + this->_M_invalidate_if(_Equal(__victim)); + _Base::erase(__victim++); + ++__count; + } + return __count; + } +# endif + #if __cplusplus >= 201103L iterator erase(const_iterator __first, const_iterator __last) diff --git a/libstdc++-v3/include/debug/multimap.h b/libstdc++-v3/include/debug/multimap.h index 4137186c5278..4b2591fdcfac 100644 --- a/libstdc++-v3/include/debug/multimap.h +++ b/libstdc++-v3/include/debug/multimap.h @@ -360,6 +360,18 @@ namespace __debug return {}; } +# ifdef __glibcxx_associative_heterogeneous_erasure + template <__heterogeneous_tree_key<multimap> _Kt> + node_type + extract(_Kt&& __key) + { + const auto __position = find(__key); + if (__position != end()) + return extract(__position); + return {}; + } +# endif + iterator insert(node_type&& __nh) { return { _Base::insert(std::move(__nh)), this }; } @@ -420,6 +432,23 @@ namespace __debug return __count; } +# ifdef __glibcxx_associative_heterogeneous_erasure + template <__heterogeneous_tree_key<multimap> _Kt> + size_type + erase(_Kt&& __x) + { + auto __victims = _Base::equal_range(__x); + size_type __count = 0; + for (auto __victim = __victims.first; __victim != __victims.second;) + { + this->_M_invalidate_if(_Equal(__victim)); + _Base::erase(__victim++); + ++__count; + } + return __count; + } +# endif + #if __cplusplus >= 201103L iterator erase(const_iterator __first, const_iterator __last) diff --git a/libstdc++-v3/include/debug/multiset.h b/libstdc++-v3/include/debug/multiset.h index 6fa499228f5e..2b70dcd8b1f4 100644 --- a/libstdc++-v3/include/debug/multiset.h +++ b/libstdc++-v3/include/debug/multiset.h @@ -331,6 +331,18 @@ namespace __debug return {}; } +# ifdef __glibcxx_associative_heterogeneous_erasure + template <__heterogeneous_tree_key<multiset> _Kt> + node_type + extract(_Kt&& __key) + { + const auto __position = find(__key); + if (__position != end()) + return extract(__position); + return {}; + } +#endif + iterator insert(node_type&& __nh) { return { _Base::insert(std::move(__nh)), this }; } @@ -387,6 +399,23 @@ namespace __debug return __count; } +# ifdef __glibcxx_associative_heterogeneous_erasure + template <__heterogeneous_tree_key<multiset> _Kt> + size_type + erase(_Kt&& __x) + { + auto __victims = _Base::equal_range(__x); + size_type __count = 0; + for (auto __victim = __victims.first; __victim != __victims.second;) + { + this->_M_invalidate_if(_Equal(__victim)); + _Base::erase(__victim++); + ++__count; + } + return __count; + } +# endif + #if __cplusplus >= 201103L _GLIBCXX_ABI_TAG_CXX11 iterator diff --git a/libstdc++-v3/include/debug/set.h b/libstdc++-v3/include/debug/set.h index 99701d4a6d7e..81c2fa6e739f 100644 --- a/libstdc++-v3/include/debug/set.h +++ b/libstdc++-v3/include/debug/set.h @@ -340,6 +340,18 @@ namespace __debug return {}; } +# ifdef __glibcxx_associative_heterogeneous_erasure + template <__heterogeneous_tree_key<set> _Kt> + node_type + extract(_Kt&& __key) + { + const auto __position = find(__key); + if (__position != end()) + return extract(__position); + return {}; + } +#endif + insert_return_type insert(node_type&& __nh) { @@ -398,6 +410,26 @@ namespace __debug } } +# ifdef __glibcxx_associative_heterogeneous_erasure + // Note that for some types _Kt this may erase more than + // one element, such as if _Kt::operator< checks only part + // of the key. + template <__heterogeneous_tree_key<set> _Kt> + size_type + erase(_Kt&& __x) + { + auto __victims = _Base::equal_range(__x); + size_type __count = 0; + for (auto __victim = __victims.first; __victim != __victims.second;) + { + this->_M_invalidate_if(_Equal(__victim)); + _Base::erase(__victim++); + ++__count; + } + return __count; + } +#endif + #if __cplusplus >= 201103L _GLIBCXX_ABI_TAG_CXX11 iterator diff --git a/libstdc++-v3/include/debug/unordered_map b/libstdc++-v3/include/debug/unordered_map index 4bde18c917b2..1ea480a4e8ba 100644 --- a/libstdc++-v3/include/debug/unordered_map +++ b/libstdc++-v3/include/debug/unordered_map @@ -581,6 +581,18 @@ namespace __debug return {}; } +# ifdef __glibcxx_associative_heterogeneous_erasure + template <__heterogeneous_hash_key<unordered_map> _Kt> + node_type + extract(_Kt&& __key) + { + const auto __position = _Base::find(__key); + if (__position != _Base::end()) + return _M_extract(__position); + return {}; + } +#endif + insert_return_type insert(node_type&& __nh) { @@ -713,6 +725,18 @@ namespace __debug return __ret; } +# ifdef __glibcxx_associative_heterogeneous_erasure + template <__heterogeneous_hash_key<unordered_map> _Kt> + size_type + erase(_Kt&& __key) + { + auto __victim = _Base::find(__key); + if (__victim != _Base::end()) + return _M_erase(__victim), 1; + return 0; + } +#endif + iterator erase(const_iterator __it) { @@ -1381,6 +1405,18 @@ namespace __debug return {}; } +# ifdef __glibcxx_associative_heterogeneous_erasure + template <__heterogeneous_hash_key<unordered_multimap> _Kt> + node_type + extract(_Kt&& __key) + { + const auto __position = _Base::find(__key); + if (__position != _Base::end()) + return _M_extract(__position); + return {}; + } +#endif + iterator insert(node_type&& __nh) { return { _Base::insert(std::move(__nh)), this }; } @@ -1510,6 +1546,23 @@ namespace __debug return __ret; } +# ifdef __glibcxx_associative_heterogeneous_erasure + template <__heterogeneous_hash_key<unordered_multimap> _Kt> + size_type + erase(_Kt&& __key) + { + size_type __count(0); + auto __victims = _Base::equal_range(__key); + for (auto __victim = __victims.first; __victim != __victims.second;) + { + _M_invalidate(__victim); + __victim = _Base::erase(__victim); + ++__count; + } + return __count; + } +#endif + iterator erase(const_iterator __it) { diff --git a/libstdc++-v3/include/debug/unordered_set b/libstdc++-v3/include/debug/unordered_set index de999a76890e..e26b52d70299 100644 --- a/libstdc++-v3/include/debug/unordered_set +++ b/libstdc++-v3/include/debug/unordered_set @@ -468,6 +468,18 @@ namespace __debug return {}; } +# ifdef __glibcxx_associative_heterogeneous_erasure + template <__heterogeneous_hash_key<unordered_set> _Kt> + node_type + extract(_Kt&& __key) + { + const auto __position = _Base::find(__key); + if (__position != _Base::end()) + return _M_extract(__position); + return {}; + } +#endif + insert_return_type insert(node_type&& __nh) { @@ -598,6 +610,18 @@ namespace __debug return __ret; } +# ifdef __glibcxx_associative_heterogeneous_erasure + template <__heterogeneous_hash_key<unordered_set> _Kt> + size_type + erase(_Kt&& __key) + { + auto __victim = _Base::find(__key); + if (__victim != _Base::end()) + return _M_erase(__victim), 1; + return 0; + } +#endif + iterator erase(const_iterator __it) { @@ -1202,6 +1226,17 @@ namespace __debug return {}; } +# ifdef __glibcxx_associative_heterogeneous_erasure + template <__heterogeneous_hash_key<unordered_multiset> _Kt> + node_type + extract(const _Kt& __key) + { + const auto __position = _Base::find(__key); + return __position != _Base::end() ? + _M_extract(__position) : node_type{}; + } +#endif + iterator insert(node_type&& __nh) { return { _Base::insert(std::move(__nh)), this }; } @@ -1318,18 +1353,34 @@ namespace __debug size_type erase(const key_type& __key) { - size_type __ret(0); - auto __pair = _Base::equal_range(__key); - for (auto __victim = __pair.first; __victim != __pair.second;) + size_type __count(0); + auto __victims = _Base::equal_range(__key); + for (auto __victim = __victims.first; __victim != __victims.second;) { _M_invalidate(__victim); __victim = _Base::erase(__victim); - ++__ret; + ++__count; } - - return __ret; + return __count; } +# ifdef __glibcxx_associative_heterogeneous_erasure + template <__heterogeneous_hash_key<unordered_multiset> _Kt> + size_type + erase(_Kt&& __key) + { + size_type __count(0); + auto __victims = _Base::equal_range(__key); + for (auto __victim = __victims.first; __victim != __victims.second;) + { + _M_invalidate(__victim); + __victim = _Base::erase(__victim); + ++__count; + } + return __count; + } +#endif + iterator erase(const_iterator __it) {
