[gcc r15-9751] libstdc++: Fix tuple/pair confusion with std::erase_if(flat_map) [PR120465]

Patrick Palka ppalka@gcc.gnu.org
Sun Jun 1 15:09:42 GMT 2025


https://gcc.gnu.org/g:48d6f5dbb0e412266ebb77def04ed378ca856029

commit r15-9751-g48d6f5dbb0e412266ebb77def04ed378ca856029
Author: Patrick Palka <ppalka@redhat.com>
Date:   Thu May 29 10:11:57 2025 -0400

    libstdc++: Fix tuple/pair confusion with std::erase_if(flat_map) [PR120465]
    
    std::erase_if for flat_map/multimap is implemented via ranges::erase_if
    over a zip_view of the keys and values, the value_type of which is a
    tuple, but the given predicate needs to be called with a pair (flat_map's
    value_type).  So use a projection to convert the tuple into a suitable
    pair.
    
            PR libstdc++/120465
    
    libstdc++-v3/ChangeLog:
    
            * include/std/flat_map (_Flat_map_impl::_M_erase_if): Use a
            projection with ranges::remove_if to pass a pair instead of
            a tuple to the predicate.
            * testsuite/23_containers/flat_map/1.cc (test07): Strengthen
            to expect the argument passed to the predicate is a pair.
            * testsuite/23_containers/flat_multimap/1.cc (test07): Likewise.
    
    Co-authored-by: Jonathan Wakely <jwakely@redhat.com>
    Reviewed-by: Tomasz Kamiński <tkaminsk@redhat.com>
    Reviewed-by: Jonathan Wakely <jwakely@redhat.com>
    (cherry picked from commit 589b27ec5769410e036df57645ff1eb7c765f692)

Diff:
---
 libstdc++-v3/include/std/flat_map                       | 5 ++++-
 libstdc++-v3/testsuite/23_containers/flat_map/1.cc      | 3 ++-
 libstdc++-v3/testsuite/23_containers/flat_multimap/1.cc | 3 ++-
 3 files changed, 8 insertions(+), 3 deletions(-)

diff --git a/libstdc++-v3/include/std/flat_map b/libstdc++-v3/include/std/flat_map
index 6593988d213c..cec7f36cff9f 100644
--- a/libstdc++-v3/include/std/flat_map
+++ b/libstdc++-v3/include/std/flat_map
@@ -895,7 +895,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	{
 	  auto __guard = _M_make_clear_guard();
 	  auto __zv = views::zip(_M_cont.keys, _M_cont.values);
-	  auto __sr = ranges::remove_if(__zv, __pred);
+	  auto __sr = ranges::remove_if(__zv, __pred,
+					[](const auto& __e) {
+					  return const_reference(__e);
+					});
 	  auto __erased = __sr.size();
 	  erase(end() - __erased, end());
 	  __guard._M_disable();
diff --git a/libstdc++-v3/testsuite/23_containers/flat_map/1.cc b/libstdc++-v3/testsuite/23_containers/flat_map/1.cc
index 38fd449c56b3..9d99796878e1 100644
--- a/libstdc++-v3/testsuite/23_containers/flat_map/1.cc
+++ b/libstdc++-v3/testsuite/23_containers/flat_map/1.cc
@@ -245,8 +245,9 @@ void
 test07()
 {
   // PR libstdc++/119427 - std::erase_if(std::flat_foo) does not work
+  // PR libstdc++/120465 - erase_if for flat_map calls predicate with incorrect type
   std::flat_map<int, int> m = {std::pair{1, 2}, {3, 4}, {5, 6}};
-  auto n = std::erase_if(m, [](auto x) { auto [k,v] = x; return k == 1 || v == 6; });
+  auto n = std::erase_if(m, [](auto x) { return x.first == 1 || x.second == 6; });
   VERIFY( n == 2 );
   VERIFY( std::ranges::equal(m, (std::pair<int,int>[]){{3,4}}) );
 }
diff --git a/libstdc++-v3/testsuite/23_containers/flat_multimap/1.cc b/libstdc++-v3/testsuite/23_containers/flat_multimap/1.cc
index 79fbc1a7f6a9..001095587f4b 100644
--- a/libstdc++-v3/testsuite/23_containers/flat_multimap/1.cc
+++ b/libstdc++-v3/testsuite/23_containers/flat_multimap/1.cc
@@ -223,8 +223,9 @@ void
 test07()
 {
   // PR libstdc++/119427 - std::erase_if(std::flat_foo) does not work
+  // PR libstdc++/120465 - erase_if for flat_map calls predicate with incorrect type
   std::flat_multimap<int, int> m = {std::pair{1, 2}, {3, 4}, {3, 3}, {5, 6}, {6, 6}};
-  auto n = std::erase_if(m, [](auto x) { auto [k,v] = x; return k == 1 || v == 6; });
+  auto n = std::erase_if(m, [](auto x) { return x.first == 1 || x.second == 6; });
   VERIFY( n == 3 );
   VERIFY( std::ranges::equal(m, (std::pair<int,int>[]){{3,4},{3,3}}) );
 }


More information about the Libstdc++-cvs mailing list