I stumbled upon a problem with ambiguous overload for operator<<
when using std::views::enumerate
with size_t
range.
More specifically using this code:
#include <iostream>
#include <ranges>
namespace rv = std::ranges::views;
int main()
{
for (const auto& [idx, value] : rv::iota(0zu, 5zu) | rv::enumerate)
std::cout << idx << '\n';
}
and compiling with gcc 13.1.1
on linux using: g++ --std=c++23 main.cpp
.
I get the error:
main.cpp: In function ‘int main()’:
main.cpp:11:19: error: ambiguous overload for ‘operator<<’ (operand types are ‘std::ostream’ {aka ‘std::basic_ostream<char>’} and ‘std::tuple_element<0, const std::tuple<__int128, long unsigned int> >::type’ {aka ‘const __int128’})
11 | std::cout << idx << '\n';
| ~~~~~~~~~ ^~ ~
| | |
| | std::tuple_element<0, const std::tuple<__int128, long unsigned int> >::type {aka const __int128}
| std::ostream {aka std::basic_ostream<char>}
and then a bunch of candidates for the <<
operator.
This can be remediated by casting idx
(e.g., using std::cout << (size_t)idx
) but it seems unnecessary tedious.
The problem seems to only occur when using long
variables as start and end for the range.
For instance if we use rv::iota(begin, end)
with either int begin{0}, end{5}
(whether signed or unsigned) the problem disappears.
Is this a simple bug at the compiler level or is there something deeper preventing it from matching the correct type?
idx
is an implementation detail ofrv::iota
that shouldn't be relevant to whether or not OP's code is valid. – Furfuraceousrv::iota(0zu, 5zu) | rv::enumerate
can be printed with<<
and if it isn't how it can be printed.__in128
appears nowhere in this and is an implementation-detail. The user should not need to know or rely on the exact type. – Furfuraceousidx
is unspecified. – Furfuraceousiota_view::iterator
is supposed to choose adifference_type
that is wider than the type iterated over. IOTA-DIFF-T(W) So not really a compiler bug. – Sheff