o is determined by enumerating the applicable
operator co_await functions for an argument
a ([over.match.oper]), and choosing the best one through
overload resolution ([over.match]). If overload resolution is ambiguous,
the program is ill-formed
. If no viable functions are found,
o is
a. Otherwise,
o is a call to the selected function
with the argument
a. If
o would be a prvalue,
the temporary materialization conversion (
[conv.rval]) is applied
.e is an lvalue
referring to the result of evaluating
the (possibly-converted)
o. h is an object of type
std::coroutine_handle<P>
referring to the enclosing coroutine
. await-ready is the expression
e.await_ready(),
contextually converted to
bool. await-suspend is the expression
e.await_suspend(h),
which shall be a prvalue of type
void, bool, or
std::coroutine_handle<Z> for some type Z. await-resume is the expression
e.await_resume(). The
await-expression has the same type and value category
as the
await-resume expression
.The
await-expression evaluates
the (possibly-converted)
o expression and
the
await-ready expression, then:
If the result of
await-ready is
false,
the coroutine is considered suspended. Then:
If the type of
await-suspend
is
std::coroutine_handle<Z>,
await-suspend.resume() is evaluated
. [
Note 1:
This resumes the coroutine referred to
by the result of
await-suspend. Any number of coroutines can be successively resumed in this fashion,
eventually returning control flow to the current coroutine caller or
resumer (
[dcl.fct.def.coroutine])
. —
end note]
Otherwise, if the type of
await-suspend
is
bool,
await-suspend is evaluated,
and the coroutine is resumed if the result is false.Otherwise,
await-suspend is evaluated
.
If the evaluation of
await-suspend
exits via an exception, the exception is caught,
the coroutine is resumed, and the exception is immediately
rethrown (
[except.throw])
. The point in the coroutine
immediately prior to control returning to its caller or resumer
is a coroutine
suspend point.If the result of
await-ready is
true,
or when the coroutine is resumed
other than by rethrowing an exception from await-suspend,
the await-resume expression is evaluated, and
its result is the result of the await-expression. [
Example 1:
template <typename T>
struct my_future {
bool await_ready();
void await_suspend(std::coroutine_handle<>);
T await_resume();
};
template <class Rep, class Period>
auto operator co_await(std::chrono::duration<Rep, Period> d) {
struct awaiter {
std::chrono::system_clock::duration duration;
awaiter(std::chrono::system_clock::duration d) : duration(d) {}
bool await_ready() const { return duration.count() <= 0; }
void await_resume() {}
void await_suspend(std::coroutine_handle<> h) { }
};
return awaiter{d};
}
using namespace std::chrono;
my_future<int> h();
my_future<void> g() {
std::cout << "just about to go to sleep...\n";
co_await 10ms;
std::cout << "resumed\n";
co_await h();
}
auto f(int x = co_await h();
int a[] = { co_await h() };
—
end example]