This is an unofficial snapshot of the ISO/IEC JTC1 SC22 WG21 Core Issues List revision 115d. See http://www.open-std.org/jtc1/sc22/wg21/ for the official list.

2024-10-26


2436. Copy semantics of coroutine parameters

Section: 9.5.4  [dcl.fct.def.coroutine]     Status: C++20     Submitter: Mathias Stearn     Date: 2018-06-09

[Accepted (as paper P2107R0) at the February, 2020 (Prague) meeting.]

(This was previously issue 33 in the coroutine issue list.)

According to 9.5.4 [dcl.fct.def.coroutine] paragraph 13,

When a coroutine is invoked, a copy is created for each coroutine parameter. Each such copy is an object with automatic storage duration that is direct-initialized from an lvalue referring to the corresponding parameter if the parameter is an lvalue reference, and from an xvalue referring to it otherwise.

This means that parameters to a coroutine that are const-qualified will be copy-constructed rather than move-constructed. For example, changing the signature of a coroutine from task<void> f(std::string) to task<void>(const std::string) can introduce an extra string copy and potential heap allocation that may not be obvious to the author.

It also means that it is not possible to write a coroutine with a const-qualified move-only parameter type like const std::unique_ptr<T>.

The original parameter to the function is generally not observable to the coroutine body, so there seems to be little benefit to preserving the constness of the original parameter when copying the parameter into the coroutine frame.

Suggested resolution:

When a coroutine is invoked, a copy is created for each coroutine parameter. Each such copy is an object or reference with automatic storage duration that and has the same type as the corresponding parameter. Each copy is direct-initialized (9.4 [dcl.init]) from an lvalue referring to the corresponding parameter if the parameter is an lvalue reference, and from an xvalue referring to it otherwise. If the type of the copy is an rvalue reference type, then for the purpose of this initialization the value category of the corresponding parameter is an rvalue. A reference to use of a parameter in the function-body function-body of the coroutine and in the call to the coroutine promise constructor is replaced by a reference to its copy. The initialization and destruction of each parameter copy...