What's the difference between a coroutine and a function with static variables?

Viewed 481

I've been learning about what's new in C++20 and I'm trying to understand the commonly discussed "Generator" use case of co-routines. I've tried to create a small example here but apologies if there is some mistake:

generator<int> Generate() {
    int i = 0;
    while(1) {
        co_yield i++;
    }
}

int main()
{
    auto gen { Generate() };
    for (int x = 0; x < 10; ++x) {
        gen.next();
        std::cout << gen.getValue() << std::endl;
    }
    return 0;
}

But I don't see how this is any different from a function with static variables like:

auto gen() {
    static int i = 0;
    return i++;
}

int main()
{
    for (int x = 0; x < 10; ++x)
        std::cout << gen() << std::endl;
    return 0;
}

I think I can maybe see how asynchronous I/O is a usecase, especially with the co_await keyword, but for this generator example I'm sure I'm misunderstanding something about how they should be used. I'd be very grateful for any explanation

1 Answers

Perhaps the most obvious difference is that static local variables means you effectively have one instance... total. Whereas each generator is completely independent.

// with coroutines
assert(Generator().next() == 0);
assert(Generator().next() == 0);
assert(Generator().next() == 0);
assert(Generator().next() == 0);

Every call to Generator() is creating a new generator, each of which starts counting at 0. So every new generator's next() gives me zero. As expected.

But that's not the case with static local variables:

assert(gen() == 0);
assert(gen() == 1);
assert(gen() == 2);
assert(gen() == 3);

So you could imagine how if what you wanted was to create a generator that gave you an infinite stream of integers, it'd be nice if you could use that function reliably more than one time total in your entire program.

This isn't to say that static local variables aren't useful. It's just that they're not usable for this particular use-case.

Related