A simple program implementing one specific capability of C++20 coroutines - a generator.
This generator example generates the Fibonacci Sequence up to some specified ceiling.
Here is the function - its the use of co_yield
that make it a C++20 coroutine (as opposed to an ordinary function):
generator<double> fibonacci(const double ceiling) {
double j = 0;
double i = 1;
co_yield j;
if (ceiling > j) {
do {
co_yield i;
double tmp = i;
i += j;
j = tmp;
} while (i <= ceiling);
}
}
The generator function's return value generator<double>
is an iterator for the type of its template argument. In this programming example it is using the template class coro_exp::generator<>
which the implementation of is provided. However, the C++20 standard is specifying std::generator<>
1, but it is not available in the Clang++ (9.0.0) experimental implementation yet.
NOTE: The template class coro_exp::generator<>
has been customized off of Rainer Grimm's implementation.2
Here is code that consumes generated values from fibonacci()
:
const double demo_ceiling = 10E44;
auto iter = fibonacci(demo_ceiling);
while(iter.next()) {
const auto value = iter.getValue();
std::cout << value << '\n';
}
This will print out 217 values of the Fibonacci Sequence.
The consuming code and the generator code are executing on the same thread context and yet the fibonacci()
function enjoys a preserved local scope state as it executes and then resumes from co_yield
. The generator function just falls out of the loop when the specified ceiling is exceeded to terminate itself - the consuming code will detect this in the while(iter.next()) {...}
loop condition and fall out of the loop.
The program can be built with cmake as a CMakeLists.txt
file is provided. Because it depends on using a Clang C++ compiler that has the experimental implementation of coroutines, will need to insure that the cmake variable CMAKE_CXX_COMPILER
is suitably defined to clang++
.
I installed Clang/LLVM from the version 9.0.0 pre-built binary distribution3. On my Ubuntu Linux 18.04 I had to also install libtinfo5
4, which clang required:
sudo apt-get install libtinfo5
Adjust accordingly to suit your environment.
1: cppreference.com - Coroutines (C++20)
2: Rainer Grimm, Concurrency with Modern C++ (Leanpub, 2017 - 2019), 207-209.