[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<P> 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<Z> 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<Z>,*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 <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()); // 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*]
