Article by Ayman Alheraki on January 11 2026 10:36 AM
Coroutines are one of the powerful features introduced with the C++20 standard. However, their complexity and the lack of supporting tools have made many programmers find them difficult to adopt or consider them less useful compared to the complexities they bring. In this article, we will discuss how easy it is to use Coroutines in C++20, whether they have been improved in C++23, and why some consider them complex.
Coroutines are functions that can pause their execution (suspend) and later resume it. This feature is particularly useful in asynchronous programming, such as handling long-running tasks (e.g., I/O operations or network communications) without blocking the main thread.
struct MyCoroutine { struct promise_type { MyCoroutine get_return_object() { return {}; } std::suspend_always initial_suspend() { return {}; } std::suspend_always final_suspend() noexcept { return {}; } void return_void() {} void unhandled_exception() {} };};
MyCoroutine myCoroutine() { std::cout << "Coroutine started\n"; co_await std::suspend_always{}; std::cout << "Coroutine resumed\n";}
int main() { auto coro = myCoroutine(); std::cout << "Main function\n"; coro; // Resume the coroutine}Despite their power, Coroutines are considered complex for several reasons:
C++20 introduced the basics for Coroutines but did not provide ready-to-use libraries or helper tools. This means programmers are required to write a lot of boilerplate code to implement simple tasks.
For example, creating a Coroutine requires manually defining a promise_type, which is complex and difficult for beginners to understand.
Coroutines can be difficult to debug due to their asynchronous nature. Tracing the execution flow between coroutines and regular functions can be confusing.
Due to the novelty of the feature, educational resources and practical examples were initially scarce, making it harder for programmers to learn and use them effectively.
Yes, Coroutines have been improved in C++23 to make them easier to use and less complex. Some of the key improvements include:
C++23 introduced helper libraries like std::generator and std::task to simplify the creation and management of Coroutines. These libraries reduce the need for writing boilerplate code and make Coroutines more accessible.
std::generator in C++23:
std::generator<int> generateNumbers(int start, int end) { for (int i = start; i <= end; ++i) { co_yield i; }}
int main() { for (int num : generateNumbers(1, 5)) { std::cout << num << "\n"; }}This code is much simpler than its C++20 equivalent.
Coroutines have been optimized in C++23 to make them more efficient in terms of memory and time usage.
Over time, educational resources and examples have become more abundant, helping programmers better understand and use Coroutines.
Yes, Coroutines are a very powerful feature, especially in the following scenarios:
Asynchronous Programming: Such as handling asynchronous I/O or network communications.
Creating Generators: For example, generating a sequence of values lazily (lazy evaluation).
Improving Application Performance: By avoiding blocking threads and optimizing resource usage.
If you want to use Coroutines without dealing with their complexities, follow these tips:
Use C++23: If possible, as it provides helper libraries that make Coroutines easier to use.
Use Ready-Made Libraries: Such as cppcoro (an external library) or std::generator in C++23.
Start with Simple Examples: Like creating generators before moving on to more complex use cases.
Learn the Basics Well: Understanding how promise_type, co_await, and co_yield work will help you avoid mistakes.
Coroutines in C++20 were a powerful but complex feature due to the lack of supporting tools and the need for writing a lot of boilerplate code. However, in C++23, they have been significantly improved with the addition of helper libraries like std::generator, making them much easier to use. If you are working on projects that require asynchronous programming or creating generators, Coroutines are a powerful tool worth learning, especially with the improvements introduced in C++23.