alex gimenez
alex gimenez

Reputation: 163

C++ coroutines / Visual Studio: How can a generator call a function that yields values on its behalf?

With coroutines defined as of http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/n4628.pdf and implemented in VS2015/Update 3, how can a generator invoke a function that emits values on its behalf?

Clarifying example

I would like to write code as follows...

static void yield_for_me()
{
    co_yield 27; // does not compile 
                 //  co_yield relies on hidden definitions
}
std::experimental::generator<int> testf()
{
    yield_for_me();
    co_yield 28;
}

...in hopes that it will have the exact same outcome as the following code:

std::experimental::generator<int> testf()
{
    co_yield 27;
    co_yield 28;
}

Upvotes: 1

Views: 2267

Answers (2)

Gor Nishanov
Gor Nishanov

Reputation: 46

Using co_yield/co_await/co_return in a function turns it into a coroutine, thus it needs to have a signature that allows compiler to discover library classes explaining to the compiler what that coroutine means.

The generator included with Visual Studio does not support delegating co_yield to another generator. But is is not difficult to create a recursive_generator that can.

Here is an example of a recursive_generator that allows to yield either a value or the result of execution of a different generator.

https://gist.github.com/GorNishanov/29e813139175b1c5299ad01021d2556d

The promise_type of the recursive_generator defines two yield_value functions:

yield_value(T const&); // This one yields individual values
yield_value(recursive_generator<T>&&); // delegates to another generator

Using the recursive_generator above, just change the return type of yield_from_me function from void to recursive_generator and you are good to go.

recursive_generator<int> yield_for_me()
{
    co_yield 27; 
}
recursive_generator<int> testf()
{
    co_yield yield_for_me();
    co_yield 28;
}

Upvotes: 3

Jamboree
Jamboree

Reputation: 5309

It can't. It's a well-known limitation of the coroutine model proposed by P0057. Although in the paper, it also describes a recursive_generator (not included in MSVC) that allows you to do something like this:

recursive_generator<int> yield_for_me()
{
    co_yield 27;
}
recursive_generator<int> testf()
{
    co_yield yield_for_me();
    co_yield 28;
}

BTW, such a thing is implemented in CO2, which is an emulation of the proposed model.

Upvotes: 3

Related Questions