[expr.await] # 7 Expressions [[expr]](./#expr) ## 7.6 Compound expressions [[expr.compound]](expr.compound#expr.await) ### 7.6.2 Unary expressions [[expr.unary]](expr.unary#expr.await) #### 7.6.2.4 Await [expr.await] [1](#1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L5411) The co_await expression is used to suspend evaluation of a coroutine ([[dcl.fct.def.coroutine]](dcl.fct.def.coroutine "9.6.4 Coroutine definitions")) while awaiting completion of the computation represented by the operand expression[.](#1.sentence-1) Suspending the evaluation of a coroutine transfers control to its caller or resumer[.](#1.sentence-2) [await-expression:](#nt:await-expression "7.6.2.4 Await [expr.await]") co_await [*cast-expression*](expr.cast#nt:cast-expression "7.6.3 Explicit type conversion (cast notation) [expr.cast]") [2](#2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L5423) An [*await-expression*](#nt:await-expression "7.6.2.4 Await [expr.await]") shall appear only as a potentially-evaluated expression within the [*compound-statement*](stmt.block#nt:compound-statement "8.4 Compound statement or block [stmt.block]") of a[*function-body*](dcl.fct.def.general#nt:function-body "9.6.1 General [dcl.fct.def.general]") or [*lambda-expression*](expr.prim.lambda.general#nt:lambda-expression "7.5.6.1 General [expr.prim.lambda.general]"), in either case outside of a [*handler*](except.pre#nt:handler "14.1 Preamble [except.pre]") ([[except.pre]](except.pre "14.1 Preamble"))[.](#2.sentence-1) In a [*declaration-statement*](stmt.dcl#nt:declaration-statement "8.10 Declaration statement [stmt.dcl]") or in the[*simple-declaration*](dcl.pre#nt:simple-declaration "9.1 Preamble [dcl.pre]") (if any) of an [*init-statement*](stmt.pre#nt:init-statement "8.1 Preamble [stmt.pre]"), an [*await-expression*](#nt:await-expression "7.6.2.4 Await [expr.await]") shall appear only in an [*initializer*](dcl.init.general#nt:initializer "9.5.1 General [dcl.init.general]") of that[*declaration-statement*](stmt.dcl#nt:declaration-statement "8.10 Declaration statement [stmt.dcl]") or [*simple-declaration*](dcl.pre#nt:simple-declaration "9.1 Preamble [dcl.pre]")[.](#2.sentence-2) An [*await-expression*](#nt:await-expression "7.6.2.4 Await [expr.await]") shall not appear in a default argument ([[dcl.fct.default]](dcl.fct.default "9.3.4.7 Default arguments"))[.](#2.sentence-3) An [*await-expression*](#nt:await-expression "7.6.2.4 Await [expr.await]") shall not appear in the initializer of a block variable with static or thread storage duration[.](#2.sentence-4) An [*await-expression*](#nt:await-expression "7.6.2.4 Await [expr.await]") shall not be a potentially-evaluated subexpression of the predicate of a contract assertion ([[basic.contract]](basic.contract "6.11 Contract assertions"))[.](#2.sentence-5) A context within a function where an [*await-expression*](#nt:await-expression "7.6.2.4 Await [expr.await]") can appear is called a [*suspension context*](#def:suspension_context) of the function[.](#2.sentence-6) [3](#3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L5444) Evaluation of an [*await-expression*](#nt:await-expression "7.6.2.4 Await [expr.await]") involves the following auxiliary types, expressions, and objects: - [(3.1)](#3.1) *p* is an lvalue naming the promise object ([[dcl.fct.def.coroutine]](dcl.fct.def.coroutine "9.6.4 Coroutine definitions")) of the enclosing coroutine and P is the type of that object[.](#3.1.sentence-1) - [(3.2)](#3.2) Unless the [*await-expression*](#nt:await-expression "7.6.2.4 Await [expr.await]") was implicitly produced by a [*yield-expression*](expr.yield#nt:yield-expression "7.6.17 Yielding a value [expr.yield]") ([[expr.yield]](expr.yield "7.6.17 Yielding a value")), an initial await expression, or a final await expression ([[dcl.fct.def.coroutine]](dcl.fct.def.coroutine "9.6.4 Coroutine definitions")), a search is performed for the name await_transform in the scope of P ([[class.member.lookup]](class.member.lookup "6.5.2 Member name lookup"))[.](#3.2.sentence-1) If this search is performed and finds at least one declaration, then *a* is*p*.await_transform([*cast-expression*](expr.cast#nt:cast-expression "7.6.3 Explicit type conversion (cast notation) [expr.cast]")); otherwise, *a* is the [*cast-expression*](expr.cast#nt:cast-expression "7.6.3 Explicit type conversion (cast notation) [expr.cast]")[.](#3.2.sentence-2) - [(3.3)](#3.3) *o* is determined by enumerating the applicableoperator co_await functions for an argument*a* ([[over.match.oper]](over.match.oper "12.2.2.3 Operators in expressions")), and choosing the best one through overload resolution ([[over.match]](over.match "12.2 Overload resolution"))[.](#3.3.sentence-1) If overload resolution is ambiguous, the program is ill-formed[.](#3.3.sentence-2) If no viable functions are found, *o* is *a*[.](#3.3.sentence-3) Otherwise, *o* is a call to the selected function with the argument *a*[.](#3.3.sentence-4) If *o* would be a prvalue, the temporary materialization conversion ([[conv.rval]](conv.rval "7.3.5 Temporary materialization conversion")) is applied[.](#3.3.sentence-5) - [(3.4)](#3.4) *e* is an lvalue referring to the result of evaluating the (possibly-converted) *o*[.](#3.4.sentence-1) - [(3.5)](#3.5) *h* is an object of typestd​::​coroutine_handle

referring to the enclosing coroutine[.](#3.5.sentence-1) - [(3.6)](#3.6) *await-ready* is the expression*e*.await_ready(), contextually converted to bool[.](#3.6.sentence-1) - [(3.7)](#3.7) *await-suspend* is the expression*e*.await_suspend(*h*), which shall be a prvalue of type void, bool, orstd​::​coroutine_handle for some type Z[.](#3.7.sentence-1) - [(3.8)](#3.8) *await-resume* is the expression*e*.await_resume()[.](#3.8.sentence-1) [4](#4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L5507) The [*await-expression*](#nt:await-expression "7.6.2.4 Await [expr.await]") has the same type and value category as the *await-resume* expression[.](#4.sentence-1) [5](#5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L5511) The [*await-expression*](#nt:await-expression "7.6.2.4 Await [expr.await]") evaluates the (possibly-converted) *o* expression and the *await-ready* expression, then: - [(5.1)](#5.1) If the result of *await-ready* is false, the coroutine is considered suspended[.](#5.1.sentence-1) Then: * [(5.1.1)](#5.1.1) If the type of *await-suspend* is std​::​coroutine_handle,*await-suspend*.resume() is evaluated[.](#5.1.1.sentence-1) [*Note [1](#note-1)*: This resumes the coroutine referred to by the result of *await-suspend*[.](#5.1.1.sentence-2) 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]](dcl.fct.def.coroutine "9.6.4 Coroutine definitions"))[.](#5.1.1.sentence-3) — *end note*] * [(5.1.2)](#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.2.sentence-1) * [(5.1.3)](#5.1.3) Otherwise, *await-suspend* is evaluated[.](#5.1.3.sentence-1) 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]](except.throw "14.2 Throwing an exception"))[.](#5.1.sentence-3) Otherwise, control flow returns to the current coroutine caller or resumer ([[dcl.fct.def.coroutine]](dcl.fct.def.coroutine "9.6.4 Coroutine definitions")) without exiting any scopes ([[stmt.jump]](stmt.jump "8.8 Jump statements"))[.](#5.1.sentence-4) The point in the coroutine immediately prior to control returning to its caller or resumer is a coroutine [*suspend point*](#def:suspend_point "7.6.2.4 Await [expr.await]")[.](#5.1.sentence-5) - [(5.2)](#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*](#nt:await-expression "7.6.2.4 Await [expr.await]")[.](#5.2.sentence-1) [*Note [2](#note-2)*: With respect to sequencing, an [*await-expression*](#nt:await-expression "7.6.2.4 Await [expr.await]") is indivisible ([[intro.execution]](intro.execution "6.10.1 Sequential execution"))[.](#5.sentence-2) — *end note*] [6](#6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L5565) [*Example [1](#example-1)*: template struct my_future {/* ... */bool await_ready(); void await_suspend(std::coroutine_handle<>); T await_resume();}; template auto operator co_await(std::chrono::duration 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*](#nt:await-expression "7.6.2.4 Await [expr.await]") outside of function suspension contextint a[] = { co_await h() }; // error: [*await-expression*](#nt:await-expression "7.6.2.4 Await [expr.await]") outside of function suspension context — *end example*]