C++ Logo

std-proposals

Advanced search

Re: [std-proposals] Coroutines: Add explicit initialization by "co_init" operator

From: Jason McKesson <jmckesson_at_[hidden]>
Date: Thu, 10 Aug 2023 19:27:30 -0400
On Thu, Aug 10, 2023 at 6:52 PM Stefan Sichler via Std-Proposals
<std-proposals_at_[hidden]> wrote:
>
> Am 10.08.23 um 16:16 schrieb Pavel Vazharov via Std-Proposals:
> >
> > Once all of the parameters have been copied into the coroutine frame,
> > the coroutine then constructs the promise object. The reason the
> > parameters are copied prior to the promise object being constructed is
> > to allow the promise object to be given access to the post-copied
> > parameters in its constructor.*First, the compiler checks to see if
> > there is an overload of the promise constructor that can accept lvalue
> > references to each of the copied parameters. If the compiler finds such
> > an overload then the compiler generates a call to that constructor
> > overload*. If it does not find such an overload then the compiler falls
> > back to generating a call to the promise type’s default constructor.
> >
>
> Thank you, Pavel! I forgot about that detail. So the need for being able
> to pass parameters to the promise constructor has already been identified!
> For me, that only again emphasizes the need for some kind of explicit
> initialization, like proposed in my initial post.
>
> Let's image a promise type like this:
>
> promise_type
> {
> promise_type(void* some_arg_for_promise) { ... }
> ...
> };
>
> And a coroutine like this:
>
> ret my_coroutine(t1 some_arg_for_coroutine, t2 some_arg_for_promise)
> {
> ...
> };
>
> In that case, the c-tor parameters wouldn't match and the compiler would
> yield an error.
> So, I would be forced to also add the some_arg_for_coroutine parameter
> to the promise c-tor, even though I actually don't need that value
> there, just to be able to call that c-tor! Hm, that seems like a pretty
> clumsy design.

Is it? Or is it that your use of the design is clumsy?

I already outlined the fundamental misunderstanding prevalent in your
coroutine design. We shouldn't add a feature for allowing people to
couple things that don't need coupling.

> So even here, an explicit initialization would bring relief! Then, I
> could change the implementation of my coroutine to:
>
> ret my_coroutine(t1 some_arg_for_coroutine, t2 some_arg_for_promise)
> : co_init( promise_type { some_arg_for_promise } )
> {
> ...
> }
>
>
> This is now clearly stating that only the some_arg_for_promise should be
> passed on to the promise c-tor. This is ok, because the
> some_arg_for_coroutine parameter is only consumed in the coroutine body
> itself.
> And not only that! It would also allow additional functionality, that is
> currently completely inaccessible, like passing a "this" pointer or some
> class member to the promise c-tor if the coroutine is itself a member
> coroutine:

C++ already covers this, as the first parameter for any member
function in the lookup is always `*this`. Naturally C++23 continues
with this with explicit object parameter functions.

>
> class my_class
> {
> ret my_coroutine(t1 some_arg_for_coroutine, t2 some_arg_for_promise)
> : co_init( promise_type
> { this, some_arg_for_promise, _some_class_member } )
> {
> ...
> }
> };
>
>
> Last not least, one really big advantage that I again want to emphasize
> here is that the promise_type can then completely be decoupled from the
> coroutine signature, so the coroutine body, and *only* the coroutine
> body now defines both the actual type of the promise and the parameters
> to be passed to the c-tor of the promise.

Can you give an example where this is useful, using a design that
actually works the way coroutines are meant to work?

Received on 2023-08-10 23:27:42