[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 {template<auto>concept [*is-constant*](#concept:is-constant "33.9.3 Sender concepts [exec.snd.concepts]") = true; // *exposition only*template<class Sndr>concept [*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]")<typename Sndr::sender_concept, sender_t>; template<class Sndr>concept [*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]")<Sndr> ||[*is-awaitable*](exec.awaitable#concept:is-awaitable "33.9.4 Awaitable helpers [exec.awaitable]")<Sndr, *env-promise*<env<>>>; // [[exec.awaitable]](exec.awaitable "33.9.4 Awaitable helpers")template<class Sndr>inline constexpr bool enable_sender = [*enable-sender*](#concept:enable-sender "33.9.3 Sender concepts [exec.snd.concepts]")<Sndr>; template<class Sndr>consteval bool *is-dependent-sender-helper*() try { // *exposition only* get_completion_signatures<Sndr>(); return false; } catch (dependent_sender_error&) {return true; }template<class Sndr>concept [sender](#concept:sender "33.9.3 Sender concepts [exec.snd.concepts]") = enable_sender<remove_cvref_t<Sndr>> &&requires (const remove_cvref_t<Sndr>& 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]")<remove_cvref_t<Sndr>> &&[constructible_from](concept.constructible#concept:constructible_from "18.4.11 Concept constructible_­from [concept.constructible]")<remove_cvref_t<Sndr>, Sndr>; template<class Sndr, class... Env>concept [sender_in](#concept:sender_in "33.9.3 Sender concepts [exec.snd.concepts]") =[sender](#concept:sender "33.9.3 Sender concepts [exec.snd.concepts]")<Sndr> &&(sizeof...(Env) <= 1) &&([*queryable*](exec.queryable.concept#concept:queryable "33.2.2 queryable concept [exec.queryable.concept]")<Env> &&...) &&[*is-constant*](#concept:is-constant "33.9.3 Sender concepts [exec.snd.concepts]")<get_completion_signatures<Sndr, Env...>()>; template<class Sndr>concept [dependent_sender](#concept:dependent_sender "33.9.3 Sender concepts [exec.snd.concepts]") =[sender](#concept:sender "33.9.3 Sender concepts [exec.snd.concepts]")<Sndr> && bool_constant<*is-dependent-sender-helper*<Sndr>()>::value; template<class Sndr, class Rcvr>concept [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]")<Sndr, env_of_t<Rcvr>> &&[receiver_of](exec.recv.concepts#concept:receiver_of "33.7.1 Receiver concepts [exec.recv.concepts]")<Rcvr, completion_signatures_of_t<Sndr, env_of_t<Rcvr>>> &&requires (Sndr&& sndr, Rcvr&& rcvr) { connect(std::forward<Sndr>(sndr), std::forward<Rcvr>(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]")<Sndr> is true and[dependent_sender](#concept:dependent_sender "33.9.3 Sender concepts [exec.snd.concepts]")<Sndr> 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<Sndr, Env>[.](#3.sentence-2)

Sndr and Env model [sender_in](#concept:sender_in "33.9.3 Sender concepts [exec.snd.concepts]")<Sndr, Env> 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 {template<class... As>using *value-signature* = set_value_t(As...); // *exposition only*template<class Sndr, class SetValue, class... Env>concept [*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]")<Sndr, Env...> &&*MATCHING-SIG*(SetValue, // see [[exec.general]](exec.general "33.1 General")*gather-signatures*<set_value_t, // see [[exec.cmplsig]](exec.cmplsig "33.10 Completion signatures") completion_signatures_of_t<Sndr, Env...>, *value-signature*,
 type_identity_t>); template<class Sndr, class Env, class... Values>concept [*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]")<Sndr, set_value_t(Values...), Env>; template<class Sndr, class... Values>concept [*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]")<Sndr, set_value_t(Values...)>;}

[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<Sndr> is as follows:

- [(6.1)](#6.1)

If the declarationauto&& [tag, data, ...children] = sndr; would be well-formed, tag_of_t<Sndr> is
an alias for decltype(auto(tag)).

- [(6.2)](#6.2)

Otherwise, tag_of_t<Sndr> 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 {template<class Sndr, class Tag>concept [*sender-for*](#concept:sender-for "33.9.3 Sender concepts [exec.snd.concepts]") =[sender](#concept:sender "33.9.3 Sender concepts [exec.snd.concepts]")<Sndr> &&[same_as](concept.same#concept:same_as "18.4.2 Concept same_­as [concept.same]")<tag_of_t<Sndr>, 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)
