[PATCHv3] libstdc++: container erasure overloads (P2077) [PR117404]
Nathan Myers
ncm@cantrip.org
Sat Jan 24 01:05:59 GMT 2026
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.
>> + 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.
>> +
>> __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.
>>
>> + ///@{
>> /**
>> * @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.
>> );
>> #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.
> 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.
More information about the Libstdc++
mailing list