[PATCHv3] libstdc++: container erasure overloads (P2077) [PR117404]

Jonathan Wakely jwakely@redhat.com
Mon Jan 26 15:56:30 GMT 2026


On Fri, 23 Jan 2026 at 20:05 -0500, Nathan Myers wrote:
>Thank you.
>
>On 1/23/26 12:48 PM, Jonathan Wakely wrote:
>>On Thu, 11 Dec 2025 at 13:19 -0500, Nathan Myers wrote:
>>>...
>>>libstdc++-v3/ChangeLog:
>>>    PR libstdc++/117404
>>>    * include/bits/version.def: Add feature macro
>>>    __cpplib_heterogeneous_erasure.
>>
>>Please name the thing being added using the usual ChangeLog format
>>described at https://www.gnu.org/prep/standards/html_node/Style-of- 
>>Change-Logs.html
>>
>>     * filename (name_of_thing): Define.
>>
>>But also __cpplib_heterogeneous_erasure isn't the right name.
>>
>>So:
>>
>>     * include/bits/version.def (associative_heterogeneous_erasure):
>>     Define.
>
>OK.
>
>>>    * include/bits/version.h: Regenerate.
>>>    * include/std/map: Request new feature from version.h.
>>>    * include/std/set: Same.
>>>    * include/std/unordered_map: Same.
>>>    * include/std/unordered_set: Same.
>>>    * include/bits/stl_map.h: Add specified new overloads.
>>
>>This should say which overloads.
>
>OK.
>
>>>    * include/bits/stl_set.h: Same.
>>>    * include/bits/stl_multimap.h: Same.
>>>    * include/bits/stl_multiset.h: Same.
>>>    * include/bits/unordered_map.h: Same.
>>>    * include/bits/unordered_set.h: Same.
>>>    * include/bits/hashtable.h: Add supporting overloads, new concept
>>>    __heterogeneous_hash_key.
>>
>>Ditto, and then add:
>>
>>     (__heterogeneous_hash_key): New concept.
>
>OK
>
>>>    * include/bits/stl_tree.h: Add supporting overloads, new concept
>>>    __heterogeneous_tree_key.
>>>    * include/bits/stl_function.h: Add concepts 
>>>__not_container_iterator and
>>>    __heterogeneous_key.
>>>    * testsuite/23_containers/map/modifiers/hetero/erase.cc: New test.
>>>    * testsuite/23_containers/multimap/modifiers/hetero/erase.cc: Same.
>>>    * testsuite/23_containers/multiset/modifiers/hetero/erase.cc: Same.
>>>    * testsuite/23_containers/set/modifiers/hetero/erase.cc: Same.
>>>    * 
>>>testsuite/23_containers/unordered_map/modifiers/hetero/erase.cc: 
>>>Same.
>>>    * testsuite/23_containers/unordered_multimap/modifiers/hetero/ 
>>>erase.cc:
>>>    Same.
>>>    * testsuite/23_containers/unordered_multiset/modifiers/hetero/ 
>>>erase.cc:
>>>    Same.
>>>    * 
>>>testsuite/23_containers/unordered_set/modifiers/hetero/erase.cc: 
>>>Same.
>>>---
>>>libstdc++-v3/include/bits/hashtable.h         | 182 +++++++++++++++---
>>>libstdc++-v3/include/bits/stl_function.h      |  12 ++
>>>libstdc++-v3/include/bits/stl_map.h           |  20 ++
>>>libstdc++-v3/include/bits/stl_multimap.h      |  15 ++
>>>libstdc++-v3/include/bits/stl_multiset.h      |  15 ++
>>>libstdc++-v3/include/bits/stl_set.h           |  18 ++
>>>libstdc++-v3/include/bits/stl_tree.h          |  96 ++++++++-
>>>libstdc++-v3/include/bits/unordered_map.h     |  28 +++
>>>libstdc++-v3/include/bits/unordered_set.h     |  28 +++
>>>libstdc++-v3/include/bits/version.def         |   8 +
>>>libstdc++-v3/include/bits/version.h           |  12 +-
>>>libstdc++-v3/include/std/map                  |  22 +--
>>>libstdc++-v3/include/std/set                  |  19 +-
>>>libstdc++-v3/include/std/unordered_map        |  19 +-
>>>libstdc++-v3/include/std/unordered_set        |  17 +-
>>>.../map/modifiers/hetero/erase.cc             |  95 +++++++++
>>>.../multimap/modifiers/hetero/erase.cc        |  95 +++++++++
>>>.../multiset/modifiers/hetero/erase.cc        |  88 +++++++++
>>>.../set/modifiers/hetero/erase.cc             |  88 +++++++++
>>>.../unordered_map/modifiers/hetero/erase.cc   |  76 ++++++++
>>>.../modifiers/hetero/erase.cc                 |  75 ++++++++
>>>.../modifiers/hetero/erase.cc                 |  73 +++++++
>>>.../unordered_set/modifiers/hetero/erase.cc   |  73 +++++++
>>>23 files changed, 1102 insertions(+), 72 deletions(-)
>>>create mode 100644 
>>>libstdc++-v3/testsuite/23_containers/map/modifiers/ 
>>>hetero/erase.cc
>>>create mode 100644 libstdc++-v3/testsuite/23_containers/multimap/ 
>>>modifiers/hetero/erase.cc
>>>create mode 100644 libstdc++-v3/testsuite/23_containers/multiset/ 
>>>modifiers/hetero/erase.cc
>>>create mode 100644 
>>>libstdc++-v3/testsuite/23_containers/set/modifiers/ 
>>>hetero/erase.cc
>>>create mode 100644 
>>>libstdc++-v3/testsuite/23_containers/unordered_map/ 
>>>modifiers/hetero/erase.cc
>>>create mode 100644 libstdc++-v3/testsuite/23_containers/ 
>>>unordered_multimap/modifiers/hetero/erase.cc
>>>create mode 100644 libstdc++-v3/testsuite/23_containers/ 
>>>unordered_multiset/modifiers/hetero/erase.cc
>>>create mode 100644 
>>>libstdc++-v3/testsuite/23_containers/unordered_set/ 
>>>modifiers/hetero/erase.cc
>>>
>>>diff --git a/libstdc++-v3/include/bits/hashtable.h b/libstdc++-v3/ 
>>>include/bits/hashtable.h
>>>index 06cc51ac4a0..bd5c9dc64e5 100644
>>>--- a/libstdc++-v3/include/bits/hashtable.h
>>>+++ b/libstdc++-v3/include/bits/hashtable.h
>>>@@ -905,6 +905,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>>>      __location_type
>>>      _M_locate(const key_type& __k) const;
>>>
>>>+      // We would like to extend _M_locate for heterogeneous
>>>+      // keys, and use try_emplace as is, but ABI forbids it.
>>
>>Why? Because of explicit instantiations, or something else?
>
>Guessing that CUs built before this may have it as a global symbol
>reference. If not, I am happy to remove it.

But everything here is a template, so every object file contains
implicit instantiations of all the member functions it uses.

>>>+      template <typename _HetKey>
>>
>>We use _Kt everywhere else for heterogeneous key parameters. The fact
>>it's a template parameter (rather than just using _Key or key_type)
>>already implies it's a heterogeneous key type.
>
>OK.
>
>>>+    __location_type
>>>+    _M_locate_tr(const _HetKey& __k) const;
>>
>>Should this be guarded by __glibcxx_associative_heterogeneous_erasure ?
>>Patch v2 called _M_locate_tr from pre-C++23 code, but v3 doesn't seem
>>to.
>
>P2363 updates various existing members to use _M_locate_tr with
>the regular key, in an effort to minimize code duplication.

OK, that makes sense.

>>>+
>>>      __node_ptr
>>>      _M_find_node(size_type __bkt, const key_type& __key,
>>>           __hash_code __c) const
>>>@@ -1016,6 +1022,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>>>      iterator
>>>      _M_erase(size_type __bkt, __node_base_ptr __prev_n, 
>>>__node_ptr __n);
>>>
>>>+      size_type
>>>+      _M_erase_some(size_type __bkt, __node_base_ptr __prev_n, 
>>>__node_ptr __n);
>>>+
>>>      template<typename _InputIterator>
>>>    void
>>>    _M_insert_range_multi(_InputIterator __first, _InputIterator __last);
>>>@@ -1163,6 +1172,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>>>      size_type
>>>      erase(const key_type& __k);
>>>
>>>+#if __glibcxx_associative_heterogeneous_erasure // C++23, P2077
>>
>>We don't put the paper number on these feature test checks anywhere
>>else in our headers.
>
>OK, removing.
>
>>>+      template <typename _HetKey>
>>>+    size_type
>>>+    _M_erase_tr(const _HetKey& __k);
>>>+#endif
>>>...
>>> +#if __glibcxx_associative_heterogeneous_erasure // C++23, P2077>> 
>+  template<typename _Key, typename _Value, typename _Alloc,
>>>+       typename _ExtractKey, typename _Equal,
>>>+       typename _Hash, typename _RangeHash, typename _Unused,
>>>+       typename _RehashPolicy, typename _Traits>
>>>+    template <typename _HetKey>
>>>+      auto
>>>+      _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
>>>+         _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
>>>+      _M_erase_tr(const _HetKey& __k)
>>>+    -> size_type
>>>+      {
>>>+    auto __loc = _M_locate_tr(__k);
>>>+    if (!__loc)
>>>+      return 0;
>>>+
>>>+    __node_base_ptr __prev_n = __loc._M_before;
>>>+    __node_ptr __n = __loc._M_node();
>>>+    auto __bkt = __loc._M_bucket_index;
>>>+    if (__bkt == size_type(-1))
>>>+      __bkt = _M_bucket_index(*__n);
>>>+    if constexpr (__unique_keys::value)
>>>+      {
>>>+        _M_erase(__bkt, __prev_n, __n);
>>>+        return 1;
>>>+      }
>>>+    else
>>>+      return _M_erase_some(__bkt, __prev_n, __n);
>>>+      }
>>>+#endif // P2207
>>
>>This should definitely not be the paper number here, but the macro
>>name (omitting the prefix if you want to keep it brief):
>>
>># endif // associative_heterogeneous_erasure
>
>OK.
>
>>>+
>>>#pragma GCC diagnostic pop
>>>
>>>  template<typename _Key, typename _Value, typename _Alloc,
>>>@@ -2977,6 +3087,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>>>      = __enable_if_t<!__or_<is_integral<_Hash>, 
>>>__is_allocator<_Hash>>::value>;
>>>#endif
>>>
>>>+#if __glibcxx_associative_heterogeneous_erasure // C++23, P2077
>>>+template <typename _Kt, typename _Container>
>>>+  concept __heterogeneous_hash_key =
>>>+    __transparent_comparator<typename _Container::hasher> &&
>>>+    __transparent_comparator<typename _Container::key_equal> &&
>>>+    __heterogeneous_key<_Kt, _Container>;
>>>+#endif
>>>+
>>>/// @endcond
>>>_GLIBCXX_END_NAMESPACE_VERSION
>>>} // namespace std
>>>diff --git a/libstdc++-v3/include/bits/stl_function.h 
>>>b/libstdc++-v3/ include/bits/stl_function.h
>>>index ff3f8f4c6e7..7f99ffe1566 100644
>>>--- a/libstdc++-v3/include/bits/stl_function.h
>>>+++ b/libstdc++-v3/include/bits/stl_function.h
>>>@@ -1486,6 +1486,18 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>>>#endif
>>>#endif
>>>
>>>+#if __glibcxx_associative_heterogeneous_erasure // C++23, P2077
>>>+template <typename _Kt, typename _Container>
>>>+  concept __not_container_iterator =
>>>+    (!is_convertible_v<_Kt&&, typename _Container::iterator> &&
>>>+     !is_convertible_v<_Kt&&, typename _Container::const_iterator>);
>>>+
>>>+template <typename _Kt, typename _Container>
>>>+  concept __heterogeneous_key =
>>>+    (!is_same_v<typename _Container::key_type, remove_cvref_t<_Kt>>) &&
>>>+    __not_container_iterator<_Kt&&, _Container>;
>>
>>Do you need to add the && here when __not_container_iterator
>>explicitly adds it again?
>
>OK.
>
>>>+#endif
>>>+
>>>_GLIBCXX_END_NAMESPACE_VERSION
>>>} // namespace
>>>
>>>diff --git a/libstdc++-v3/include/bits/stl_map.h b/libstdc++-v3/ 
>>>include/bits/stl_map.h
>>>index 62d66cef6b2..686ab792399 100644
>>>--- a/libstdc++-v3/include/bits/stl_map.h
>>>+++ b/libstdc++-v3/include/bits/stl_map.h
>>>@@ -65,6 +65,7 @@
>>>#if __glibcxx_containers_ranges // C++ >= 23
>>># include <bits/ranges_base.h> // ranges::begin, ranges::distance etc.
>>>#endif
>>>+#include <bits/stl_tree.h>
>>
>>If this is included here, it doesn't need to be included in <regex>
>>prior to including stl_map.h.
>
>Is this a suggestion to patch std/regex too?
>Ready to do, if so.

It can be part of a separate patch though.

>>>
>>>+      ///@{
>>>      /**
>>>       *  @brief Erases elements according to the provided key.
>>>       *  @param  __x  Key of element to be erased.
>>>@@ -1158,6 +1167,17 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
>>>      erase(const key_type& __x)
>>>      { return _M_t._M_erase_unique(__x); }
>>>
>>>+#if __glibcxx_associative_heterogeneous_erasure // C++23, P2077
>>>+      // 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)
>>>+    { return _M_t._M_erase_tr(__x); }
>>>+#endif
>>>+      ///@}
>>>+
>>>#if __cplusplus >= 201103L
>>>      // _GLIBCXX_RESOLVE_LIB_DEFECTS
>>>      // DR 130. Associative erase should return an iterator.
>>>diff --git a/libstdc++-v3/include/bits/stl_multimap.h 
>>>b/libstdc++-v3/ include/bits/stl_multimap.h
>>>index b2ae2bae745..7576653c8b9 100644
>>>--- a/libstdc++-v3/include/bits/stl_multimap.h
>>>+++ b/libstdc++-v3/include/bits/stl_multimap.h
>>>@@ -63,6 +63,7 @@
>>>#if __glibcxx_containers_ranges // C++ >= 23
>>># include <bits/ranges_base.h> // ranges::begin, ranges::distance etc.
>>>#endif
>>>+#include <bits/stl_tree.h>
>>
>>Adding this is redundant. stl_multimap.h is included in exactly one
>>file, <map>, and that includes stl_tree.h before it includes stl_map.h
>>and stl_multimap.h
>
>OK.
>
>>Although GCC optimizes includes to avoid reopening the file on disk,
>>we now do #include <bits/stl_tree.h> three times in <set> and three
>>times in <map>.
>>
>>The only reason that a "single use" header like stl_set.h needs to be
>>self-sufficient in terms of "include what you use" is if you are
>>compiling individual bits/*.h headers as header units so they can be
>>imported, which Nathan Sidwell was at one time making changes to
>>support.
>>
>>I have a weak preference for not adding these redundant includes.
>>
>>P.S. oh I see later in the patch that including bits/stl_tree.h is
>>removed from <map> and <set>, so it's only being included twice now,
>>not three times as I said above. So that's less bad.
>
>I will clean up redundant includes.
>
>>>...
>>>--- a/libstdc++-v3/include/bits/stl_tree.h
>>>+++ b/libstdc++-v3/include/bits/stl_tree.h
>>>@@ -1399,8 +1399,8 @@ namespace __rb_tree
>>>#if __cplusplus >= 201103L
>>>      // Enforce this here with a user-friendly message.
>>>      static_assert(
>>>-        __is_invocable<const _Compare&, const _Key&, const 
>>>_Key&>::value,
>>>-        "comparison object must be invocable with two arguments 
>>>of key type"
>>>+        __is_invocable<const _Compare&, const _Key1&, const 
>>>_Key2&>::value,
>>>+        "comparison object must be invocable with key types used"
>>
>>IIRC I made this function a template so the static_assert would only
>>be checked if a comparison was actually performed (so not checked for
>>the default constructor and destructor, for example). But the fact
>>that it tested invocation with _Key not with _Key1 and _Key2 was
>>intentional. The point of this static_assert is to check that _Compare
>>accepts arguments of type const _Key& because those are the template
>>parameters of the whole class.
>>
>>Specifically, it was for diagnosing Gaby's example in
>>https://gcc.gnu.org/PR48101
>>
>>So I'm not sure we need to generalize the assertion for all uses of
>>transparent comparators, but I suppose it doesn't hurt.
>
>Taking this as permission to retain the change...
>Clear error messages in more use cases seems like a benefit.

Agreed, but "with key types used" doesn't seem entirely clear, due to
English ambiguity. It could mean "invocable using arguments of the key
types used in this expression" or it could mean "must be invocable,
and key types must be used"

Is an unambiguous phrasing possible?

>>>      );
>>>#endif
>>>      return _M_impl._M_key_compare(__k1, __k2);
>>>@@ -1539,10 +1539,24 @@ namespace __rb_tree
>>>      _M_lower_bound(_Base_ptr __x, _Base_ptr __y,
>>>             const _Key& __k) const;
>>>
>>>+#if __glibcxx_associative_heterogeneous_erasure // C++23, P2077
>>>+      template <typename _HetKey>
>>
>>Again, we just use _Kt for e.g. _Rb_tree::_M_find_tr
>
>OK.
>
>>>...
>>> diff --git a/libstdc++-v3/include/bits/version.def b/libstdc++-v3/ 
>>> include/bits/version.def
>>>index 04232187965..e3b9627b022 100644
>>>--- a/libstdc++-v3/include/bits/version.def
>>>+++ b/libstdc++-v3/include/bits/version.def
>>>@@ -1589,6 +1589,14 @@ ftms = {
>>>  };
>>>};
>>>
>>>+ftms = {
>>>+  name = associative_heterogeneous_erasure;
>>>+  values = {
>>>+    v = 202110;
>>>+    cxxmin = 23;
>>>+  };
>>>+};
>>>+
>>>ftms = {
>>>  name = is_scoped_enum;
>>>  values = {
>>>diff --git a/libstdc++-v3/include/bits/version.h b/libstdc++-v3/ 
>>>include/bits/version.h
>>>index df7a291b05f..39f5d462550 100644
>>>--- a/libstdc++-v3/include/bits/version.h
>>>+++ b/libstdc++-v3/include/bits/version.h
>>>@@ -1756,6 +1756,16 @@
>>>#endif /* !defined(__cpp_lib_invoke_r) */
>>>#undef __glibcxx_want_invoke_r
>>>
>>>+#if !defined(__cpp_lib_associative_heterogeneous_erasure)
>>>+# if (__cplusplus >= 202100L)
>>>+#  define __glibcxx_associative_heterogeneous_erasure 202110L
>>>+#  if defined(__glibcxx_want_all) || 
>>>defined(__glibcxx_want_associative_heterogeneous_erasure)
>>>+#   define __cpp_lib_associative_heterogeneous_erasure 202110L
>>>+#  endif
>>>+# endif
>>>+#endif /* !defined(__cpp_lib_associative_heterogeneous_erasure) */
>>>+#undef __glibcxx_want_associative_heterogeneous_erasure
>>>+
>>>#if !defined(__cpp_lib_is_scoped_enum)
>>># if (__cplusplus >= 202100L)
>>>#  define __glibcxx_is_scoped_enum 202011L
>>>@@ -2198,7 +2208,7 @@
>>>#   define __cpp_lib_observable_checkpoint 202506L
>>>#  endif
>>># endif
>>>-#endif /* !defined(__cpp_lib_observable_checkpoint) && 
>>>defined(__glibcxx_want_observable_checkpoint) */
>>>+#endif /* !defined(__cpp_lib_observable_checkpoint) */
>>
>>This was already removed in late October. Please be sure to rebase
>>this patch to make sure it applies to current trunk.
>
>OK.
>
>>>#undef __glibcxx_want_observable_checkpoint
>>>
>>>#if !defined(__cpp_lib_algorithm_default_value_type)
>>>diff --git a/libstdc++-v3/include/std/map b/libstdc++-v3/include/std/map
>>>index 6bfb53848ba..efdf915f081 100644
>>>--- a/libstdc++-v3/include/std/map
>>>+++ b/libstdc++-v3/include/std/map
>>>@@ -59,9 +59,19 @@
>>>#pragma GCC system_header
>>>#endif
>>>
>>>+#define __glibcxx_want_allocator_traits_is_always_equal
>>>+#define __glibcxx_want_containers_ranges
>>>+#define __glibcxx_want_erase_if
>>>+#define __glibcxx_want_generic_associative_lookup
>>>+#define __glibcxx_want_map_try_emplace
>>>+#define __glibcxx_want_node_extract
>>>+#define __glibcxx_want_nonmember_container_access
>>>+#define __glibcxx_want_tuple_like
>>>+#define __glibcxx_want_associative_heterogeneous_erasure
>>>+#include <bits/version.h>
>>
>>Is there a reason to move these earlier?
>>
>>The downside of doing this is that the __cpp_lib_xxx forms of the
>>macros are all defined while preprocessing the headers that follow,
>>not *only* for the code that appears directly in *this* header.
>>
>>That's not necessarily a problem, but it makes it easier to
>>accidentally rely on #if __cpp_lib_xxx in other files which should
>>be relying on the #if __glibcxx_xxx form instead.
>
>Not seeing how __glibcxx_... would be defined without the
>__glibcxx_want_... names defined here.


Because that's how version.h works.

Every time you inclkude version.h *all* the __glibcxx_xxx macros are
defined if they match the conditions (i.e. __cplusplus is high enough,
cxx11abi=yes and extra_cond are met if appropriate).

You never need the "want" macros to get the __glibcxx_xxx macros.

The "want" macros are *only* to cause the __cpp_lib_xxx macros to be
defined. That's why we include version.h and check __glibcxx_xxx in
most headers, because those ones are always defined.

And in the public headers like <string> and <vector> we define the
"want" macros and then include version.h, which defines the
__cpp_lib_xxx macros. But that should only be done in the appropriate
public headers, and doesn't need to be before including any bits/foo.h
headers.


>>With the current ordering, the effects of the "want" macros are
>>limited to a smaller scope, just this file and user code that includes
>>it, but not all the other library internals this this file includes.
>>
>>So the current ordering is intentional, not accidental, and this patch
>>doesn't mention any rationale for changing that.
>
>I was having trouble with things I needed not being defined yet.
>I will try to evolve a less intrusive change that works.
>
>>>#include <bits/requires_hosted.h> // containers
>>
>>This one should certainly be first, it just has a #error for
>>non-hosted. We want the "die or continue" header to be first, before
>>we waste time processing any other code.
>
>OK.
>
>>>
>>>-#include <bits/stl_tree.h>
>>>#include <bits/stl_map.h>
>>>#include <bits/stl_multimap.h>
>>>#include <bits/range_access.h>
>>>@@ -71,16 +81,6 @@
>>># include <debug/map>
>>>#endif
>>>
>>>-#define __glibcxx_want_allocator_traits_is_always_equal
>>>-#define __glibcxx_want_containers_ranges
>>>-#define __glibcxx_want_erase_if
>>>-#define __glibcxx_want_generic_associative_lookup
>>>-#define __glibcxx_want_map_try_emplace
>>>-#define __glibcxx_want_node_extract
>>>-#define __glibcxx_want_nonmember_container_access
>>>-#define __glibcxx_want_tuple_like
>>>-#include <bits/version.h>
>>>-
>>>#if __cplusplus >= 201703L
>>>#include <bits/memory_resource.h>
>>>namespace std _GLIBCXX_VISIBILITY(default)
>>>diff --git a/libstdc++-v3/include/std/set b/libstdc++-v3/include/std/set
>>>index cf7057aa6c6..0e6fb3e88c6 100644
>>>--- a/libstdc++-v3/include/std/set
>>>+++ b/libstdc++-v3/include/std/set
>>>@@ -59,9 +59,18 @@
>>>#pragma GCC system_header
>>>#endif
>>>
>>>+#define __glibcxx_want_allocator_traits_is_always_equal
>>>+#define __glibcxx_want_containers_ranges
>>>+#define __glibcxx_want_erase_if
>>>+#define __glibcxx_want_generic_associative_lookup
>>>+#define __glibcxx_want_node_extract
>>>+#define __glibcxx_want_nonmember_container_access
>>>+#define __glibcxx_want_associative_heterogeneous_erasure
>>>+#define __glibcxx_want_associative_heterogeneous_insertion
>>>+#include <bits/version.h>
>>>+
>>>#include <bits/requires_hosted.h> // containers
>>>
>>>-#include <bits/stl_tree.h>
>>>#include <bits/stl_set.h>
>>>#include <bits/stl_multiset.h>
>>>#include <bits/range_access.h>
>>>@@ -71,14 +80,6 @@
>>># include <debug/set>
>>>#endif
>>>
>>>-#define __glibcxx_want_allocator_traits_is_always_equal
>>>-#define __glibcxx_want_containers_ranges
>>>-#define __glibcxx_want_erase_if
>>>-#define __glibcxx_want_generic_associative_lookup
>>>-#define __glibcxx_want_node_extract
>>>-#define __glibcxx_want_nonmember_container_access
>>>-#include <bits/version.h>
>>>-
>>>#if __cplusplus >= 201703L
>>>#include <bits/memory_resource.h>
>>>namespace std _GLIBCXX_VISIBILITY(default)
>>>diff --git a/libstdc++-v3/include/std/unordered_map 
>>>b/libstdc++-v3/ include/std/unordered_map
>>>index 3ae25d758ac..783ead99a4b 100644
>>>--- a/libstdc++-v3/include/std/unordered_map
>>>+++ b/libstdc++-v3/include/std/unordered_map
>>>@@ -39,15 +39,6 @@
>>># include <bits/c++0x_warning.h>
>>>#else
>>>
>>>-#include <initializer_list>
>>>-#include <bits/unordered_map.h>
>>>-#include <bits/range_access.h>
>>>-#include <bits/erase_if.h>
>>>-
>>>-#ifdef _GLIBCXX_DEBUG
>>>-# include <debug/unordered_map>
>>>-#endif
>>>-
>>>#define __glibcxx_want_allocator_traits_is_always_equal
>>>#define __glibcxx_want_containers_ranges
>>>#define __glibcxx_want_erase_if
>>>@@ -56,8 +47,18 @@
>>>#define __glibcxx_want_nonmember_container_access
>>>#define __glibcxx_want_unordered_map_try_emplace
>>>#define __glibcxx_want_tuple_like
>>>+#define __glibcxx_want_associative_heterogeneous_erasure
>>>#include <bits/version.h>
>>>
>>>+#include <initializer_list>
>>>+#include <bits/unordered_map.h>
>>>+#include <bits/range_access.h>
>>>+#include <bits/erase_if.h>
>>>+
>>>+#ifdef _GLIBCXX_DEBUG
>>>+# include <debug/unordered_map>
>>>+#endif
>>>+
>>>#if __cplusplus >= 201703L
>>>#include <bits/memory_resource.h>
>>>namespace std _GLIBCXX_VISIBILITY(default)
>>>diff --git a/libstdc++-v3/include/std/unordered_set 
>>>b/libstdc++-v3/ include/std/unordered_set
>>>index b561163d31d..9dcecb050b0 100644
>>>--- a/libstdc++-v3/include/std/unordered_set
>>>+++ b/libstdc++-v3/include/std/unordered_set
>>>@@ -39,6 +39,15 @@
>>># include <bits/c++0x_warning.h>
>>>#else
>>>
>>>+#define __glibcxx_want_allocator_traits_is_always_equal
>>>+#define __glibcxx_want_containers_ranges
>>>+#define __glibcxx_want_erase_if
>>>+#define __glibcxx_want_generic_unordered_lookup
>>>+#define __glibcxx_want_node_extract
>>>+#define __glibcxx_want_nonmember_container_access
>>>+#define __glibcxx_want_associative_heterogeneous_erasure
>>>+#include <bits/version.h>
>>>+
>>>#include <initializer_list>
>>>#include <bits/unordered_set.h>
>>>#include <bits/range_access.h>
>>>@@ -48,14 +57,6 @@
>>># include <debug/unordered_set>
>>>#endif
>>>
>>>-#define __glibcxx_want_allocator_traits_is_always_equal
>>>-#define __glibcxx_want_containers_ranges
>>>-#define __glibcxx_want_erase_if
>>>-#define __glibcxx_want_generic_unordered_lookup
>>>-#define __glibcxx_want_node_extract
>>>-#define __glibcxx_want_nonmember_container_access
>>>-#include <bits/version.h>
>>>-
>>>#if __cplusplus >= 201703L
>>>#include <bits/memory_resource.h>
>>>namespace std _GLIBCXX_VISIBILITY(default)
>>>diff --git a/libstdc++-v3/testsuite/23_containers/map/modifiers/ 
>>>hetero/erase.cc 
>>>b/libstdc++-v3/testsuite/23_containers/map/modifiers/ 
>>>hetero/erase.cc
>>>new file mode 100644
>>>index 00000000000..711ba05952c
>>>--- /dev/null
>>>+++ b/libstdc++-v3/testsuite/23_containers/map/modifiers/hetero/erase.cc
>>>@@ -0,0 +1,95 @@
>>>+// { dg-do compile { target c++23 } }
>>
>>All these tests use dg-do compile but have main() functions. Those
>>main functions aren't going to run, so you're only testing that the
>>code compiles, not that it runs.
>>
>>Presumably they should be dg-do run.
>
><grimace>
>I was lucky the tests passed when actually run.
>
>I had the same problem in the p2363 patch, with worse effect, fixed
>in v3.

I have a precommit hook to check for main() in dg-do compile tests.



More information about the Libstdc++ mailing list