Documentation Index
Fetch the complete documentation index at: https://docs.syntblaze.com/llms.txt
Use this file to discover all available pages before exploring further.
std::coroutine_handle is a non-owning, trivially copyable handle to a compiler-generated coroutine state (the coroutine frame). It provides the low-level interface required to resume execution of a suspended coroutine, query its execution status, access its associated promise object, or explicitly destroy its state.
Defined in the <coroutine> header, the handle acts essentially as a type-safe wrapper around a void* pointer pointing to the coroutine frame. While conceptually dynamically allocated, C++20 explicitly supports Heap Allocation Elision (HALO). This means the compiler is permitted to optimize the coroutine state to be allocated on the stack or inlined into the caller’s frame, rather than strictly relying on heap allocation.
Template Structure and Specializations
The handle is implemented as a class template withvoid as the default template argument (template <typename Promise = void>), alongside an explicit specialization for void (coroutine_handle<void>). There is no inheritance relationship between the primary template and the explicit specialization.
1. std::coroutine_handle<void> (Type-Erased Handle)
Often written as std::coroutine_handle<>, this explicit specialization knows nothing about the coroutine’s return type or promise object. It is used when the caller only needs to control the execution flow (resume or destroy) without interacting with the data yielded or returned by the coroutine.
2. std::coroutine_handle<Promise> (Strongly-Typed Handle)
The primary template is bound to a specific Promise type, allowing bidirectional data transfer between the caller and the coroutine frame via the promise object. It independently declares all the execution control and state observation methods found in the void specialization, alongside promise-specific methods and a conversion operator.
Core Mechanics and Member Functions
Execution Control
resume()/operator()(): Resumes the execution of a suspended coroutine. The call blocks until the coroutine suspends again or runs to completion. Invokingresume()on a coroutine that is already executing, or one that has completed (done() == true), results in undefined behavior.
State Observation
done(): Returnstrueif the coroutine is suspended at its final suspension point, andfalseif suspended at any other point. Crucially, callingdone()on a coroutine that is currently executing is Undefined Behavior. This method can only be safely invoked when the coroutine is known to be in a suspended state.operator bool(): Returnstrueif the handle points to a valid coroutine frame (i.e., the internal pointer is notnullptr). It does not indicate whether the coroutine has finished executing.
Promise Interaction (Typed Handle Only)
promise(): Returns a reference to the promise object stored inside the coroutine frame.from_promise(Promise& p): A static factory function that reconstructs thecoroutine_handlefrom a reference to the promise object. This relies on the compiler’s deterministic memory layout of the coroutine frame.
Memory and Lifecycle Management
destroy(): Explicitly destroys the coroutine frame, invoking the destructors of all in-scope local variables and the promise object, and deallocates the memory. Likedone(), callingdestroy()on a currently executing coroutine is undefined behavior.
std::coroutine_handle does not implement RAII. It is a raw handle. If a handle goes out of scope, the underlying coroutine frame is not automatically destroyed, leading to a memory leak. Conversely, if a coroutine reaches the end of its execution and its promise type’s final_suspend returns std::suspend_never, the frame destroys itself automatically, leaving any existing coroutine_handle instances dangling.
Interoperability
address(): Extracts the underlyingvoid*pointer. Useful for passing the coroutine through C-style APIs or storing it in type-erased contexts.from_address(void* addr): Reconstructs acoroutine_handlefrom a raw pointer previously obtained viaaddress(). This function is intentionally notnoexceptbecause it possesses a narrow contract: passing an invalid or unaligned address results in undefined behavior.
Identity and Comparison
The<coroutine> header defines namespace-scope comparison operators (operator== and operator<=>) and specializes std::hash for the handle. These operate directly on the underlying memory addresses, allowing handles to be checked for identity or used as keys in associative containers (e.g., std::unordered_map or std::set). Because strongly-typed handles implicitly convert to coroutine_handle<void>, these operators seamlessly support all handle types.
Type Conversion
Because the primary template provides an implicit conversion operator (operator coroutine_handle<void>()), implicit type conversion is supported. You can pass a strongly-typed handle to any function expecting a type-erased handle.
Converting back from a type-erased handle to a strongly-typed handle requires explicit reconstruction using the underlying memory address.
Master C++ with Deep Grasping Methodology!Learn More





