aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatrick Palka <ppalka@redhat.com>2025-04-29 08:21:35 -0400
committerPatrick Palka <ppalka@redhat.com>2025-05-12 09:23:47 -0400
commit0ff3b3122adfe0c479901da4fc28e367d89f185b (patch)
tree82e3543180bdc34cb4d4f9defd80a1c099063020
parenta341d96add049e1ebc94e7350ff59e82b03043d2 (diff)
downloadgcc-0ff3b3122adfe0c479901da4fc28e367d89f185b.zip
gcc-0ff3b3122adfe0c479901da4fc28e367d89f185b.tar.gz
gcc-0ff3b3122adfe0c479901da4fc28e367d89f185b.tar.bz2
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 <jwakely@redhat.com> (cherry picked from commit aa93272cfd2233858da0792761387cc27f4d5ff3)
-rw-r--r--libstdc++-v3/include/std/flat_map28
-rw-r--r--libstdc++-v3/include/std/flat_set28
-rw-r--r--libstdc++-v3/testsuite/23_containers/flat_map/1.cc11
-rw-r--r--libstdc++-v3/testsuite/23_containers/flat_multimap/1.cc11
-rw-r--r--libstdc++-v3/testsuite/23_containers/flat_multiset/1.cc11
-rw-r--r--libstdc++-v3/testsuite/23_containers/flat_set/1.cc11
6 files changed, 89 insertions, 11 deletions
diff --git a/libstdc++-v3/include/std/flat_map b/libstdc++-v3/include/std/flat_map
index 405caa8..6593988 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<typename _Predicate>
- 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<typename _KeyContainer, typename _MappedContainer,
@@ -1412,6 +1414,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
&& uses_allocator_v<_MappedContainer, _Alloc>>
{ };
+ template<typename _Key, typename _Tp, typename _Compare,
+ typename _KeyContainer, typename _MappedContainer, typename _Predicate>
+ 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<typename _KeyContainer, typename _MappedContainer,
@@ -1571,6 +1582,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
&& uses_allocator_v<_MappedContainer, _Alloc>>
{ };
+ template<typename _Key, typename _Tp, typename _Compare,
+ typename _KeyContainer, typename _MappedContainer, typename _Predicate>
+ 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 3e15d1a..c48340d 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<typename _Predicate>
- 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<typename _KeyContainer,
@@ -930,6 +932,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
: bool_constant<uses_allocator_v<_KeyContainer, _Alloc>>
{ };
+ template<typename _Key, typename _Compare, typename _KeyContainer,
+ typename _Predicate>
+ 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<typename _KeyContainer,
@@ -1069,6 +1079,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
: bool_constant<uses_allocator_v<_KeyContainer, _Alloc>>
{ };
+ template<typename _Key, typename _Compare, typename _KeyContainer,
+ typename _Predicate>
+ 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 d9d88c4..38fd449 100644
--- a/libstdc++-v3/testsuite/23_containers/flat_map/1.cc
+++ b/libstdc++-v3/testsuite/23_containers/flat_map/1.cc
@@ -241,6 +241,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<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; });
+ VERIFY( n == 2 );
+ VERIFY( std::ranges::equal(m, (std::pair<int,int>[]){{3,4}}) );
+}
+
int
main()
{
@@ -253,4 +263,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 ff180bf..79fbc1a 100644
--- a/libstdc++-v3/testsuite/23_containers/flat_multimap/1.cc
+++ b/libstdc++-v3/testsuite/23_containers/flat_multimap/1.cc
@@ -219,6 +219,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<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; });
+ VERIFY( n == 3 );
+ VERIFY( std::ranges::equal(m, (std::pair<int,int>[]){{3,4},{3,3}}) );
+}
+
int
main()
{
@@ -231,4 +241,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 7d9a33c..63855e0 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<int> 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 ed24fab..b1d9002 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<int> 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();
}