In my last post in this mini-series on coroutines from the practical perspective, I presented the workflow of “An Infinite Data Stream with Coroutines in C++20“. In this post, I use the generic potential of the data stream.
This post assumes that you know the previous post, “An Infinite Data Stream with Coroutines in C++20“, in which I explained very detailed the workflow of an infinite generator based on the new keyword
co_yield So far, I have written about the new keywords
co_yield, which makes out of a function a coroutine. In the next post, I will have a closer look at the most challenging new keyword
- Implementing Simple Futures With Coroutines
- Lazy Futures with Coroutines in C++20
- Executing a Future in a separate Thread with Coroutines
Finally, to something new.
Generalization of the Generator
You may wonder why I never used the full generic potential of Generator in my last post. Let me adjust its implementation to produce the successive elements of an arbitrary container of the Standard Template Library.
In this example, the generator is instantiated and used three times. In the first two cases,
gen (line 1) and
gen2 (line 2) are initialized with
std::string helloWorld, while
gen3 uses a
std::vector<int> (line 3). The output of the program should not be surprising. Line 4 returns all characters of the string
helloWorld successively, line 5 only the first five characters, and line 6 the elements of the
Generator<T>is almost identical to the previous one in the post An Infinite Data Stream with Coroutines in C++20. The crucial difference with the previous program is the coroutine
getNext is a function template that takes a container as an argument and iterates in a range-based for loop through all container elements. After each iteration, the function template pauses. The return type
Generator<typename Cont::value_type> may look surprising to you.
Cont::value_type is a dependent template parameter for which the parser needs a hint. By default, the compiler assumes a non-type if it could be interpreted as a type or a non-type. For this reason, I have to put
typename in front of
The compiler transforms your coroutine and runs the outer promise workflow and the inner awaiter workflow.
The Promise Workflow
So far, I have only written about the outer workflow, which is based on the member functions of the
Following my previous post, this workflow should look familiar to you. You already know the components of this workflow, such as
prom.initial_suspend(), the function body, and
The Awaiter Workflow
The outer workflow is based on the Awaitables, which return Awaiters. I intentionally simplified this explanation. You already know two predefined Awaitables:
No, you may already guess which parts the awaiter workflow is based on. Right! On the member functions
await_resume() of the Awaitable.
I presented the awaiter workflow in a pseudo-language. Understanding the awaiter workflow is the final puzzle for having an intuition about the behavior of coroutines and how you can adapt them.
In my next post, I dig deeper into the awaiter workflow based on the Awaitable. Be prepared for the double-edged sword. User-defined Awaitables give you great power but are challenging to understand.
Thanks a lot to my Patreon Supporters: Matt Braun, Roman Postanciuc, Tobias Zindl, G Prvulovic, Reinhold Dröge, Abernitzke, Frank Grimm, Sakib, Broeserl, António Pina, Sergey Agafyin, Андрей Бурмистров, Jake, GS, Lawton Shoemake, Jozo Leko, John Breland, Venkat Nandam, Jose Francisco, Douglas Tinkham, Kuchlong Kuchlong, Robert Blanch, Truels Wissneth, Kris Kafka, Mario Luoni, Friedrich Huber, lennonli, Pramod Tikare Muralidhara, Peter Ware, Daniel Hufschläger, Alessandro Pezzato, Bob Perry, Satish Vangipuram, Andi Ireland, Richard Ohnemus, Michael Dunsky, Leo Goodstadt, John Wiederhirn, Yacob Cohen-Arazi, Florian Tischler, Robin Furness, Michael Young, Holger Detering, Bernd Mühlhaus, Matthieu Bolt, Stephen Kelley, Kyle Dean, Tusar Palauri, Dmitry Farberov, Juan Dent, George Liao, Daniel Ceperley, Jon T Hess, Stephen Totten, Wolfgang Fütterer, Matthias Grün, Phillip Diekmann, Ben Atakora, Ann Shatoff, Rob North, Bhavith C Achar, and Marco Parri Empoli.
Thanks, in particular, to Jon Hess, Lakshman, Christian Wittenhorst, Sherhy Pyton, Dendi Suhubdy, Sudhakar Belagurusamy, Richard Sargeant, Rusty Fleming, John Nebel, Mipko, Alicja Kaminska, Slavko Radman, and David Poole.
|My special thanks to Embarcadero|
|My special thanks to PVS-Studio|
|My special thanks to Tipi.build|
|My special thanks to Take Up Code|
I’m happy to give online seminars or face-to-face seminars worldwide. Please call me if you have any questions.
- Embedded Programmierung mit modernem C++ 12.12.2023 – 14.12.2023 (Präsenzschulung, Termingarantie)
Standard Seminars (English/German)
Here is a compilation of my standard seminars. These seminars are only meant to give you a first orientation.
- C++ – The Core Language
- C++ – The Standard Library
- C++ – Compact
- C++11 and C++14
- Concurrency with Modern C++
- Design Pattern and Architectural Pattern with C++
- Embedded Programming with Modern C++
- Generic Programming (Templates) with C++
- Clean Code with Modern C++
- Phone: +49 7472 917441
- Mobil:: +49 176 5506 5086
- Mail: schulung@ModernesCpp.de
- German Seminar Page: www.ModernesCpp.de
- Mentoring Page: www.ModernesCpp.org
Modernes C++ Mentoring,