Hi Arthur,
Thanks for the response, I'll take a look at making a PR in the Core Guidelines to clarify the example a bit further.
I wasn't very familiar yet with the explicit parameter object, especially not in lambdas, and after reading a bit about I did find that you can refer to the captured variables in a lambda by using the `self` parameter you declare:
https://godbolt.org/z/9d1oPv9fGNow, this is pretty painful syntax, as we'd constantly have to type `std::forward_like<decltype(self)>(value)` to be able to use our values safely.
The good news: you don't have to, and should not, use `std::forward_like<decltype(self)>`, because `self` is not a forwarding reference. Never forward things that aren't forwarding references!
Because `decltype(self)` is a prvalue type (namely `Lambda`), therefore `std::forward<decltype(self)>(...)` expands to `static_cast<Lambda&&>(...)`, and `std::forward_like<decltype(self)>(...)` expands to basically `std::move(...)`.
The better news: Hm, you seem to have discovered that lambdas with explicit `this` parameters already work the way I was hoping they could be made to!
auto lambda = [x=2](this auto self) { return &x; };
int *px = lambda(); // return a (dangling) pointer into `self`'s captures, not a pointer into `lambda`'s captures!
Looks like this comes from
I can't find where this is normatively specified; the closest I've gotten so far is
"Every id-expression within the compound-statement of a lambda-expression [...] is transformed into an access to the corresponding unnamed data member of the closure type" — but this seems like a category error to me; it should be saying something about the corresponding unnamed data member of some particular object (not some type), and in our example above, we need to ensure that that particular object is specifically the by-value parameter `self` and not some other object. And:
"the type of [an expression such as `x`] is the type of a class member access expression naming the non-static data member that would be declared for such a capture in the object parameter of the function call operator of E" — but this describes only the expression's type; it doesn't specify how to compute the expression's value.
But, on the assumption that it's supposed to work this way — and all three compiler vendors seem to agree it is —
it looks like your problem can be solved by simply adding `(this auto)` to your coroutine lambdas' signatures. (You don't need to, and therefore probably shouldn't, give that parameter any name.) It might even be worth creating a macro something like
#define DEFERRED this auto
so such lambdas really stand out:
int x = 1;
auto lambda = [&](DEFERRED, int y) -> Deferred { co_return x + y; };
co_await lambda();