[exec.snd.concepts] # 33 Execution control library [[exec]](./#exec) ## 33.9 Senders [[exec.snd]](exec.snd#concepts) ### 33.9.3 Sender concepts [exec.snd.concepts] [1](#1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L2127) The [sender](#concept:sender "33.9.3 Sender concepts [exec.snd.concepts]") concept defines the requirements for a sender type ([[exec.async.ops]](exec.async.ops "33.3 Asynchronous operations"))[.](#1.sentence-1) The [sender_in](#concept:sender_in "33.9.3 Sender concepts [exec.snd.concepts]") concept defines the requirements for a sender type that can create asynchronous operations given an associated environment type[.](#1.sentence-2) The [sender_to](#concept:sender_to "33.9.3 Sender concepts [exec.snd.concepts]") concept defines the requirements for a sender type that can connect with a specific receiver type[.](#1.sentence-3) The get_env customization point object is used to access a sender's associated attributes[.](#1.sentence-4) The connect customization point object is used to connect ([[exec.async.ops]](exec.async.ops "33.3 Asynchronous operations")) a sender and a receiver to produce an operation state[.](#1.sentence-5) [🔗](#lib:is-dependent-sender-helper) namespace std::execution {templateconcept [*is-constant*](#concept:is-constant "33.9.3 Sender concepts [exec.snd.concepts]") = true; // *exposition only*templateconcept [*is-sender*](#concept:is-sender "33.9.3 Sender concepts [exec.snd.concepts]") = // *exposition only*[derived_from](concept.derived#concept:derived_from "18.4.3 Concept derived_­from [concept.derived]"); templateconcept [*enable-sender*](#concept:enable-sender "33.9.3 Sender concepts [exec.snd.concepts]") = // *exposition only*[*is-sender*](#concept:is-sender "33.9.3 Sender concepts [exec.snd.concepts]") ||[*is-awaitable*](exec.awaitable#concept:is-awaitable "33.9.4 Awaitable helpers [exec.awaitable]")>>; // [[exec.awaitable]](exec.awaitable "33.9.4 Awaitable helpers")templateinline constexpr bool enable_sender = [*enable-sender*](#concept:enable-sender "33.9.3 Sender concepts [exec.snd.concepts]"); templateconsteval bool *is-dependent-sender-helper*() try { // *exposition only* get_completion_signatures(); return false; } catch (dependent_sender_error&) {return true; }templateconcept [sender](#concept:sender "33.9.3 Sender concepts [exec.snd.concepts]") = enable_sender> &&requires (const remove_cvref_t& sndr) {{ get_env(sndr) } -> [*queryable*](exec.queryable.concept#concept:queryable "33.2.2 queryable concept [exec.queryable.concept]"); } &&[move_constructible](concept.moveconstructible#concept:move_constructible "18.4.13 Concept move_­constructible [concept.moveconstructible]")> &&[constructible_from](concept.constructible#concept:constructible_from "18.4.11 Concept constructible_­from [concept.constructible]"), Sndr>; templateconcept [sender_in](#concept:sender_in "33.9.3 Sender concepts [exec.snd.concepts]") =[sender](#concept:sender "33.9.3 Sender concepts [exec.snd.concepts]") &&(sizeof...(Env) <= 1) &&([*queryable*](exec.queryable.concept#concept:queryable "33.2.2 queryable concept [exec.queryable.concept]") &&...) &&[*is-constant*](#concept:is-constant "33.9.3 Sender concepts [exec.snd.concepts]")()>; templateconcept [dependent_sender](#concept:dependent_sender "33.9.3 Sender concepts [exec.snd.concepts]") =[sender](#concept:sender "33.9.3 Sender concepts [exec.snd.concepts]") && bool_constant<*is-dependent-sender-helper*()>::value; templateconcept [sender_to](#concept:sender_to "33.9.3 Sender concepts [exec.snd.concepts]") =[sender_in](#concept:sender_in "33.9.3 Sender concepts [exec.snd.concepts]")> &&[receiver_of](exec.recv.concepts#concept:receiver_of "33.7.1 Receiver concepts [exec.recv.concepts]")>> &&requires (Sndr&& sndr, Rcvr&& rcvr) { connect(std::forward(sndr), std::forward(rcvr)); };} [2](#2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L2197) For a type Sndr, if[sender](#concept:sender "33.9.3 Sender concepts [exec.snd.concepts]") is true and[dependent_sender](#concept:dependent_sender "33.9.3 Sender concepts [exec.snd.concepts]") is false, then Sndr is a non-dependent sender ([[exec.async.ops]](exec.async.ops "33.3 Asynchronous operations"))[.](#2.sentence-1) [3](#3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L2203) Given a subexpression sndr, let Sndr be decltype((sndr)) and let rcvr be a receiver with an associated environment whose type is Env[.](#3.sentence-1) A completion operation is a [*permissible completion*](#def:completion,permissible "33.9.3 Sender concepts [exec.snd.concepts]") for Sndr and Env if its completion signature appears in the argument list of the specialization of completion_signatures denoted bycompletion_signatures_of_t[.](#3.sentence-2) Sndr and Env model [sender_in](#concept:sender_in "33.9.3 Sender concepts [exec.snd.concepts]") if all the completion operations that are potentially evaluated by connecting sndr to rcvr and starting the resulting operation state are permissible completions for Sndr and Env[.](#3.sentence-3) [4](#4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L2218) *Remarks*: Pursuant to [[namespace.std]](namespace.std "16.4.5.2.1 Namespace std"), users may specialize enable_sender totrue for cv-unqualified program-defined types that model [sender](#concept:sender "33.9.3 Sender concepts [exec.snd.concepts]"), andfalse for types that do not[.](#4.sentence-1) Such specializations shall be usable in constant expressions ([[expr.const]](expr.const "7.7 Constant expressions")) and have type const bool[.](#4.sentence-2) [5](#5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L2229) The exposition-only concepts[*sender-of*](#concept:sender-of "33.9.3 Sender concepts [exec.snd.concepts]") and [*sender-in-of*](#concept:sender-in-of "33.9.3 Sender concepts [exec.snd.concepts]") define the requirements for a sender type that completes with a given unique set of value result types[.](#5.sentence-1) namespace std::execution {templateusing *value-signature* = set_value_t(As...); // *exposition only*templateconcept [*sender-in-of-impl*](#concept:sender-in-of-impl "33.9.3 Sender concepts [exec.snd.concepts]") = // *exposition only*[sender_in](#concept:sender_in "33.9.3 Sender concepts [exec.snd.concepts]") &&*MATCHING-SIG*(SetValue, // see [[exec.general]](exec.general "33.1 General")*gather-signatures*, *value-signature*, type_identity_t>); templateconcept [*sender-in-of*](#concept:sender-in-of "33.9.3 Sender concepts [exec.snd.concepts]") = // *exposition only*[*sender-in-of-impl*](#concept:sender-in-of-impl "33.9.3 Sender concepts [exec.snd.concepts]"); templateconcept [*sender-of*](#concept:sender-of "33.9.3 Sender concepts [exec.snd.concepts]") = // *exposition only*[*sender-in-of-impl*](#concept:sender-in-of-impl "33.9.3 Sender concepts [exec.snd.concepts]");} [6](#6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L2258) Let sndr be an expression such that decltype((sndr)) is Sndr[.](#6.sentence-1) The type tag_of_t is as follows: - [(6.1)](#6.1) If the declarationauto&& [tag, data, ...children] = sndr; would be well-formed, tag_of_t is an alias for decltype(auto(tag)). - [(6.2)](#6.2) Otherwise, tag_of_t is ill-formed. [7](#7) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L2274) Let [*sender-for*](#concept:sender-for "33.9.3 Sender concepts [exec.snd.concepts]") be an exposition-only concept defined as follows:namespace std::execution {templateconcept [*sender-for*](#concept:sender-for "33.9.3 Sender concepts [exec.snd.concepts]") =[sender](#concept:sender "33.9.3 Sender concepts [exec.snd.concepts]") &&[same_as](concept.same#concept:same_as "18.4.2 Concept same_­as [concept.same]"), Tag>;} [8](#8) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L2285) For a type T,*SET-VALUE-SIG*(T) denotes the type set_value_t() if T is cv void; otherwise, it denotes the type set_value_t(T)[.](#8.sentence-1) [9](#9) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L2291) Library-provided sender types - [(9.1)](#9.1) always expose an overload of a member connect that accepts an rvalue sender and - [(9.2)](#9.2) only expose an overload of a member connect that accepts an lvalue sender if they model [copy_constructible](concept.copyconstructible#concept:copy_constructible "18.4.14 Concept copy_­constructible [concept.copyconstructible]")[.](#9.sentence-1)