Carsten
Carsten

Reputation: 11636

Why can't I zip an lvalue generator?

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?

Upvotes: 6

Views: 162

Answers (1)

康桓瑋
康桓瑋

Reputation: 43026

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);

Upvotes: 8

Related Questions