On Thu, May 29, 2025 at 4:01 AM Patrick Palka <ppa...@redhat.com> wrote:
> std::erase_if for flat_map / flat_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. So use a projection to convert the tuple into the corresponding > pair type. > > 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 <jwak...@redhat.com> > --- > LGTM. > 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 5f9a2eda1939..c0716d12412a 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 2af516410279..01278d7dc33c 100644 > --- a/libstdc++-v3/testsuite/23_containers/flat_map/1.cc > +++ b/libstdc++-v3/testsuite/23_containers/flat_map/1.cc > @@ -247,8 +247,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 1c5c9a88ab6b..d746614401de 100644 > --- a/libstdc++-v3/testsuite/23_containers/flat_multimap/1.cc > +++ b/libstdc++-v3/testsuite/23_containers/flat_multimap/1.cc > @@ -225,8 +225,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}}) ); > } > -- > 2.50.0.rc0 > >