std::coroutine_handle, std::noop_coroutine_handle

From cppreference.com
< cpp‎ | coroutine
 
 
Utilities library
General utilities
Date and time
Function objects
Formatting library (C++20)
(C++11)
Relational operators (deprecated in C++20)
Integer comparison functions
(C++20)
Swap and type operations
(C++14)
(C++11)
(C++11)
(C++11)
(C++17)
Common vocabulary types
(C++11)
(C++17)
(C++17)
(C++17)
(C++17)

Elementary string conversions
(C++17)
(C++17)
 
Coroutine support
Coroutine traits
Coroutine handle
coroutine_handle
(C++20)
No-op coroutines
Trivial awaitables
 
 
Defined in header <coroutine>
template< class Promise = void > struct coroutine_handle;
(1) (since C++20)
template<> struct coroutine_handle<void>;
(2) (since C++20)
template<> struct coroutine_handle<std::noop_coroutine_promise>;
(3) (since C++20)
using noop_coroutine_handle =
    std::coroutine_handle<std::noop_coroutine_promise>;
(4) (since C++20)

The class template coroutine_handle can be used to refer to a suspended or executing coroutine. Every specialization of coroutine_handle is a LiteralType.

1) Primary template, can be created from the promise object of type Promise.
2) Specialization std::coroutine_handle<void> erases the promise type. It is convertible from other specializations.
3) Specialization std::coroutine_handle<std::noop_coroutine_promise> refers to no-op coroutines. It cannot be created from a promise object.

On typical implementations, every specialization of std::coroutine_handle is TriviallyCopyable, and holds a pointer to the coroutine state as its only non-static data member.

The behavior of a program that adds specializations for coroutine_handle is undefined.

Member functions

constructs a coroutine_handle object
(public member function)
(C++20)
assigns the coroutine_handle object
(public member function)
[static] (C++20)
creates a coroutine_handle from the promise object of a coroutine
(public static member function)
Observers
(C++20)
check if the coroutine has completed
(public member function)
check if the handle represents a coroutine
(public member function)
Control
resumes execution of the coroutine
(public member function)
(C++20)
destroys a coroutine
(public member function)
Promise Access
(C++20)
access the promise of a coroutine
(public member function)
Export/Import
(C++20)
exports the underlying address, i.e. the pointer backing the coroutine
(public member function)
[static] (C++20)
import a coroutine from a pointer
(public static member function)

Non-member functions

compares two coroutine_handle objects
(function)

Helper classes

hash support for std::coroutine_handle
(class template specialization)

Notes

A coroutine_handle may be dangling, in which case the coroutine_handle must be used carefully in order to avoid undefined behavior.

Example

#include <coroutine>
#include <iostream>
#include <ranges>
 
template<class T>
struct generator {
    struct promise_type {
        auto get_return_object() {
            return generator(std::coroutine_handle<promise_type>::from_promise(*this));
        }
        std::suspend_always initial_suspend() { return {}; }
        std::suspend_always final_suspend() noexcept { return {}; }
        void unhandled_exception() { throw; }
        std::suspend_always yield_value(T value) {
            current_value = std::move(value);
            return {};
        }
        void await_transform() = delete; // disallow co_await in generator coroutines
        T current_value;
    };
 
    generator(std::coroutine_handle<promise_type> h) : coro(h) {}
    generator(generator&& other) : coro(other.coro) { other.coro = {}; }
    ~generator() { if (coro) coro.destroy(); }
 
    // range-based for support
    struct iter {
        explicit iter(std::coroutine_handle<promise_type> h) : coro(h) {}
        void operator++() { coro.resume(); }
        T operator*() const { return coro.promise().current_value; }
        bool operator==(std::default_sentinel_t) const { return coro.done(); }
    private:
        std::coroutine_handle<promise_type> coro;
    };
    iter begin() { coro.resume(); return iter(coro); }
    std::default_sentinel_t end() { return {}; }
 
private:
    std::coroutine_handle<promise_type> coro;
};
 
generator<int> ints(int x) {
    for (int i = 0; i < x; ++i)
        co_yield i;
}
 
int main() {
    for (auto i : ints(5))
        std::cout << i << '\n';
}

Output:

0
1
2
3
4