{"id":2226899,"url":"http://patchwork.ozlabs.org/api/patches/2226899/?format=json","web_url":"http://patchwork.ozlabs.org/project/gcc/patch/bmm.hhupnyl5bc.gcc.gcc-TEST.fdumont.131.1.1@forge-stage.sourceware.org/","project":{"id":17,"url":"http://patchwork.ozlabs.org/api/projects/17/?format=json","name":"GNU Compiler Collection","link_name":"gcc","list_id":"gcc-patches.gcc.gnu.org","list_email":"gcc-patches@gcc.gnu.org","web_url":null,"scm_url":null,"webscm_url":null,"list_archive_url":"","list_archive_url_format":"","commit_url_format":""},"msgid":"<bmm.hhupnyl5bc.gcc.gcc-TEST.fdumont.131.1.1@forge-stage.sourceware.org>","list_archive_url":null,"date":"2026-04-22T19:08:44","name":"[v1,1/1] libstdc++: Fix std::erase_if behavior for std::__debug containers","commit_ref":null,"pull_url":null,"state":"new","archived":false,"hash":"d7746582e479abab8dace85886b0868943fad601","submitter":{"id":93220,"url":"http://patchwork.ozlabs.org/api/people/93220/?format=json","name":"François Dumont via Sourceware Forge","email":"forge-bot+fdumont@forge-stage.sourceware.org"},"delegate":null,"mbox":"http://patchwork.ozlabs.org/project/gcc/patch/bmm.hhupnyl5bc.gcc.gcc-TEST.fdumont.131.1.1@forge-stage.sourceware.org/mbox/","series":[{"id":501110,"url":"http://patchwork.ozlabs.org/api/series/501110/?format=json","web_url":"http://patchwork.ozlabs.org/project/gcc/list/?series=501110","date":"2026-04-22T19:05:12","name":"libstdc++: Fix std::erase_if behavior for std::__debug::deque","version":1,"mbox":"http://patchwork.ozlabs.org/series/501110/mbox/"}],"comments":"http://patchwork.ozlabs.org/api/patches/2226899/comments/","check":"pending","checks":"http://patchwork.ozlabs.org/api/patches/2226899/checks/","tags":{},"related":[],"headers":{"Return-Path":"<gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org>","X-Original-To":["incoming@patchwork.ozlabs.org","gcc-patches@gcc.gnu.org"],"Delivered-To":["patchwork-incoming@legolas.ozlabs.org","gcc-patches@gcc.gnu.org"],"Authentication-Results":["legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org\n (client-ip=2620:52:6:3111::32; helo=vm01.sourceware.org;\n envelope-from=gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org;\n receiver=patchwork.ozlabs.org)","sourceware.org; dmarc=none (p=none dis=none)\n header.from=forge-stage.sourceware.org","sourceware.org;\n spf=pass smtp.mailfrom=forge-stage.sourceware.org","server2.sourceware.org;\n arc=none smtp.remote-ip=38.145.34.39"],"Received":["from vm01.sourceware.org (vm01.sourceware.org\n [IPv6:2620:52:6:3111::32])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange x25519 server-signature ECDSA (secp384r1) server-digest SHA384)\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4g1C155Nf5z1yGs\n\tfor <incoming@patchwork.ozlabs.org>; Thu, 23 Apr 2026 07:24:57 +1000 (AEST)","from vm01.sourceware.org (localhost [127.0.0.1])\n\tby sourceware.org (Postfix) with ESMTP id E40C446A26C6\n\tfor <incoming@patchwork.ozlabs.org>; Wed, 22 Apr 2026 21:24:55 +0000 (GMT)","from forge-stage.sourceware.org (vm08.sourceware.org [38.145.34.39])\n by sourceware.org (Postfix) with ESMTPS id AE22A42939A7\n for <gcc-patches@gcc.gnu.org>; Wed, 22 Apr 2026 19:09:42 +0000 (GMT)","from forge-stage.sourceware.org (localhost [IPv6:::1])\n (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n key-exchange x25519 server-signature ECDSA (prime256v1) server-digest SHA256)\n (No client certificate requested)\n by forge-stage.sourceware.org (Postfix) with ESMTPS id 88560435DD\n for <gcc-patches@gcc.gnu.org>; Wed, 22 Apr 2026 19:09:42 +0000 (UTC)"],"DKIM-Filter":["OpenDKIM Filter v2.11.0 sourceware.org E40C446A26C6","OpenDKIM Filter v2.11.0 sourceware.org AE22A42939A7"],"DMARC-Filter":"OpenDMARC Filter v1.4.2 sourceware.org AE22A42939A7","ARC-Filter":"OpenARC Filter v1.0.0 sourceware.org AE22A42939A7","ARC-Seal":"i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1776884982; cv=none;\n b=X5atxl2YlshywrvY7fIuA8MJYQxITs4HiQ7yEc9mnv4F2JFy5Tp7FNWSOVGWcagHIAYp4Ix4yDgoLwcSmpnX3zLBEqjSbWN4nb5Xf/kbFB48OPEnXdN8nzeAi5Lbr0Vh/Xpzv7P8YgKd1wIkKjYoYr5NhLMEkq+Y/U8Nm1fQ5t8=","ARC-Message-Signature":"i=1; a=rsa-sha256; d=sourceware.org; s=key;\n t=1776884982; c=relaxed/simple;\n bh=NtGb89n2u5/d/ofluWw88j9N98Ahx1GwXKgZhlvitbI=;\n h=From:Date:Subject:MIME-Version:To:Message-ID;\n b=AO4KJuJCHJrnzOw+3zzYm84TeHMnezMAncOUlE3rqI9QRNH+8K0q9mIq8pXpexfmMfHt86JQoeyB91ckqLKJVZZ0wbOH68pi3t3ZVwygd6YT5YUK9wPAt/h0Fn4QBHY01l8wKOfjP+m1lvA0f2B/WxBdFEAqSwl1OTnF/IAELrM=","ARC-Authentication-Results":"i=1; server2.sourceware.org","From":"=?utf-8?q?Fran=C3=A7ois_Dumont_via_Sourceware_Forge?=\n <forge-bot+fdumont@forge-stage.sourceware.org>","Date":"Wed, 22 Apr 2026 19:08:44 +0000","Subject":"[PATCH v1 1/1] libstdc++: Fix std::erase_if behavior for std::__debug\n containers","MIME-Version":"1.0","Content-Type":"text/plain; charset=UTF-8","Content-Transfer-Encoding":"8bit","To":"gcc-patches mailing list <gcc-patches@gcc.gnu.org>","Message-ID":"\n <bmm.hhupnyl5bc.gcc.gcc-TEST.fdumont.131.1.1@forge-stage.sourceware.org>","X-Mailer":"batrachomyomachia","X-Pull-Request-Organization":"gcc","X-Pull-Request-Repository":"gcc-TEST","X-Pull-Request":"https://forge.sourceware.org/gcc/gcc-TEST/pulls/131","References":"\n <bmm.hhupnyl5bc.gcc.gcc-TEST.fdumont.131.1.0@forge-stage.sourceware.org>","In-Reply-To":"\n <bmm.hhupnyl5bc.gcc.gcc-TEST.fdumont.131.1.0@forge-stage.sourceware.org>","X-Patch-URL":"\n https://forge.sourceware.org/fdumont/gcc-TEST/commit/add9e3dd616da332ea69afbb583fd0cfdfc970cf","X-BeenThere":"gcc-patches@gcc.gnu.org","X-Mailman-Version":"2.1.30","Precedence":"list","List-Id":"Gcc-patches mailing list <gcc-patches.gcc.gnu.org>","List-Unsubscribe":"<https://gcc.gnu.org/mailman/options/gcc-patches>,\n <mailto:gcc-patches-request@gcc.gnu.org?subject=unsubscribe>","List-Archive":"<https://gcc.gnu.org/pipermail/gcc-patches/>","List-Post":"<mailto:gcc-patches@gcc.gnu.org>","List-Help":"<mailto:gcc-patches-request@gcc.gnu.org?subject=help>","List-Subscribe":"<https://gcc.gnu.org/mailman/listinfo/gcc-patches>,\n <mailto:gcc-patches-request@gcc.gnu.org?subject=subscribe>","Reply-To":"gcc-patches mailing list <gcc-patches@gcc.gnu.org>,\n fdumont@gcc.gnu.org","Errors-To":"gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org"},"content":"From: François Dumont <frs.dumont@gmail.com>\n\nComplete fix of std::erase_if/std::erase for all std::__debug containers and\n__gnu_debug::basic_string. Make sure that iterators erased by this function\nwill be properly detected as such by the debug container and so considered as\ninvalid.\n\nDoing so introduce a new std::__detail::__erase_if function dealing, similarly\nto std::__detail::__erase_node_if, with non-node containers.\n\nlibstdc++-v3/ChangeLog:\n\n\t* include/bits/erase_if.h (__detail::__erase_if): New.\n\t* include/debug/deque (std::erase_if<>(__debug::deque<>&, _Pred): Use latter.\n\t* include/debug/inplace_vector (std::erase_if<>(__debug::inplace_vector<>&, _Pred)):\n\tLikewise.\n\t* include/debug/vector (std::erase_if<>(__debug::vector<>&, _Pred)): Likewise.\n\t* include/std/deque: Include erase_if.h.\n\t(std::erase_if<>(std::vector<>&, _Pred)): Adapt to use __detail::__erase_if.\n\t* include/std/inplace_vector (std::erase_if<>(std::inplace_vector<>&, _Pred)):\n\tLikewise.\n\t* include/std/string (std::erase_if<>(std::basic_string<>&, _Pred)): Likewise.\n\t* include/std/vector (std::erase_if<>(std::vector<>&, _Pred)): Likewise.\n\t* include/debug/forward_list\n\t(std::erase_if<>(__debug::forward_list<>&, _Pred)): New.\n\t(std::erase<>(__debug::forward_list<>&, const _Up&)): New.\n\t* include/debug/list\n\t(std::erase_if<>(__debug::list<>&, _Pred)): New.\n\t(std::erase<>(__debug::list<>&, const _Up&)): New.\n\t* include/debug/map (std::erase_if<>(__debug::map<>&, _Pred)): New.\n\t(std::erase_if<>(__debug::multimap<>&, _Pred)): New.\n\t* include/debug/set (std::erase_if<>(__debug::set<>&, _Pred)): New.\n\t(std::erase_if<>(__debug::multiset<>&, _Pred)): New.\n\t* include/debug/string\n\t(std::erase_if<>(__gnu_debug::basic_string<>&, _Pred)): New.\n\t(std::erase<>(__gnu_debug::basic_string<>&, const _Up&)): New.\n\t* include/debug/unordered_map\n\t(std::erase_if<>(__debug::unordered_map<>&, _Pred)): New.\n\t(std::erase_if<>(__debug::unordered_multimap<>&, _Pred)): New.\n\t* include/debug/unordered_set\n\t(std::erase_if<>(__debug::unordered_set<>&, _Pred)): New.\n\t(std::erase_if<>(__debug::unordered_multiset<>&, _Pred)): New.\n\t* include/std/forward_list (std::erase_if<>(std::forward_list<>&, _Pred)):\n\tAdapt to work exclusively for normal implementation.\n\t(std::erase<>(std::forward_list<>&, const _Up&)): Likewise.\n\t* include/std/list (std::erase_if<>(std::list<>&, _Pred)): Likewise.\n\t(std::erase<>(std::list<>&, const _Up&)): Likewise.\n\t* include/std/map (std::erase_if<>(std::map<>&, _Pred)): Likewise.\n\t(std::erase_if<>(std::multimap<>&, _Pred)): Likewise.\n\t* include/debug/set (std::erase_if<>(std::set<>&, _Pred)): Likewise.\n\t(std::erase_if<>(std::multiset<>&, _Pred)): Likewise.\n\t* include/std/unordered_map\n\t(std::erase_if<>(std::unordered_map<>&, _Pred)): Likewise.\n\t(std::erase_if<>(std::unordered_multimap<>&, _Pred)): Likewise.\n\t* include/std/unordered_set\n\t(std::erase_if<>(std::unordered_set<>&, _Pred)): Likewise.\n\t(std::erase_if<>(std::unordered_multiset<>&, _Pred)): Likewise.\n\t* testsuite/21_strings/basic_string/debug/erase.cc: New test case.\n\t* testsuite/23_containers/forward_list/debug/erase.cc: New test case.\n\t* testsuite/23_containers/forward_list/debug/invalidation/erase.cc: New test case.\n\t* testsuite/23_containers/list/debug/erase.cc: New test case.\n\t* testsuite/23_containers/list/debug/invalidation/erase.cc: New test case.\n\t* testsuite/23_containers/map/debug/erase_if.cc: New test case.\n\t* testsuite/23_containers/map/debug/invalidation/erase_if.cc: New test case.\n\t* testsuite/23_containers/multimap/debug/erase_if.cc: New test case.\n\t* testsuite/23_containers/multimap/debug/invalidation/erase_if.cc: New test case.\n\t* testsuite/23_containers/multiset/debug/erase_if.cc: New test case.\n\t* testsuite/23_containers/multiset/debug/invalidation/erase_if.cc: New test case.\n\t* testsuite/23_containers/set/debug/erase_if.cc: New test case.\n\t* testsuite/23_containers/set/debug/invalidation/erase_if.cc: New test case.\n\t* testsuite/23_containers/unordered_map/debug/erase_if.cc: New test case.\n\t* testsuite/23_containers/unordered_map/debug/invalidation/erase_if.cc: New test case.\n\t* testsuite/23_containers/unordered_multimap/debug/erase_if.cc: New test case.\n\t* testsuite/23_containers/unordered_multimap/debug/invalidation/erase_if.cc: New test case.\n\t* testsuite/23_containers/unordered_multiset/debug/erase_if.cc: New test case.\n\t* testsuite/23_containers/unordered_multiset/debug/invalidation/erase_if.cc: New test case.\n\t* testsuite/23_containers/unordered_set/debug/erase_if.cc: New test case.\n\t* testsuite/23_containers/unordered_set/debug/invalidation/erase_if.cc: New test case.\n---\n libstdc++-v3/include/bits/erase_if.h          | 22 ++++++++++++\n libstdc++-v3/include/debug/deque              | 16 ++-------\n libstdc++-v3/include/debug/forward_list       | 21 ++++++++++++\n libstdc++-v3/include/debug/inplace_vector     | 15 ++------\n libstdc++-v3/include/debug/list               | 21 ++++++++++++\n libstdc++-v3/include/debug/map                | 21 ++++++++++++\n libstdc++-v3/include/debug/set                | 19 +++++++++++\n libstdc++-v3/include/debug/string             | 20 +++++++++++\n libstdc++-v3/include/debug/unordered_map      | 20 +++++++++++\n libstdc++-v3/include/debug/unordered_set      | 20 +++++++++++\n libstdc++-v3/include/debug/vector             | 14 +-------\n libstdc++-v3/include/std/deque                | 15 ++------\n libstdc++-v3/include/std/forward_list         |  8 ++---\n libstdc++-v3/include/std/inplace_vector       | 13 ++-----\n libstdc++-v3/include/std/list                 |  8 ++---\n libstdc++-v3/include/std/map                  | 25 ++++++--------\n libstdc++-v3/include/std/set                  | 24 ++++++-------\n libstdc++-v3/include/std/string               | 11 ++----\n libstdc++-v3/include/std/unordered_map        | 29 +++++++---------\n libstdc++-v3/include/std/unordered_set        | 26 ++++++--------\n libstdc++-v3/include/std/vector               | 15 ++------\n .../21_strings/basic_string/debug/erase.cc    | 25 ++++++++++++++\n .../23_containers/forward_list/debug/erase.cc | 26 ++++++++++++++\n .../forward_list/debug/invalidation/erase.cc  | 27 +++++++++++++++\n .../23_containers/list/debug/erase.cc         | 29 ++++++++++++++++\n .../list/debug/invalidation/erase.cc          | 30 ++++++++++++++++\n .../23_containers/map/debug/erase_if.cc       | 33 ++++++++++++++++++\n .../map/debug/invalidation/erase_if.cc        | 34 +++++++++++++++++++\n .../23_containers/multimap/debug/erase_if.cc  | 33 ++++++++++++++++++\n .../multimap/debug/invalidation/erase_if.cc   | 34 +++++++++++++++++++\n .../23_containers/multiset/debug/erase_if.cc  | 31 +++++++++++++++++\n .../multiset/debug/invalidation/erase_if.cc   | 32 +++++++++++++++++\n .../23_containers/set/debug/erase_if.cc       | 31 +++++++++++++++++\n .../set/debug/invalidation/erase_if.cc        | 32 +++++++++++++++++\n .../unordered_map/debug/erase_if.cc           | 33 ++++++++++++++++++\n .../debug/invalidation/erase_if.cc            | 34 +++++++++++++++++++\n .../unordered_multimap/debug/erase_if.cc      | 33 ++++++++++++++++++\n .../debug/invalidation/erase_if.cc            | 34 +++++++++++++++++++\n .../unordered_multiset/debug/erase_if.cc      | 31 +++++++++++++++++\n .../debug/invalidation/erase_if.cc            | 32 +++++++++++++++++\n .../unordered_set/debug/erase_if.cc           | 31 +++++++++++++++++\n .../debug/invalidation/erase_if.cc            | 32 +++++++++++++++++\n 42 files changed, 886 insertions(+), 154 deletions(-)\n create mode 100644 libstdc++-v3/testsuite/21_strings/basic_string/debug/erase.cc\n create mode 100644 libstdc++-v3/testsuite/23_containers/forward_list/debug/erase.cc\n create mode 100644 libstdc++-v3/testsuite/23_containers/forward_list/debug/invalidation/erase.cc\n create mode 100644 libstdc++-v3/testsuite/23_containers/list/debug/erase.cc\n create mode 100644 libstdc++-v3/testsuite/23_containers/list/debug/invalidation/erase.cc\n create mode 100644 libstdc++-v3/testsuite/23_containers/map/debug/erase_if.cc\n create mode 100644 libstdc++-v3/testsuite/23_containers/map/debug/invalidation/erase_if.cc\n create mode 100644 libstdc++-v3/testsuite/23_containers/multimap/debug/erase_if.cc\n create mode 100644 libstdc++-v3/testsuite/23_containers/multimap/debug/invalidation/erase_if.cc\n create mode 100644 libstdc++-v3/testsuite/23_containers/multiset/debug/erase_if.cc\n create mode 100644 libstdc++-v3/testsuite/23_containers/multiset/debug/invalidation/erase_if.cc\n create mode 100644 libstdc++-v3/testsuite/23_containers/set/debug/erase_if.cc\n create mode 100644 libstdc++-v3/testsuite/23_containers/set/debug/invalidation/erase_if.cc\n create mode 100644 libstdc++-v3/testsuite/23_containers/unordered_map/debug/erase_if.cc\n create mode 100644 libstdc++-v3/testsuite/23_containers/unordered_map/debug/invalidation/erase_if.cc\n create mode 100644 libstdc++-v3/testsuite/23_containers/unordered_multimap/debug/erase_if.cc\n create mode 100644 libstdc++-v3/testsuite/23_containers/unordered_multimap/debug/invalidation/erase_if.cc\n create mode 100644 libstdc++-v3/testsuite/23_containers/unordered_multiset/debug/erase_if.cc\n create mode 100644 libstdc++-v3/testsuite/23_containers/unordered_multiset/debug/invalidation/erase_if.cc\n create mode 100644 libstdc++-v3/testsuite/23_containers/unordered_set/debug/erase_if.cc\n create mode 100644 libstdc++-v3/testsuite/23_containers/unordered_set/debug/invalidation/erase_if.cc","diff":"diff --git a/libstdc++-v3/include/bits/erase_if.h b/libstdc++-v3/include/bits/erase_if.h\nindex a445a53bcfbf..d5a5278d1282 100644\n--- a/libstdc++-v3/include/bits/erase_if.h\n+++ b/libstdc++-v3/include/bits/erase_if.h\n@@ -35,6 +35,7 @@\n #endif\n \n #include <bits/c++config.h>\n+#include <bits/stl_algobase.h>\n \n // Used by C++17 containers and Library Fundamentals v2 headers.\n #if __cplusplus >= 201402L\n@@ -44,6 +45,27 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION\n \n   namespace __detail\n   {\n+    template<typename _Container, typename _UnsafeContainer,\n+\t     typename _Predicate>\n+      _GLIBCXX20_CONSTEXPR\n+      typename _Container::size_type\n+      __erase_if(_Container& __cont, _UnsafeContainer& __ucont,\n+\t\t _Predicate __pred)\n+      {\n+\tconst auto __osz = __ucont.size();\n+\tconst auto __end = __ucont.end();\n+\tauto __removed = std::__remove_if(__ucont.begin(), __end,\n+\t\t\t\t\t  std::move(__pred));\n+\tif (__removed != __end)\n+\t  {\n+\t    __cont.erase(__niter_wrap(__cont.cbegin(), __removed),\n+\t\t\t __cont.cend());\n+\t    return __osz - __ucont.size();\n+\t  }\n+\n+\treturn 0;\n+      }\n+\n     template<typename _Container, typename _UnsafeContainer,\n \t     typename _Predicate>\n       typename _Container::size_type\ndiff --git a/libstdc++-v3/include/debug/deque b/libstdc++-v3/include/debug/deque\nindex b3e72eb30163..9fba4ffc4997 100644\n--- a/libstdc++-v3/include/debug/deque\n+++ b/libstdc++-v3/include/debug/deque\n@@ -778,19 +778,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION\n     inline typename __debug::deque<_Tp, _Alloc>::size_type\n     erase_if(__debug::deque<_Tp, _Alloc>& __cont, _Predicate __pred)\n     {\n-      _GLIBCXX_STD_C::deque<_Tp, _Alloc>& __unsafe_cont = __cont;\n-      const auto __osz = __cont.size();\n-      const auto __end = __unsafe_cont.end();\n-      auto __removed = std::__remove_if(__unsafe_cont.begin(), __end,\n-\t\t\t\t\tstd::move(__pred));\n-      if (__removed != __end)\n-\t{\n-\t  __cont.erase(__niter_wrap(__cont.begin(), __removed),\n-\t\t       __cont.end());\n-\t  return __osz - __cont.size();\n-\t}\n-\n-      return 0;\n+      return __detail::__erase_if(__cont, __cont._M_base(), std::move(__pred));\n     }\n \n   template<typename _Tp, typename _Alloc, typename _Up = _Tp>\n@@ -798,7 +786,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION\n     erase(__debug::deque<_Tp, _Alloc>& __cont, const _Up& __value)\n     { return std::erase_if(__cont, __gnu_cxx::__ops::__equal_to(__value)); }\n _GLIBCXX_END_NAMESPACE_VERSION\n-#endif // __cpp_lib_erase_if\n+#endif // __glibcxx_erase_if\n } // namespace std\n \n #endif\ndiff --git a/libstdc++-v3/include/debug/forward_list b/libstdc++-v3/include/debug/forward_list\nindex 1fe3a4f2830b..7d615978000e 100644\n--- a/libstdc++-v3/include/debug/forward_list\n+++ b/libstdc++-v3/include/debug/forward_list\n@@ -981,6 +981,27 @@ namespace __debug\n     { __lx.swap(__ly); }\n \n } // namespace __debug\n+\n+#ifdef __glibcxx_erase_if // C++ >= 20 && HOSTED\n+_GLIBCXX_BEGIN_NAMESPACE_VERSION\n+  template<typename _Tp, typename _Alloc, typename _Predicate>\n+    inline typename __debug::forward_list<_Tp, _Alloc>::size_type\n+    erase_if(__debug::forward_list<_Tp, _Alloc>& __cont, _Predicate __pred)\n+    { return __cont.remove_if(__pred); }\n+\n+  template<typename _Tp, typename _Alloc,\n+\t   typename _Up _GLIBCXX26_DEF_VAL_T(_Tp)>\n+    inline typename __debug::forward_list<_Tp, _Alloc>::size_type\n+    erase(__debug::forward_list<_Tp, _Alloc>& __cont, const _Up& __value)\n+    {\n+      // _GLIBCXX_RESOLVE_LIB_DEFECTS\n+      // 4135. helper lambda of std::erase for list should specify return type\n+      return std::erase_if(__cont, [&](const auto& __elem) -> bool {\n+\t  return __elem == __value;\n+      });\n+    }\n+_GLIBCXX_END_NAMESPACE_VERSION\n+#endif // __glibcxx_erase_if\n } // namespace std\n \n namespace __gnu_debug\ndiff --git a/libstdc++-v3/include/debug/inplace_vector b/libstdc++-v3/include/debug/inplace_vector\nindex c7e301efc621..750b0a7343ca 100644\n--- a/libstdc++-v3/include/debug/inplace_vector\n+++ b/libstdc++-v3/include/debug/inplace_vector\n@@ -566,13 +566,13 @@ namespace __debug\n       noexcept( noexcept(__x.swap(__y)) )\n       { __x.swap(__y); }\n \n-    private:\n       constexpr _Base&\n       _M_base() noexcept { return *this; }\n \n       constexpr const _Base&\n       _M_base() const noexcept { return *this; }\n \n+    private:\n       constexpr void\n       _M_invalidate_after_nth(difference_type __n) noexcept\n       {\n@@ -663,17 +663,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION\n     {\n       if constexpr (_Nm != 0)\n \t{\n-\t  _GLIBCXX_STD_C::inplace_vector<_Tp, _Nm>& __ucont = __cont;\n-\t  const auto __osz = __cont.size();\n-\t  const auto __end = __ucont.end();\n-\t  auto __removed = std::__remove_if(__ucont.begin(), __end,\n-\t\t\t\t\t    std::move(__pred));\n-\t  if (__removed != __end)\n-\t    {\n-\t      __cont.erase(__niter_wrap(__cont.cbegin(), __removed),\n-\t\t\t   __cont.cend());\n-\t      return __osz - __cont.size();\n-\t    }\n+\t  return __detail::__erase_if(__cont, __cont._M_base(),\n+\t\t\t\t      std::move(__pred));\n \t}\n \n       return 0;\ndiff --git a/libstdc++-v3/include/debug/list b/libstdc++-v3/include/debug/list\nindex 48ec1966d97e..d06e9e4c2f84 100644\n--- a/libstdc++-v3/include/debug/list\n+++ b/libstdc++-v3/include/debug/list\n@@ -1031,6 +1031,27 @@ namespace __debug\n     { __lhs.swap(__rhs); }\n \n } // namespace __debug\n+\n+#ifdef __glibcxx_erase_if // C++ >= 20 && HOSTED\n+_GLIBCXX_BEGIN_NAMESPACE_VERSION\n+  template<typename _Tp, typename _Alloc, typename _Predicate>\n+    inline typename __debug::list<_Tp, _Alloc>::size_type\n+    erase_if(__debug::list<_Tp, _Alloc>& __cont, _Predicate __pred)\n+    { return __cont.remove_if(__pred); }\n+\n+  template<typename _Tp, typename _Alloc,\n+\t   typename _Up _GLIBCXX26_DEF_VAL_T(_Tp)>\n+    inline typename __debug::list<_Tp, _Alloc>::size_type\n+    erase(__debug::list<_Tp, _Alloc>& __cont, const _Up& __value)\n+    {\n+      // _GLIBCXX_RESOLVE_LIB_DEFECTS\n+      // 4135. helper lambda of std::erase for list should specify return type\n+      return std::erase_if(__cont, [&](const auto& __elem) -> bool {\n+\t  return __elem == __value;\n+      });\n+    }\n+_GLIBCXX_END_NAMESPACE_VERSION\n+#endif // __glibcxx_erase_if\n } // namespace std\n \n namespace __gnu_debug\ndiff --git a/libstdc++-v3/include/debug/map b/libstdc++-v3/include/debug/map\nindex 360325f03ad2..b07c17f2320e 100644\n--- a/libstdc++-v3/include/debug/map\n+++ b/libstdc++-v3/include/debug/map\n@@ -45,4 +45,25 @@ namespace std _GLIBCXX_VISIBILITY(default) { namespace __debug {\n #include <debug/map.h>\n #include <debug/multimap.h>\n \n+#ifdef __glibcxx_erase_if // C++ >= 20 && HOSTED\n+namespace std _GLIBCXX_VISIBILITY(default)\n+{\n+_GLIBCXX_BEGIN_NAMESPACE_VERSION\n+  template<typename _Key, typename _Tp, typename _Compare, typename _Alloc,\n+\t   typename _Predicate>\n+    inline typename __debug::map<_Key, _Tp, _Compare, _Alloc>::size_type\n+    erase_if(__debug::map<_Key, _Tp, _Compare, _Alloc>& __cont,\n+\t     _Predicate __pred)\n+    { return __detail::__erase_nodes_if(__cont, __cont._M_base(), __pred); }\n+\n+  template<typename _Key, typename _Tp, typename _Compare, typename _Alloc,\n+\t   typename _Predicate>\n+    inline typename __debug::multimap<_Key, _Tp, _Compare, _Alloc>::size_type\n+    erase_if(__debug::multimap<_Key, _Tp, _Compare, _Alloc>& __cont,\n+\t     _Predicate __pred)\n+    { return __detail::__erase_nodes_if(__cont, __cont._M_base(), __pred); }\n+_GLIBCXX_END_NAMESPACE_VERSION\n+} // namespace std\n+#endif // __glibcxx_erase_if\n+\n #endif\ndiff --git a/libstdc++-v3/include/debug/set b/libstdc++-v3/include/debug/set\nindex 6645032c349c..508c0cd05fd2 100644\n--- a/libstdc++-v3/include/debug/set\n+++ b/libstdc++-v3/include/debug/set\n@@ -43,4 +43,23 @@ namespace std _GLIBCXX_VISIBILITY(default) { namespace __debug {\n #include <debug/set.h>\n #include <debug/multiset.h>\n \n+#ifdef __glibcxx_erase_if // C++ >= 20 && HOSTED\n+namespace std _GLIBCXX_VISIBILITY(default)\n+{\n+_GLIBCXX_BEGIN_NAMESPACE_VERSION\n+  template<typename _Key, typename _Compare, typename _Alloc,\n+\t   typename _Predicate>\n+    inline typename __debug::set<_Key, _Compare, _Alloc>::size_type\n+    erase_if(__debug::set<_Key, _Compare, _Alloc>& __cont, _Predicate __pred)\n+    { return __detail::__erase_nodes_if(__cont, __cont._M_base(), __pred); }\n+\n+  template<typename _Key, typename _Compare, typename _Alloc,\n+\t   typename _Predicate>\n+    inline typename __debug::multiset<_Key, _Compare, _Alloc>::size_type\n+    erase_if(__debug::multiset<_Key, _Compare, _Alloc>& __cont, _Predicate __pred)\n+    { return __detail::__erase_nodes_if(__cont, __cont._M_base(), __pred); }\n+_GLIBCXX_END_NAMESPACE_VERSION\n+} // namespace std\n+#endif // __glibcxx_erase_if\n+\n #endif\ndiff --git a/libstdc++-v3/include/debug/string b/libstdc++-v3/include/debug/string\nindex 6d30d7d036ac..d5ee1d9e1938 100644\n--- a/libstdc++-v3/include/debug/string\n+++ b/libstdc++-v3/include/debug/string\n@@ -1331,6 +1331,26 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION\n     : __is_fast_hash<hash<std::basic_string<_CharT>>>\n     { };\n \n+#ifdef __glibcxx_erase_if // C++ >= 20 && HOSTED\n+  template<typename _CharT, typename _Traits, typename _Alloc,\n+\t   typename _Predicate>\n+    constexpr typename __gnu_debug::basic_string<_CharT,\n+\t\t\t\t\t\t _Traits, _Alloc>::size_type\n+    erase_if(__gnu_debug::basic_string<_CharT, _Traits, _Alloc>& __cont,\n+\t     _Predicate __pred)\n+    {\n+      return __detail::__erase_if(__cont, __cont._M_base(), std::move(__pred));\n+    }\n+\n+  template<typename _CharT, typename _Traits, typename _Alloc,\n+\t   typename _Up _GLIBCXX26_DEF_VAL_T(_CharT)>\n+    constexpr typename __gnu_debug::basic_string<_CharT,\n+\t\t\t\t\t\t _Traits, _Alloc>::size_type\n+    erase(__gnu_debug::basic_string<_CharT, _Traits, _Alloc>& __cont,\n+\t  const _Up& __value)\n+    { return std::erase_if(__cont, __gnu_cxx::__ops::__equal_to(__value)); }\n+#endif // __glibcxx_erase_if\n+\n _GLIBCXX_END_NAMESPACE_VERSION\n }\n #endif /* C++11 */\ndiff --git a/libstdc++-v3/include/debug/unordered_map b/libstdc++-v3/include/debug/unordered_map\nindex 8e286b733362..4bde18c917b2 100644\n--- a/libstdc++-v3/include/debug/unordered_map\n+++ b/libstdc++-v3/include/debug/unordered_map\n@@ -1748,6 +1748,26 @@ namespace __debug\n #endif\n \n } // namespace __debug\n+\n+#ifdef __glibcxx_erase_if // C++ >= 20 && HOSTED\n+_GLIBCXX_BEGIN_NAMESPACE_VERSION\n+  template<typename _Key, typename _Tp, typename _Hash, typename _CPred,\n+\t   typename _Alloc, typename _Predicate>\n+    inline typename __debug::unordered_map<_Key, _Tp, _Hash,\n+\t\t\t\t\t   _CPred, _Alloc>::size_type\n+    erase_if(__debug::unordered_map<_Key, _Tp, _Hash, _CPred, _Alloc>& __cont,\n+\t     _Predicate __pred)\n+    { return __detail::__erase_nodes_if(__cont, __cont._M_base(), __pred); }\n+\n+  template<typename _Key, typename _Tp, typename _Hash, typename _CPred,\n+\t   typename _Alloc, typename _Predicate>\n+    inline typename __debug::unordered_multimap<_Key, _Tp, _Hash,\n+\t\t\t\t\t\t_CPred, _Alloc>::size_type\n+    erase_if(__debug::unordered_multimap<_Key, _Tp, _Hash, _CPred, _Alloc>& __cont,\n+\t     _Predicate __pred)\n+    { return __detail::__erase_nodes_if(__cont, __cont._M_base(), __pred); }\n+_GLIBCXX_END_NAMESPACE_VERSION\n+#endif // __glibcxx_erase_if\n } // namespace std\n \n #endif // C++11\ndiff --git a/libstdc++-v3/include/debug/unordered_set b/libstdc++-v3/include/debug/unordered_set\nindex 8951604f03bf..de999a76890e 100644\n--- a/libstdc++-v3/include/debug/unordered_set\n+++ b/libstdc++-v3/include/debug/unordered_set\n@@ -1597,6 +1597,26 @@ namespace __debug\n #endif\n \n } // namespace __debug\n+\n+#ifdef __glibcxx_erase_if // C++ >= 20 && HOSTED\n+_GLIBCXX_BEGIN_NAMESPACE_VERSION\n+  template<typename _Key, typename _Hash, typename _CPred, typename _Alloc,\n+\t   typename _Predicate>\n+    inline typename __debug::unordered_set<_Key, _Hash,\n+\t\t\t\t\t   _CPred, _Alloc>::size_type\n+    erase_if(__debug::unordered_set<_Key, _Hash, _CPred, _Alloc>& __cont,\n+\t     _Predicate __pred)\n+    { return __detail::__erase_nodes_if(__cont, __cont._M_base(), __pred); }\n+\n+  template<typename _Key, typename _Hash, typename _CPred, typename _Alloc,\n+\t   typename _Predicate>\n+    inline typename __debug::unordered_multiset<_Key, _Hash,\n+\t\t\t\t\t\t_CPred, _Alloc>::size_type\n+    erase_if(__debug::unordered_multiset<_Key, _Hash, _CPred, _Alloc>& __cont,\n+\t     _Predicate __pred)\n+    { return __detail::__erase_nodes_if(__cont, __cont._M_base(), __pred); }\n+_GLIBCXX_END_NAMESPACE_VERSION\n+#endif // __glibcxx_erase_if\n } // namespace std\n \n #endif // C++11\ndiff --git a/libstdc++-v3/include/debug/vector b/libstdc++-v3/include/debug/vector\nindex e652260860a2..61e5ff78a7a4 100644\n--- a/libstdc++-v3/include/debug/vector\n+++ b/libstdc++-v3/include/debug/vector\n@@ -1043,19 +1043,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION\n     constexpr typename __debug::vector<_Tp, _Alloc>::size_type\n     erase_if(__debug::vector<_Tp, _Alloc>& __cont, _Predicate __pred)\n     {\n-      _GLIBCXX_STD_C::vector<_Tp, _Alloc>& __unsafe_cont = __cont;\n-      const auto __osz = __cont.size();\n-      const auto __end = __unsafe_cont.end();\n-      auto __removed = std::__remove_if(__unsafe_cont.begin(), __end,\n-\t\t\t\t\tstd::move(__pred));\n-      if (__removed != __end)\n-\t{\n-\t  __cont.erase(__niter_wrap(__cont.begin(), __removed),\n-\t\t       __cont.end());\n-\t  return __osz - __cont.size();\n-\t}\n-\n-      return 0;\n+      return __detail::__erase_if(__cont, __cont._M_base(), std::move(__pred));\n     }\n \n   template<typename _Tp, typename _Alloc, typename _Up = _Tp>\ndiff --git a/libstdc++-v3/include/std/deque b/libstdc++-v3/include/std/deque\nindex ea426196ca54..3899b68e7367 100644\n--- a/libstdc++-v3/include/std/deque\n+++ b/libstdc++-v3/include/std/deque\n@@ -68,6 +68,7 @@\n #include <bits/stl_uninitialized.h>\n #include <bits/stl_deque.h>\n #include <bits/range_access.h>\n+#include <bits/erase_if.h>\n #include <bits/deque.tcc>\n \n #define __glibcxx_want_algorithm_default_value_type\n@@ -103,19 +104,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION\n   template<typename _Tp, typename _Alloc, typename _Predicate>\n     inline typename _GLIBCXX_STD_C::deque<_Tp, _Alloc>::size_type\n     erase_if(_GLIBCXX_STD_C::deque<_Tp, _Alloc>& __cont, _Predicate __pred)\n-    {\n-      const auto __osz = __cont.size();\n-      const auto __end = __cont.end();\n-      auto __removed = std::__remove_if(__cont.begin(), __end,\n-\t\t\t\t\tstd::move(__pred));\n-      if (__removed != __end)\n-\t{\n-\t  __cont.erase(__removed, __end);\n-\t  return __osz - __cont.size();\n-\t}\n-\n-      return 0;\n-    }\n+    { return __detail::__erase_if(__cont, __cont, std::move(__pred)); }\n \n   template<typename _Tp, typename _Alloc,\n \t   typename _Up _GLIBCXX26_DEF_VAL_T(_Tp)>\ndiff --git a/libstdc++-v3/include/std/forward_list b/libstdc++-v3/include/std/forward_list\nindex 413fcaf3b4c4..ff0c58455cf5 100644\n--- a/libstdc++-v3/include/std/forward_list\n+++ b/libstdc++-v3/include/std/forward_list\n@@ -75,14 +75,14 @@ namespace std _GLIBCXX_VISIBILITY(default)\n {\n _GLIBCXX_BEGIN_NAMESPACE_VERSION\n   template<typename _Tp, typename _Alloc, typename _Predicate>\n-    inline typename forward_list<_Tp, _Alloc>::size_type\n-    erase_if(forward_list<_Tp, _Alloc>& __cont, _Predicate __pred)\n+    inline typename _GLIBCXX_STD_C::forward_list<_Tp, _Alloc>::size_type\n+    erase_if(_GLIBCXX_STD_C::forward_list<_Tp, _Alloc>& __cont, _Predicate __pred)\n     { return __cont.remove_if(__pred); }\n \n   template<typename _Tp, typename _Alloc,\n \t   typename _Up _GLIBCXX26_DEF_VAL_T(_Tp)>\n-    inline typename forward_list<_Tp, _Alloc>::size_type\n-    erase(forward_list<_Tp, _Alloc>& __cont, const _Up& __value)\n+    inline typename _GLIBCXX_STD_C::forward_list<_Tp, _Alloc>::size_type\n+    erase(_GLIBCXX_STD_C::forward_list<_Tp, _Alloc>& __cont, const _Up& __value)\n     {\n       // _GLIBCXX_RESOLVE_LIB_DEFECTS\n       // 4135. helper lambda of std::erase for list should specify return type\ndiff --git a/libstdc++-v3/include/std/inplace_vector b/libstdc++-v3/include/std/inplace_vector\nindex df95c1e5c021..c22a9e1f9b40 100644\n--- a/libstdc++-v3/include/std/inplace_vector\n+++ b/libstdc++-v3/include/std/inplace_vector\n@@ -46,6 +46,7 @@\n #include <bits/stl_construct.h>\n #include <bits/stl_uninitialized.h>\n #include <bits/stl_algo.h> // rotate\n+#include <bits/erase_if.h>\n \n namespace std _GLIBCXX_VISIBILITY(default)\n {\n@@ -1339,17 +1340,7 @@ _GLIBCXX_END_NAMESPACE_CONTAINER\n \t     _Predicate __pred)\n     {\n       if constexpr (_Nm != 0)\n-\t{\n-\t  const auto __osz = __cont.size();\n-\t  const auto __end = __cont.end();\n-\t  auto __removed = std::__remove_if(__cont.begin(), __end,\n-\t\t\t\t\t    std::move(__pred));\n-\t  if (__removed != __end)\n-\t    {\n-\t      __cont.erase(__removed, __end);\n-\t      return __osz - __cont.size();\n-\t    }\n-\t}\n+\treturn __detail::__erase_if(__cont, __cont, std::move(__pred));\n \n       return 0;\n     }\ndiff --git a/libstdc++-v3/include/std/list b/libstdc++-v3/include/std/list\nindex 3feff4d7b8b0..a3e7c81680a9 100644\n--- a/libstdc++-v3/include/std/list\n+++ b/libstdc++-v3/include/std/list\n@@ -99,14 +99,14 @@ namespace std _GLIBCXX_VISIBILITY(default)\n {\n _GLIBCXX_BEGIN_NAMESPACE_VERSION\n   template<typename _Tp, typename _Alloc, typename _Predicate>\n-    inline typename list<_Tp, _Alloc>::size_type\n-    erase_if(list<_Tp, _Alloc>& __cont, _Predicate __pred)\n+    inline typename _GLIBCXX_STD_C::list<_Tp, _Alloc>::size_type\n+    erase_if(_GLIBCXX_STD_C::list<_Tp, _Alloc>& __cont, _Predicate __pred)\n     { return __cont.remove_if(__pred); }\n \n   template<typename _Tp, typename _Alloc,\n \t   typename _Up _GLIBCXX26_DEF_VAL_T(_Tp)>\n-    inline typename list<_Tp, _Alloc>::size_type\n-    erase(list<_Tp, _Alloc>& __cont, const _Up& __value)\n+    inline typename _GLIBCXX_STD_C::list<_Tp, _Alloc>::size_type\n+    erase(_GLIBCXX_STD_C::list<_Tp, _Alloc>& __cont, const _Up& __value)\n     {\n       // _GLIBCXX_RESOLVE_LIB_DEFECTS\n       // 4135. helper lambda of std::erase for list should specify return type\ndiff --git a/libstdc++-v3/include/std/map b/libstdc++-v3/include/std/map\nindex b4d39959f0d1..88e549411afd 100644\n--- a/libstdc++-v3/include/std/map\n+++ b/libstdc++-v3/include/std/map\n@@ -101,29 +101,26 @@ _GLIBCXX_END_NAMESPACE_VERSION\n } // namespace std\n #endif // C++17\n \n-#if __cplusplus > 201703L\n+#ifdef __cpp_lib_erase_if // C++ >= 20 && HOSTED\n namespace std _GLIBCXX_VISIBILITY(default)\n {\n _GLIBCXX_BEGIN_NAMESPACE_VERSION\n   template<typename _Key, typename _Tp, typename _Compare, typename _Alloc,\n \t   typename _Predicate>\n-    inline typename map<_Key, _Tp, _Compare, _Alloc>::size_type\n-    erase_if(map<_Key, _Tp, _Compare, _Alloc>& __cont, _Predicate __pred)\n-    {\n-      _GLIBCXX_STD_C::map<_Key, _Tp, _Compare, _Alloc>& __ucont = __cont;\n-      return __detail::__erase_nodes_if(__cont, __ucont, __pred);\n-    }\n+    inline typename _GLIBCXX_STD_C::map<_Key, _Tp, _Compare, _Alloc>::size_type\n+    erase_if(_GLIBCXX_STD_C::map<_Key, _Tp, _Compare, _Alloc>& __cont,\n+\t     _Predicate __pred)\n+    { return __detail::__erase_nodes_if(__cont, __cont, __pred); }\n \n   template<typename _Key, typename _Tp, typename _Compare, typename _Alloc,\n \t   typename _Predicate>\n-    inline typename multimap<_Key, _Tp, _Compare, _Alloc>::size_type\n-    erase_if(multimap<_Key, _Tp, _Compare, _Alloc>& __cont, _Predicate __pred)\n-    {\n-      _GLIBCXX_STD_C::multimap<_Key, _Tp, _Compare, _Alloc>& __ucont = __cont;\n-      return __detail::__erase_nodes_if(__cont, __ucont, __pred);\n-    }\n+    inline typename _GLIBCXX_STD_C::multimap<_Key, _Tp,\n+\t\t\t\t\t     _Compare, _Alloc>::size_type\n+    erase_if(_GLIBCXX_STD_C::multimap<_Key, _Tp, _Compare, _Alloc>& __cont,\n+\t     _Predicate __pred)\n+    { return __detail::__erase_nodes_if(__cont, __cont, __pred); }\n _GLIBCXX_END_NAMESPACE_VERSION\n } // namespace std\n-#endif // C++20\n+#endif // __cpp_lib_erase_if\n \n #endif /* _GLIBCXX_MAP */\ndiff --git a/libstdc++-v3/include/std/set b/libstdc++-v3/include/std/set\nindex 95b9e26a99fb..af6d3814b4b1 100644\n--- a/libstdc++-v3/include/std/set\n+++ b/libstdc++-v3/include/std/set\n@@ -95,29 +95,25 @@ _GLIBCXX_END_NAMESPACE_VERSION\n } // namespace std\n #endif // C++17\n \n-#if __cplusplus > 201703L\n+#ifdef __cpp_lib_erase_if // C++ >= 20 && HOSTED\n namespace std _GLIBCXX_VISIBILITY(default)\n {\n _GLIBCXX_BEGIN_NAMESPACE_VERSION\n   template<typename _Key, typename _Compare, typename _Alloc,\n \t   typename _Predicate>\n-    inline typename set<_Key, _Compare, _Alloc>::size_type\n-    erase_if(set<_Key, _Compare, _Alloc>& __cont, _Predicate __pred)\n-    {\n-      _GLIBCXX_STD_C::set<_Key, _Compare, _Alloc>& __ucont = __cont;\n-      return __detail::__erase_nodes_if(__cont, __ucont, __pred);\n-    }\n+    inline typename _GLIBCXX_STD_C::set<_Key, _Compare, _Alloc>::size_type\n+    erase_if(_GLIBCXX_STD_C::set<_Key, _Compare, _Alloc>& __cont,\n+\t     _Predicate __pred)\n+    { return __detail::__erase_nodes_if(__cont, __cont, __pred); }\n \n   template<typename _Key, typename _Compare, typename _Alloc,\n \t   typename _Predicate>\n-    inline typename multiset<_Key, _Compare, _Alloc>::size_type\n-    erase_if(multiset<_Key, _Compare, _Alloc>& __cont, _Predicate __pred)\n-    {\n-      _GLIBCXX_STD_C::multiset<_Key, _Compare, _Alloc>& __ucont = __cont;\n-      return __detail::__erase_nodes_if(__cont, __ucont, __pred);\n-    }\n+    inline typename _GLIBCXX_STD_C::multiset<_Key, _Compare, _Alloc>::size_type\n+    erase_if(_GLIBCXX_STD_C::multiset<_Key, _Compare, _Alloc>& __cont,\n+\t     _Predicate __pred)\n+    { return __detail::__erase_nodes_if(__cont, __cont, __pred); }\n _GLIBCXX_END_NAMESPACE_VERSION\n } // namespace std\n-#endif // C++20\n+#endif // __cpp_lib_erase_if\n \n #endif /* _GLIBCXX_SET */\ndiff --git a/libstdc++-v3/include/std/string b/libstdc++-v3/include/std/string\nindex 3748e64964f9..c2b37391fc7a 100644\n--- a/libstdc++-v3/include/std/string\n+++ b/libstdc++-v3/include/std/string\n@@ -54,6 +54,7 @@\n #include <bits/stdexcept_throw.h>\n #include <bits/stl_algobase.h>\n #include <bits/range_access.h>\n+#include <bits/erase_if.h>\n #include <bits/basic_string.h>\n #include <bits/basic_string.tcc>\n #if (_GLIBCXX_HOSTED && __cpp_exceptions && __cplusplus > 202302L \\\n@@ -108,15 +109,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION\n \t   typename _Predicate>\n     constexpr typename basic_string<_CharT, _Traits, _Alloc>::size_type\n     erase_if(basic_string<_CharT, _Traits, _Alloc>& __cont, _Predicate __pred)\n-    {\n-      using namespace __gnu_cxx;\n-      const auto __osz = __cont.size();\n-      const auto __end = __cont.end();\n-      auto __removed = std::__remove_if(__cont.begin(), __end,\n-\t\t\t\t\tstd::move(__pred));\n-      __cont.erase(__removed, __end);\n-      return __osz - __cont.size();\n-    }\n+    { return __detail::__erase_if(__cont, __cont, std::move(__pred)); }\n \n   template<typename _CharT, typename _Traits, typename _Alloc,\n \t   typename _Up _GLIBCXX26_DEF_VAL_T(_CharT)>\ndiff --git a/libstdc++-v3/include/std/unordered_map b/libstdc++-v3/include/std/unordered_map\nindex c49c5c6835f5..9166f569ab1d 100644\n--- a/libstdc++-v3/include/std/unordered_map\n+++ b/libstdc++-v3/include/std/unordered_map\n@@ -80,35 +80,30 @@ _GLIBCXX_END_NAMESPACE_VERSION\n } // namespace std\n #endif // C++17\n \n-#if __cplusplus > 201703L\n+#ifdef __cpp_lib_erase_if // C++ >= 20 && HOSTED\n namespace std _GLIBCXX_VISIBILITY(default)\n {\n _GLIBCXX_BEGIN_NAMESPACE_VERSION\n   template<typename _Key, typename _Tp, typename _Hash, typename _CPred,\n \t   typename _Alloc, typename _Predicate>\n-    inline typename unordered_map<_Key, _Tp, _Hash, _CPred, _Alloc>::size_type\n-    erase_if(unordered_map<_Key, _Tp, _Hash, _CPred, _Alloc>& __cont,\n+    inline typename _GLIBCXX_STD_C::unordered_map<_Key, _Tp, _Hash,\n+\t\t\t\t\t\t  _CPred, _Alloc>::size_type\n+    erase_if(_GLIBCXX_STD_C::unordered_map<_Key, _Tp, _Hash,\n+\t\t\t\t\t   _CPred, _Alloc>& __cont,\n \t     _Predicate __pred)\n-    {\n-      _GLIBCXX_STD_C::unordered_map<_Key, _Tp, _Hash, _CPred, _Alloc>&\n-\t__ucont = __cont;\n-      return __detail::__erase_nodes_if(__cont, __ucont, __pred);\n-    }\n+    { return __detail::__erase_nodes_if(__cont, __cont, __pred); }\n \n   template<typename _Key, typename _Tp, typename _Hash, typename _CPred,\n \t   typename _Alloc, typename _Predicate>\n-    inline typename unordered_multimap<_Key, _Tp, _Hash, _CPred, _Alloc>::\n-\t\t    size_type\n-    erase_if(unordered_multimap<_Key, _Tp, _Hash, _CPred, _Alloc>& __cont,\n+    inline typename _GLIBCXX_STD_C::unordered_multimap<_Key, _Tp, _Hash,\n+\t\t\t\t\t\t      _CPred, _Alloc>::size_type\n+    erase_if(_GLIBCXX_STD_C::unordered_multimap<_Key, _Tp, _Hash,\n+\t\t\t\t\t\t_CPred, _Alloc>& __cont,\n \t     _Predicate __pred)\n-    {\n-      _GLIBCXX_STD_C::unordered_multimap<_Key, _Tp, _Hash, _CPred, _Alloc>&\n-\t__ucont = __cont;\n-      return __detail::__erase_nodes_if(__cont, __ucont, __pred);\n-    }\n+    { return __detail::__erase_nodes_if(__cont, __cont, __pred); }\n _GLIBCXX_END_NAMESPACE_VERSION\n } // namespace std\n-#endif // C++20\n+#endif // __cpp_lib_erase_if\n \n #endif // C++11\n \ndiff --git a/libstdc++-v3/include/std/unordered_set b/libstdc++-v3/include/std/unordered_set\nindex 512d542a0b58..157f72ce32df 100644\n--- a/libstdc++-v3/include/std/unordered_set\n+++ b/libstdc++-v3/include/std/unordered_set\n@@ -78,34 +78,28 @@ _GLIBCXX_END_NAMESPACE_VERSION\n } // namespace std\n #endif // C++17\n \n-#if __cplusplus > 201703L\n+#ifdef __cpp_lib_erase_if // C++ >= 20 && HOSTED\n namespace std _GLIBCXX_VISIBILITY(default)\n {\n _GLIBCXX_BEGIN_NAMESPACE_VERSION\n   template<typename _Key, typename _Hash, typename _CPred, typename _Alloc,\n \t   typename _Predicate>\n-    inline typename unordered_set<_Key, _Hash, _CPred, _Alloc>::size_type\n-    erase_if(unordered_set<_Key, _Hash, _CPred, _Alloc>& __cont,\n+    inline typename _GLIBCXX_STD_C::unordered_set<_Key, _Hash,\n+\t\t\t\t\t\t  _CPred, _Alloc>::size_type\n+    erase_if(_GLIBCXX_STD_C::unordered_set<_Key, _Hash, _CPred, _Alloc>& __cont,\n \t     _Predicate __pred)\n-    {\n-      _GLIBCXX_STD_C::unordered_set<_Key, _Hash, _CPred, _Alloc>&\n-\t__ucont = __cont;\n-      return __detail::__erase_nodes_if(__cont, __ucont, __pred);\n-    }\n+    { return __detail::__erase_nodes_if(__cont, __cont, __pred); }\n \n   template<typename _Key, typename _Hash, typename _CPred, typename _Alloc,\n \t   typename _Predicate>\n-    inline typename unordered_multiset<_Key, _Hash, _CPred, _Alloc>::size_type\n-    erase_if(unordered_multiset<_Key, _Hash, _CPred, _Alloc>& __cont,\n+    inline typename _GLIBCXX_STD_C::unordered_multiset<_Key, _Hash,\n+\t\t\t\t\t\t      _CPred, _Alloc>::size_type\n+    erase_if(_GLIBCXX_STD_C::unordered_multiset<_Key, _Hash, _CPred, _Alloc>& __cont,\n \t     _Predicate __pred)\n-    {\n-      _GLIBCXX_STD_C::unordered_multiset<_Key, _Hash, _CPred, _Alloc>&\n-\t__ucont = __cont;\n-      return __detail::__erase_nodes_if(__cont, __ucont, __pred);\n-    }\n+    { return __detail::__erase_nodes_if(__cont, __cont, __pred); }\n _GLIBCXX_END_NAMESPACE_VERSION\n } // namespace std\n-#endif // C++20\n+#endif // __cpp_lib_erase_if\n \n #endif // C++11\n \ndiff --git a/libstdc++-v3/include/std/vector b/libstdc++-v3/include/std/vector\nindex 61c750f94ff2..343483e95191 100644\n--- a/libstdc++-v3/include/std/vector\n+++ b/libstdc++-v3/include/std/vector\n@@ -68,6 +68,7 @@\n #include <bits/stl_vector.h>\n #include <bits/stl_bvector.h>\n #include <bits/range_access.h>\n+#include <bits/erase_if.h>\n \n #ifndef _GLIBCXX_EXPORT_TEMPLATE\n # include <bits/vector.tcc>\n@@ -114,19 +115,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION\n   template<typename _Tp, typename _Alloc, typename _Predicate>\n     constexpr typename _GLIBCXX_STD_C::vector<_Tp, _Alloc>::size_type\n     erase_if(_GLIBCXX_STD_C::vector<_Tp, _Alloc>& __cont, _Predicate __pred)\n-    {\n-      const auto __osz = __cont.size();\n-      const auto __end = __cont.end();\n-      auto __removed = std::__remove_if(__cont.begin(), __end,\n-\t\t\t\t\tstd::move(__pred));\n-      if (__removed != __end)\n-\t{\n-\t  __cont.erase(__removed, __end);\n-\t  return __osz - __cont.size();\n-\t}\n-\n-      return 0;\n-    }\n+    { return __detail::__erase_if(__cont, __cont, std::move(__pred)); }\n \n   template<typename _Tp, typename _Alloc,\n \t   typename _Up _GLIBCXX26_DEF_VAL_T(_Tp)>\ndiff --git a/libstdc++-v3/testsuite/21_strings/basic_string/debug/erase.cc b/libstdc++-v3/testsuite/21_strings/basic_string/debug/erase.cc\nnew file mode 100644\nindex 000000000000..b381ad157382\n--- /dev/null\n+++ b/libstdc++-v3/testsuite/21_strings/basic_string/debug/erase.cc\n@@ -0,0 +1,25 @@\n+// { dg-do run { target c++20 } }\n+\n+#include <debug/string>\n+#include <testsuite_hooks.h>\n+\n+using __gnu_debug::string;\n+\n+void test01()\n+{\n+  string str(\"abcdefghijklmnopqrstuvwxyz\");\n+\n+  auto before = str.begin();\n+  auto last = str.end() - 1;\n+\n+  VERIFY( std::erase(str, 'd') == 1 );\n+\n+  VERIFY(before._M_singular());\n+  VERIFY(last._M_singular());\n+}\n+\n+int main()\n+{\n+  test01();\n+  return 0;\n+}\ndiff --git a/libstdc++-v3/testsuite/23_containers/forward_list/debug/erase.cc b/libstdc++-v3/testsuite/23_containers/forward_list/debug/erase.cc\nnew file mode 100644\nindex 000000000000..061dfcbd9e31\n--- /dev/null\n+++ b/libstdc++-v3/testsuite/23_containers/forward_list/debug/erase.cc\n@@ -0,0 +1,26 @@\n+// { dg-do run { target c++20 } }\n+// { dg-require-debug-mode \"\" }\n+\n+#include <forward_list>\n+#include <testsuite_hooks.h>\n+\n+void test01()\n+{\n+  std::forward_list<int> fl({ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 });\n+\n+  auto before = ++fl.begin();\n+  auto match = std::next(fl.begin(), 6);\n+  auto last = std::next(fl.begin(), 9);\n+\n+  VERIFY( std::erase(fl, 6) == 1 );\n+\n+  VERIFY(before._M_dereferenceable());\n+  VERIFY(match._M_singular());\n+  VERIFY(last._M_dereferenceable());\n+}\n+\n+int main()\n+{\n+  test01();\n+  return 0;\n+}\ndiff --git a/libstdc++-v3/testsuite/23_containers/forward_list/debug/invalidation/erase.cc b/libstdc++-v3/testsuite/23_containers/forward_list/debug/invalidation/erase.cc\nnew file mode 100644\nindex 000000000000..15194173cc34\n--- /dev/null\n+++ b/libstdc++-v3/testsuite/23_containers/forward_list/debug/invalidation/erase.cc\n@@ -0,0 +1,27 @@\n+// { dg-do run { target c++20 } }\n+\n+#include <debug/forward_list>\n+#include <testsuite_hooks.h>\n+\n+using __gnu_debug::forward_list;\n+\n+void test01()\n+{\n+  forward_list<int> fl({ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 });\n+\n+  auto before = ++fl.begin();\n+  auto match = std::next(fl.begin(), 6);\n+  auto last = std::next(fl.begin(), 9);\n+\n+  VERIFY( std::erase(fl, 6) == 1 );\n+\n+  VERIFY(before._M_dereferenceable());\n+  VERIFY(match._M_singular());\n+  VERIFY(last._M_dereferenceable());\n+}\n+\n+int main()\n+{\n+  test01();\n+  return 0;\n+}\ndiff --git a/libstdc++-v3/testsuite/23_containers/list/debug/erase.cc b/libstdc++-v3/testsuite/23_containers/list/debug/erase.cc\nnew file mode 100644\nindex 000000000000..d6210daf3446\n--- /dev/null\n+++ b/libstdc++-v3/testsuite/23_containers/list/debug/erase.cc\n@@ -0,0 +1,29 @@\n+// { dg-do run { target c++20 } }\n+// { dg-require-debug-mode \"\" }\n+\n+#include <list>\n+#include <testsuite_hooks.h>\n+\n+void test01()\n+{\n+  std::list<int> l;\n+\n+  for (int i = 0; i != 10; ++i)\n+    l.push_back(i);\n+\n+  auto before = ++l.begin();\n+  auto match = std::next(l.begin(), 6);\n+  auto last = --l.end();\n+\n+  VERIFY( std::erase(l, 6) == 1 );\n+\n+  VERIFY(before._M_dereferenceable());\n+  VERIFY(match._M_singular());\n+  VERIFY(last._M_dereferenceable());\n+}\n+\n+int main()\n+{\n+  test01();\n+  return 0;\n+}\ndiff --git a/libstdc++-v3/testsuite/23_containers/list/debug/invalidation/erase.cc b/libstdc++-v3/testsuite/23_containers/list/debug/invalidation/erase.cc\nnew file mode 100644\nindex 000000000000..57137fd08d62\n--- /dev/null\n+++ b/libstdc++-v3/testsuite/23_containers/list/debug/invalidation/erase.cc\n@@ -0,0 +1,30 @@\n+// { dg-do run { target c++20 } }\n+\n+#include <debug/list>\n+#include <testsuite_hooks.h>\n+\n+using __gnu_debug::list;\n+\n+void test01()\n+{\n+  list<int> l;\n+\n+  for (int i = 0; i != 10; ++i)\n+    l.push_back(i);\n+\n+  auto before = ++l.begin();\n+  auto match = std::next(l.begin(), 6);\n+  auto last = --l.end();\n+\n+  VERIFY( std::erase(l, 6) == 1 );\n+\n+  VERIFY(before._M_dereferenceable());\n+  VERIFY(match._M_singular());\n+  VERIFY(last._M_dereferenceable());\n+}\n+\n+int main()\n+{\n+  test01();\n+  return 0;\n+}\ndiff --git a/libstdc++-v3/testsuite/23_containers/map/debug/erase_if.cc b/libstdc++-v3/testsuite/23_containers/map/debug/erase_if.cc\nnew file mode 100644\nindex 000000000000..dfdfc1340fac\n--- /dev/null\n+++ b/libstdc++-v3/testsuite/23_containers/map/debug/erase_if.cc\n@@ -0,0 +1,33 @@\n+// { dg-do run { target c++20 } }\n+// { dg-require-debug-mode \"\" }\n+\n+#include <map>\n+#include <testsuite_hooks.h>\n+\n+auto is_six_pair = [](const std::pair<const int, int>& p)\n+{\n+  return p.first == 6;\n+};\n+\n+void test01()\n+{\n+  std::map<int, int> m;\n+  for (int i = 0; i != 10; ++i)\n+    m.insert({ i, i });\n+\n+  auto before = ++m.begin();\n+  auto match = std::next(m.begin(), 6);\n+  auto last = std::next(m.begin(), 9);\n+\n+  VERIFY( std::erase_if(m, is_six_pair) == 1 );\n+\n+  VERIFY(before._M_dereferenceable());\n+  VERIFY(match._M_singular());\n+  VERIFY(last._M_dereferenceable());\n+}\n+\n+int main()\n+{\n+  test01();\n+  return 0;\n+}\ndiff --git a/libstdc++-v3/testsuite/23_containers/map/debug/invalidation/erase_if.cc b/libstdc++-v3/testsuite/23_containers/map/debug/invalidation/erase_if.cc\nnew file mode 100644\nindex 000000000000..ee080c31160f\n--- /dev/null\n+++ b/libstdc++-v3/testsuite/23_containers/map/debug/invalidation/erase_if.cc\n@@ -0,0 +1,34 @@\n+// { dg-do run { target c++20 } }\n+\n+#include <debug/map>\n+#include <testsuite_hooks.h>\n+\n+auto is_six_pair = [](const std::pair<const int, int>& p)\n+{\n+  return p.first == 6;\n+};\n+\n+using __gnu_debug::map;\n+\n+void test01()\n+{\n+  map<int, int> m;\n+  for (int i = 0; i != 10; ++i)\n+    m.insert({ i, i });\n+\n+  auto before = ++m.begin();\n+  auto match = std::next(m.begin(), 6);\n+  auto last = std::next(m.begin(), 9);\n+\n+  VERIFY( std::erase_if(m, is_six_pair) == 1 );\n+\n+  VERIFY(before._M_dereferenceable());\n+  VERIFY(match._M_singular());\n+  VERIFY(last._M_dereferenceable());\n+}\n+\n+int main()\n+{\n+  test01();\n+  return 0;\n+}\ndiff --git a/libstdc++-v3/testsuite/23_containers/multimap/debug/erase_if.cc b/libstdc++-v3/testsuite/23_containers/multimap/debug/erase_if.cc\nnew file mode 100644\nindex 000000000000..30b6b65e703c\n--- /dev/null\n+++ b/libstdc++-v3/testsuite/23_containers/multimap/debug/erase_if.cc\n@@ -0,0 +1,33 @@\n+// { dg-do run { target c++20 } }\n+// { dg-require-debug-mode \"\" }\n+\n+#include <map>\n+#include <testsuite_hooks.h>\n+\n+auto is_six_pair = [](const std::pair<const int, int>& p)\n+{\n+  return p.first == 6;\n+};\n+\n+void test01()\n+{\n+  std::multimap<int, int> m;\n+  for (int i = 0; i != 10; ++i)\n+    m.insert({ i, i });\n+\n+  auto before = ++m.begin();\n+  auto match = std::next(m.begin(), 6);\n+  auto last = std::next(m.begin(), 9);\n+\n+  VERIFY( std::erase_if(m, is_six_pair) == 1 );\n+\n+  VERIFY(before._M_dereferenceable());\n+  VERIFY(match._M_singular());\n+  VERIFY(last._M_dereferenceable());\n+}\n+\n+int main()\n+{\n+  test01();\n+  return 0;\n+}\ndiff --git a/libstdc++-v3/testsuite/23_containers/multimap/debug/invalidation/erase_if.cc b/libstdc++-v3/testsuite/23_containers/multimap/debug/invalidation/erase_if.cc\nnew file mode 100644\nindex 000000000000..c9f740ea4e6f\n--- /dev/null\n+++ b/libstdc++-v3/testsuite/23_containers/multimap/debug/invalidation/erase_if.cc\n@@ -0,0 +1,34 @@\n+// { dg-do run { target c++20 } }\n+\n+#include <debug/map>\n+#include <testsuite_hooks.h>\n+\n+auto is_six_pair = [](const std::pair<const int, int>& p)\n+{\n+  return p.first == 6;\n+};\n+\n+using __gnu_debug::multimap;\n+\n+void test01()\n+{\n+  multimap<int, int> m;\n+  for (int i = 0; i != 10; ++i)\n+    m.insert({ i, i });\n+\n+  auto before = ++m.begin();\n+  auto match = std::next(m.begin(), 6);\n+  auto last = std::next(m.begin(), 9);\n+\n+  VERIFY( std::erase_if(m, is_six_pair) == 1 );\n+\n+  VERIFY(before._M_dereferenceable());\n+  VERIFY(match._M_singular());\n+  VERIFY(last._M_dereferenceable());\n+}\n+\n+int main()\n+{\n+  test01();\n+  return 0;\n+}\ndiff --git a/libstdc++-v3/testsuite/23_containers/multiset/debug/erase_if.cc b/libstdc++-v3/testsuite/23_containers/multiset/debug/erase_if.cc\nnew file mode 100644\nindex 000000000000..e54eaa797f87\n--- /dev/null\n+++ b/libstdc++-v3/testsuite/23_containers/multiset/debug/erase_if.cc\n@@ -0,0 +1,31 @@\n+// { dg-do run { target c++20 } }\n+// { dg-require-debug-mode \"\" }\n+\n+#include <set>\n+#include <testsuite_hooks.h>\n+\n+auto is_six = [](int p)\n+{ return p == 6; };\n+\n+void test01()\n+{\n+  std::multiset<int> s;\n+  for (int i = 0; i != 10; ++i)\n+    s.insert(i);\n+\n+  auto before = ++s.begin();\n+  auto match = std::next(s.begin(), 6);\n+  auto last = std::next(s.begin(), 9);\n+\n+  VERIFY( std::erase_if(s, is_six) == 1 );\n+\n+  VERIFY(before._M_dereferenceable());\n+  VERIFY(match._M_singular());\n+  VERIFY(last._M_dereferenceable());\n+}\n+\n+int main()\n+{\n+  test01();\n+  return 0;\n+}\ndiff --git a/libstdc++-v3/testsuite/23_containers/multiset/debug/invalidation/erase_if.cc b/libstdc++-v3/testsuite/23_containers/multiset/debug/invalidation/erase_if.cc\nnew file mode 100644\nindex 000000000000..c85b76fc506d\n--- /dev/null\n+++ b/libstdc++-v3/testsuite/23_containers/multiset/debug/invalidation/erase_if.cc\n@@ -0,0 +1,32 @@\n+// { dg-do run { target c++20 } }\n+\n+#include <debug/set>\n+#include <testsuite_hooks.h>\n+\n+auto is_six = [](int p)\n+{ return p == 6; };\n+\n+using __gnu_debug::multiset;\n+\n+void test01()\n+{\n+  multiset<int> s;\n+  for (int i = 0; i != 10; ++i)\n+    s.insert(i);\n+\n+  auto before = ++s.begin();\n+  auto match = std::next(s.begin(), 6);\n+  auto last = std::next(s.begin(), 9);\n+\n+  VERIFY( std::erase_if(s, is_six) == 1 );\n+\n+  VERIFY(before._M_dereferenceable());\n+  VERIFY(match._M_singular());\n+  VERIFY(last._M_dereferenceable());\n+}\n+\n+int main()\n+{\n+  test01();\n+  return 0;\n+}\ndiff --git a/libstdc++-v3/testsuite/23_containers/set/debug/erase_if.cc b/libstdc++-v3/testsuite/23_containers/set/debug/erase_if.cc\nnew file mode 100644\nindex 000000000000..e8c64628a658\n--- /dev/null\n+++ b/libstdc++-v3/testsuite/23_containers/set/debug/erase_if.cc\n@@ -0,0 +1,31 @@\n+// { dg-do run { target c++20 } }\n+// { dg-require-debug-mode \"\" }\n+\n+#include <set>\n+#include <testsuite_hooks.h>\n+\n+auto is_six = [](int p)\n+{ return p == 6; };\n+\n+void test01()\n+{\n+  std::set<int> s;\n+  for (int i = 0; i != 10; ++i)\n+    s.insert(i);\n+\n+  auto before = ++s.begin();\n+  auto match = std::next(s.begin(), 6);\n+  auto last = std::next(s.begin(), 9);\n+\n+  VERIFY( std::erase_if(s, is_six) == 1 );\n+\n+  VERIFY(before._M_dereferenceable());\n+  VERIFY(match._M_singular());\n+  VERIFY(last._M_dereferenceable());\n+}\n+\n+int main()\n+{\n+  test01();\n+  return 0;\n+}\ndiff --git a/libstdc++-v3/testsuite/23_containers/set/debug/invalidation/erase_if.cc b/libstdc++-v3/testsuite/23_containers/set/debug/invalidation/erase_if.cc\nnew file mode 100644\nindex 000000000000..99dde9bfcf29\n--- /dev/null\n+++ b/libstdc++-v3/testsuite/23_containers/set/debug/invalidation/erase_if.cc\n@@ -0,0 +1,32 @@\n+// { dg-do run { target c++20 } }\n+\n+#include <debug/set>\n+#include <testsuite_hooks.h>\n+\n+auto is_six = [](int p)\n+{ return p == 6; };\n+\n+using __gnu_debug::set;\n+\n+void test01()\n+{\n+  set<int> s;\n+  for (int i = 0; i != 10; ++i)\n+    s.insert(i);\n+\n+  auto before = ++s.begin();\n+  auto match = std::next(s.begin(), 6);\n+  auto last = std::next(s.begin(), 9);\n+\n+  VERIFY( std::erase_if(s, is_six) == 1 );\n+\n+  VERIFY(before._M_dereferenceable());\n+  VERIFY(match._M_singular());\n+  VERIFY(last._M_dereferenceable());\n+}\n+\n+int main()\n+{\n+  test01();\n+  return 0;\n+}\ndiff --git a/libstdc++-v3/testsuite/23_containers/unordered_map/debug/erase_if.cc b/libstdc++-v3/testsuite/23_containers/unordered_map/debug/erase_if.cc\nnew file mode 100644\nindex 000000000000..e7ac643c8ec5\n--- /dev/null\n+++ b/libstdc++-v3/testsuite/23_containers/unordered_map/debug/erase_if.cc\n@@ -0,0 +1,33 @@\n+// { dg-do run { target c++20 } }\n+// { dg-require-debug-mode \"\" }\n+\n+#include <unordered_map>\n+#include <testsuite_hooks.h>\n+\n+auto is_six_pair = [](const std::pair<const int, int>& p)\n+{\n+  return p.first == 6;\n+};\n+\n+void test01()\n+{\n+  std::unordered_map<int, int> m;\n+  for (int i = 0; i != 10; ++i)\n+    m.insert({ i, i });\n+\n+  auto before = m.find(1);\n+  auto match = m.find(6);\n+  auto last = m.find(9);\n+\n+  VERIFY( std::erase_if(m, is_six_pair) == 1 );\n+\n+  VERIFY(before._M_dereferenceable());\n+  VERIFY(match._M_singular());\n+  VERIFY(last._M_dereferenceable());\n+}\n+\n+int main()\n+{\n+  test01();\n+  return 0;\n+}\ndiff --git a/libstdc++-v3/testsuite/23_containers/unordered_map/debug/invalidation/erase_if.cc b/libstdc++-v3/testsuite/23_containers/unordered_map/debug/invalidation/erase_if.cc\nnew file mode 100644\nindex 000000000000..303692838ac4\n--- /dev/null\n+++ b/libstdc++-v3/testsuite/23_containers/unordered_map/debug/invalidation/erase_if.cc\n@@ -0,0 +1,34 @@\n+// { dg-do run { target c++20 } }\n+\n+#include <debug/unordered_map>\n+#include <testsuite_hooks.h>\n+\n+auto is_six_pair = [](const std::pair<const int, int>& p)\n+{\n+  return p.first == 6;\n+};\n+\n+using __gnu_debug::unordered_map;\n+\n+void test01()\n+{\n+  unordered_map<int, int> m;\n+  for (int i = 0; i != 10; ++i)\n+    m.insert({ i, i });\n+\n+  auto before = m.find(1);\n+  auto match = m.find(6);\n+  auto last = m.find(9);\n+\n+  VERIFY( std::erase_if(m, is_six_pair) == 1 );\n+\n+  VERIFY(before._M_dereferenceable());\n+  VERIFY(match._M_singular());\n+  VERIFY(last._M_dereferenceable());\n+}\n+\n+int main()\n+{\n+  test01();\n+  return 0;\n+}\ndiff --git a/libstdc++-v3/testsuite/23_containers/unordered_multimap/debug/erase_if.cc b/libstdc++-v3/testsuite/23_containers/unordered_multimap/debug/erase_if.cc\nnew file mode 100644\nindex 000000000000..e8d98c96e6b6\n--- /dev/null\n+++ b/libstdc++-v3/testsuite/23_containers/unordered_multimap/debug/erase_if.cc\n@@ -0,0 +1,33 @@\n+// { dg-do run { target c++20 } }\n+// { dg-require-debug-mode \"\" }\n+\n+#include <unordered_map>\n+#include <testsuite_hooks.h>\n+\n+auto is_six_pair = [](const std::pair<const int, int>& p)\n+{\n+  return p.first == 6;\n+};\n+\n+void test01()\n+{\n+  std::unordered_multimap<int, int> m;\n+  for (int i = 0; i != 10; ++i)\n+    m.insert({ i, i });\n+\n+  auto before = m.find(1);\n+  auto match = m.find(6);\n+  auto last = m.find(9);\n+\n+  VERIFY( std::erase_if(m, is_six_pair) == 1 );\n+\n+  VERIFY(before._M_dereferenceable());\n+  VERIFY(match._M_singular());\n+  VERIFY(last._M_dereferenceable());\n+}\n+\n+int main()\n+{\n+  test01();\n+  return 0;\n+}\ndiff --git a/libstdc++-v3/testsuite/23_containers/unordered_multimap/debug/invalidation/erase_if.cc b/libstdc++-v3/testsuite/23_containers/unordered_multimap/debug/invalidation/erase_if.cc\nnew file mode 100644\nindex 000000000000..375393365051\n--- /dev/null\n+++ b/libstdc++-v3/testsuite/23_containers/unordered_multimap/debug/invalidation/erase_if.cc\n@@ -0,0 +1,34 @@\n+// { dg-do run { target c++20 } }\n+\n+#include <debug/unordered_map>\n+#include <testsuite_hooks.h>\n+\n+auto is_six_pair = [](const std::pair<const int, int>& p)\n+{\n+  return p.first == 6;\n+};\n+\n+using __gnu_debug::unordered_multimap;\n+\n+void test01()\n+{\n+  unordered_multimap<int, int> m;\n+  for (int i = 0; i != 10; ++i)\n+    m.insert({ i, i });\n+\n+  auto before = m.find(1);\n+  auto match = m.find(6);\n+  auto last = m.find(9);\n+\n+  VERIFY( std::erase_if(m, is_six_pair) == 1 );\n+\n+  VERIFY(before._M_dereferenceable());\n+  VERIFY(match._M_singular());\n+  VERIFY(last._M_dereferenceable());\n+}\n+\n+int main()\n+{\n+  test01();\n+  return 0;\n+}\ndiff --git a/libstdc++-v3/testsuite/23_containers/unordered_multiset/debug/erase_if.cc b/libstdc++-v3/testsuite/23_containers/unordered_multiset/debug/erase_if.cc\nnew file mode 100644\nindex 000000000000..8969a9dad5f1\n--- /dev/null\n+++ b/libstdc++-v3/testsuite/23_containers/unordered_multiset/debug/erase_if.cc\n@@ -0,0 +1,31 @@\n+// { dg-do run { target c++20 } }\n+// { dg-require-debug-mode \"\" }\n+\n+#include <unordered_set>\n+#include <testsuite_hooks.h>\n+\n+auto is_six = [](int p)\n+{ return p == 6; };\n+\n+void test01()\n+{\n+  std::unordered_multiset<int> s;\n+  for (int i = 0; i != 10; ++i)\n+    s.insert(i);\n+\n+  auto before = s.find(1);\n+  auto match = s.find(6);\n+  auto last = s.find(9);\n+\n+  VERIFY( std::erase_if(s, is_six) == 1 );\n+\n+  VERIFY(before._M_dereferenceable());\n+  VERIFY(match._M_singular());\n+  VERIFY(last._M_dereferenceable());\n+}\n+\n+int main()\n+{\n+  test01();\n+  return 0;\n+}\ndiff --git a/libstdc++-v3/testsuite/23_containers/unordered_multiset/debug/invalidation/erase_if.cc b/libstdc++-v3/testsuite/23_containers/unordered_multiset/debug/invalidation/erase_if.cc\nnew file mode 100644\nindex 000000000000..f5ec00e2c1a6\n--- /dev/null\n+++ b/libstdc++-v3/testsuite/23_containers/unordered_multiset/debug/invalidation/erase_if.cc\n@@ -0,0 +1,32 @@\n+// { dg-do run { target c++20 } }\n+\n+#include <debug/unordered_set>\n+#include <testsuite_hooks.h>\n+\n+auto is_six = [](int p)\n+{ return p == 6; };\n+\n+using __gnu_debug::unordered_multiset;\n+\n+void test01()\n+{\n+  unordered_multiset<int> s;\n+  for (int i = 0; i != 10; ++i)\n+    s.insert(i);\n+\n+  auto before = s.find(1);\n+  auto match = s.find(6);\n+  auto last = s.find(9);\n+\n+  VERIFY( std::erase_if(s, is_six) == 1 );\n+\n+  VERIFY(before._M_dereferenceable());\n+  VERIFY(match._M_singular());\n+  VERIFY(last._M_dereferenceable());\n+}\n+\n+int main()\n+{\n+  test01();\n+  return 0;\n+}\ndiff --git a/libstdc++-v3/testsuite/23_containers/unordered_set/debug/erase_if.cc b/libstdc++-v3/testsuite/23_containers/unordered_set/debug/erase_if.cc\nnew file mode 100644\nindex 000000000000..c725b94558ab\n--- /dev/null\n+++ b/libstdc++-v3/testsuite/23_containers/unordered_set/debug/erase_if.cc\n@@ -0,0 +1,31 @@\n+// { dg-do run { target c++20 } }\n+// { dg-require-debug-mode \"\" }\n+\n+#include <unordered_set>\n+#include <testsuite_hooks.h>\n+\n+auto is_six = [](int p)\n+{ return p == 6; };\n+\n+void test01()\n+{\n+  std::unordered_set<int> s;\n+  for (int i = 0; i != 10; ++i)\n+    s.insert(i);\n+\n+  auto before = s.find(1);\n+  auto match = s.find(6);\n+  auto last = s.find(9);\n+\n+  VERIFY( std::erase_if(s, is_six) == 1 );\n+\n+  VERIFY(before._M_dereferenceable());\n+  VERIFY(match._M_singular());\n+  VERIFY(last._M_dereferenceable());\n+}\n+\n+int main()\n+{\n+  test01();\n+  return 0;\n+}\ndiff --git a/libstdc++-v3/testsuite/23_containers/unordered_set/debug/invalidation/erase_if.cc b/libstdc++-v3/testsuite/23_containers/unordered_set/debug/invalidation/erase_if.cc\nnew file mode 100644\nindex 000000000000..61c1cffca222\n--- /dev/null\n+++ b/libstdc++-v3/testsuite/23_containers/unordered_set/debug/invalidation/erase_if.cc\n@@ -0,0 +1,32 @@\n+// { dg-do run { target c++20 } }\n+\n+#include <debug/unordered_set>\n+#include <testsuite_hooks.h>\n+\n+auto is_six = [](int p)\n+{ return p == 6; };\n+\n+using __gnu_debug::unordered_set;\n+\n+void test01()\n+{\n+  unordered_set<int> s;\n+  for (int i = 0; i != 10; ++i)\n+    s.insert(i);\n+\n+  auto before = s.find(1);\n+  auto match = s.find(6);\n+  auto last = s.find(9);\n+\n+  VERIFY( std::erase_if(s, is_six) == 1 );\n+\n+  VERIFY(before._M_dereferenceable());\n+  VERIFY(match._M_singular());\n+  VERIFY(last._M_dereferenceable());\n+}\n+\n+int main()\n+{\n+  test01();\n+  return 0;\n+}\n","prefixes":["v1","1/1"]}