Files
cppdraft_translate/cppdraft/expr/await.md
2025-10-25 03:02:53 +03:00

9.9 KiB
Raw Blame History

[expr.await]

7 Expressions [expr]

7.6 Compound expressions [expr.compound]

7.6.2 Unary expressions [expr.unary]

7.6.2.4 Await [expr.await]

1

#

The co_await expression is used to suspend evaluation of a coroutine ([dcl.fct.def.coroutine]) while awaiting completion of the computation represented by the operand expression.

Suspending the evaluation of a coroutine transfers control to its caller or resumer.

await-expression:
co_await cast-expression

2

#

An await-expression shall appear only as a potentially-evaluated expression within the compound-statement of afunction-body or lambda-expression, in either case outside of a handler ([except.pre]).

In a declaration-statement or in thesimple-declaration (if any) of an init-statement, an await-expression shall appear only in an initializer of thatdeclaration-statement or simple-declaration.

An await-expression shall not appear in a default argument ([dcl.fct.default]).

An await-expression shall not appear in the initializer of a block variable with static or thread storage duration.

An await-expression shall not be a potentially-evaluated subexpression of the predicate of a contract assertion ([basic.contract]).

A context within a function where an await-expression can appear is called a suspension context of the function.

3

#

Evaluation of an await-expression involves the following auxiliary types, expressions, and objects:

  • (3.1)

    p is an lvalue naming the promise object ([dcl.fct.def.coroutine]) of the enclosing coroutine and P is the type of that object.

  • (3.2)

    Unless the await-expression was implicitly produced by a yield-expression ([expr.yield]), an initial await expression, or a final await expression ([dcl.fct.def.coroutine]), a search is performed for the name await_transform in the scope of P ([class.member.lookup]). If this search is performed and finds at least one declaration, then a isp.await_transform(cast-expression); otherwise, a is the cast-expression.

  • (3.3)

    o is determined by enumerating the applicableoperator co_await functions for an argumenta ([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.

  • (3.4)

    e is an lvalue referring to the result of evaluating the (possibly-converted) o.

  • (3.5)

    h is an object of typestd::coroutine_handle

    referring to the enclosing coroutine.

  • (3.6)

    await-ready is the expressione.await_ready(), contextually converted to bool.

  • (3.7)

    await-suspend is the expressione.await_suspend(h), which shall be a prvalue of type void, bool, orstd::coroutine_handle for some type Z.

  • (3.8)

    await-resume is the expressione.await_resume().

4

#

The await-expression has the same type and value category as the await-resume expression.

5

#

The await-expression evaluates the (possibly-converted) o expression and the await-ready expression, then:

  • (5.1)

    If the result of await-ready is false, the coroutine is considered suspended. Then:

    • (5.1.1)

      If the type of await-suspend is std::coroutine_handle,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]

    • (5.1.2)

      Otherwise, if the type of await-suspend is bool,await-suspend is evaluated, and the coroutine is resumed if the result is false.

    • (5.1.3)

      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]). Otherwise, control flow returns to the current coroutine caller or resumer ([dcl.fct.def.coroutine]) without exiting any scopes ([stmt.jump]). The point in the coroutine immediately prior to control returning to its caller or resumer is a coroutine suspend point.

  • (5.2)

    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.

[Note 2:

With respect to sequencing, an await-expression is indivisible ([intro.execution]).

— end note]

6

#

[Example 1: template 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 h();

my_future 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()); // error: await-expression outside of function suspension contextint a[] = { co_await h() }; // error: await-expression outside of function suspension context — end example]