The following simple program compiles and works:
std::generator<int> get_ints(int n)
{
for (int i{0}; i < n; ++i)
co_yield i;
}
int main(int argc, char* argv[])
{
std::vector<float> floats { 0.0f, 1.0f, 2.0f, 3.0f };
for (auto [i, f] : std::views::zip(get_ints(4), floats))
std::println("{}: {}", i, f);
}
However, if I instead store the generator in a variable and attempt the same, it does not compile:
std::generator<int> get_ints(int n)
{
for (int i{0}; i < n; ++i)
co_yield i;
}
int main(int argc, char* argv[])
{
std::vector<float> floats { 0.0f, 1.0f, 2.0f, 3.0f };
auto ints = get_ints(4);
for (auto [i, f] : std::views::zip(ints, floats))
std::println("{}: {}", i, f);
}
From my understanding this fails, because std::ranges::viewable_range<std::generator<int>&>
evaluates to false
, while std::ranges::viewable_range<std::generator<int>&&>
evaluates to true. But why is the first case forbidden? I know that generator
is not a range, but it behaves like one and every other range type that I tested (although I only tested a few) satisfies this constraint when passed as an lvalue reference. So why makes generator
special in this case?
std::generator
is a move-only range
with a deleted copy constructor, you need to move it into the zip_view
:
for (auto [i, f] : std::views::zip(std::move(ints), floats))
std::println("{}: {}", i, f);