Генератор на сопрограммах в C++
Несколько методов обещания можно спрятать
в генератор - обертку с
next и value для пошаговой
отдачи.
Каждый next делает resume,
а value читает поле, куда попало
последнее co_yield. Запишем
генератор с числами 1 и 2
и выведем оба:
#include <coroutine>
#include <iostream>
struct gen {
struct promise_type {
int current = 0;
gen get_return_object() {
return gen{
std::coroutine_handle<promise_type>::from_promise(*this)};
}
std::suspend_always initial_suspend() { return {}; }
std::suspend_always final_suspend() noexcept { return {}; }
std::suspend_always yield_value(int value) {
current = value;
return {};
}
void return_void() {}
void unhandled_exception() { std::terminate(); }
};
std::coroutine_handle<promise_type> h;
explicit gen(std::coroutine_handle<promise_type> handle)
: h(handle) {}
~gen() {
if (h) {
h.destroy();
}
}
bool next() {
if (h.done()) {
return false;
}
h.resume();
return !h.done();
}
int value() const {
return h.promise().current;
}
};
static gen sequence() {
co_yield 1;
co_yield 2;
}
int main() {
gen g = sequence();
if (g.next()) {
std::cout << g.value() << "\n";
}
if (g.next()) {
std::cout << g.value() << "\n";
}
return 0;
}
После второго next сопрограмма
останавливается на конечной точке, и
дескриптор освобождает деструктор.
Соберите генератор, который отдает
10 и 20. Выведите оба
значения через next и value.