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)
{ 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;
}
using _Impl::lower_bound;
using _Impl::upper_bound;
using _Impl::equal_range;
+
+ using _Impl::_M_erase_if;
};
template<typename _KeyContainer, typename _MappedContainer,
&& 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
using _Impl::lower_bound;
using _Impl::upper_bound;
using _Impl::equal_range;
+
+ using _Impl::_M_erase_if;
};
template<typename _KeyContainer, typename _MappedContainer,
&& 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
{ 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;
}
using _Impl::lower_bound;
using _Impl::upper_bound;
using _Impl::equal_range;
+
+ using _Impl::_M_erase_if;
};
template<typename _KeyContainer,
: 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
using _Impl::lower_bound;
using _Impl::upper_bound;
using _Impl::equal_range;
+
+ using _Impl::_M_erase_if;
};
template<typename _KeyContainer,
: 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
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()
{
test04();
test05();
test06();
+ test07();
}
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()
{
test04();
test05();
test06();
+ test07();
}
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()
{
test06();
test07();
test08();
+ test09();
}
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()
{
test06();
test07();
test08();
+ test09();
}