-
Notifications
You must be signed in to change notification settings - Fork 5
Description
@haggaie makes an interesting observation about the following sender:
let_value(whatever, [](things...) { return just(stuff...); })let_value is going to call the lambda with whatever's value completions, and then immediately connect and start the resulting sender (just(stuff...)). the just sender's operation state, including copies of stuff..., will be stored in let_value's operation state. but after the just operation is started, stuff... isn't needed anymore and is just uselessly taking up space in let_value's operation state.
imagine we add back a submit customization that connects and immediately starts an operation ... but that returns the operation (instead of returning void like the old one did). it has an obvious default implementation in terms of connect and start:
template <class Sndr, class Rcvr>
auto submit(Sndr&& sndr, Rcvr rcvr)
{
struct storage
{
op(Sndr&& sndr, Rcvr rcvr)
: op_(connect(forward<Sndr>(sndr), move(rcvr)))
{
start(op_);
}
connect_result_t<Sndr, Rcvr> op_;
};
return storage{forward<Sndr>(sndr), move(rcvr)};
}but a sender like just could customize it like:
struct _empty {};
template <class... Values>
struct just_sender
{
template <class Self, class Rcvr>
_empty submit(this Self&& self, Rcvr rcvr)
{
std::apply(
[&](auto... vals) noexcept { set_value(move(rcvr), move(vals)...); },
forward<Self>(self).vals_
);
return {};
}
...
tuple<Values...> vals_;
};in this case, the returned object doesn't even need to store the receiver.
adding this customization point after c++26 would be possible as an extension, but we may not be able to customize we may not be able to change just for itlet_value to use it because it would change the ABI of operation states. :-/