[exec.adapt.obj] # 33 Execution control library [[exec]](./#exec) ## 33.9 Senders [[exec.snd]](exec.snd#exec.adapt.obj) ### 33.9.12 Sender adaptors [[exec.adapt]](exec.adapt#obj) #### 33.9.12.2 Closure objects [exec.adapt.obj] [1](#1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L3055) A [*pipeable sender adaptor closure object*](#def:sender_adaptor_closure_object,pipeable "33.9.12.2 Closure objects [exec.adapt.obj]") is a function object that accepts one or more [sender](exec.snd.concepts#concept:sender "33.9.3 Sender concepts [exec.snd.concepts]") arguments and returns a [sender](exec.snd.concepts#concept:sender "33.9.3 Sender concepts [exec.snd.concepts]")[.](#1.sentence-1) For a pipeable sender adaptor closure object c and an expression sndr such that decltype((sndr)) models [sender](exec.snd.concepts#concept:sender "33.9.3 Sender concepts [exec.snd.concepts]"), the following expressions are equivalent and yield a [sender](exec.snd.concepts#concept:sender "33.9.3 Sender concepts [exec.snd.concepts]"):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]](func.require "22.10.4 Requirements")) with the following properties: - [(1.1)](#1.1) Its target object is an object d2 of type decltype(auto(d)) direct-non-list-initialized with d[.](#1.1.sentence-1) - [(1.2)](#1.2) It has one bound argument entity, an object c2 of type decltype(auto(c)) direct-non-list-initialized with c[.](#1.2.sentence-1) - [(1.3)](#1.3) Its call pattern is d2(c2(arg)), where arg is the argument used in a function call expression of e[.](#1.3.sentence-1) The expression c | d is well-formed if and only if the initializations of the state entities ([[func.def]](func.def "22.10.3 Definitions")) of e are all well-formed[.](#1.sentence-5) [2](#2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L3088) An object t of type T is a pipeable sender adaptor closure object if T models [derived_from](concept.derived#concept:derived_from "18.4.3 Concept derived_­from [concept.derived]")>,T has no other base classes of type sender_adaptor_closure for any other type U, andT does not satisfy [sender](exec.snd.concepts#concept:sender "33.9.3 Sender concepts [exec.snd.concepts]")[.](#2.sentence-1) [3](#3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L3096) The template parameter D for sender_adaptor_closure can be an incomplete type[.](#3.sentence-1) Before any expression of type cv D appears as an operand to the | operator,D shall be complete and model [derived_from](concept.derived#concept:derived_from "18.4.3 Concept derived_­from [concept.derived]")>[.](#3.sentence-2) 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[.](#3.sentence-3) [4](#4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L3107) A [*pipeable sender adaptor object*](#def:sender_adaptor_object,pipeable "33.9.12.2 Closure objects [exec.adapt.obj]") is a customization point object that accepts a [sender](exec.snd.concepts#concept:sender "33.9.3 Sender concepts [exec.snd.concepts]") as its first argument and returns a [sender](exec.snd.concepts#concept:sender "33.9.3 Sender concepts [exec.snd.concepts]")[.](#4.sentence-1) If a pipeable sender adaptor object accepts only one argument, then it is a pipeable sender adaptor closure object[.](#4.sentence-2) [5](#5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L3114) If a pipeable sender adaptor object adaptor accepts more than one argument, then let sndr be an expression such that decltype((sndr)) models [sender](exec.snd.concepts#concept:sender "33.9.3 Sender concepts [exec.snd.concepts]"), 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))...[.](#5.sentence-1) The expression adaptor(args...) produces a pipeable sender adaptor closure object f that is a perfect forwarding call wrapper with the following properties: - [(5.1)](#5.1) Its target object is a copy of adaptor[.](#5.1.sentence-1) - [(5.2)](#5.2) Its bound argument entities bound_args consist of objects of types BoundArgs... direct-non-list-initialized withstd​::​forward(args)..., respectively[.](#5.2.sentence-1) - [(5.3)](#5.3) Its call pattern is adaptor(rcvr, bound_args...), where rcvr is the argument used in a function call expression of f[.](#5.3.sentence-1) 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[.](#5.sentence-3)