https://gcc.gnu.org/bugzilla/show_bug.cgi?id=126716
Bug ID: 126716
Summary: under _GLIBCXX_DEBUG, std::erase_if on unordered
container with transparent comparator fails to compile
in C++23
Product: gcc
Version: 16.1.1
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: libstdc++
Assignee: unassigned at gcc dot gnu.org
Reporter: sberg.fun at gmail dot com
Target Milestone: ---
At least with
gcc-c++-16.1.1-2.fc44.x86_64/libstdc++-devel-16.1.1-2.fc44.x86_64, as well as
with a recent local GCC 17 trunk installation,
```
$ cat test.cc
#include <functional>
#include <unordered_set>
struct H {
using is_transparent = void;
std::size_t operator()(int) const noexcept { return 0; }
};
int main() {
std::unordered_set<int, H, std::equal_to<>> s;
std::erase_if(s, [](int){ return true; });
}
```
```
$ g++ -fsyntax-only -std=c++23 -D_GLIBCXX_DEBUG test.cc
In file included from /usr/include/c++/16/unordered_map:45,
from /usr/include/c++/16/functional:80,
from test.cc:1:
/usr/include/c++/16/bits/erase_if.h: In instantiation of ‘typename
_Container::size_type std::__detail::__erase_nodes_if(_Container&,
_UnsafeContainer&, _Predicate) [with _Container =
std::__debug::unordered_set<int, H, std::equal_to<void> >; _UnsafeContainer =
std::__cxx1998::unordered_set<int, H, std::equal_to<void>, std::allocator<int>
>; _Predicate = main()::<lambda(int)>; typename _Container::size_type = long
unsigned int]’:
/usr/include/c++/16/debug/unordered_set:1676:40: required from ‘typename
std::__debug::unordered_set<_Key, _Hash, _Pred, _Allocator>::size_type
std::erase_if(__debug::unordered_set<_Tp, _Hash, _Pred, _Allocator>&,
_Predicate) [with _Key = int; _Hash = H; _CPred = equal_to<void>; _Alloc =
allocator<int>; _Predicate = main()::<lambda(int)>; typename
__debug::unordered_set<_Key, _Hash, _Pred, _Allocator>::size_type = long
unsigned int]’
1676 | { return __detail::__erase_nodes_if(__cont, __cont._M_base(),
__pred); }
|
~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
test.cc:9:18: required from here
9 | std::erase_if(s, [](int){ return true; });
| ~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/include/c++/16/bits/erase_if.h:81:24: error: no match for ‘operator=’
(operand types are ‘std::__detail::_Node_iterator<int, true, false>’ and
‘std::__debug::unordered_set<int, H, std::equal_to<void> >::size_type’ {aka
‘long unsigned int’})
81 | __iter = __cont.erase(__iter);
| ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~
• there are 2 candidates
In file included from /usr/include/c++/16/bits/hashtable.h:37,
from /usr/include/c++/16/bits/unordered_map.h:33,
from /usr/include/c++/16/unordered_map:43:
• candidate 1: ‘constexpr std::__detail::_Node_iterator<int, true, false>&
std::__detail::_Node_iterator<int, true, false>::operator=(const
std::__detail::_Node_iterator<int, true, false>&)’
/usr/include/c++/16/bits/hashtable_policy.h:401:12:
401 | struct _Node_iterator
| ^~~~~~~~~~~~~~
• no known conversion for argument 1 from
‘std::__debug::unordered_set<int, H, std::equal_to<void> >::size_type’ {aka
‘long unsigned int’} to ‘const std::__detail::_Node_iterator<int, true,
false>&’
• candidate 2: ‘constexpr std::__detail::_Node_iterator<int, true, false>&
std::__detail::_Node_iterator<int, true,
false>::operator=(std::__detail::_Node_iterator<int, true, false>&&)’
• no known conversion for argument 1 from
‘std::__debug::unordered_set<int, H, std::equal_to<void> >::size_type’ {aka
‘long unsigned int’} to ‘std::__detail::_Node_iterator<int, true, false>&&’
```
fails (and works if you either drop -D_GLIBCXX_DEBUG or go from -std=c++23 down
to -std=c++20).