C++20's coroutines and views can work together to create powerful, lazy-evaluated pipelines for data processing. Coroutines allow you to define sequences of values that can be produced on-demand, and views can consume these sequences efficiently.
Here’s a simple example of a coroutine that generates an infinite sequence of numbers, which can be consumed by a view:
#include <coroutine>
#include <iostream>
#include <ranges>
class Generator {
public:
struct promise_type {
int value_;
std::suspend_always yield_value(int value) {
value_ = value;
return {};
}
std::suspend_always initial_suspend() {
return {};
}
std::suspend_always final_suspend() noexcept {
return {};
}
void unhandled_exception() {
std::terminate();
}
Generator get_return_object() {
return Generator{std::coroutine_handle<
promise_type>::from_promise(*this)};
}
void return_void() {}
};
using handle_type =
std::coroutine_handle<promise_type>;
handle_type coro_;
Generator(handle_type h) : coro_(h) {}
~Generator() {
if (coro_) coro_.destroy();
}
bool next() {
coro_.resume();
return !coro_.done();
}
int value() const {
return coro_.promise().value_; }
};
Generator GenerateNumbers() {
for (int i = 1;; ++i) co_yield i;
}
int main() {
auto gen = GenerateNumbers();
auto view = std::views::iota(0)
| std::views::transform([&gen](int) {
if (gen.next()) return gen.value();
return -1; // Placeholder value
});
for (int x : view | std::views::take(10)) {
std::cout << x << ", ";
}
}
1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
std::coroutine_handle
to manage the coroutine state.std::views::iota
and std::views::transform
to produce the sequence.Combining coroutines and views can help create highly efficient and readable code for complex data processing tasks.
Answers to questions are automatically generated and may not have been reviewed.
Learn how to create and use views in C++ using examples from std::views