From: Patrick Palka Date: Tue, 29 Apr 2025 12:21:35 +0000 (-0400) Subject: libstdc++: Fix availability of std::erase_if(std::flat_foo) [PR119427] X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=aa93272cfd2233858da0792761387cc27f4d5ff3;p=thirdparty%2Fgcc.git libstdc++: Fix availability of std::erase_if(std::flat_foo) [PR119427] These std::erase_if overloads were wrongly implemented as hidden friends, visible only via ADL, so erase_if(x) would work but not std::erase_if(x). PR libstdc++/119427 libstdc++-v3/ChangeLog: * include/std/flat_map (_Flat_map_impl::erase_if): Replace this hidden friend with ... (_Flat_map_impl::_M_erase_if): ... this member function. (flat_map): Export _Flat_map_impl::_M_erase_if. (erase_if(flat_map)): Define. (flat_multimap): Export _Flat_map_impl::_M_erase_if. (erase_if(flat_multimap)): Define. * include/std/flat_set (_Flat_set_impl::erase_if): Replace with ... (_Flat_set_impl::_M_erase_if): ... this member function. (flat_set): Export _Flat_set_impl::_M_erase_if. (erase_if(flat_set)): Define. (flat_multiset): Export _Flat_set_impl::_M_erase_if. (erase_if(flat_multiset)): Define. * testsuite/23_containers/flat_map/1.cc (test07): New test. * testsuite/23_containers/flat_multimap/1.cc (test07): New test. * testsuite/23_containers/flat_multiset/1.cc (test09): New test. * testsuite/23_containers/flat_set/1.cc (test09): New test. Reviewed-by: Jonathan Wakely --- diff --git a/libstdc++-v3/include/std/flat_map b/libstdc++-v3/include/std/flat_map index 405caa8a81b..6593988d213 100644 --- a/libstdc++-v3/include/std/flat_map +++ b/libstdc++-v3/include/std/flat_map @@ -890,14 +890,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return __x.swap(__y); } template - friend size_type - erase_if(_Derived& __c, _Predicate __pred) + size_type + _M_erase_if(_Predicate __pred) { - auto __guard = __c._M_make_clear_guard(); - auto __zv = views::zip(__c._M_cont.keys, __c._M_cont.values); + auto __guard = _M_make_clear_guard(); + auto __zv = views::zip(_M_cont.keys, _M_cont.values); auto __sr = ranges::remove_if(__zv, __pred); auto __erased = __sr.size(); - __c.erase(__c.end() - __erased, __c.end()); + erase(end() - __erased, end()); __guard._M_disable(); return __erased; } @@ -1329,6 +1329,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION using _Impl::lower_bound; using _Impl::upper_bound; using _Impl::equal_range; + + using _Impl::_M_erase_if; }; template> { }; + template + typename flat_map<_Key, _Tp, _Compare, _KeyContainer, _MappedContainer>::size_type + erase_if(flat_map<_Key, _Tp, _Compare, _KeyContainer, _MappedContainer>& __c, + _Predicate __pred) + { return __c._M_erase_if(std::move(__pred)); } + /* Class template flat_multimap - container adaptor * * @ingroup @@ -1487,6 +1496,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION using _Impl::lower_bound; using _Impl::upper_bound; using _Impl::equal_range; + + using _Impl::_M_erase_if; }; template> { }; + template + typename flat_multimap<_Key, _Tp, _Compare, _KeyContainer, _MappedContainer>::size_type + erase_if(flat_multimap<_Key, _Tp, _Compare, _KeyContainer, _MappedContainer>& __c, + _Predicate __pred) + { return __c._M_erase_if(std::move(__pred)); } + _GLIBCXX_END_NAMESPACE_VERSION } // namespace std #endif // __cpp_lib_flat_map diff --git a/libstdc++-v3/include/std/flat_set b/libstdc++-v3/include/std/flat_set index 3e15d1af416..c48340d7980 100644 --- a/libstdc++-v3/include/std/flat_set +++ b/libstdc++-v3/include/std/flat_set @@ -745,15 +745,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return __x.swap(__y); } template - friend size_type - erase_if(_Derived& __c, _Predicate __pred) + size_type + _M_erase_if(_Predicate __pred) { - auto __guard = __c._M_make_clear_guard(); - auto __first = __c._M_cont.begin(); - auto __last = __c._M_cont.end(); + auto __guard = _M_make_clear_guard(); + auto __first = _M_cont.begin(); + auto __last = _M_cont.end(); __first = std::remove_if(__first, __last, __pred); auto __n = __last - __first; - __c.erase(__first, __last); + erase(__first, __last); __guard._M_disable(); return __n; } @@ -860,6 +860,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION using _Impl::lower_bound; using _Impl::upper_bound; using _Impl::equal_range; + + using _Impl::_M_erase_if; }; template> { }; + template + typename flat_set<_Key, _Compare, _KeyContainer>::size_type + erase_if(flat_set<_Key, _Compare, _KeyContainer>& __c, _Predicate __pred) + { return __c._M_erase_if(std::move(__pred)); } + /* Class template flat_multiset - container adaptor * * @ingroup @@ -999,6 +1007,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION using _Impl::lower_bound; using _Impl::upper_bound; using _Impl::equal_range; + + using _Impl::_M_erase_if; }; template> { }; + template + typename flat_multiset<_Key, _Compare, _KeyContainer>::size_type + erase_if(flat_multiset<_Key, _Compare, _KeyContainer>& __c, _Predicate __pred) + { return __c._M_erase_if(std::move(__pred)); } + _GLIBCXX_END_NAMESPACE_VERSION } // namespace std #endif // __cpp_lib_flat_set diff --git a/libstdc++-v3/testsuite/23_containers/flat_map/1.cc b/libstdc++-v3/testsuite/23_containers/flat_map/1.cc index a4e0d867c93..a9690208b09 100644 --- a/libstdc++-v3/testsuite/23_containers/flat_map/1.cc +++ b/libstdc++-v3/testsuite/23_containers/flat_map/1.cc @@ -243,6 +243,16 @@ test06() VERIFY( std::ranges::equal(m | std::views::values, (int[]){2, 3, 4, 5, 6}) ); } +void +test07() +{ + // PR libstdc++/119427 - std::erase_if(std::flat_foo) does not work + std::flat_map 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; }); + VERIFY( n == 2 ); + VERIFY( std::ranges::equal(m, (std::pair[]){{3,4}}) ); +} + int main() { @@ -255,4 +265,5 @@ main() test04(); test05(); test06(); + test07(); } diff --git a/libstdc++-v3/testsuite/23_containers/flat_multimap/1.cc b/libstdc++-v3/testsuite/23_containers/flat_multimap/1.cc index 1e70535286a..1c5c9a88ab6 100644 --- a/libstdc++-v3/testsuite/23_containers/flat_multimap/1.cc +++ b/libstdc++-v3/testsuite/23_containers/flat_multimap/1.cc @@ -221,6 +221,16 @@ test06() VERIFY( std::ranges::equal(m | std::views::values, (int[]){2, 3, 4, 5, 6}) ); } +void +test07() +{ + // PR libstdc++/119427 - std::erase_if(std::flat_foo) does not work + std::flat_multimap 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; }); + VERIFY( n == 3 ); + VERIFY( std::ranges::equal(m, (std::pair[]){{3,4},{3,3}}) ); +} + int main() { @@ -233,4 +243,5 @@ main() test04(); test05(); test06(); + test07(); } diff --git a/libstdc++-v3/testsuite/23_containers/flat_multiset/1.cc b/libstdc++-v3/testsuite/23_containers/flat_multiset/1.cc index 7d9a33c6b00..63855e07065 100644 --- a/libstdc++-v3/testsuite/23_containers/flat_multiset/1.cc +++ b/libstdc++-v3/testsuite/23_containers/flat_multiset/1.cc @@ -235,6 +235,16 @@ test08() VERIFY( copy_counter == 2 ); } +void +test09() +{ + // PR libstdc++/119427 - std::erase_if(std::flat_foo) does not work + std::flat_multiset s = {1,1,2,2,3,4,5}; + auto n = std::erase_if(s, [](int x) { return x % 2 != 0; }); + VERIFY( n == 4 ); + VERIFY( std::ranges::equal(s, (int[]){2,2,4}) ); +} + int main() { @@ -247,4 +257,5 @@ main() test06(); test07(); test08(); + test09(); } diff --git a/libstdc++-v3/testsuite/23_containers/flat_set/1.cc b/libstdc++-v3/testsuite/23_containers/flat_set/1.cc index ed24fab785b..b1d9002caba 100644 --- a/libstdc++-v3/testsuite/23_containers/flat_set/1.cc +++ b/libstdc++-v3/testsuite/23_containers/flat_set/1.cc @@ -248,6 +248,16 @@ test08() VERIFY( copy_counter == 1 ); } +void +test09() +{ + // PR libstdc++/119427 - std::erase_if(std::flat_foo) does not work + std::flat_set s = {1,2,3,4,5}; + auto n = std::erase_if(s, [](int x) { return x % 2 != 0; }); + VERIFY( n == 3 ); + VERIFY( std::ranges::equal(s, (int[]){2,4}) ); +} + int main() { @@ -260,4 +270,5 @@ main() test06(); test07(); test08(); + test09(); }