Open ericniebler opened 5 months ago
A draft paper is available here: https://docs.google.com/document/d/1J8qWc1aYmNj40R86K0yhFY2OMdH9XlGmJlxsKpkx7Rg/edit?usp=sharing
The other thing that needs to be incorporated here, I believe, is to require receivers to be nothrow-move-constructible.
Without that, it is not possible to infer from a call to connect()
with the receiver_archetype
being noexcept that the connect()
with another receiver is going to be noexcept, because the other receiver might have a potentially-throwing move constructor.
I think that this approach has a lot of benefits and simplifies the implementation.
As it is often the case that an operation-state class has an internal receiver class that it passes to connect() on child operations, and the environment type returned from that receiver's get_env()
method is often dependent on the parent operation_state
class, it makes sense to
I have two initial concerns, however.
This approach requires instantiating the entire operation-state class, potentially with a dummy receiver_archetype
class, in order to query the completion-signatures.
This can potentially result in a whole raft of instantiations (base-classes, data-members, member-functions, etc.) of operation-states for the whole tree that would not be necessary for just computing the completion-signatures.
I would be interested to see differences in compile-times compared to the alternative approach of just making get_completion_signatures()
swap taking an env for taking a receiver.
Simply checking whether a sender can be connected to a receiver_archetype
is not sufficient to be able to determine if a sender is dependent or not.
Consider the sender returned by read_env(get_allocator)
.
This sender can be connected to a receiver_archetype
.
As its get_env()
method returns the empty-env, the read_env
sender, which completes with the result of get_allocator(get_env(rcvr))
, will complete with std::allocator<void>
- the default allocator returned by get_allocator
if the env does not provide an allocator.
However, this sender is not a non-dependent sender - the result of this sender does depend on the environment/receiver that is connected to it.
@ericniebler @lewissbaker @kirkshoop - it seems like more design discussion is needed here before we can move forward with this change.
i wonder how common it is to ask for a sender's completion signatures without also wanting to connect
the sender to a receiver.
fwiw, i agree that changing get_completion_signatures
to take the receiver is a smaller, simpler, safer fix. someone needs to implement it tho.
i wonder how common it is to ask for a sender's completion signatures without also wanting to
connect
the sender to a receiver.
The only case I can think of where this would be done is where you want to do early type-checking of senders - which is the whole point of P3164.
fwiw, i agree that changing
get_completion_signatures
to take the receiver is a smaller, simpler, safer fix. someone needs to implement it tho.
I can potentially implement in squiz. I already have the additional query for is_always_nothrow_connectable
and would just need to change the get_completion_signatures()
query from taking an optional env to taking an optional receiver.
I will need to work through a potential basic_sender implementation, though, as I do not have this facility in my implementation.
it is desirable to compute completion signatures with the type of the receiver instead of with the environment only, as is done in P2300R9. this makes it possible to know whether
connect(sndr, rcvr)
can throw, which can effect the sender's completion signatures.the easiest solution is to remove
get_completion_signatures
and put the completion signatures in the operation state as a nested typedef. doing that involves the following:operation_state
concept to require types to have a nested::completion_signatures
alias that denotes a specialization of thecompletion_signatures<>
class template.connect
return an operation state.::completion_signatures
alias tooperation-state-task
receiver_archetype
as follows:completion_signatures_of_t
to take a sender type and a receiver type. default the receiver parameter toreceiver_archetype
. Make similar changes tovalue_types_of_t
,error_types_of_t
andsends_stopped
.sender_in
conceptsender_to
concept as follows:change
sender-of
andsender-of-in
as follows:sender_in
concept to instead usesender_to
with an appropriate receiver type.transform_sender
andtransform_env
need to change.let_value
, changelet-bind
to conditionally handle an exception fromconnect
.transform_completion_signatures
to propagate type errors.