P4223R1 — Towards senders in interfaces
Ian Petersen
LEWGSG1SG14
Revisions R1Oct 2026R0May 2026
The standard library offers two ways to declare an asynchronous function in one place and define it in another, and each falls short. Returning a sender whose type is specific to the function’s implementation puts the structure of that implementation in its declaration, so the implementation can’t change without changing the interface, and overrides of a virtual function can’t differ in structure. `std::execution::task` keeps the implementation out of the declaration, but it’s a coroutine type, and coroutines don’t fit every domain. This paper argues for a third way that avoids both shortcomings, sets out the requirements a solution must meet, compares candidate designs against them, and proposes `std::execution::function` as the best fit. Its main advantage is how it allocates: its only allocation is the activation frame that separating declaration from definition requires, made when the operation is connected, through an allocator that the caller’s environment chooses.