33 Execution control library [exec]

33.9 Senders [exec.snd]

33.9.12 Sender adaptors [exec.adapt]

33.9.12.2 Closure objects [exec.adapt.obj]

A pipeable sender adaptor closure object is a function object that accepts one or more sender arguments and returns a sender.
For a pipeable sender adaptor closure object c and an expression sndr such that decltype((sndr)) models sender, the following expressions are equivalent and yield a sender: c(sndr) sndr | c
Given an additional pipeable sender adaptor closure object d, the expression c | d produces another pipeable sender adaptor closure object e:
e is a perfect forwarding call wrapper ([func.require]) with the following properties:
  • Its target object is an object d2 of type decltype(auto(d)) direct-non-list-initialized with d.
  • It has one bound argument entity, an object c2 of type decltype(auto(c)) direct-non-list-initialized with c.
  • Its call pattern is d2(c2(arg)), where arg is the argument used in a function call expression of e.
The expression c | d is well-formed if and only if the initializations of the state entities ([func.def]) of e are all well-formed.
An object t of type T is a pipeable sender adaptor closure object if T models derived_from<sender_adaptor_closure<T>>, T has no other base classes of type sender_adaptor_closure<U> for any other type U, and T does not satisfy sender.
The template parameter D for sender_adaptor_closure can be an incomplete type.
Before any expression of type cv D appears as an operand to the | operator, D shall be complete and model derived_from<sender_adaptor_closure<D>>.
The behavior of an expression involving an object of type cv D as an operand to the | operator is undefined if overload resolution selects a program-defined operator| function.
A pipeable sender adaptor object is a customization point object that accepts a sender as its first argument and returns a sender.
If a pipeable sender adaptor object accepts only one argument, then it is a pipeable sender adaptor closure object.
If a pipeable sender adaptor object adaptor accepts more than one argument, then let sndr be an expression such that decltype((sndr)) models sender, let args... be arguments such that adaptor(sndr, args...) is a well-formed expression as specified below, and let BoundArgs be a pack that denotes decltype(auto(args))....
The expression adaptor(args...) produces a pipeable sender adaptor closure object f that is a perfect forwarding call wrapper with the following properties:
  • Its target object is a copy of adaptor.
  • Its bound argument entities bound_args consist of objects of types BoundArgs... direct-non-list-initialized with std​::​forward<decltype((args))>(args)..., respectively.
  • Its call pattern is adaptor(rcvr, bound_args...), where rcvr is the argument used in a function call expression of f.
The expression adaptor(args...) is well-formed if and only if the initializations of the bound argument entities of the result, as specified above, are all well-formed.