main()
auto
co_return
statementco_await
expressionco_await
co_yield
expressionprintf(const char*, ...);
// not allowedgenerator my_coroutine() {
int n = 0;
while (true) {
co_yield n++;
}
}
int main() {
generator x = my_coroutine();
cout << x.get() << endl;
cout << x.get() << endl;
cout << x.get() << endl;
}
0
1
2
Program ended with exit code: 0
namespace v0 {
struct my_coroutine_t {
// ...
};
} // namespace v0
namespace v1 {
struct my_coroutine_t {
int n = 0;
// ...
};
} // namespace v1
namespace v2 {
struct my_coroutine_t {
int n = 0;
void (my_coroutine_t::*_resume)();
my_coroutine_t() : _resume{&my_coroutine_t::state_01} {}
void resume() { (this->*_resume)(); }
void state_01(); //...
};
} // namespace v2
namespace {
struct my_coroutine_t {
int n = 0;
void (my_coroutine_t::*_resume)();
int _promise;
my_coroutine_t() : _resume{&my_coroutine_t::state_01} {}
void resume() { (this->*_resume)(); }
void state_01() {
_promise = n++; // co_yield n++
_resume = &my_coroutine_t::state_01; // on resume, loop
}
};
} // namespace v3
namespace v3 {
using coroutine_handle = unique_ptr<my_coroutine_t>;
struct generator {
coroutine_handle _handle;
generator(coroutine_handle h) : _handle(move(h)) {}
// ...
};
generator my_coroutine() { return generator(make_unique<my_coroutine_t>()); }
} // namespace v3
namespace v4 {
struct generator {
coroutine_handle _handle;
generator(coroutine_handle h) : _handle(move(h)) {}
int get() {
_handle->resume();
return _handle->_promise;
}
};
} // namespace v3
generator x = my_coroutine();
cout << x.get() << endl;
cout << x.get() << endl;
cout << x.get() << endl;
generator
type used for the C++TS version is declared as:struct generator {
struct promise_type;
using handle = coroutine_handle<promise_type>;
struct promise_type {
int current_value;
auto initial_suspend() { return suspend_always{}; }
auto final_suspend() { return suspend_always{}; }
void unhandled_exception() { terminate(); }
void return_void() {}
auto yield_value(int value) {
current_value = value;
return suspend_always{};
}
generator get_return_object() {
return generator{handle::from_promise(*this)};
}
};
handle _coro;
generator(handle h) : _coro(h) {}
generator(generator const&) = delete;
generator(generator&& rhs) : _coro(rhs._coro) { rhs._coro = nullptr; }
~generator() {
if (_coro) _coro.destroy();
}
int get() {
_coro.resume();
return _coro.promise().current_value;
}
};
co_await
expression will suspend the coroutine until resume is called after a value is availablefuture<void> do_it(future<int> x) {
int result = co_await move(x);
cout << result << endl;
co_return;
}
auto done = do_it(async(default_executor, []{ return 42; }));
done.then([]{ cout << "done" << endl; });
42
done