Namespaces
Variants
Actions

std::coroutine_handle, std::noop_coroutine_handle

From cppreference.com
< cpp‎ | coroutine
 
 
Utilities library
Type support (basic types, RTTI)
(C++20)
(C++20)
(C++20)(C++20)(C++20)  
(C++20)(C++20)(C++20)

General utilities
Relational operators (deprecated in C++20)
Integer comparison functions
(C++20)(C++20)(C++20)  
(C++20)
Swap and type operations
(C++20)
(C++14)
(C++11)
(C++11)
(C++23)
(C++11)
(C++17)
Common vocabulary types
(C++11)
(C++17)
(C++17)
(C++17)
(C++11)
(C++17)
(C++23)


 
Coroutine support
Coroutine traits
Coroutine handle
coroutine_handle
(C++20)
No-op coroutines
Trivial awaitables
Range generators
(C++23)
 
 
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.

If the program adds specializations for std::coroutine_handle, the behavior is undefined.

[edit] Data members

Member name Definition
ptr (private) A pointer void* to the coroutine state.
(exposition-only member object*)

[edit] Member functions

constructs a coroutine_handle object
(public member function) [edit]
assigns the coroutine_handle object
(public member function) [edit]
Conversion
obtains a type-erased coroutine_handle
(public member function) [edit]
Observers
checks if the coroutine has completed
(public member function) [edit]
checks if the handle represents a coroutine
(public member function) [edit]
Control
resumes execution of the coroutine
(public member function) [edit]
destroys a coroutine
(public member function) [edit]
Promise Access
access the promise of a coroutine
(public member function) [edit]
[static]
creates a coroutine_handle from the promise object of a coroutine
(public static member function) [edit]
Export/Import
exports the underlying address, i.e. the pointer backing the coroutine
(public member function) [edit]
[static]
imports a coroutine from a pointer
(public static member function) [edit]

[edit] Non-member functions

compares two coroutine_handle objects
(function) [edit]

[edit] Helper classes

hash support for std::coroutine_handle
(class template specialization) [edit]

[edit] Notes

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

[edit] Example

Run this code
#include <coroutine>
#include <iostream>
#include <optional>
 
template<std::movable T>
class Generator
{
public:
 struct promise_type
 {
 Generator<T> get_return_object()
 {
 return Generator{Handle::from_promise(*this)};
 }
 static std::suspend_always initial_suspend() noexcept
 {
 return {};
 }
 static std::suspend_always final_suspend() noexcept
 {
 return {};
 }
 std::suspend_always yield_value(T value) noexcept
 {
 current_value = std::move(value);
 return {};
 }
 // Disallow co_await in generator coroutines.
 void await_transform() = delete;
 [[noreturn]]
 static void unhandled_exception() { throw; }
 
 std::optional <T> current_value;
 };
 
 using Handle = std::coroutine_handle<promise_type>;
 
 explicit Generator(const Handle coroutine) :
 m_coroutine{coroutine}
 {}
 
 Generator() = default;
 ~Generator()
 {
 if (m_coroutine)
 m_coroutine.destroy();
 }
 
 Generator(const Generator&) = delete;
 Generator& operator=(const Generator&) = delete;
 
 Generator(Generator&& other) noexcept :
 m_coroutine{other.m_coroutine}
 {
 other.m_coroutine = {};
 }
 Generator& operator=(Generator&& other) noexcept
 {
 if (this != &other)
 {
 if (m_coroutine)
 m_coroutine.destroy();
 m_coroutine = other.m_coroutine;
 other.m_coroutine = {};
 }
 return *this;
 }
 
 // Range-based for loop support.
 class Iter
 {
 public:
 void operator++()
 {
 m_coroutine.resume();
 }
 const T& operator*() const
 {
 return *m_coroutine.promise().current_value;
 }
 bool operator==(std::default_sentinel_t ) const
 {
 return !m_coroutine || m_coroutine.done();
 }
 
 explicit Iter(const Handle coroutine) :
 m_coroutine{coroutine}
 {}
 
 private:
 Handle m_coroutine;
 };
 
 Iter begin()
 {
 if (m_coroutine)
 m_coroutine.resume();
 return Iter{m_coroutine};
 }
 
 std::default_sentinel_t end() { return {}; }
 
private:
 Handle m_coroutine;
};
 
template<std::integral T>
Generator<T> range(T first, const T last)
{
 while (first < last)
 co_yield first++;
}
 
int main()
{
 for (const char i : range(65, 91))
 std::cout << i << ' ';
 std::cout << '\n';
}

Output:

A B C D E F G H I J K L M N O P Q R S T U V W X Y Z

[edit] Defect reports

The following behavior-changing defect reports were applied retroactively to previously published C++ standards.

DR Applied to Behavior as published Correct behavior
LWG 3460 C++20 the public base class of coroutine_handle could leave it in an undesired state inheritance removed

[edit] See also

(C++23)
A view that represents synchronous coroutine generator
(class template) [edit]

AltStyle によって変換されたページ (->オリジナル) /