tmp/tmpeeqz164x/{from.md → to.md}
RENAMED
|
@@ -0,0 +1,122 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#### Await <a id="expr.await">[[expr.await]]</a>
|
| 2 |
+
|
| 3 |
+
The `co_await` expression is used to suspend evaluation of a coroutine
|
| 4 |
+
[[dcl.fct.def.coroutine]] while awaiting completion of the computation
|
| 5 |
+
represented by the operand expression.
|
| 6 |
+
|
| 7 |
+
``` bnf
|
| 8 |
+
await-expression:
|
| 9 |
+
'co_await' cast-expression
|
| 10 |
+
```
|
| 11 |
+
|
| 12 |
+
An *await-expression* shall appear only in a potentially-evaluated
|
| 13 |
+
expression within the *compound-statement* of a *function-body* outside
|
| 14 |
+
of a *handler* [[except.pre]]. In a *declaration-statement* or in the
|
| 15 |
+
*simple-declaration* (if any) of a *for-init-statement*, an
|
| 16 |
+
*await-expression* shall appear only in an *initializer* of that
|
| 17 |
+
*declaration-statement* or *simple-declaration*. An *await-expression*
|
| 18 |
+
shall not appear in a default argument [[dcl.fct.default]]. An
|
| 19 |
+
*await-expression* shall not appear in the initializer of a block-scope
|
| 20 |
+
variable with static or thread storage duration. A context within a
|
| 21 |
+
function where an *await-expression* can appear is called a *suspension
|
| 22 |
+
context* of the function.
|
| 23 |
+
|
| 24 |
+
Evaluation of an *await-expression* involves the following auxiliary
|
| 25 |
+
types, expressions, and objects:
|
| 26 |
+
|
| 27 |
+
- *p* is an lvalue naming the promise object [[dcl.fct.def.coroutine]]
|
| 28 |
+
of the enclosing coroutine and `P` is the type of that object.
|
| 29 |
+
- *a* is the *cast-expression* if the *await-expression* was implicitly
|
| 30 |
+
produced by a *yield-expression* [[expr.yield]], an initial suspend
|
| 31 |
+
point, or a final suspend point [[dcl.fct.def.coroutine]]. Otherwise,
|
| 32 |
+
the *unqualified-id* `await_transform` is looked up within the scope
|
| 33 |
+
of `P` by class member access lookup [[basic.lookup.classref]], and if
|
| 34 |
+
this lookup finds at least one declaration, then *a* is
|
| 35 |
+
*p*`.await_transform(`*cast-expression*`)`; otherwise, *a* is the
|
| 36 |
+
*cast-expression*.
|
| 37 |
+
- *o* is determined by enumerating the applicable `operator co_await`
|
| 38 |
+
functions for an argument *a* [[over.match.oper]], and choosing the
|
| 39 |
+
best one through overload resolution [[over.match]]. If overload
|
| 40 |
+
resolution is ambiguous, the program is ill-formed. If no viable
|
| 41 |
+
functions are found, *o* is *a*. Otherwise, *o* is a call to the
|
| 42 |
+
selected function with the argument *a*. If *o* would be a prvalue,
|
| 43 |
+
the temporary materialization conversion [[conv.rval]] is applied.
|
| 44 |
+
- *e* is an lvalue referring to the result of evaluating the
|
| 45 |
+
(possibly-converted) *o*.
|
| 46 |
+
- *h* is an object of type `std::coroutine_handle<P>` referring to the
|
| 47 |
+
enclosing coroutine.
|
| 48 |
+
- *await-ready* is the expression *e*`.await_ready()`, contextually
|
| 49 |
+
converted to `bool`.
|
| 50 |
+
- *await-suspend* is the expression *e*`.await_suspend(`*h*`)`, which
|
| 51 |
+
shall be a prvalue of type `void`, `bool`, or
|
| 52 |
+
`std::coroutine_handle<Z>` for some type `Z`.
|
| 53 |
+
- *await-resume* is the expression *e*`.await_resume()`.
|
| 54 |
+
|
| 55 |
+
The *await-expression* has the same type and value category as the
|
| 56 |
+
*await-resume* expression.
|
| 57 |
+
|
| 58 |
+
The *await-expression* evaluates the (possibly-converted) *o* expression
|
| 59 |
+
and the *await-ready* expression, then:
|
| 60 |
+
|
| 61 |
+
- If the result of *await-ready* is `false`, the coroutine is considered
|
| 62 |
+
suspended. Then:
|
| 63 |
+
- If the type of *await-suspend* is `std::coroutine_handle<Z>`,
|
| 64 |
+
*await-suspend*`.resume()` is evaluated. \[*Note 1*: This resumes
|
| 65 |
+
the coroutine referred to by the result of *await-suspend*. Any
|
| 66 |
+
number of coroutines may be successively resumed in this fashion,
|
| 67 |
+
eventually returning control flow to the current coroutine caller or
|
| 68 |
+
resumer [[dcl.fct.def.coroutine]]. — *end note*]
|
| 69 |
+
- Otherwise, if the type of *await-suspend* is `bool`, *await-suspend*
|
| 70 |
+
is evaluated, and the coroutine is resumed if the result is `false`.
|
| 71 |
+
- Otherwise, *await-suspend* is evaluated.
|
| 72 |
+
|
| 73 |
+
If the evaluation of *await-suspend* exits via an exception, the
|
| 74 |
+
exception is caught, the coroutine is resumed, and the exception is
|
| 75 |
+
immediately re-thrown [[except.throw]]. Otherwise, control flow
|
| 76 |
+
returns to the current coroutine caller or resumer
|
| 77 |
+
[[dcl.fct.def.coroutine]] without exiting any scopes [[stmt.jump]].
|
| 78 |
+
- If the result of *await-ready* is `true`, or when the coroutine is
|
| 79 |
+
resumed, the *await-resume* expression is evaluated, and its result is
|
| 80 |
+
the result of the *await-expression*.
|
| 81 |
+
|
| 82 |
+
[*Example 1*:
|
| 83 |
+
|
| 84 |
+
``` cpp
|
| 85 |
+
template <typename T>
|
| 86 |
+
struct my_future {
|
| 87 |
+
...
|
| 88 |
+
bool await_ready();
|
| 89 |
+
void await_suspend(std::coroutine_handle<>);
|
| 90 |
+
T await_resume();
|
| 91 |
+
};
|
| 92 |
+
|
| 93 |
+
template <class Rep, class Period>
|
| 94 |
+
auto operator co_await(std::chrono::duration<Rep, Period> d) {
|
| 95 |
+
struct awaiter {
|
| 96 |
+
std::chrono::system_clock::duration duration;
|
| 97 |
+
...
|
| 98 |
+
awaiter(std::chrono::system_clock::duration d) : duration(d) {}
|
| 99 |
+
bool await_ready() const { return duration.count() <= 0; }
|
| 100 |
+
void await_resume() {}
|
| 101 |
+
void await_suspend(std::coroutine_handle<> h) { ... }
|
| 102 |
+
};
|
| 103 |
+
return awaiter{d};
|
| 104 |
+
}
|
| 105 |
+
|
| 106 |
+
using namespace std::chrono;
|
| 107 |
+
|
| 108 |
+
my_future<int> h();
|
| 109 |
+
|
| 110 |
+
my_future<void> g() {
|
| 111 |
+
std::cout << "just about go to sleep...\n";
|
| 112 |
+
co_await 10ms;
|
| 113 |
+
std::cout << "resumed\n";
|
| 114 |
+
co_await h();
|
| 115 |
+
}
|
| 116 |
+
|
| 117 |
+
auto f(int x = co_await h()); // error: await-expression outside of function suspension context
|
| 118 |
+
int a[] = { co_await h() }; // error: await-expression outside of function suspension context
|
| 119 |
+
```
|
| 120 |
+
|
| 121 |
+
— *end example*]
|
| 122 |
+
|