libstdc++: Make std::erase for linked lists convert to bool

LWG 4135 (approved in Wrocław, November 2024) fixes the lambda
expressions used by std::erase for std::list and std::forward_list.
Previously they attempted to copy something that isn't required to be
copyable. Instead they should convert it to bool right away.

The issue resolution also changes the lambda's parameter to be const, so
that it can't modify the elements while comparing them.

libstdc++-v3/ChangeLog:

	* include/std/forward_list (erase): Change lambda to have
	explicit return type and const parameter type.
	* include/std/list (erase): Likewise.
	* testsuite/23_containers/forward_list/erasure.cc: Check lambda
	is correct.
	* testsuite/23_containers/list/erasure.cc: Likewise.

Reviewed-by: Patrick Palka <ppalka@redhat.com>
This commit is contained in:
Jonathan Wakely 2025-03-06 21:18:21 +00:00 committed by Jonathan Wakely
parent 4b18045962
commit e6e7b477bb
No known key found for this signature in database
4 changed files with 50 additions and 4 deletions

View file

@ -83,8 +83,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
inline typename forward_list<_Tp, _Alloc>::size_type
erase(forward_list<_Tp, _Alloc>& __cont, const _Up& __value)
{
using __elem_type = typename forward_list<_Tp, _Alloc>::value_type;
return std::erase_if(__cont, [&](__elem_type& __elem) {
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// 4135. helper lambda of std::erase for list should specify return type
return std::erase_if(__cont, [&](const auto& __elem) -> bool {
return __elem == __value;
});
}

View file

@ -107,8 +107,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
inline typename list<_Tp, _Alloc>::size_type
erase(list<_Tp, _Alloc>& __cont, const _Up& __value)
{
using __elem_type = typename list<_Tp, _Alloc>::value_type;
return std::erase_if(__cont, [&](__elem_type& __elem) {
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// 4135. helper lambda of std::erase for list should specify return type
return std::erase_if(__cont, [&](const auto& __elem) -> bool {
return __elem == __value;
});
}

View file

@ -53,6 +53,28 @@ test02()
VERIFY( num == 0 );
}
// LWG 4135.
// The helper lambda of std::erase for list should specify return type as bool
void
test_lwg4135()
{
struct Bool {
Bool() = default;
Bool(const Bool&) = delete;
operator bool() const { return false; }
};
static Bool b;
struct Int {
Bool& operator==(Int) const { return b; }
void operator==(Int) = delete;
};
std::forward_list<Int> l;
std::erase(l, Int{});
}
int
main()
{

View file

@ -52,6 +52,28 @@ test02()
VERIFY( num == 0 );
}
// LWG 4135.
// The helper lambda of std::erase for list should specify return type as bool
void
test_lwg4135()
{
struct Bool {
Bool() = default;
Bool(const Bool&) = delete;
operator bool() const { return false; }
};
static Bool b;
struct Int {
Bool& operator==(Int) const { return b; }
void operator==(Int) = delete;
};
std::list<Int> l;
std::erase(l, Int{});
}
int
main()
{