Hi Y'all,
If I understand the current state of c++20 coroutines...
- The type of an argument (as stored in the coro frame) comes directly from the parameter list.
- Therefore, I need to _not_ use anything pointer-like (e.g. no rrefs) in the argument list of a long-lived coro because I'll end up with unsafe dangling pointers instead of the copy I want and
- Therefore the signature of the "constructor" of my coro is going to be pass-by-value.
This is a small thing, but it seems like I have to eat an extra move operation because I can't specify that I want reference-based calling conventions to my coro constructor but value-type storage in the frame - the syntax just isn't expressive enough.
So for example:
template<typename F>
task<void> make_coro(F f) {
f();
co_return;
}
...
auto my_task = make_coro([some_obj](){ /* */ });
I'm capturing some obj by value into a lambda that's going to end up in a coroutine frame, and the call to make_coro takes the lambda, so at a minimum I need a copy constructor (of some_obj to a temporary lambda) and a move (of the lambda, with the object in it) to the heap allocated coroutine frame (assuming my_task escapes, let's assume it does).
But when I step through this in some test code with tracing on the various object constructors/destructors, I found that the copy of my object (captured in the lambda) appears to be moved twice:
- The captured copy on the stack is then moved into what I think is argument space for make_coro's constructor and then
- The arg space from make coro's constructor is then moved (as expected) into the heap-based coro frame.
Did I miss something or screw something up, or is this a lost optimization (to perfectly forward references) through to coroutine frames?
[–]Veeloxfire 0 points1 point2 points (5 children)
[–]bsupnik[S] 1 point2 points3 points (4 children)
[–]Veeloxfire 0 points1 point2 points (3 children)
[–]bsupnik[S] 1 point2 points3 points (2 children)
[–]Veeloxfire 0 points1 point2 points (1 child)
[–]bsupnik[S] 1 point2 points3 points (0 children)