Ключевое слово co_yield
Ключевое слово co_yield используется внутри корутин для
приостановки выполнения функции и возврата значения.
В отличие от return, которое завершает функцию,
co_yield сохраняет состояние корутины, позволяя
продолжить выполнение с того же места при следующем вызове.
Это делает его похожим на генераторы в других языках
программирования. Значение, указанное после co_yield,
передается наружу через объект-обещание (promise).
Синтаксис
co_yield expression;
Здесь expression - значение, которое возвращается
вызывающей стороне при каждой приостановке корутины.
Пример
Рассмотрим простой генератор, который выдает числа
от 1 до 5:
#include <iostream>
#include <coroutine>
using namespace std;
struct Generator {
struct promise_type {
int current_value;
Generator get_return_object() {
return Generator{
handle::from_promise(*this)
};
}
suspend_always initial_suspend() {
return {};
}
suspend_always final_suspend() noexcept {
return {};
}
suspend_always yield_value(int value) {
current_value = value;
return {};
}
void return_void() {}
void unhandled_exception() {}
};
using handle = coroutine_handle<promise_type>;
handle h;
Generator(handle h) : h(h) {}
~Generator() {
if (h) h.destroy();
}
bool next() {
h.resume();
return !h.done();
}
int value() {
return h.promise().current_value;
}
};
Generator generate() {
for (int i = 1; i <= 5; ++i) {
co_yield i;
}
}
int main()
{
Generator gen = generate();
while (gen.next()) {
cout << gen.value() << " ";
}
cout << endl;
return 0;
}
Результат выполнения кода:
1 2 3 4 5
Пример
Давайте создадим генератор, который выдает строки из массива по одной:
#include <iostream>
#include <coroutine>
#include <string>
using namespace std;
struct StringGenerator {
struct promise_type {
string current_value;
StringGenerator get_return_object() {
return StringGenerator{
handle::from_promise(*this)
};
}
suspend_always initial_suspend() {
return {};
}
suspend_always final_suspend() noexcept {
return {};
}
suspend_always yield_value(string value) {
current_value = value;
return {};
}
void return_void() {}
void unhandled_exception() {}
};
using handle = coroutine_handle<promise_type>;
handle h;
StringGenerator(handle h) : h(h) {}
~StringGenerator() {
if (h) h.destroy();
}
bool next() {
h.resume();
return !h.done();
}
string value() {
return h.promise().current_value;
}
};
StringGenerator generate_strings() {
co_yield "abcde";
co_yield "12345";
}
int main()
{
StringGenerator gen = generate_strings();
while (gen.next()) {
cout << gen.value() << endl;
}
return 0;
}
Результат выполнения кода:
"abcde"
12345