C++ Logo

std-proposals

Advanced search

Re: async coroutines vs. lambdas

From: Marcin Jaczewski <marcinjaczewski86_at_[hidden]>
Date: Thu, 14 May 2020 16:54:43 +0200
czw., 14 maj 2020 o 16:11 Avi Kivity <avi_at_[hidden]> napisał(a):
>
>
> On 14/05/2020 16.56, Marcin Jaczewski wrote:
> > czw., 14 maj 2020 o 15:43 Avi Kivity <avi_at_[hidden]> napisał(a):
> >>
> >> On 14/05/2020 16.30, Marcin Jaczewski via Std-Proposals wrote:
> >>> And code like:
> >>>
> >>> ```
> >>> lazy<int> get_custom_lambda() {
> >>> struct X
> >>> {
> >>> int i = 3;
> >>> lazy<int> operator()(){ co_return i; }
> >>> } x();
> >>> return x();
> >>> }
> >>>
> >>> ```
> >>>
> >>> This still crash, and this is same code as `get_real_lambda`.
> >>> How do you like fix it?
> >>
> >> If the coroutine is a member function, then
> >>
> >> If the member function was called on an rvalue object, the object is
> >> captured in the coroutine frame by value (and is not a reference in
> >> coroutine_trait's type parameters)
> >>
> >> If the member function was called on an lvalue object, the object is
> >> captured by reference (as the current standard requires).
> >>
> >>
> >>> and what if lambda is not movable?
> >>
> >> If the lambda cannot be moved or copied to the coroutine frame, then the
> >> program is ill formed (same as passing a non-copyable, non-movable
> >> argument).
> >>
> >>
> >>
> > But then corutine can see only this:
> >
> > ```
> > lazy<int> X::operator()() const
> > {
> > co_return this->i;
> > }
> > ```
> > There is no info if you have rvalue or lvalue; If we had
> > `X::operator()() &&` then it could work, but this will need lot more
>
>
> We do have X::operator()():
>
>
> https://godbolt.org/z/_YSsB4
>
>
> > changes than you propose.
>
>
> For a lambda, the compiler can see that it is called as an rvalue and
> tack on && by itself.
>
>

My point was that AFIK current lambda do not have `&&` and adding it
could be visible for user in other contexts,
If we can safely add new overload and change new case for corutines
that copy move `*this` if function is defined with `&&` then this
problem is fixed.
Other wise we should stick to current behavior and do not returns
corutines from local objects.

btw in case you show:
```
int bar;

   get_int().then([foo] (int val) -> future<> {

        int another = co_await get_int();

        bar = foo + val + another;

   });
```
is different case, because do you not call `operator()()` there.

if `then` look like this:
```
task<> then(T call)
{
   co_await call();
}
```
Then you do not have problem with not coping lambda. because `call`
will be embedded in context of `then`.

Received on 2020-05-14 09:57:57