<!doctype html><html lang="en">
 <head>
  <meta content="text/html; charset=utf-8" http-equiv="Content-Type">
  <meta content="width=device-width, initial-scale=1, shrink-to-fit=no" name="viewport">
  <title>P2300R8: `std::execution`</title>
<style data-fill-with="stylesheet">/******************************************************************************
 *                   Style sheet for the W3C specifications                   *
 *
 * Special classes handled by this style sheet include:
 *
 * Indices
 *   - .toc for the Table of Contents (<ol class="toc">)
 *     + <span class="secno"> for the section numbers
 *   - #toc for the Table of Contents (<nav id="toc">)
 *   - ul.index for Indices (<a href="#ref">term</a><span>, in § N.M</span>)
 *   - table.index for Index Tables (e.g. for properties or elements)
 *
 * Structural Markup
 *   - table.data for general data tables
 *     -> use 'scope' attribute, <colgroup>, <thead>, and <tbody> for best results !
 *     -> use <table class='complex data'> for extra-complex tables
 *     -> use <td class='long'> for paragraph-length cell content
 *     -> use <td class='pre'> when manual line breaks/indentation would help readability
 *   - dl.switch for switch statements
 *   - ol.algorithm for algorithms (helps to visualize nesting)
 *   - .figure and .caption (HTML4) and figure and figcaption (HTML5)
 *     -> .sidefigure for right-floated figures
 *   - ins/del
 *     -> ins/del.c### for candidate and proposed changes (amendments)
 *
 * Code
 *   - pre and code
 *
 * Special Sections
 *   - .note       for informative notes             (div, p, span, aside, details)
 *   - .example    for informative examples          (div, p, pre, span)
 *   - .issue      for issues                        (div, p, span)
 *   - .advisement for loud normative statements     (div, p, strong)
 *   - .annoying-warning for spec obsoletion notices (div, aside, details)
 *   - .correction for "candidate corrections"       (div, aside, details, section)
 *   - .addition   for "candidate additions"         (div, aside, details, section)
 *   - .correction.proposed for "proposed corrections" (div, aside, details, section)
 *   - .addition.proposed   for "proposed additions"   (div, aside, details, section)
 *
 * Definition Boxes
 *   - pre.def   for WebIDL definitions
 *   - table.def for tables that define other entities (e.g. CSS properties)
 *   - dl.def    for definition lists that define other entitles (e.g. HTML elements)
 *
 * Numbering
 *   - .secno for section numbers in .toc and headings (<span class='secno'>3.2</span>)
 *   - .marker for source-inserted example/figure/issue numbers (<span class='marker'>Issue 4</span>)
 *   - ::before styled for CSS-generated issue/example/figure numbers:
 *     -> Documents wishing to use this only need to add
 *        figcaption::before,
 *        .caption::before { content: "Figure "  counter(figure) " ";  }
 *        .example::before { content: "Example " counter(example) " "; }
 *        .issue::before   { content: "Issue "   counter(issue) " ";   }
 *
 * Header Stuff (ignore, just don't conflict with these classes)
 *   - .head for the header
 *   - .copyright for the copyright
 *
 * Outdated warning for old specs
 *
 * Miscellaneous
 *   - .overlarge for things that should be as wide as possible, even if
 *     that overflows the body text area. This can be used on an item or
 *     on its container, depending on the effect desired.
 *     Note that this styling basically doesn't help at all when printing,
 *     since A4 paper isn't much wider than the max-width here.
 *     It's better to design things to fit into a narrower measure if possible.
 *
 *   - js-added ToC jump links (see fixup.js)
 *
 ******************************************************************************/

/* color variables included separately for reliability */

/******************************************************************************/
/*                                    Body                                    */
/******************************************************************************/

	html {
	}

	body {
		counter-reset: example figure issue;

		/* Layout */
		max-width: 50em;			  /* limit line length to 50em for readability   */
		margin: 0 auto;				/* center text within page                    */
		padding: 1.6em 1.5em 2em 50px; /* assume 16px font size for downlevel clients */
		padding: 1.6em 1.5em 2em calc(26px + 1.5em); /* leave space for status flag    */

		/* Typography */
		line-height: 1.5;
		font-family: sans-serif;
		widows: 2;
		orphans: 2;
		word-wrap: break-word;
		overflow-wrap: break-word;
		hyphens: auto;

		color: black;
		color: var(--text);
		background: white top left fixed no-repeat;
		background: var(--bg) top left fixed no-repeat;
		background-size: 25px auto;
	}


/******************************************************************************/
/*                         Front Matter & Navigation                          */
/******************************************************************************/

/** Header ********************************************************************/

	div.head { margin-bottom: 1em; }
	div.head hr { border-style: solid; }

	div.head h1 {
		font-weight: bold;
		margin: 0 0 .1em;
		font-size: 220%;
	}

	div.head h2 { margin-bottom: 1.5em;}

/** W3C Logo ******************************************************************/

	.head .logo {
		float: right;
		margin: 0.4rem 0 0.2rem .4rem;
	}

	.head img[src*="logos/W3C"] {
		display: block;
		border: solid #1a5e9a;
		border: solid var(--logo-bg);
		border-width: .65rem .7rem .6rem;
		border-radius: .4rem;
		background: #1a5e9a;
		background: var(--logo-bg);
		color: white;
		color: var(--logo-text);
		font-weight: bold;
	}

	.head a:hover > img[src*="logos/W3C"],
	.head a:focus > img[src*="logos/W3C"] {
		opacity: .8;
	}

	.head a:active > img[src*="logos/W3C"] {
		background: #c00;
		background: var(--logo-active-bg);
		border-color: #c00;
		border-color: var(--logo-active-bg);
	}

	/* see also additional rules in Link Styling section */

/** Copyright *****************************************************************/

	p.copyright,
	p.copyright small { font-size: small; }

/** Back to Top / ToC Toggle **************************************************/

	@media print {
		#toc-nav {
			display: none;
		}
	}
	@media not print {
		#toc-nav {
			position: fixed;
			z-index: 3;
			bottom: 0; left: 0;
			margin: 0;
			min-width: 1.33em;
			border-top-right-radius: 2rem;
			box-shadow: 0 0 2px;
			font-size: 1.5em;
		}
		#toc-nav > a {
			display: block;
			white-space: nowrap;

			height: 1.33em;
			padding: .1em 0.3em;
			margin: 0;

			box-shadow: 0 0 2px;
			border: none;
			border-top-right-radius: 1.33em;

			color: #707070;
			color: var(--tocnav-normal-text);
			background: white;
			background: var(--tocnav-normal-bg);
		}
		#toc-nav > a:hover,
		#toc-nav > a:focus {
			color: black;
			color: var(--tocnav-hover-text);
			background: #f8f8f8;
			background: var(--tocnav-hover-bg);
		}
		#toc-nav > a:active {
			color: #c00;
			color: var(--tocnav-active-text);
			background: white;
			background: var(--tocnav-active-bg);
		}

		#toc-nav > #toc-jump {
			padding-bottom: 2em;
			margin-bottom: -1.9em;
		}

		/* statusbar gets in the way on keyboard focus; remove once browsers fix */
		#toc-nav > a[href="#toc"]:not(:hover):focus:last-child {
			padding-bottom: 1.5rem;
		}

		#toc-nav:not(:hover) > a:not(:focus) > span + span {
			/* Ideally this uses :focus-within on #toc-nav */
			display: none;
		}
		#toc-nav > a > span + span {
			padding-right: 0.2em;
		}
	}

/** ToC Sidebar ***************************************************************/

	/* Floating sidebar */
	@media screen {
		body.toc-sidebar #toc {
			position: fixed;
			top: 0; bottom: 0;
			left: 0;
			width: 23.5em;
			max-width: 80%;
			max-width: calc(100% - 2em - 26px);
			overflow: auto;
			padding: 0 1em;
			padding-left: 42px;
			padding-left: calc(1em + 26px);
			color: black;
			color: var(--tocsidebar-text);
			background: inherit;
			background-color: #f7f8f9;
			background-color: var(--tocsidebar-bg);
			z-index: 1;
			box-shadow: -.1em 0 .25em rgba(0,0,0,.1) inset;
			box-shadow: -.1em 0 .25em var(--tocsidebar-shadow) inset;
		}
		body.toc-sidebar #toc h2 {
			margin-top: .8rem;
			font-variant: small-caps;
			font-variant: all-small-caps;
			text-transform: lowercase;
			font-weight: bold;
			color: gray;
			color: hsla(203,20%,40%,.7);
			color: var(--tocsidebar-heading-text);
		}
		body.toc-sidebar #toc-jump:not(:focus) {
			width: 0;
			height: 0;
			padding: 0;
			position: absolute;
			overflow: hidden;
		}
	}
	/* Hide main scroller when only the ToC is visible anyway */
	@media screen and (max-width: 28em) {
		body.toc-sidebar {
			overflow: hidden;
		}
	}

	/* Sidebar with its own space */
	@media screen and (min-width: 78em) {
		body:not(.toc-inline) #toc {
			position: fixed;
			top: 0; bottom: 0;
			left: 0;
			width: 23.5em;
			overflow: auto;
			padding: 0 1em;
			padding-left: 42px;
			padding-left: calc(1em + 26px);
			color: black;
			color: var(--tocsidebar-text);
			background: inherit;
			background-color: #f7f8f9;
			background-color: var(--tocsidebar-bg);
			z-index: 1;
			box-shadow: -.1em 0 .25em rgba(0,0,0,.1) inset;
			box-shadow: -.1em 0 .25em var(--tocsidebar-shadow) inset;
		}
		body:not(.toc-inline) #toc h2 {
			margin-top: .8rem;
			font-variant: small-caps;
			font-variant: all-small-caps;
			text-transform: lowercase;
			font-weight: bold;
			color: gray;
			color: hsla(203,20%,40%,.7);
			color: var(--tocsidebar-heading-text);
		}

		body:not(.toc-inline) {
			padding-left: 29em;
		}
		/* See also Overflow section at the bottom */

		body:not(.toc-inline) #toc-jump:not(:focus) {
			width: 0;
			height: 0;
			padding: 0;
			position: absolute;
			overflow: hidden;
		}
	}
	@media screen and (min-width: 90em) {
		body:not(.toc-inline) {
			margin: 0 4em;
		}
	}

/******************************************************************************/
/*                                Sectioning                                  */
/******************************************************************************/

/** Headings ******************************************************************/

	h1, h2, h3, h4, h5, h6, dt {
		page-break-after: avoid;
		page-break-inside: avoid;
		font: 100% sans-serif;   /* Reset all font styling to clear out UA styles */
		font-family: inherit;	/* Inherit the font family. */
		line-height: 1.2;		/* Keep wrapped headings compact */
		hyphens: manual;		/* Hyphenated headings look weird */
	}

	h2, h3, h4, h5, h6 {
		margin-top: 3rem;
	}

	h1, h2, h3 {
		color: #005A9C;
		color: var(--heading-text);
	}

	h1 { font-size: 170%; }
	h2 { font-size: 140%; }
	h3 { font-size: 120%; }
	h4 { font-weight: bold; }
	h5 { font-style: italic; }
	h6 { font-variant: small-caps; }
	dt { font-weight: bold; }

/** Subheadings ***************************************************************/

	h1 + h2,
	#profile-and-date {
		/* #profile-and-date is a subtitle in an H2 under the H1 */
		margin-top: 0;
	}
	h2 + h3,
	h3 + h4,
	h4 + h5,
	h5 + h6 {
		margin-top: 1.2em; /* = 1 x line-height */
	}

/** Section divider ***********************************************************/

	:not(.head) > :not(.head) + hr {
		font-size: 1.5em;
		text-align: center;
		margin: 1em auto;
		height: auto;
		color: black;
		color: var(--hr-text);
		border: transparent solid 0;
		background: transparent;
	}
	:not(.head) > hr::before {
		content: "\2727\2003\2003\2727\2003\2003\2727";
	}

/******************************************************************************/
/*                            Paragraphs and Lists                            */
/******************************************************************************/

	p {
		margin: 1em 0;
	}

	dd > p:first-child,
	li > p:first-child {
		margin-top: 0;
	}

	ul, ol {
		margin-left: 0;
		padding-left: 2em;
	}

	li {
		margin: 0.25em 0 0.5em;
		padding: 0;
	}

	dl dd {
		margin: 0 0 .5em 2em;
	}

	.head dd + dd { /* compact for header */
		margin-top: -.5em;
	}

	/* Style for algorithms */
	ol.algorithm ol:not(.algorithm),
	.algorithm > ol ol:not(.algorithm) {
	border-left: 0.5em solid #DEF;
	border-left: 0.5em solid var(--algo-border);
	}

	/* Put nice boxes around each algorithm. */
	[data-algorithm]:not(.heading) {
	 padding: .5em;
	 border: thin solid #ddd;
	 border: thin solid var(--algo-border);
	 border-radius: .5em;
	 margin: .5em calc(-0.5em - 1px);
	}
	[data-algorithm]:not(.heading) > :first-child {
	 margin-top: 0;
	}
	[data-algorithm]:not(.heading) > :last-child {
	 margin-bottom: 0;
	}

	/* Style for switch/case <dl>s */
	dl.switch > dd > ol.only,
	dl.switch > dd > .only > ol {
	margin-left: 0;
	}
	dl.switch > dd > ol.algorithm,
	dl.switch > dd > .algorithm > ol {
	margin-left: -2em;
	}
	dl.switch {
	padding-left: 2em;
	}
	dl.switch > dt {
	text-indent: -1.5em;
	margin-top: 1em;
	}
	dl.switch > dt + dt {
	margin-top: 0;
	}
	dl.switch > dt::before {
	content: '\21AA';
	padding: 0 0.5em 0 0;
	display: inline-block;
	width: 1em;
	text-align: right;
	line-height: 0.5em;
	}

/** Terminology Markup ********************************************************/


/******************************************************************************/
/*                                 Inline Markup                              */
/******************************************************************************/

/** Terminology Markup ********************************************************/
	dfn   { /* Defining instance */
		font-weight: bolder;
	}
	a > i { /* Instance of term */
		font-style: normal;
	}
	dt dfn code, code.idl {
		font-size: inherit;
	}
	dfn var {
		font-style: normal;
	}

/** Change Marking ************************************************************/

	del {
		color: #aa0000;
		color: var(--del-text);
		background: transparent;
		background: var(--del-bg);
		text-decoration: line-through;
	}
	ins {
		color: #006100;
		color: var(--ins-text);
		background: transparent;
		background: var(--ins-bg);
		text-decoration: underline;
	}

	/* for amendments (candidate/proposed changes) */

	.amendment ins, .correction ins, .addition ins,
	ins[class^=c] {
		text-decoration-style: dotted;
	}
	.amendment del, .correction del, .addition del,
	del[class^=c] {
		text-decoration-style: dotted;
	}
	.amendment.proposed ins, .correction.proposed ins, .addition.proposed ins,
	ins[class^=c].proposed {
		text-decoration-style: double;
	}
	.amendment.proposed del, .correction.proposed del, .addition.proposed del,
	del[class^=c].proposed {
		text-decoration-style: double;
	}

/** Miscellaneous improvements to inline formatting ***************************/

	sup {
		vertical-align: super;
		font-size: 80%
	}

/******************************************************************************/
/*                                    Code                                    */
/******************************************************************************/

/** General monospace/pre rules ***********************************************/

	pre, code, samp {
		font-family: Menlo, Consolas, "DejaVu Sans Mono", Monaco, monospace;
		font-size: .9em;
		hyphens: none;
		text-transform: none;
		text-align: left;
		text-align: start;
		font-variant: normal;
		orphans: 3;
		widows: 3;
		page-break-before: avoid;
	}
	pre code,
	code code {
		font-size: 100%;
	}

	pre {
		margin-top: 1em;
		margin-bottom: 1em;
		overflow: auto;
	}

/** Inline Code fragments *****************************************************/

	/* Do something nice. */

/******************************************************************************/
/*                                    Links                                   */
/******************************************************************************/

/** General Hyperlinks ********************************************************/

	/* We hyperlink a lot, so make it less intrusive */
	a[href] {
		color: #034575;
		color: var(--a-normal-text);
		text-decoration: underline #707070;
		text-decoration: underline var(--a-normal-underline);
		text-decoration-skip-ink: none;
	}
	a:visited {
		color: #034575;
		color: var(--a-visited-text);
		text-decoration-color: #bbb;
		text-decoration-color: var(--a-visited-underline);
	}

	/* Indicate interaction with the link */
	a[href]:focus,
	a[href]:hover {
		text-decoration-thickness: 2px;
	}
	a[href]:active {
		color: #c00;
		color: var(--a-active-text);
		text-decoration-color: #c00;
		text-decoration-color: var(--a-active-underline);
	}

	/* Backout above styling for W3C logo */
	.head .logo,
	.head .logo a {
		border: none;
		text-decoration: none;
		background: transparent;
	}

/******************************************************************************/
/*                                    Images                                  */
/******************************************************************************/

	img {
		border-style: none;
	}

	img, svg {
		/* Intentionally not color-scheme aware. */
		background: white;
	}

	/* For autogen numbers, add
	  .caption::before, figcaption::before { content: "Figure " counter(figure) ". "; }
	*/

	figure, .figure, .sidefigure {
		page-break-inside: avoid;
		text-align: center;
		margin: 2.5em 0;
	}
	.figure img,	.sidefigure img,	figure img,
	.figure object, .sidefigure object, figure object {
		max-width: 100%;
		margin: auto;
		height: auto;
	}
	.figure pre, .sidefigure pre, figure pre {
		text-align: left;
		display: table;
		margin: 1em auto;
	}
	.figure table, figure table {
		margin: auto;
	}
	@media screen and (min-width: 20em) {
		.sidefigure {
			float: right;
			width: 50%;
			margin: 0 0 0.5em 0.5em;
		}
	}
	.caption, figcaption, caption {
		font-style: italic;
		font-size: 90%;
	}
	.caption::before, figcaption::before, figcaption > .marker {
		font-weight: bold;
	}
	.caption, figcaption {
		counter-increment: figure;
	}

	/* DL list is indented 2em, but figure inside it is not */
	dd > .figure, dd > figure { margin-left: -2em; }

/******************************************************************************/
/*                             Colored Boxes                                  */
/******************************************************************************/

	.issue, .note, .example, .assertion, .advisement, blockquote,
	.amendment, .correction, .addition {
		margin: 1em auto;
		padding: .5em;
		border: .5em;
		border-left-style: solid;
		page-break-inside: avoid;
	}
	span.issue, span.note {
		padding: .1em .5em .15em;
		border-right-style: solid;
	}

	blockquote > :first-child,
	.note  > p:first-child,
	.issue > p:first-child,
	.amendment > p:first-child,
	.correction > p:first-child,
	.addition > p:first-child {
		margin-top: 0;
	}
	blockquote > :last-child,
	.note  > p:last-child,
	.issue > p:last-child,
	.amendment > p:last-child,
	.correction > p:last-child,
	.addition > p:last-child {
		margin-bottom: 0;
	}


	.issue::before, .issue > .marker,
	.example::before, .example > .marker,
	.note::before, .note > .marker,
	details.note > summary > .marker,
	.amendment::before, .amendment > .marker,
	details.amendment > summary > .marker,
	.addition::before, .addition > .marker,
	addition.amendment > summary > .marker,
	.correction::before, .correction > .marker,
	correction.amendment > summary > .marker
	{
		text-transform: uppercase;
		padding-right: 1em;
	}

	.example::before, .example > .marker {
		display: block;
		padding-right: 0em;
	}

/** Blockquotes ***************************************************************/

	blockquote {
		border-color: silver;
		border-color: var(--blockquote-border);
		background: transparent;
		background: var(--blockquote-bg);
		color: currentcolor;
		color: var(--blockquote-text);
	}

/** Open issue ****************************************************************/

	.issue {
		border-color: #e05252;
		border-color: var(--issue-border);
		background: #fbe9e9;
		background: var(--issue-bg);
		color: black;
		color: var(--issue-text);
		counter-increment: issue;
		overflow: auto;
	}
	.issue::before, .issue > .marker {
		color: #831616;
		color: var(--issueheading-text);
	}
	/* Add .issue::before { content: "Issue " counter(issue) " "; } for autogen numbers,
	  or use class="marker" to mark up the issue number in source. */

/** Example *******************************************************************/

	.example {
		border-color: #e0cb52;
		border-color: var(--example-border);
		background: #fcfaee;
		background: var(--example-bg);
		color: black;
		color: var(--example-text);
		counter-increment: example;
		overflow: auto;
		clear: both;
	}
	.example::before, .example > .marker {
		color: #574b0f;
		color: var(--exampleheading-text);
	}
	/* Add .example::before { content: "Example " counter(example) " "; } for autogen numbers,
	  or use class="marker" to mark up the example number in source. */

/** Non-normative Note ********************************************************/

	.note {
		border-color: #52e052;
		border-color: var(--note-border);
		background: #e9fbe9;
		background: var(--note-bg);
		color: black;
		color: var(--note-text);
		overflow: auto;
	}

	.note::before, .note > .marker,
	details.note > summary {
		color: hsl(120, 70%, 30%);
		color: var(--noteheading-text);
	}
	/* Add .note::before { content: "Note "; } for autogen label,
	  or use class="marker" to mark up the label in source. */

	details.note[open] > summary {
		border-bottom: 1px silver solid;
		border-bottom: 1px var(--notesummary-underline) solid;
	}

/** Assertion Box *************************************************************/
	/*  for assertions in algorithms */

	.assertion {
		border-color: #AAA;
		border-color: var(--assertion-border);
		background: #EEE;
		background: var(--assertion-bg);
		color: black;
		color: var(--assertion-text);
	}

/** Advisement Box ************************************************************/
	/*  for attention-grabbing normative statements */

	.advisement {
		border-color: orange;
		border-color: var(--advisement-border);
		border-style: none solid;
		background: #fec;
		background: var(--advisement-bg);
		color: black;
		color: var(--advisement-text);
	}
	strong.advisement {
		display: block;
		text-align: center;
	}
	.advisement::before, .advisement > .marker {
		color: #b35f00;
		color: var(--advisementheading-text);
	}

/** Amendment Box *************************************************************/

	.amendment, .correction, .addition {
		border-color: #330099;
		border-color: var(--amendment-border);
		background: #F5F0FF;
		background: var(--amendment-bg);
		color: black;
		color: var(--amendment-text);
	}
	.amendment.proposed, .correction.proposed, .addition.proposed {
		border-style: solid;
		border-block-width: 0.25em;
	}
	.amendment::before, .amendment > .marker,
	details.amendment > summary::before, details.amendment > summary > .marker,
	.correction::before, .correction > .marker,
	details.correction > summary::before, details.correction > summary > .marker,
	.addition::before, .addition > .marker,
	details.addition > summary::before, details.addition > summary > .marker {
		color: #220066;
		color: var(--amendmentheading-text);
	}
	.amendment.proposed::before, .amendment.proposed > .marker,
	details.amendment.proposed > summary::before, details.amendment.proposed > summary > .marker,
	.correction.proposed::before, .correction.proposed > .marker,
	details.correction.proposed > summary::before, details.correction.proposed > summary > .marker,
	.addition.proposed::before, .addition.proposed > .marker,
	details.addition.proposed > summary::before, details.addition.proposed > summary > .marker {
		font-weight: bold;
	}

/** Spec Obsoletion Notice ****************************************************/
	/* obnoxious obsoletion notice for older/abandoned specs. */

	details {
		display: block;
	}
	summary {
		font-weight: bolder;
	}

	.annoying-warning:not(details),
	details.annoying-warning:not([open]) > summary,
	details.annoying-warning[open] {
		background: hsla(40,100%,50%,0.95);
		background: var(--warning-bg);
		color: black;
		color: var(--warning-text);
		padding: .75em 1em;
		border: red;
		border: var(--warning-border);
		border-style: solid none;
		box-shadow: 0 2px 8px black;
		text-align: center;
	}
	.annoying-warning :last-child {
		margin-bottom: 0;
	}

@media not print {
	details.annoying-warning[open] {
		position: fixed;
		left: 0;
		right: 0;
		bottom: 2em;
		z-index: 1000;
	}
}

	details.annoying-warning:not([open]) > summary {
		text-align: center;
	}

/** Entity Definition Boxes ***************************************************/

	.def {
		padding: .5em 1em;
		background: #def;
		background: var(--def-bg);
		margin: 1.2em 0;
		border-left: 0.5em solid #8ccbf2;
		border-left: 0.5em solid var(--def-border);
		color: black;
		color: var(--def-text);
	}

/******************************************************************************/
/*                                    Tables                                  */
/******************************************************************************/

	th, td {
		text-align: left;
		text-align: start;
	}

/** Property/Descriptor Definition Tables *************************************/

	table.def {
		/* inherits .def box styling, see above */
		width: 100%;
		border-spacing: 0;
	}

	table.def td,
	table.def th {
		padding: 0.5em;
		vertical-align: baseline;
		border-bottom: 1px solid #bbd7e9;
		border-bottom: 1px solid var(--defrow-border);
	}

	table.def > tbody > tr:last-child th,
	table.def > tbody > tr:last-child td {
		border-bottom: 0;
	}

	table.def th {
		font-style: italic;
		font-weight: normal;
		padding-left: 1em;
		width: 3em;
	}

	/* For when values are extra-complex and need formatting for readability */
	table td.pre {
		white-space: pre-wrap;
	}

	/* A footnote at the bottom of a def table */
	table.def td.footnote {
		padding-top: 0.6em;
	}
	table.def td.footnote::before {
		content: " ";
		display: block;
		height: 0.6em;
		width: 4em;
		border-top: thin solid;
	}

/** Data tables (and properly marked-up index tables) *************************/
	/*
		<table class="data"> highlights structural relationships in a table
		when correct markup is used (e.g. thead/tbody, th vs. td, scope attribute)

		Use class="complex data" for particularly complicated tables --
		(This will draw more lines: busier, but clearer.)

		Use class="long" on table cells with paragraph-like contents
		(This will adjust text alignment accordingly.)
		Alternately use class="longlastcol" on tables, to have the last column assume "long".
	*/

	table {
		word-wrap: normal;
		overflow-wrap: normal;
		hyphens: manual;
	}

	table.data,
	table.index {
		margin: 1em auto;
		border-collapse: collapse;
		border: hidden;
		width: 100%;
	}
	table.data caption,
	table.index caption {
		max-width: 50em;
		margin: 0 auto 1em;
	}

	table.data td,  table.data th,
	table.index td, table.index th {
		padding: 0.5em 1em;
		border-width: 1px;
		border-color: silver;
		border-color: var(--datacell-border);
		border-top-style: solid;
	}

	table.data thead td:empty {
		padding: 0;
		border: 0;
	}

	table.data  thead,
	table.index thead,
	table.data  tbody,
	table.index tbody {
		border-bottom: 2px solid;
	}

	table.data colgroup,
	table.index colgroup {
		border-left: 2px solid;
	}

	table.data  tbody th:first-child,
	table.index tbody th:first-child  {
		border-right: 2px solid;
		border-top: 1px solid silver;
		border-top: 1px solid var(--datacell-border);
		padding-right: 1em;
	}

	table.data th[colspan],
	table.data td[colspan] {
		text-align: center;
	}

	table.complex.data th,
	table.complex.data td {
		border: 1px solid silver;
		border: 1px solid var(--datacell-border);
		text-align: center;
	}

	table.data.longlastcol td:last-child,
	table.data td.long {
		vertical-align: baseline;
		text-align: left;
	}

	table.data img {
		vertical-align: middle;
	}


/*
Alternate table alignment rules

	table.data,
	table.index {
		text-align: center;
	}

	table.data  thead th[scope="row"],
	table.index thead th[scope="row"] {
		text-align: right;
	}

	table.data  tbody th:first-child,
	table.index tbody th:first-child  {
		text-align: right;
	}

Possible extra rowspan handling

	table.data  tbody th[rowspan]:not([rowspan='1']),
	table.index tbody th[rowspan]:not([rowspan='1']),
	table.data  tbody td[rowspan]:not([rowspan='1']),
	table.index tbody td[rowspan]:not([rowspan='1']) {
		border-left: 1px solid silver;
	}

	table.data  tbody th[rowspan]:first-child,
	table.index tbody th[rowspan]:first-child,
	table.data  tbody td[rowspan]:first-child,
	table.index tbody td[rowspan]:first-child{
		border-left: 0;
		border-right: 1px solid silver;
	}
*/

/******************************************************************************/
/*                                  Indices                                   */
/******************************************************************************/


/** Table of Contents *********************************************************/

	.toc a {
		/* More spacing; use padding to make it part of the click target. */
		padding: 0.1rem 1px 0;
		/* Larger, more consistently-sized click target */
		display: block;
		/* Switch to using border-bottom for underlines */
		text-decoration: none;
		border-bottom: 1px solid;
		/* Reverse color scheme */
		color: black;
		color: var(--toclink-text);
		border-color: #3980b5;
		border-color: var(--toclink-underline);
	}
	.toc a:visited {
		color: black;
		color: var(--toclink-visited-text);
		border-color: #054572;
		border-color: var(--toclink-visited-underline);
	}
	.toc a:focus,
	.toc a:hover {
		background: rgba(75%, 75%, 75%, .25);
		background: var(--a-hover-bg);
		border-bottom-width: 3px;
		margin-bottom: -2px;
	}
	.toc a:not(:focus):not(:hover) {
		/* Allow colors to cascade through from link styling */
		border-bottom-color: transparent;
	}

	.toc, .toc ol, .toc ul, .toc li {
		list-style: none; /* Numbers must be inlined into source */
		/* because generated content isn't search/selectable and markers can't do multilevel yet */
		margin:  0;
		padding: 0;
	}
	.toc {
		line-height: 1.1em;
	}

	/* ToC not indented until third level, but font style & margins show hierarchy */
	.toc > li			{ font-weight: bold;   }
	.toc > li li		 { font-weight: normal; }
	.toc > li li li	  { font-size:   95%;	}
	.toc > li li li li	{ font-size:   90%;	}
	.toc > li li li li li { font-size:   85%;	}

	/* @supports not (display:grid) { */
		.toc > li			{ margin: 1.5rem 0;	}
		.toc > li li		 { margin: 0.3rem 0;	}
		.toc > li li li	  { margin-left: 2rem;   }

		/* Section numbers in a column of their own */
		.toc .secno {
			float: left;
			width: 4rem;
			white-space: nowrap;
		}
		.toc > li li li li .secno { font-size: 85%; }
		.toc > li li li li li .secno { font-size: 100%; }

		.toc li {
			clear: both;
		}

		:not(li) > .toc			 { margin-left:  5rem; }
		.toc .secno				 { margin-left: -5rem; }
		.toc > li li li .secno	  { margin-left: -7rem; }
		.toc > li li li li .secno	{ margin-left: -9rem; }
		.toc > li li li li li .secno { margin-left: -11rem; }

		/* Tighten up indentation in narrow ToCs */
		@media (max-width: 30em) {
			:not(li) > .toc			 { margin-left:  4rem; }
			.toc .secno				 { margin-left: -4rem; }
			.toc > li li li			 { margin-left:  1rem; }
			.toc > li li li .secno	  { margin-left: -5rem; }
			.toc > li li li li .secno	{ margin-left: -6rem; }
			.toc > li li li li li .secno { margin-left: -7rem; }
		}
		/* Loosen it on wide screens */
		@media screen and (min-width: 78em) {
			body:not(.toc-inline) :not(li) > .toc			 { margin-left:  4rem; }
			body:not(.toc-inline) .toc .secno				 { margin-left: -4rem; }
			body:not(.toc-inline) .toc > li li li			 { margin-left:  1rem; }
			body:not(.toc-inline) .toc > li li li .secno	  { margin-left: -5rem; }
			body:not(.toc-inline) .toc > li li li li .secno	{ margin-left: -6rem; }
			body:not(.toc-inline) .toc > li li li li li .secno { margin-left: -7rem; }
	}
	/* } */

	@supports (display:grid) and (display:contents) {
		/* Use #toc over .toc to override non-@supports rules. */
		#toc {
			display: grid;
			align-content: start;
			grid-template-columns: auto 1fr;
			grid-column-gap: 1rem;
			column-gap: 1rem;
			grid-row-gap: .6rem;
			row-gap: .6rem;
		}
		#toc h2 {
			grid-column: 1 / -1;
			margin-bottom: 0;
		}
		#toc ol,
		#toc li,
		#toc a {
			display: contents;
			/* Switch <a> to subgrid when supported */
		}
		#toc span {
			margin: 0;
		}
		#toc > .toc > li > a > span {
			/* The spans of the top-level list,
			  comprising the first items of each top-level section. */
			margin-top: 1.1rem;
		}
		#toc#toc .secno { /* Ugh, need more specificity to override base.css */
			grid-column: 1;
			width: auto;
			margin-left: 0;
		}
		#toc .content {
			grid-column: 2;
			width: auto;
			margin-right: 1rem;
		}
		#toc .content:hover,
		#toc .content:focus {
			background: rgba(75%, 75%, 75%, .25);
			background: var(--a-hover-bg);
			border-bottom: 3px solid #054572;
			border-bottom: 3px solid var(--toclink-underline);
			margin-bottom: -3px;
		}
		#toc li li li .content {
			margin-left: 1rem;
		}
		#toc li li li li .content {
			margin-left: 2rem;
		}
	}


/** Index *********************************************************************/

	/* Index Lists: Layout */
	ul.index	  { margin-left: 0; columns: 15em; text-indent: 1em hanging; }
	ul.index li	{ margin-left: 0; list-style: none; break-inside: avoid; }
	ul.index li li { margin-left: 1em; }
	ul.index dl	{ margin-top: 0; }
	ul.index dt	{ margin: .2em 0 .2em 20px;}
	ul.index dd	{ margin: .2em 0 .2em 40px;}
	/* Index Lists: Typography */
	ul.index ul,
	ul.index dl { font-size: smaller; }
	@media not print {
		ul.index li a + span {
			white-space: nowrap;
			color: transparent; }
		ul.index li a:hover + span,
		ul.index li a:focus + span {
			color: #707070;
			color: var(--indexinfo-text);
		}
	}

/** Index Tables *****************************************************/
	/* See also the data table styling section, which this effectively subclasses */

	table.index {
		font-size: small;
		border-collapse: collapse;
		border-spacing: 0;
		text-align: left;
		margin: 1em 0;
	}

	table.index td,
	table.index th {
		padding: 0.4em;
	}

	table.index tr:hover td:not([rowspan]),
	table.index tr:hover th:not([rowspan]) {
		color: black;
		color: var(--indextable-hover-text);
		background: #f7f8f9;
		background: var(--indextable-hover-bg);
	}

	/* The link in the first column in the property table (formerly a TD) */
	table.index th:first-child a {
		font-weight: bold;
	}

/** Outdated warning **********************************************************/

.outdated-spec {
	color: black;
	color: var(--outdatedspec-text);
	background-color: rgba(0,0,0,0.5);
	background-color: var(--outdatedspec-bg);
}

.outdated-warning {
	position: fixed;
	bottom: 50%;
	left: 0;
	right: 0;
	margin: 0 auto;
	width: 50%;
	background: maroon;
	background: var(--outdated-bg);
	color: white;
	color: var(--outdated-text);
	border-radius: 1em;
	box-shadow: 0 0 1em red;
	box-shadow: 0 0 1em var(--outdated-shadow);
	padding: 2em;
	text-align: center;
	z-index: 2;
}

.outdated-warning a {
	color: currentcolor;
	background: transparent;
}

.edited-rec-warning {
	background: darkorange;
	background: var(--editedrec-bg);
	box-shadow: 0 0 1em;
}

.outdated-warning button {
	color: var(--outdated-text);
	border-radius: 1em;
	box-shadow: 0 0 1em red;
	box-shadow: 0 0 1em var(--outdated-shadow);
	padding: 2em;
	text-align: center;
	z-index: 2;
}

.outdated-warning a {
	color: currentcolor;
	background: transparent;
}

.edited-rec-warning {
	background: darkorange;
	background: var(--editedrec-bg);
	box-shadow: 0 0 1em;
}

.outdated-warning button {
	position: absolute;
	top: 0;
	right:0;
	margin: 0;
	border: 0;
	padding: 0.25em 0.5em;
	background: transparent;
	color: white;
	color: var(--outdated-text);
	font:1em sans-serif;
	text-align:center;
}

.outdated-warning span {
	display: block;
}

.outdated-collapsed {
	bottom: 0;
	border-radius: 0;
	width: 100%;
	padding: 0;
}

/******************************************************************************/
/*                                    Print                                   */
/******************************************************************************/

	@media print {
		/* Pages have their own margins. */
		html {
			margin: 0;
		}
		/* Serif for print. */
		body {
			font-family: serif;
		}

		.outdated-warning {
			position: absolute;
			border-style: solid;
			border-color: red;
		}

		.outdated-warning input {
			display: none;
		}
	}
	@page {
		margin: 1.5cm 1.1cm;
	}



/******************************************************************************/
/*                             Overflow Control                               */
/******************************************************************************/

	.figure .caption, .sidefigure .caption, figcaption {
		/* in case figure is overlarge, limit caption to 50em */
		max-width: 50rem;
		margin-left: auto;
		margin-right: auto;
	}
	.overlarge {
		/* Magic to create good item positioning:
		  "content column" is 50ems wide at max; less on smaller screens.
		  Extra space (after ToC + content) is empty on the right.

		  1. When item < content column, centers item in column.
		  2. When content < item < available, left-aligns.
		  3. When item > available, fills available + scroll bar.
		*/
		display: grid;
		grid-template-columns: minmax(0, 50em);
	}
	.overlarge > table {
		/* limit preferred width of table */
		max-width: 50em;
		margin-left: auto;
		margin-right: auto;
	}

	@media (min-width: 55em) {
		.overlarge {
			margin-right: calc(13px + 26.5rem - 50vw);
			max-width: none;
		}
	}
	@media screen and (min-width: 78em) {
		body:not(.toc-inline) .overlarge {
			/* 30.5em body padding 50em content area */
			margin-right: calc(40em - 50vw) !important;
		}
	}
	@media screen and (min-width: 90em) {
		body:not(.toc-inline) .overlarge {
			/* 4em html margin 30.5em body padding 50em content area */
			margin-right: calc(84.5em - 100vw) !important;
		}
	}

	@media not print {
		.overlarge {
			overflow-x: auto;
			/* See Lea Verou's explanation background-attachment:
			* http://lea.verou.me/2012/04/background-attachment-local/
			*
			background: top left  / 4em 100% linear-gradient(to right,  #ffffff, rgba(255, 255, 255, 0)) local,
						top right / 4em 100% linear-gradient(to left, #ffffff, rgba(255, 255, 255, 0)) local,
						top left  / 1em 100% linear-gradient(to right,  #c3c3c5, rgba(195, 195, 197, 0)) scroll,
						top right / 1em 100% linear-gradient(to left, #c3c3c5, rgba(195, 195, 197, 0)) scroll,
						white;
			background-repeat: no-repeat;
			*/
		}
	}
</style>
<style>
    table, th, td {
      border: 1px solid black;
      border-collapse: collapse;
      vertical-align: top;
    }
    th, td {
      border-left: none;
      border-right: none;
      padding: 0px 10px;
    }
    th {
      text-align: center;
    }

    del { background: #fcc; color: #000; text-decoration: line-through; }
    ins { background: #cfc; color: #000; }
    blockquote .highlight:not(.idl) { background: initial; margin: initial; padding: 0.5em }
    blockquote ul { background: inherit; }
    blockquote code.highlight:not(.idl) { padding: initial; }
    blockquote c-[a] { color: inherit; } /* Keyword.Declaration */
    blockquote c-[b] { color: inherit; } /* Keyword.Type */
    blockquote c-[c] { color: inherit; } /* Comment */
    blockquote c-[d] { color: inherit; } /* Comment.Multiline */
    blockquote c-[e] { color: inherit; } /* Name.Attribute */
    blockquote c-[f] { color: inherit; } /* Name.Tag */
    blockquote c-[g] { color: inherit; } /* Name.Variable */
    blockquote c-[k] { color: inherit; } /* Keyword */
    blockquote c-[l] { color: inherit; } /* Literal */
    blockquote c-[m] { color: inherit; } /* Literal.Number */
    blockquote c-[n] { color: inherit; } /* Name */
    blockquote c-[o] { color: inherit; } /* Operator */
    blockquote c-[p] { color: inherit; } /* Punctuation */
    blockquote c-[s] { color: inherit; } /* Literal.String */
    blockquote c-[t] { color: inherit; } /* Literal.String.Single */
    blockquote c-[u] { color: inherit; } /* Literal.String.Double */
    blockquote c-[cp] { color: inherit; } /* Comment.Preproc */
    blockquote c-[c1] { color: inherit; } /* Comment.Single */
    blockquote c-[cs] { color: inherit; } /* Comment.Special */
    blockquote c-[kc] { color: inherit; } /* Keyword.Constant */
    blockquote c-[kn] { color: inherit; } /* Keyword.Namespace */
    blockquote c-[kp] { color: inherit; } /* Keyword.Pseudo */
    blockquote c-[kr] { color: inherit; } /* Keyword.Reserved */
    blockquote c-[ld] { color: inherit; } /* Literal.Date */
    blockquote c-[nc] { color: inherit; } /* Name.Class */
    blockquote c-[no] { color: inherit; } /* Name.Constant */
    blockquote c-[nd] { color: inherit; } /* Name.Decorator */
    blockquote c-[ni] { color: inherit; } /* Name.Entity */
    blockquote c-[ne] { color: inherit; } /* Name.Exception */
    blockquote c-[nf] { color: inherit; } /* Name.Function */
    blockquote c-[nl] { color: inherit; } /* Name.Label */
    blockquote c-[nn] { color: inherit; } /* Name.Namespace */
    blockquote c-[py] { color: inherit; } /* Name.Property */
    blockquote c-[ow] { color: inherit; } /* Operator.Word */
    blockquote c-[mb] { color: inherit; } /* Literal.Number.Bin */
    blockquote c-[mf] { color: inherit; } /* Literal.Number.Float */
    blockquote c-[mh] { color: inherit; } /* Literal.Number.Hex */
    blockquote c-[mi] { color: inherit; } /* Literal.Number.Integer */
    blockquote c-[mo] { color: inherit; } /* Literal.Number.Oct */
    blockquote c-[sb] { color: inherit; } /* Literal.String.Backtick */
    blockquote c-[sc] { color: inherit; } /* Literal.String.Char */
    blockquote c-[sd] { color: inherit; } /* Literal.String.Doc */
    blockquote c-[se] { color: inherit; } /* Literal.String.Escape */
    blockquote c-[sh] { color: inherit; } /* Literal.String.Heredoc */
    blockquote c-[si] { color: inherit; } /* Literal.String.Interpol */
    blockquote c-[sx] { color: inherit; } /* Literal.String.Other */
    blockquote c-[sr] { color: inherit; } /* Literal.String.Regex */
    blockquote c-[ss] { color: inherit; } /* Literal.String.Symbol */
    blockquote c-[vc] { color: inherit; } /* Name.Variable.Class */
    blockquote c-[vg] { color: inherit; } /* Name.Variable.Global */
    blockquote c-[vi] { color: inherit; } /* Name.Variable.Instance */
    blockquote c-[il] { color: inherit; } /* Literal.Number.Integer.Long */
  </style>
  <meta content="Bikeshed version 44af0bf3e, updated Fri Jul 29 17:05:16 2022 -0700" name="generator">
  <link href="https://wg21.link/P2300" rel="canonical">
  <link href="https://isocpp.org/favicon.ico" rel="icon">
  <meta content="bf05569003678d17be687522ed1af94b96a11842" name="document-revision">
<style>
pre {
  margin-top: 0px;
  margin-bottom: 0px;
}
table, th, tr, td {
  border: 2px solid black !important;
}
@media (prefers-color-scheme: dark) {
  table, th, tr, td {
    border: 2px solid white !important;
  }
}
.ins, ins, ins *, span.ins, span.ins * {
  background-color: rgb(200, 250, 200);
  color: rgb(0, 136, 0);
  text-decoration: none;
}
.del, del, del *, span.del, span.del * {
  background-color: rgb(250, 200, 200);
  color: rgb(255, 0, 0);
  text-decoration: line-through;
  text-decoration-color: rgb(255, 0, 0);
}
math, span.math {
  font-family: serif;
  font-style: italic;
}
ul {
  list-style-type: "— ";
}
blockquote {
  counter-reset: paragraph;
}
div.numbered, div.newnumbered {
  margin-left: 2em;
  margin-top: 1em;
  margin-bottom: 1em;
}
div.numbered:before, div.newnumbered:before {
  position: absolute;
  margin-left: -2em;
  display-style: block;
}
div.numbered:before {
  content: counter(paragraph);
  counter-increment: paragraph;
}
div.newnumbered:before {
  content: "�";
}
div.numbered ul, div.newnumbered ul {
  counter-reset: list_item;
}
div.numbered li, div.newnumbered li {
  margin-left: 3em;
}
div.numbered li:before, div.newnumbered li:before {
  position: absolute;
  margin-left: -4.8em;
  display-style: block;
}
div.numbered li:before {
  content: "(" counter(paragraph) "." counter(list_item) ")";
  counter-increment: list_item;
}
div.newnumbered li:before {
  content: "(�." counter(list_item) ")";
  counter-increment: list_item;
}
div.ed-note {
  color: blue !important;
  margin-left: 2em;
}
div.ed-note:before {
  content: "[Editorial note: ";
  font-style: italic;
}
div.ed-note:after {
  content: " -- end note]";
  font-style: italic;
}
div.ed-note * {
  color: blue !important;
  margin-top: 0em;
  margin-bottom: 0em;
}
div.ed-note blockquote {
  margin-left: 2em;
}
div.wg21note:before, span.wg21note:before {
  content: "[Note: ";
  font-style: italic;
}
div.wg21note:after, span.wg21note:after {
  content: " -- end note]";
  font-style: italic;
}
h5 {
  font-style: normal; /* turn off italics of h5 headers */
}
</style>
<style>/* style-autolinks */

.css.css, .property.property, .descriptor.descriptor {
    color: var(--a-normal-text);
    font-size: inherit;
    font-family: inherit;
}
.css::before, .property::before, .descriptor::before {
    content: "‘";
}
.css::after, .property::after, .descriptor::after {
    content: "’";
}
.property, .descriptor {
    /* Don't wrap property and descriptor names */
    white-space: nowrap;
}
.type { /* CSS value <type> */
    font-style: italic;
}
pre .property::before, pre .property::after {
    content: "";
}
[data-link-type="property"]::before,
[data-link-type="propdesc"]::before,
[data-link-type="descriptor"]::before,
[data-link-type="value"]::before,
[data-link-type="function"]::before,
[data-link-type="at-rule"]::before,
[data-link-type="selector"]::before,
[data-link-type="maybe"]::before {
    content: "‘";
}
[data-link-type="property"]::after,
[data-link-type="propdesc"]::after,
[data-link-type="descriptor"]::after,
[data-link-type="value"]::after,
[data-link-type="function"]::after,
[data-link-type="at-rule"]::after,
[data-link-type="selector"]::after,
[data-link-type="maybe"]::after {
    content: "’";
}

[data-link-type].production::before,
[data-link-type].production::after,
.prod [data-link-type]::before,
.prod [data-link-type]::after {
    content: "";
}

[data-link-type=element],
[data-link-type=element-attr] {
    font-family: Menlo, Consolas, "DejaVu Sans Mono", monospace;
    font-size: .9em;
}
[data-link-type=element]::before { content: "<" }
[data-link-type=element]::after  { content: ">" }

[data-link-type=biblio] {
    white-space: pre;
}</style>
<style>/* style-colors */

/* Any --*-text not paired with a --*-bg is assumed to have a transparent bg */
:root {
    color-scheme: light dark;

    --text: black;
    --bg: white;

    --unofficial-watermark: url(https://www.w3.org/StyleSheets/TR/2016/logos/UD-watermark);

    --logo-bg: #1a5e9a;
    --logo-active-bg: #c00;
    --logo-text: white;

    --tocnav-normal-text: #707070;
    --tocnav-normal-bg: var(--bg);
    --tocnav-hover-text: var(--tocnav-normal-text);
    --tocnav-hover-bg: #f8f8f8;
    --tocnav-active-text: #c00;
    --tocnav-active-bg: var(--tocnav-normal-bg);

    --tocsidebar-text: var(--text);
    --tocsidebar-bg: #f7f8f9;
    --tocsidebar-shadow: rgba(0,0,0,.1);
    --tocsidebar-heading-text: hsla(203,20%,40%,.7);

    --toclink-text: var(--text);
    --toclink-underline: #3980b5;
    --toclink-visited-text: var(--toclink-text);
    --toclink-visited-underline: #054572;

    --heading-text: #005a9c;

    --hr-text: var(--text);

    --algo-border: #def;

    --del-text: red;
    --del-bg: transparent;
    --ins-text: #080;
    --ins-bg: transparent;

    --a-normal-text: #034575;
    --a-normal-underline: #bbb;
    --a-visited-text: var(--a-normal-text);
    --a-visited-underline: #707070;
    --a-hover-bg: rgba(75%, 75%, 75%, .25);
    --a-active-text: #c00;
    --a-active-underline: #c00;

    --blockquote-border: silver;
    --blockquote-bg: transparent;
    --blockquote-text: currentcolor;

    --issue-border: #e05252;
    --issue-bg: #fbe9e9;
    --issue-text: var(--text);
    --issueheading-text: #831616;

    --example-border: #e0cb52;
    --example-bg: #fcfaee;
    --example-text: var(--text);
    --exampleheading-text: #574b0f;

    --note-border: #52e052;
    --note-bg: #e9fbe9;
    --note-text: var(--text);
    --noteheading-text: hsl(120, 70%, 30%);
    --notesummary-underline: silver;

    --assertion-border: #aaa;
    --assertion-bg: #eee;
    --assertion-text: black;

    --advisement-border: orange;
    --advisement-bg: #fec;
    --advisement-text: var(--text);
    --advisementheading-text: #b35f00;

    --warning-border: red;
    --warning-bg: hsla(40,100%,50%,0.95);
    --warning-text: var(--text);

    --amendment-border: #330099;
    --amendment-bg: #F5F0FF;
    --amendment-text: var(--text);
    --amendmentheading-text: #220066;

    --def-border: #8ccbf2;
    --def-bg: #def;
    --def-text: var(--text);
    --defrow-border: #bbd7e9;

    --datacell-border: silver;

    --indexinfo-text: #707070;

    --indextable-hover-text: black;
    --indextable-hover-bg: #f7f8f9;

    --outdatedspec-bg: rgba(0, 0, 0, .5);
    --outdatedspec-text: black;
    --outdated-bg: maroon;
    --outdated-text: white;
    --outdated-shadow: red;

    --editedrec-bg: darkorange;
}</style>
<style>/* style-counters */

body {
    counter-reset: example figure issue;
}
.issue {
    counter-increment: issue;
}
.issue:not(.no-marker)::before {
    content: "Issue " counter(issue);
}

.example {
    counter-increment: example;
}
.example:not(.no-marker)::before {
    content: "Example " counter(example);
}
.invalid.example:not(.no-marker)::before,
.illegal.example:not(.no-marker)::before {
    content: "Invalid Example" counter(example);
}

figcaption {
    counter-increment: figure;
}
figcaption:not(.no-marker)::before {
    content: "Figure " counter(figure) " ";
}</style>
<style>/* style-dfn-panel */

:root {
    --dfnpanel-bg: #ddd;
    --dfnpanel-text: var(--text);
}
.dfn-panel {
    position: absolute;
    z-index: 35;
    height: auto;
    width: -webkit-fit-content;
    width: fit-content;
    max-width: 300px;
    max-height: 500px;
    overflow: auto;
    padding: 0.5em 0.75em;
    font: small Helvetica Neue, sans-serif, Droid Sans Fallback;
    background: var(--dfnpanel-bg);
    color: var(--dfnpanel-text);
    border: outset 0.2em;
}
.dfn-panel:not(.on) { display: none; }
.dfn-panel * { margin: 0; padding: 0; text-indent: 0; }
.dfn-panel > b { display: block; }
.dfn-panel a { color: var(--dfnpanel-text); }
.dfn-panel a:not(:hover) { text-decoration: none !important; border-bottom: none !important; }
.dfn-panel > b + b { margin-top: 0.25em; }
.dfn-panel ul { padding: 0; }
.dfn-panel li { list-style: inside; }
.dfn-panel.activated {
    display: inline-block;
    position: fixed;
    left: .5em;
    bottom: 2em;
    margin: 0 auto;
    max-width: calc(100vw - 1.5em - .4em - .5em);
    max-height: 30vh;
}

.dfn-paneled { cursor: pointer; }
</style>
<style>/* style-issues */

a[href].issue-return {
    float: right;
    float: inline-end;
    color: var(--issueheading-text);
    font-weight: bold;
    text-decoration: none;
}
</style>
<style>/* style-md-lists */

/* This is a weird hack for me not yet following the commonmark spec
   regarding paragraph and lists. */
[data-md] > :first-child {
    margin-top: 0;
}
[data-md] > :last-child {
    margin-bottom: 0;
}</style>
<style>/* style-selflinks */

:root {
    --selflink-text: white;
    --selflink-bg: gray;
    --selflink-hover-text: black;
}
.heading, .issue, .note, .example, li, dt {
    position: relative;
}
a.self-link {
    position: absolute;
    top: 0;
    left: calc(-1 * (3.5rem - 26px));
    width: calc(3.5rem - 26px);
    height: 2em;
    text-align: center;
    border: none;
    transition: opacity .2s;
    opacity: .5;
}
a.self-link:hover {
    opacity: 1;
}
.heading > a.self-link {
    font-size: 83%;
}
li > a.self-link {
    left: calc(-1 * (3.5rem - 26px) - 2em);
}
dfn > a.self-link {
    top: auto;
    left: auto;
    opacity: 0;
    width: 1.5em;
    height: 1.5em;
    background: var(--selflink-bg);
    color: var(--selflink-text);
    font-style: normal;
    transition: opacity .2s, background-color .2s, color .2s;
}
dfn:hover > a.self-link {
    opacity: 1;
}
dfn > a.self-link:hover {
    color: var(--selflink-hover-text);
}

a.self-link::before            { content: "¶"; }
.heading > a.self-link::before { content: "§"; }
dfn > a.self-link::before      { content: "#"; }
</style>
<style>/* style-syntax-highlighting */

code.highlight { padding: .1em; border-radius: .3em; }
pre.highlight, pre > code.highlight { display: block; padding: 1em; margin: .5em 0; overflow: auto; border-radius: 0; }

.highlight:not(.idl) { background: rgba(0, 0, 0, .03); }
c-[a] { color: #990055 } /* Keyword.Declaration */
c-[b] { color: #990055 } /* Keyword.Type */
c-[c] { color: #708090 } /* Comment */
c-[d] { color: #708090 } /* Comment.Multiline */
c-[e] { color: #0077aa } /* Name.Attribute */
c-[f] { color: #669900 } /* Name.Tag */
c-[g] { color: #222222 } /* Name.Variable */
c-[k] { color: #990055 } /* Keyword */
c-[l] { color: #000000 } /* Literal */
c-[m] { color: #000000 } /* Literal.Number */
c-[n] { color: #0077aa } /* Name */
c-[o] { color: #999999 } /* Operator */
c-[p] { color: #999999 } /* Punctuation */
c-[s] { color: #a67f59 } /* Literal.String */
c-[t] { color: #a67f59 } /* Literal.String.Single */
c-[u] { color: #a67f59 } /* Literal.String.Double */
c-[cp] { color: #708090 } /* Comment.Preproc */
c-[c1] { color: #708090 } /* Comment.Single */
c-[cs] { color: #708090 } /* Comment.Special */
c-[kc] { color: #990055 } /* Keyword.Constant */
c-[kn] { color: #990055 } /* Keyword.Namespace */
c-[kp] { color: #990055 } /* Keyword.Pseudo */
c-[kr] { color: #990055 } /* Keyword.Reserved */
c-[ld] { color: #000000 } /* Literal.Date */
c-[nc] { color: #0077aa } /* Name.Class */
c-[no] { color: #0077aa } /* Name.Constant */
c-[nd] { color: #0077aa } /* Name.Decorator */
c-[ni] { color: #0077aa } /* Name.Entity */
c-[ne] { color: #0077aa } /* Name.Exception */
c-[nf] { color: #0077aa } /* Name.Function */
c-[nl] { color: #0077aa } /* Name.Label */
c-[nn] { color: #0077aa } /* Name.Namespace */
c-[py] { color: #0077aa } /* Name.Property */
c-[ow] { color: #999999 } /* Operator.Word */
c-[mb] { color: #000000 } /* Literal.Number.Bin */
c-[mf] { color: #000000 } /* Literal.Number.Float */
c-[mh] { color: #000000 } /* Literal.Number.Hex */
c-[mi] { color: #000000 } /* Literal.Number.Integer */
c-[mo] { color: #000000 } /* Literal.Number.Oct */
c-[sb] { color: #a67f59 } /* Literal.String.Backtick */
c-[sc] { color: #a67f59 } /* Literal.String.Char */
c-[sd] { color: #a67f59 } /* Literal.String.Doc */
c-[se] { color: #a67f59 } /* Literal.String.Escape */
c-[sh] { color: #a67f59 } /* Literal.String.Heredoc */
c-[si] { color: #a67f59 } /* Literal.String.Interpol */
c-[sx] { color: #a67f59 } /* Literal.String.Other */
c-[sr] { color: #a67f59 } /* Literal.String.Regex */
c-[ss] { color: #a67f59 } /* Literal.String.Symbol */
c-[vc] { color: #0077aa } /* Name.Variable.Class */
c-[vg] { color: #0077aa } /* Name.Variable.Global */
c-[vi] { color: #0077aa } /* Name.Variable.Instance */
c-[il] { color: #000000 } /* Literal.Number.Integer.Long */
</style>
<style>/* style-darkmode */

@media (prefers-color-scheme: dark) {
    :root {
        --text: #ddd;
        --bg: black;

        --unofficial-watermark: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='400' height='400'%3E%3Cg fill='%23100808' transform='translate(200 200) rotate(-45) translate(-200 -200)' stroke='%23100808' stroke-width='3'%3E%3Ctext x='50%25' y='220' style='font: bold 70px sans-serif; text-anchor: middle; letter-spacing: 6px;'%3EUNOFFICIAL%3C/text%3E%3Ctext x='50%25' y='305' style='font: bold 70px sans-serif; text-anchor: middle; letter-spacing: 6px;'%3EDRAFT%3C/text%3E%3C/g%3E%3C/svg%3E");

        --logo-bg: #1a5e9a;
        --logo-active-bg: #c00;
        --logo-text: white;

        --tocnav-normal-text: #999;
        --tocnav-normal-bg: var(--bg);
        --tocnav-hover-text: var(--tocnav-normal-text);
        --tocnav-hover-bg: #080808;
        --tocnav-active-text: #f44;
        --tocnav-active-bg: var(--tocnav-normal-bg);

        --tocsidebar-text: var(--text);
        --tocsidebar-bg: #080808;
        --tocsidebar-shadow: rgba(255,255,255,.1);
        --tocsidebar-heading-text: hsla(203,20%,40%,.7);

        --toclink-text: var(--text);
        --toclink-underline: #6af;
        --toclink-visited-text: var(--toclink-text);
        --toclink-visited-underline: #054572;

        --heading-text: #8af;

        --hr-text: var(--text);

        --algo-border: #456;

        --del-text: #f44;
        --del-bg: transparent;
        --ins-text: #4a4;
        --ins-bg: transparent;

        --a-normal-text: #6af;
        --a-normal-underline: #555;
        --a-visited-text: var(--a-normal-text);
        --a-visited-underline: var(--a-normal-underline);
        --a-hover-bg: rgba(25%, 25%, 25%, .2);
        --a-active-text: #f44;
        --a-active-underline: var(--a-active-text);

        --borderedblock-bg: rgba(255, 255, 255, .05);

        --blockquote-border: silver;
        --blockquote-bg: var(--borderedblock-bg);
        --blockquote-text: currentcolor;

        --issue-border: #e05252;
        --issue-bg: var(--borderedblock-bg);
        --issue-text: var(--text);
        --issueheading-text: hsl(0deg, 70%, 70%);

        --example-border: hsl(50deg, 90%, 60%);
        --example-bg: var(--borderedblock-bg);
        --example-text: var(--text);
        --exampleheading-text: hsl(50deg, 70%, 70%);

        --note-border: hsl(120deg, 100%, 35%);
        --note-bg: var(--borderedblock-bg);
        --note-text: var(--text);
        --noteheading-text: hsl(120, 70%, 70%);
        --notesummary-underline: silver;

        --assertion-border: #444;
        --assertion-bg: var(--borderedblock-bg);
        --assertion-text: var(--text);

        --advisement-border: orange;
        --advisement-bg: #222218;
        --advisement-text: var(--text);
        --advisementheading-text: #f84;

        --warning-border: red;
        --warning-bg: hsla(40,100%,20%,0.95);
        --warning-text: var(--text);

        --amendment-border: #330099;
        --amendment-bg: #080010;
        --amendment-text: var(--text);
        --amendmentheading-text: #cc00ff;

        --def-border: #8ccbf2;
        --def-bg: #080818;
        --def-text: var(--text);
        --defrow-border: #136;

        --datacell-border: silver;

        --indexinfo-text: #aaa;

        --indextable-hover-text: var(--text);
        --indextable-hover-bg: #181818;

        --outdatedspec-bg: rgba(255, 255, 255, .5);
        --outdatedspec-text: black;
        --outdated-bg: maroon;
        --outdated-text: white;
        --outdated-shadow: red;

        --editedrec-bg: darkorange;
    }
    /* In case a transparent-bg image doesn't expect to be on a dark bg,
       which is quite common in practice... */
    img { background: white; }
}
@media (prefers-color-scheme: dark) {
    :root {
        --selflink-text: black;
        --selflink-bg: silver;
        --selflink-hover-text: white;
    }
}

@media (prefers-color-scheme: dark) {
    .highlight:not(.idl) { background: rgba(255, 255, 255, .05); }

    c-[a] { color: #d33682 } /* Keyword.Declaration */
    c-[b] { color: #d33682 } /* Keyword.Type */
    c-[c] { color: #2aa198 } /* Comment */
    c-[d] { color: #2aa198 } /* Comment.Multiline */
    c-[e] { color: #268bd2 } /* Name.Attribute */
    c-[f] { color: #b58900 } /* Name.Tag */
    c-[g] { color: #cb4b16 } /* Name.Variable */
    c-[k] { color: #d33682 } /* Keyword */
    c-[l] { color: #657b83 } /* Literal */
    c-[m] { color: #657b83 } /* Literal.Number */
    c-[n] { color: #268bd2 } /* Name */
    c-[o] { color: #657b83 } /* Operator */
    c-[p] { color: #657b83 } /* Punctuation */
    c-[s] { color: #6c71c4 } /* Literal.String */
    c-[t] { color: #6c71c4 } /* Literal.String.Single */
    c-[u] { color: #6c71c4 } /* Literal.String.Double */
    c-[ch] { color: #2aa198 } /* Comment.Hashbang */
    c-[cp] { color: #2aa198 } /* Comment.Preproc */
    c-[cpf] { color: #2aa198 } /* Comment.PreprocFile */
    c-[c1] { color: #2aa198 } /* Comment.Single */
    c-[cs] { color: #2aa198 } /* Comment.Special */
    c-[kc] { color: #d33682 } /* Keyword.Constant */
    c-[kn] { color: #d33682 } /* Keyword.Namespace */
    c-[kp] { color: #d33682 } /* Keyword.Pseudo */
    c-[kr] { color: #d33682 } /* Keyword.Reserved */
    c-[ld] { color: #657b83 } /* Literal.Date */
    c-[nc] { color: #268bd2 } /* Name.Class */
    c-[no] { color: #268bd2 } /* Name.Constant */
    c-[nd] { color: #268bd2 } /* Name.Decorator */
    c-[ni] { color: #268bd2 } /* Name.Entity */
    c-[ne] { color: #268bd2 } /* Name.Exception */
    c-[nf] { color: #268bd2 } /* Name.Function */
    c-[nl] { color: #268bd2 } /* Name.Label */
    c-[nn] { color: #268bd2 } /* Name.Namespace */
    c-[py] { color: #268bd2 } /* Name.Property */
    c-[ow] { color: #657b83 } /* Operator.Word */
    c-[mb] { color: #657b83 } /* Literal.Number.Bin */
    c-[mf] { color: #657b83 } /* Literal.Number.Float */
    c-[mh] { color: #657b83 } /* Literal.Number.Hex */
    c-[mi] { color: #657b83 } /* Literal.Number.Integer */
    c-[mo] { color: #657b83 } /* Literal.Number.Oct */
    c-[sa] { color: #6c71c4 } /* Literal.String.Affix */
    c-[sb] { color: #6c71c4 } /* Literal.String.Backtick */
    c-[sc] { color: #6c71c4 } /* Literal.String.Char */
    c-[dl] { color: #6c71c4 } /* Literal.String.Delimiter */
    c-[sd] { color: #6c71c4 } /* Literal.String.Doc */
    c-[se] { color: #6c71c4 } /* Literal.String.Escape */
    c-[sh] { color: #6c71c4 } /* Literal.String.Heredoc */
    c-[si] { color: #6c71c4 } /* Literal.String.Interpol */
    c-[sx] { color: #6c71c4 } /* Literal.String.Other */
    c-[sr] { color: #6c71c4 } /* Literal.String.Regex */
    c-[ss] { color: #6c71c4 } /* Literal.String.Symbol */
    c-[fm] { color: #268bd2 } /* Name.Function.Magic */
    c-[vc] { color: #cb4b16 } /* Name.Variable.Class */
    c-[vg] { color: #cb4b16 } /* Name.Variable.Global */
    c-[vi] { color: #cb4b16 } /* Name.Variable.Instance */
    c-[vm] { color: #cb4b16 } /* Name.Variable.Magic */
    c-[il] { color: #657b83 } /* Literal.Number.Integer.Long */
}
</style>
 <body class="h-entry">
  <div class="head">
   <p data-fill-with="logo"></p>
   <h1 class="p-name no-ref" id="title">P2300R8<br><code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>execution</c-></code></h1>
   <h2 class="no-num no-toc no-ref heading settled" id="profile-and-date"><span class="content">Published Proposal, <time class="dt-updated" datetime="2024-02-22">2024-02-22</time></span></h2>
   <div data-fill-with="spec-metadata">
    <dl>
     <dt class="editor">Authors:
     <dd class="editor p-author h-card vcard"><a class="p-name fn u-email email" href="mailto:griwes@griwes.info">Michał Dominiak</a>
     <dd class="editor p-author h-card vcard"><a class="p-name fn u-email email" href="mailto:evtushenko.georgy@gmail.com">Georgy Evtushenko</a>
     <dd class="editor p-author h-card vcard"><a class="p-name fn u-email email" href="mailto:lewissbaker@gmail.com">Lewis Baker</a>
     <dd class="editor p-author h-card vcard"><a class="p-name fn u-email email" href="mailto:lucteo@lucteo.ro">Lucian Radu Teodorescu</a>
     <dd class="editor p-author h-card vcard"><a class="p-name fn u-email email" href="mailto:xrikcus@gmail.com">Lee Howes</a>
     <dd class="editor p-author h-card vcard"><a class="p-name fn u-email email" href="mailto:kirk.shoop@gmail.com">Kirk Shoop</a>
     <dd class="editor p-author h-card vcard"><a class="p-name fn u-email email" href="mailto:mgarland@nvidia.com">Michael Garland</a>
     <dd class="editor p-author h-card vcard"><a class="p-name fn u-email email" href="mailto:eric.niebler@gmail.com">Eric Niebler</a>
     <dd class="editor p-author h-card vcard"><a class="p-name fn u-email email" href="mailto:brycelelbach@gmail.com">Bryce Adelstein Lelbach</a>
     <dt>Source:
     <dd><a href="https://github.com/brycelelbach/wg21_p2300_execution/blob/main/execution.bs">GitHub</a>
     <dt>Issue Tracking:
     <dd><a href="https://github.com/brycelelbach/wg21_p2300_execution/issues">GitHub</a>
     <dt>Project:
     <dd>ISO/IEC JTC1/SC22/WG21 14882: Programming Language — C++
     <dt>Audience:
     <dd>SG1, LEWG
    </dl>
   </div>
   <div data-fill-with="warning"></div>
   <hr title="Separator for header">
  </div>
  <nav data-fill-with="table-of-contents" id="toc">
   <h2 class="no-num no-toc no-ref" id="contents">Table of Contents</h2>
   <ol class="toc" role="directory">
    <li>
     <a href="#intro"><span class="secno">1</span> <span class="content">Introduction</span></a>
     <ol class="toc">
      <li><a href="#motivation"><span class="secno">1.1</span> <span class="content">Motivation</span></a>
      <li><a href="#priorities"><span class="secno">1.2</span> <span class="content">Priorities</span></a>
      <li>
       <a href="#example-end-user"><span class="secno">1.3</span> <span class="content">Examples: End User</span></a>
       <ol class="toc">
        <li><a href="#example-hello-world"><span class="secno">1.3.1</span> <span class="content">Hello world</span></a>
        <li><a href="#example-async-inclusive-scan"><span class="secno">1.3.2</span> <span class="content">Asynchronous inclusive scan</span></a>
        <li><a href="#example-async-dynamically-sized-read"><span class="secno">1.3.3</span> <span class="content">Asynchronous dynamically-sized read</span></a>
       </ol>
      <li>
       <a href="#example-async-windows-socket-recv"><span class="secno">1.4</span> <span class="content">Asynchronous Windows socket <code class="highlight"><c- n>recv</c-></code></span></a>
       <ol class="toc">
        <li>
         <a href="#example-moar"><span class="secno">1.4.1</span> <span class="content">More end-user examples</span></a>
         <ol class="toc">
          <li><a href="#example-sudoku"><span class="secno">1.4.1.1</span> <span class="content">Sudoku solver</span></a>
          <li><a href="#example-file-copy"><span class="secno">1.4.1.2</span> <span class="content">File copy</span></a>
          <li><a href="#example-echo-server"><span class="secno">1.4.1.3</span> <span class="content">Echo server</span></a>
         </ol>
       </ol>
      <li>
       <a href="#example-algorithm"><span class="secno">1.5</span> <span class="content">Examples: Algorithms</span></a>
       <ol class="toc">
        <li><a href="#example-then"><span class="secno">1.5.1</span> <span class="content"><code class="highlight"><c- n>then</c-></code></span></a>
        <li><a href="#example-retry"><span class="secno">1.5.2</span> <span class="content"><code class="highlight"><c- n>retry</c-></code></span></a>
       </ol>
      <li>
       <a href="#example-schedulers"><span class="secno">1.6</span> <span class="content">Examples: Schedulers</span></a>
       <ol class="toc">
        <li><a href="#example-schedulers-inline"><span class="secno">1.6.1</span> <span class="content">Inline scheduler</span></a>
        <li><a href="#example-single-thread"><span class="secno">1.6.2</span> <span class="content">Single thread scheduler</span></a>
       </ol>
      <li>
       <a href="#example-server"><span class="secno">1.7</span> <span class="content">Examples: Server theme</span></a>
       <ol class="toc">
        <li><a href="#example-server-let"><span class="secno">1.7.1</span> <span class="content">Composability with <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>let_</c-><c- o>*</c-></code></span></a>
        <li><a href="#example-server-on"><span class="secno">1.7.2</span> <span class="content">Moving between execution resources with <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>on</c-></code> and <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>transfer</c-></code></span></a>
       </ol>
      <li><a href="#intro-is-not"><span class="secno">1.8</span> <span class="content">What this proposal is <strong>not</strong></span></a>
      <li><a href="#intro-compare"><span class="secno">1.9</span> <span class="content">Design changes from P0443</span></a>
      <li>
       <a href="#intro-prior-art"><span class="secno">1.10</span> <span class="content">Prior art</span></a>
       <ol class="toc">
        <li><a href="#intro-prior-art-futures"><span class="secno">1.10.1</span> <span class="content">Futures</span></a>
        <li><a href="#intro-prior-art-coroutines"><span class="secno">1.10.2</span> <span class="content">Coroutines</span></a>
        <li><a href="#intro-prior-art-callbacks"><span class="secno">1.10.3</span> <span class="content">Callbacks</span></a>
       </ol>
      <li>
       <a href="#intro-field-experience"><span class="secno">1.11</span> <span class="content">Field experience</span></a>
       <ol class="toc">
        <li><a href="#intro-field-experience-libunifex"><span class="secno">1.11.1</span> <span class="content">libunifex</span></a>
        <li><a href="#intro-field-experience-other-implementations"><span class="secno">1.11.2</span> <span class="content">Other implementations</span></a>
        <li><a href="#intro-field-experience-inspirations"><span class="secno">1.11.3</span> <span class="content">Inspirations</span></a>
       </ol>
     </ol>
    <li>
     <a href="#revisions"><span class="secno">2</span> <span class="content">Revision history</span></a>
     <ol class="toc">
      <li><a href="#r8"><span class="secno">2.1</span> <span class="content">R8</span></a>
      <li><a href="#r7"><span class="secno">2.2</span> <span class="content">R7</span></a>
      <li>
       <a href="#r6"><span class="secno">2.3</span> <span class="content">R6</span></a>
       <ol class="toc">
        <li><a href="#environments-and-attributes"><span class="secno">2.3.1</span> <span class="content">Environments and attributes</span></a>
       </ol>
      <li><a href="#r5"><span class="secno">2.4</span> <span class="content">R5</span></a>
      <li>
       <a href="#r4"><span class="secno">2.5</span> <span class="content">R4</span></a>
       <ol class="toc">
        <li><a href="#dependently-typed-senders"><span class="secno">2.5.1</span> <span class="content">Dependently-typed senders</span></a>
       </ol>
      <li><a href="#r3"><span class="secno">2.6</span> <span class="content">R3</span></a>
      <li><a href="#r2"><span class="secno">2.7</span> <span class="content">R2</span></a>
      <li><a href="#r1"><span class="secno">2.8</span> <span class="content">R1</span></a>
      <li><a href="#r0"><span class="secno">2.9</span> <span class="content">R0</span></a>
     </ol>
    <li>
     <a href="#design-intro"><span class="secno">3</span> <span class="content">Design - introduction</span></a>
     <ol class="toc">
      <li><a href="#design-conventions"><span class="secno">3.1</span> <span class="content">Conventions</span></a>
      <li><a href="#design-queries-and-algorithms"><span class="secno">3.2</span> <span class="content">Queries and algorithms</span></a>
     </ol>
    <li>
     <a href="#design-user"><span class="secno">4</span> <span class="content">Design - user side</span></a>
     <ol class="toc">
      <li><a href="#design-contexts"><span class="secno">4.1</span> <span class="content">Execution resources describe the place of execution</span></a>
      <li><a href="#design-schedulers"><span class="secno">4.2</span> <span class="content">Schedulers represent execution resources</span></a>
      <li><a href="#design-senders"><span class="secno">4.3</span> <span class="content">Senders describe work</span></a>
      <li><a href="#design-composable"><span class="secno">4.4</span> <span class="content">Senders are composable through sender algorithms</span></a>
      <li>
       <a href="#design-propagation"><span class="secno">4.5</span> <span class="content">Senders can propagate completion schedulers</span></a>
       <ol class="toc">
        <li><a href="#design-sender-query-get_completion_scheduler"><span class="secno">4.5.1</span> <span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>get_completion_scheduler</c-></code></span></a>
       </ol>
      <li><a href="#design-transitions"><span class="secno">4.6</span> <span class="content">Execution resource transitions are explicit</span></a>
      <li><a href="#design-shot"><span class="secno">4.7</span> <span class="content">Senders can be either multi-shot or single-shot</span></a>
      <li><a href="#design-forkable"><span class="secno">4.8</span> <span class="content">Senders are forkable</span></a>
      <li>
       <a href="#design-cancellation"><span class="secno">4.9</span> <span class="content">Senders support cancellation</span></a>
       <ol class="toc">
        <li><a href="#design-cancellation-summary"><span class="secno">4.9.1</span> <span class="content">Cancellation design summary</span></a>
        <li><a href="#design-cancellation-optional"><span class="secno">4.9.2</span> <span class="content">Support for cancellation is optional</span></a>
        <li><a href="#design-cancellation-racy"><span class="secno">4.9.3</span> <span class="content">Cancellation is inherently racy</span></a>
        <li><a href="#design-cancellation-status"><span class="secno">4.9.4</span> <span class="content">Cancellation design status</span></a>
       </ol>
      <li>
       <a href="#design-lazy-algorithms"><span class="secno">4.10</span> <span class="content">Sender factories and adaptors are lazy</span></a>
       <ol class="toc">
        <li><a href="#design-lazy-algorithms-detached"><span class="secno">4.10.1</span> <span class="content">Eager execution leads to detached work or worse</span></a>
        <li><a href="#design-lazy-algorithms-complexity"><span class="secno">4.10.2</span> <span class="content">Eager senders complicate algorithm implementations</span></a>
        <li><a href="#design-lazy-algorithms-runtime"><span class="secno">4.10.3</span> <span class="content">Eager senders incur cancellation-related overhead</span></a>
        <li><a href="#design-lazy-algorithms-context"><span class="secno">4.10.4</span> <span class="content">Eager senders cannot access execution resource from the receiver</span></a>
       </ol>
      <li><a href="#design-fpg"><span class="secno">4.11</span> <span class="content">Schedulers advertise their forward progress guarantees</span></a>
      <li><a href="#design-pipeable"><span class="secno">4.12</span> <span class="content">Most sender adaptors are pipeable</span></a>
      <li><a href="#design-range-of-senders"><span class="secno">4.13</span> <span class="content">A range of senders represents an async sequence of data</span></a>
      <li><a href="#design-partial-success"><span class="secno">4.14</span> <span class="content">Senders can represent partial success</span></a>
      <li><a href="#design-awaitables-are-senders"><span class="secno">4.15</span> <span class="content">All awaitables are senders</span></a>
      <li><a href="#design-senders-are-awaitable"><span class="secno">4.16</span> <span class="content">Many senders can be trivially made awaitable</span></a>
      <li><a href="#design-native-coro-unwind"><span class="secno">4.17</span> <span class="content">Cancellation of a sender can unwind a stack of coroutines</span></a>
      <li><a href="#design-parallel-algorithms"><span class="secno">4.18</span> <span class="content">Composition with parallel algorithms</span></a>
      <li>
       <a href="#design-sender-factories"><span class="secno">4.19</span> <span class="content">User-facing sender factories</span></a>
       <ol class="toc">
        <li><a href="#design-sender-factory-schedule"><span class="secno">4.19.1</span> <span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>schedule</c-></code></span></a>
        <li><a href="#design-sender-factory-just"><span class="secno">4.19.2</span> <span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>just</c-></code></span></a>
        <li><a href="#design-sender-factory-just_error"><span class="secno">4.19.3</span> <span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>just_error</c-></code></span></a>
        <li><a href="#design-sender-factory-just_stopped"><span class="secno">4.19.4</span> <span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>just_stopped</c-></code></span></a>
        <li><a href="#design-sender-factory-read"><span class="secno">4.19.5</span> <span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>read</c-></code></span></a>
       </ol>
      <li>
       <a href="#design-sender-adaptors"><span class="secno">4.20</span> <span class="content">User-facing sender adaptors</span></a>
       <ol class="toc">
        <li><a href="#design-sender-adaptor-transfer"><span class="secno">4.20.1</span> <span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>transfer</c-></code></span></a>
        <li><a href="#design-sender-adaptor-then"><span class="secno">4.20.2</span> <span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>then</c-></code></span></a>
        <li><a href="#design-sender-adaptor-upon"><span class="secno">4.20.3</span> <span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>upon_</c-><c- o>*</c-></code></span></a>
        <li><a href="#design-sender-adaptor-let"><span class="secno">4.20.4</span> <span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>let_</c-><c- o>*</c-></code></span></a>
        <li><a href="#design-sender-adaptor-on"><span class="secno">4.20.5</span> <span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>on</c-></code></span></a>
        <li><a href="#design-sender-adaptor-into_variant"><span class="secno">4.20.6</span> <span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>into_variant</c-></code></span></a>
        <li><a href="#design-sender-adaptor-stopped_as_optional"><span class="secno">4.20.7</span> <span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>stopped_as_optional</c-></code></span></a>
        <li><a href="#design-sender-adaptor-stopped_as_error"><span class="secno">4.20.8</span> <span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>stopped_as_error</c-></code></span></a>
        <li><a href="#design-sender-adaptor-bulk"><span class="secno">4.20.9</span> <span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>bulk</c-></code></span></a>
        <li><a href="#design-sender-adaptor-split"><span class="secno">4.20.10</span> <span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>split</c-></code></span></a>
        <li><a href="#design-sender-adaptor-when_all"><span class="secno">4.20.11</span> <span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>when_all</c-></code></span></a>
        <li><a href="#design-sender-adaptor-ensure_started"><span class="secno">4.20.12</span> <span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>ensure_started</c-></code></span></a>
       </ol>
      <li>
       <a href="#design-sender-consumers"><span class="secno">4.21</span> <span class="content">User-facing sender consumers</span></a>
       <ol class="toc">
        <li><a href="#design-sender-consumer-start_detached"><span class="secno">4.21.1</span> <span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>start_detached</c-></code></span></a>
        <li><a href="#design-sender-consumer-sync_wait"><span class="secno">4.21.2</span> <span class="content"><code class="highlight"><c- n>this_thread</c-><c- o>::</c-><c- n>sync_wait</c-></code></span></a>
       </ol>
      <li><a href="#design-execute"><span class="secno">4.22</span> <span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>execute</c-></code></span></a>
     </ol>
    <li>
     <a href="#design-implementer"><span class="secno">5</span> <span class="content">Design - implementer side</span></a>
     <ol class="toc">
      <li><a href="#design-receivers"><span class="secno">5.1</span> <span class="content">Receivers serve as glue between senders</span></a>
      <li><a href="#design-states"><span class="secno">5.2</span> <span class="content">Operation states represent work</span></a>
      <li><a href="#design-connect"><span class="secno">5.3</span> <span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>connect</c-></code></span></a>
      <li><a href="#design-customization"><span class="secno">5.4</span> <span class="content">Sender algorithms are customizable</span></a>
      <li><a href="#design-laziness"><span class="secno">5.5</span> <span class="content">Sender adaptors are lazy</span></a>
      <li><a href="#design-fusion"><span class="secno">5.6</span> <span class="content">Lazy senders provide optimization opportunities</span></a>
      <li><a href="#design-transition-details"><span class="secno">5.7</span> <span class="content">Execution resource transitions are two-step</span></a>
      <li><a href="#design-typed"><span class="secno">5.8</span> <span class="content">All senders are typed</span></a>
      <li><a href="#design-dispatch"><span class="secno">5.9</span> <span class="content">Ranges-style CPOs vs <code class="highlight"><c- n>tag_invoke</c-></code></span></a>
     </ol>
    <li><a href="#spec"><span class="secno">6</span> <span class="content">Specification</span></a>
    <li>
     <a href="#spec-except"><span class="secno">7</span> <span class="content">Exception handling [except]</span></a>
     <ol class="toc">
      <li>
       <a href="#spec-except.special"><span class="secno">7.1</span> <span class="content">Special functions [except.special]</span></a>
       <ol class="toc">
        <li>
         <a href="#spec-except.special.general"><span class="secno">7.1.1</span> <span class="content">General [except.special.general]</span></a>
         <ol class="toc">
          <li><a href="#spec-except.terminate"><span class="secno">7.1.1.1</span> <span class="content">The <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>terminate</c-></code> function [except.terminate]</span></a>
         </ol>
       </ol>
     </ol>
    <li><a href="#spec-library"><span class="secno">8</span> <span class="content">Library introduction <b>[library]</b></span></a>
    <li>
     <a href="#spec-utilities"><span class="secno">9</span> <span class="content">General utilities library <b>[utilities]</b></span></a>
     <ol class="toc">
      <li>
       <a href="#spec-function.objects"><span class="secno">9.1</span> <span class="content">Function objects <b>[function.objects]</b></span></a>
       <ol class="toc">
        <li><a href="#spec-functional.syn"><span class="secno">9.1.1</span> <span class="content">Header <code class="highlight"><c- o>&lt;</c-><c- n>functional</c-><c- o>></c-></code> synopsis <b>[functional.syn]</b></span></a>
        <li><a href="#spec-func.tag_invoke"><span class="secno">9.1.2</span> <span class="content"><code class="highlight"><c- n>tag_invoke</c-></code> <b>[func.tag_invoke]</b></span></a>
       </ol>
     </ol>
    <li>
     <a href="#spec-thread"><span class="secno">10</span> <span class="content">Thread support library <b>[thread]</b></span></a>
     <ol class="toc">
      <li>
       <a href="#spec-thread.stoptoken"><span class="secno">10.1</span> <span class="content">Stop tokens <b>[thread.stoptoken]</b></span></a>
       <ol class="toc">
        <li><a href="#spec-thread.stoptoken.syn"><span class="secno">10.1.1</span> <span class="content">Header <code class="highlight"><c- o>&lt;</c-><c- n>stop_token</c-><c- o>></c-></code> synopsis <b>[thread.stoptoken.syn]</b></span></a>
        <li><a href="#spec-thread.stoptoken.concepts"><span class="secno">10.1.2</span> <span class="content">Stop token concepts <b>[thread.stoptoken.concepts]</b></span></a>
        <li>
         <a href="#spec-stoptoken"><span class="secno">10.1.3</span> <span class="content">Class <code class="highlight"><c- n>stop_token</c-></code> <b>[stoptoken]</b></span></a>
         <ol class="toc">
          <li><a href="#spec-stoptoken.general"><span class="secno">10.1.3.1</span> <span class="content">General <b>[stoptoken.general]</b></span></a>
         </ol>
        <li>
         <a href="#spec-stoptoken.never"><span class="secno">10.1.4</span> <span class="content">Class <code class="highlight"><c- n>never_stop_token</c-></code> <b>[stoptoken.never]</b></span></a>
         <ol class="toc">
          <li><a href="#spec-stoptoken.never.general"><span class="secno">10.1.4.1</span> <span class="content">General <b>[stoptoken.never.general]</b></span></a>
         </ol>
        <li>
         <a href="#spec-stoptoken.inplace"><span class="secno">10.1.5</span> <span class="content">Class <code class="highlight"><c- n>in_place_stop_token</c-></code> <b>[stoptoken.inplace]</b></span></a>
         <ol class="toc">
          <li><a href="#spec-stoptoken.inplace.general"><span class="secno">10.1.5.1</span> <span class="content">General <b>[stoptoken.inplace.general]</b></span></a>
          <li><a href="#spec-stoptoken.inplace.cons"><span class="secno">10.1.5.2</span> <span class="content">Constructors, copy, and assignment <b>[stoptoken.inplace.cons]</b></span></a>
          <li><a href="#spec-stoptoken.inplace.mem"><span class="secno">10.1.5.3</span> <span class="content">Members <b>[stoptoken.inplace.mem]</b></span></a>
          <li><a href="#spec-stoptoken.inplace.nonmembers"><span class="secno">10.1.5.4</span> <span class="content">Non-member functions <b>[stoptoken.inplace.nonmembers]</b></span></a>
         </ol>
        <li>
         <a href="#spec-stopsource.inplace"><span class="secno">10.1.6</span> <span class="content">Class <code class="highlight"><c- n>in_place_stop_source</c-></code> <b>[stopsource.inplace]</b></span></a>
         <ol class="toc">
          <li><a href="#spec-stopsource.inplace.general"><span class="secno">10.1.6.1</span> <span class="content">General <b>[stopsource.inplace.general]</b></span></a>
          <li><a href="#spec-stopsource.inplace.cons"><span class="secno">10.1.6.2</span> <span class="content">Constructors, copy, and assignment <b>[stopsource.inplace.cons]</b></span></a>
          <li><a href="#spec-stopsource.inplace.mem"><span class="secno">10.1.6.3</span> <span class="content">Members <b>[stopsource.inplace.mem]</b></span></a>
         </ol>
        <li>
         <a href="#spec-stopcallback.inplace"><span class="secno">10.1.7</span> <span class="content">Class template <code class="highlight"><c- n>in_place_stop_callback</c-></code> <b>[stopcallback.inplace]</b></span></a>
         <ol class="toc">
          <li><a href="#spec-stopcallback.inplace.general"><span class="secno">10.1.7.1</span> <span class="content">General <b>[stopcallback.inplace.general]</b></span></a>
          <li><a href="#spec-stopcallback.inplace.cons"><span class="secno">10.1.7.2</span> <span class="content">Constructors and destructor <b>[stopcallback.inplace.cons]</b></span></a>
         </ol>
       </ol>
     </ol>
    <li>
     <a href="#spec-execution"><span class="secno">11</span> <span class="content">Execution control library <b>[exec]</b></span></a>
     <ol class="toc">
      <li><a href="#spec-execution.general"><span class="secno">11.1</span> <span class="content">General <b>[exec.general]</b></span></a>
      <li>
       <a href="#spec-execution.queryable"><span class="secno">11.2</span> <span class="content">Queries and queryables <b>[exec.queryable]</b></span></a>
       <ol class="toc">
        <li><a href="#spec-execution.queryable.general"><span class="secno">11.2.1</span> <span class="content">General <b>[exec.queryable.general]</b></span></a>
        <li><a href="#spec-execution.queryable.concept"><span class="secno">11.2.2</span> <span class="content"><code class="highlight"><c- n>queryable</c-></code> concept <b>[exec.queryable.concept]</b></span></a>
       </ol>
      <li><a href="#spec-execution-async.ops"><span class="secno">11.3</span> <span class="content">Asynchronous operations <b>[async.ops]</b></span></a>
      <li><a href="#spec-execution.syn"><span class="secno">11.4</span> <span class="content">Header <code class="highlight"><c- o>&lt;</c-><c- n>execution</c-><c- o>></c-></code> synopsis <b>[exec.syn]</b></span></a>
      <li>
       <a href="#spec-execution.queries"><span class="secno">11.5</span> <span class="content">Queries <b>[exec.queries]</b></span></a>
       <ol class="toc">
        <li><a href="#spec-execution.forwarding_query"><span class="secno">11.5.1</span> <span class="content"><code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>forwarding_query</c-></code> <b>[exec.fwd.env]</b></span></a>
        <li><a href="#spec-execution.get_allocator"><span class="secno">11.5.2</span> <span class="content"><code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>get_allocator</c-></code> <b>[exec.get.allocator]</b></span></a>
        <li><a href="#spec-execution.get_stop_token"><span class="secno">11.5.3</span> <span class="content"><code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>get_stop_token</c-></code> <b>[exec.get.stop.token]</b></span></a>
        <li><a href="#spec-execution.environment.get_env"><span class="secno">11.5.4</span> <span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>get_env</c-></code> <b>[exec.get.env]</b></span></a>
        <li><a href="#spec-execution.get_domain"><span class="secno">11.5.5</span> <span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>get_domain</c-></code> <b>[exec.get.domain]</b></span></a>
        <li><a href="#spec-execution.get_scheduler"><span class="secno">11.5.6</span> <span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>get_scheduler</c-></code> <b>[exec.get.scheduler]</b></span></a>
        <li><a href="#spec-execution.get_delegatee_scheduler"><span class="secno">11.5.7</span> <span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>get_delegatee_scheduler</c-></code> <b>[exec.get.delegatee.scheduler]</b></span></a>
        <li><a href="#spec-execution.get_forward_progress_guarantee"><span class="secno">11.5.8</span> <span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>get_forward_progress_guarantee</c-></code> <b>[exec.get.forward.progress.guarantee]</b></span></a>
        <li><a href="#spec-execution.execute_may_block_caller"><span class="secno">11.5.9</span> <span class="content"><code class="highlight"><c- n>this_thread</c-><c- o>::</c-><c- n>execute_may_block_caller</c-></code> <b>[exec.execute.may.block.caller]</b></span></a>
        <li><a href="#spec-execution.get_completion_scheduler"><span class="secno">11.5.10</span> <span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>get_completion_scheduler</c-></code> <b>[exec.completion.scheduler]</b></span></a>
       </ol>
      <li><a href="#spec-execution.schedulers"><span class="secno">11.6</span> <span class="content">Schedulers <b>[exec.sched] </b></span></a>
      <li>
       <a href="#spec-execution.receivers"><span class="secno">11.7</span> <span class="content">Receivers <b>[exec.recv]</b></span></a>
       <ol class="toc">
        <li><a href="#spec-execution.receiver_concepts"><span class="secno">11.7.1</span> <span class="content">Receiver concepts <b>[exec.recv.concepts]</b></span></a>
        <li><a href="#spec-execution.receivers.set_value"><span class="secno">11.7.2</span> <span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_value</c-></code> <b>[exec.set.value]</b></span></a>
        <li><a href="#spec-execution.receivers.set_error"><span class="secno">11.7.3</span> <span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_error</c-></code> <b>[exec.set.error]</b></span></a>
        <li><a href="#spec-execution.receivers.set_stopped"><span class="secno">11.7.4</span> <span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_stopped</c-></code> <b>[exec.set.stopped]</b></span></a>
       </ol>
      <li>
       <a href="#spec-execution.opstate"><span class="secno">11.8</span> <span class="content">Operation states <b>[exec.opstate]</b></span></a>
       <ol class="toc">
        <li><a href="#spec-execution.opstate.start"><span class="secno">11.8.1</span> <span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>start</c-></code> <b>[exec.opstate.start]</b></span></a>
       </ol>
      <li>
       <a href="#spec-execution.senders"><span class="secno">11.9</span> <span class="content">Senders <b>[exec.snd]</b></span></a>
       <ol class="toc">
        <li><a href="#spec-execution.senders.general"><span class="secno">11.9.1</span> <span class="content">General <b>[exec.snd.general]</b></span></a>
        <li><a href="#spec-execution.snd.concepts"><span class="secno">11.9.2</span> <span class="content">Sender concepts <b>[exec.snd.concepts]</b></span></a>
        <li><a href="#spec.exec-awaitables"><span class="secno">11.9.3</span> <span class="content">Awaitable helpers <b>[exec.awaitables]</b></span></a>
        <li>
         <a href="#spec-execution.default_domain"><span class="secno">11.9.4</span> <span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>default_domain</c-></code> <b>[exec.domain.default]</b></span></a>
         <ol class="toc">
          <li><a href="#spec-execution.default_domain.statics"><span class="secno">11.9.4.1</span> <span class="content">Static members <b>[exec.domain.default.statics]</b></span></a>
         </ol>
        <li><a href="#spec-execution.sender_transform"><span class="secno">11.9.5</span> <span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>transform_sender</c-></code> <b>[exec.snd.transform]</b></span></a>
        <li><a href="#spec-execution.apply_sender"><span class="secno">11.9.6</span> <span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>apply_sender</c-></code> <b>[exec.snd.apply]</b></span></a>
        <li><a href="#spec-execution.getcomplsigs"><span class="secno">11.9.7</span> <span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>get_completion_signatures</c-></code> <b>[exec.getcomplsigs]</b></span></a>
        <li><a href="#spec-execution.senders.connect"><span class="secno">11.9.8</span> <span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>connect</c-></code> <b>[exec.connect]</b></span></a>
        <li>
         <a href="#spec-execution.senders.factories"><span class="secno">11.9.9</span> <span class="content">Sender factories <b>[exec.factories]</b></span></a>
         <ol class="toc">
          <li><a href="#spec-execution.senders.schedule"><span class="secno">11.9.9.1</span> <span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>schedule</c-></code> <b>[exec.schedule]</b></span></a>
          <li><a href="#spec-execution.senders.just"><span class="secno">11.9.9.2</span> <span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>just</c-></code>, <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>just_error</c-></code>, <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>just_stopped</c-></code> <b>[exec.just]</b></span></a>
          <li><a href="#spec-execution.senders.read"><span class="secno">11.9.9.3</span> <span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>read</c-></code> <b>[exec.read]</b></span></a>
         </ol>
        <li>
         <a href="#spec-execution.senders.adapt"><span class="secno">11.9.10</span> <span class="content">Sender adaptors <b>[exec.adapt]</b></span></a>
         <ol class="toc">
          <li><a href="#spec-execution.senders.adapt.general"><span class="secno">11.9.10.1</span> <span class="content">General <b>[exec.adapt.general]</b></span></a>
          <li><a href="#spec-execution.senders.adaptor.objects"><span class="secno">11.9.10.2</span> <span class="content">Sender adaptor closure objects <b>[exec.adapt.objects]</b></span></a>
          <li><a href="#spec-execution.senders.adapt.on"><span class="secno">11.9.10.3</span> <span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>on</c-></code> <b>[exec.on]</b></span></a>
          <li><a href="#spec-execution.senders.adapt.transfer"><span class="secno">11.9.10.4</span> <span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>transfer</c-></code> <b>[exec.transfer]</b></span></a>
          <li><a href="#spec-execution.senders.adaptors.schedule_from"><span class="secno">11.9.10.5</span> <span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>schedule_from</c-></code> <b>[exec.schedule.from]</b></span></a>
          <li><a href="#spec-execution.senders.adaptor.then"><span class="secno">11.9.10.6</span> <span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>then</c-></code>, <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>upon_error</c-></code>, <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>upon_stopped</c-></code> <b>[exec.then]</b></span></a>
          <li><a href="#spec-execution.senders.adapt.let"><span class="secno">11.9.10.7</span> <span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>let_value</c-></code>, <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>let_error</c-></code>, <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>let_stopped</c-></code>, <b>[exec.let]</b></span></a>
          <li><a href="#spec-execution.senders.adapt.bulk"><span class="secno">11.9.10.8</span> <span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>bulk</c-></code> <b>[exec.bulk]</b></span></a>
          <li><a href="#spec-execution.senders.adapt.split"><span class="secno">11.9.10.9</span> <span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>split</c-></code> and <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>ensure_started</c-></code> <b>[exec.split]</b></span></a>
          <li><a href="#spec-execution.senders.adaptor.when_all"><span class="secno">11.9.10.10</span> <span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>when_all</c-></code> <b>[exec.when.all]</b></span></a>
          <li><a href="#spec-execution.senders.adapt.into_variant"><span class="secno">11.9.10.11</span> <span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>into_variant</c-></code> <b>[exec.into.variant]</b></span></a>
          <li><a href="#spec-execution.senders.adapt.stopped_as_optional"><span class="secno">11.9.10.12</span> <span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>stopped_as_optional</c-></code> <b>[exec.stopped.as.optional]</b></span></a>
          <li><a href="#spec-execution.senders.adapt.stopped_as_error"><span class="secno">11.9.10.13</span> <span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>stopped_as_error</c-></code> <b>[exec.stopped.as.error]</b></span></a>
         </ol>
        <li>
         <a href="#spec-execution.senders.consumers"><span class="secno">11.9.11</span> <span class="content">Sender consumers <b>[exec.consumers]</b></span></a>
         <ol class="toc">
          <li><a href="#spec-execution.senders.consumers.start_detached"><span class="secno">11.9.11.1</span> <span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>start_detached</c-></code> <b>[exec.start.detached]</b></span></a>
          <li><a href="#spec-execution.senders.consumers.sync_wait"><span class="secno">11.9.11.2</span> <span class="content"><code class="highlight"><c- n>this_thread</c-><c- o>::</c-><c- n>sync_wait</c-></code> <b>[exec.sync.wait]</b></span></a>
         </ol>
       </ol>
      <li><a href="#spec-execution.execute"><span class="secno">11.10</span> <span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>execute</c-></code> <b>[exec.execute]</b></span></a>
      <li>
       <a href="#spec-execution.snd_rec_utils"><span class="secno">11.11</span> <span class="content">Sender/receiver utilities <b>[exec.utils]</b></span></a>
       <ol class="toc">
        <li>
         <a href="#spec-execution.snd_rec_utils.rcvr_adptr"><span class="secno">11.11.1</span> <span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>receiver_adaptor</c-></code> <b>[exec.utils.rcvr.adptr]</b></span></a>
         <ol class="toc">
          <li><a href="#spec-execution.snd_rec_utils.receiver_adaptor.nonmembers"><span class="secno">11.11.1.1</span> <span class="content">Non-member functions <b>[exec.utils.rcvr.adptr.nonmembers]</b></span></a>
         </ol>
        <li><a href="#spec-execution.snd_rec_utils.completion_sigs"><span class="secno">11.11.2</span> <span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>completion_signatures</c-></code> <b>[exec.utils.cmplsigs]</b></span></a>
        <li><a href="#spec-execution.snd_rec_utils.transform_completion_sigs"><span class="secno">11.11.3</span> <span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>transform_completion_signatures</c-></code> <b>[exec.utils.tfxcmplsigs]</b></span></a>
       </ol>
      <li>
       <a href="#spec-execution.contexts"><span class="secno">11.12</span> <span class="content">Execution contexts <b>[exec.ctx]</b></span></a>
       <ol class="toc">
        <li>
         <a href="#spec-execution.contexts.run_loop"><span class="secno">11.12.1</span> <span class="content"><code class="highlight"><c- n>run_loop</c-></code> <b>[exec.run.loop]</b></span></a>
         <ol class="toc">
          <li><a href="#spec-execution.contexts.run_loop.types"><span class="secno">11.12.1.1</span> <span class="content">Associated types <b>[exec.run.loop.types]</b></span></a>
          <li><a href="#spec-execution.contexts.run_loop.ctor"><span class="secno">11.12.1.2</span> <span class="content">Constructor and destructor <b>[exec.run.loop.ctor]</b></span></a>
          <li><a href="#spec-execution.contexts.run_loop.members"><span class="secno">11.12.1.3</span> <span class="content">Member functions <b>[exec.run.loop.members]</b></span></a>
         </ol>
       </ol>
      <li>
       <a href="#spec-execution.coro_utils"><span class="secno">11.13</span> <span class="content">Coroutine utilities <b>[exec.coro.utils]</b></span></a>
       <ol class="toc">
        <li><a href="#spec-execution.coro_utils.as_awaitable"><span class="secno">11.13.1</span> <span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>as_awaitable</c-></code> <b>[exec.as.awaitable]</b></span></a>
        <li><a href="#spec-execution.coro_utils.with_awaitable_senders"><span class="secno">11.13.2</span> <span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>with_awaitable_senders</c-></code> <b>[exec.with.awaitable.senders]</b></span></a>
       </ol>
     </ol>
    <li>
     <a href="#index"><span class="secno"></span> <span class="content">Index</span></a>
     <ol class="toc">
      <li><a href="#index-defined-here"><span class="secno"></span> <span class="content">Terms defined by this specification</span></a>
     </ol>
    <li>
     <a href="#references"><span class="secno"></span> <span class="content">References</span></a>
     <ol class="toc">
      <li><a href="#informative"><span class="secno"></span> <span class="content">Informative References</span></a>
     </ol>
   </ol>
  </nav>
  <main>
   <h2 class="heading settled" data-level="1" id="intro"><span class="secno">1. </span><span class="content">Introduction</span><a class="self-link" href="#intro"></a></h2>
   <p>This paper proposes a self-contained design for a Standard C++ framework for managing asynchronous execution on generic execution resources. It is based on the ideas in <a data-link-type="biblio" href="https://wg21.link/p0443r14"><cite>A Unified Executors Proposal for C++</cite></a> and its companion papers.</p>
   <h3 class="heading settled" data-level="1.1" id="motivation"><span class="secno">1.1. </span><span class="content">Motivation</span><a class="self-link" href="#motivation"></a></h3>
   <p>Today, C++ software is increasingly asynchronous and parallel, a trend that is likely to only continue going forward.
Asynchrony and parallelism appears everywhere, from processor hardware interfaces, to networking, to file I/O, to GUIs, to accelerators.
Every C++ domain and every platform needs to deal with asynchrony and parallelism, from scientific computing to video games to financial services, from the smallest mobile devices to your laptop to GPUs in the world’s fastest supercomputer.</p>
   <p>While the C++ Standard Library has a rich set of concurrency primitives (<code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>atomic</c-></code>, <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>mutex</c-></code>, <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>counting_semaphore</c-></code>, etc) and lower level building blocks (<code class="highlight"><c- n>std</c-><c- o>::</c-><c- kr>thread</c-></code>, etc), we lack a Standard vocabulary and framework for asynchrony and parallelism that C++ programmers desperately need. <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>async</c-></code>/<code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>future</c-></code>/<code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>promise</c-></code>, C++11’s intended exposure for asynchrony, is inefficient, hard to use correctly, and severely lacking in genericity, making it unusable in many contexts.
We introduced parallel algorithms to the C++ Standard Library in C++17, and while they are an excellent start, they are all inherently synchronous and not composable.</p>
   <p>This paper proposes a Standard C++ model for asynchrony, based around three key abstractions: schedulers, senders, and receivers, and a set of customizable asynchronous algorithms.</p>
   <h3 class="heading settled" data-level="1.2" id="priorities"><span class="secno">1.2. </span><span class="content">Priorities</span><a class="self-link" href="#priorities"></a></h3>
   <ul>
    <li data-md>
     <p>Be composable and generic, allowing users to write code that can be used with many different types of execution resources.</p>
    <li data-md>
     <p>Encapsulate common asynchronous patterns in customizable and reusable algorithms, so users don’t have to invent things themselves.</p>
    <li data-md>
     <p>Make it easy to be correct by construction.</p>
    <li data-md>
     <p>Support the diversity of execution resources and execution agents, because not all execution agents are created equal; some are less capable than others, but not less important.</p>
    <li data-md>
     <p>Allow everything to be customized by an execution resource, including transfer to other execution resources, but don’t require that execution resources customize everything.</p>
    <li data-md>
     <p>Care about all reasonable use cases, domains and platforms.</p>
    <li data-md>
     <p>Errors must be propagated, but error handling must not present a burden.</p>
    <li data-md>
     <p>Support cancellation, which is not an error.</p>
    <li data-md>
     <p>Have clear and concise answers for where things execute.</p>
    <li data-md>
     <p>Be able to manage and terminate the lifetimes of objects asynchronously.</p>
   </ul>
   <h3 class="heading settled" data-level="1.3" id="example-end-user"><span class="secno">1.3. </span><span class="content">Examples: End User</span><a class="self-link" href="#example-end-user"></a></h3>
   <p>In this section we demonstrate the end-user experience of asynchronous programming directly with the sender algorithms presented in this paper. See <a href="#design-sender-factories">§ 4.19 User-facing sender factories</a>, <a href="#design-sender-adaptors">§ 4.20 User-facing sender adaptors</a>, and <a href="#design-sender-consumers">§ 4.21 User-facing sender consumers</a> for short explanations of the algorithms used in these code examples.</p>
   <h4 class="heading settled" data-level="1.3.1" id="example-hello-world"><span class="secno">1.3.1. </span><span class="content">Hello world</span><a class="self-link" href="#example-hello-world"></a></h4>
<pre class="language-c++ highlight"><c- n>using</c-> <c- n>namespace</c-> <c- n>std</c-><c- o>::</c-><c- n>execution</c-><c- p>;</c->

<c- n>scheduler</c-> <c- k>auto</c-> <c- n>sch</c-> <c- o>=</c-> <c- n>thread_pool</c-><c- p>.</c-><c- n>scheduler</c-><c- p>();</c->                                 <c- c1>// 1</c->

<c- n>sender</c-> <c- k>auto</c-> <c- n>begin</c-> <c- o>=</c-> <c- n>schedule</c-><c- p>(</c-><c- n>sch</c-><c- p>);</c->                                            <c- c1>// 2</c->
<c- n>sender</c-> <c- k>auto</c-> <c- n>hi</c-> <c- o>=</c-> <c- n>then</c-><c- p>(</c-><c- n>begin</c-><c- p>,</c-> <c- p>[]{</c->                                              <c- c1>// 3</c->
    <c- n>std</c-><c- o>::</c-><c- n>cout</c-> <c- o>&lt;&lt;</c-> <c- s>"Hello world! Have an int."</c-><c- p>;</c->                                 <c- c1>// 3</c->
    <c- k>return</c-> <c- mi>13</c-><c- p>;</c->                                                                <c- c1>// 3</c->
<c- p>});</c->                                                                           <c- c1>// 3</c->
<c- n>sender</c-> <c- k>auto</c-> <c- n>add_42</c-> <c- o>=</c-> <c- n>then</c-><c- p>(</c-><c- n>hi</c-><c- p>,</c-> <c- p>[](</c-><c- b>int</c-> <c- n>arg</c-><c- p>)</c-> <c- p>{</c-> <c- k>return</c-> <c- n>arg</c-> <c- o>+</c-> <c- mi>42</c-><c- p>;</c-> <c- p>});</c->              <c- c1>// 4</c->

<c- k>auto</c-> <c- p>[</c-><c- n>i</c-><c- p>]</c-> <c- o>=</c-> <c- n>this_thread</c-><c- o>::</c-><c- n>sync_wait</c-><c- p>(</c-><c- n>add_42</c-><c- p>).</c-><c- n>value</c-><c- p>();</c->                            <c- c1>// 5</c->
</pre>
   <p>This example demonstrates the basics of schedulers, senders, and receivers:</p>
   <ol>
    <li data-md>
     <p>First we need to get a scheduler from somewhere, such as a thread pool. A scheduler is a lightweight handle to an execution resource.</p>
    <li data-md>
     <p>To start a chain of work on a scheduler, we call <a href="#design-sender-factory-schedule">§ 4.19.1 execution::schedule</a>, which returns a sender that completes on the scheduler. A sender describes asynchronous work and sends a signal (value, error, or stopped) to some recipient(s) when that work completes.</p>
    <li data-md>
     <p>We use sender algorithms to produce senders and compose asynchronous work. <a href="#design-sender-adaptor-then">§ 4.20.2 execution::then</a> is a sender adaptor that takes an input sender and a <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>invocable</c-></code>, and calls the <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>invocable</c-></code> on the signal sent by the input sender. The sender returned by <code class="highlight"><c- n>then</c-></code> sends the result of that invocation. In this case, the input sender came from <code class="highlight"><c- n>schedule</c-></code>, so its <code class="highlight"><c- b>void</c-></code>, meaning it won’t send us a value, so our <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>invocable</c-></code> takes no parameters. But we return an <code class="highlight"><c- b>int</c-></code>, which will be sent to the next recipient.</p>
    <li data-md>
     <p>Now, we add another operation to the chain, again using <a href="#design-sender-adaptor-then">§ 4.20.2 execution::then</a>. This time, we get sent a value - the <code class="highlight"><c- b>int</c-></code> from the previous step. We add <code class="highlight"><c- mi>42</c-></code> to it, and then return the result.</p>
    <li data-md>
     <p>Finally, we’re ready to submit the entire asynchronous pipeline and wait for its completion. Everything up until this point has been completely asynchronous; the work may not have even started yet. To ensure the work has started and then block pending its completion, we use <a href="#design-sender-consumer-sync_wait">§ 4.21.2 this_thread::sync_wait</a>, which will either return a <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>optional</c-><c- o>&lt;</c-><c- n>std</c-><c- o>::</c-><c- n>tuple</c-><c- o>&lt;</c-><c- p>...</c-><c- o>>></c-></code> with the value sent by the last sender, or an empty <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>optional</c-></code> if the last sender sent a stopped signal, or it throws an exception if the last sender sent an error.</p>
   </ol>
   <h4 class="heading settled" data-level="1.3.2" id="example-async-inclusive-scan"><span class="secno">1.3.2. </span><span class="content">Asynchronous inclusive scan</span><a class="self-link" href="#example-async-inclusive-scan"></a></h4>
<pre class="language-c++ highlight"><c- n>using</c-> <c- n>namespace</c-> <c- n>std</c-><c- o>::</c-><c- n>execution</c-><c- p>;</c->

<c- n>sender</c-> <c- k>auto</c-> <c- n>async_inclusive_scan</c-><c- p>(</c-><c- n>scheduler</c-> <c- k>auto</c-> <c- n>sch</c-><c- p>,</c->                          <c- c1>// 2</c->
                                 <c- n>std</c-><c- o>::</c-><c- n>span</c-><c- o>&lt;</c-><c- k>const</c-> <c- b>double</c-><c- o>></c-> <c- n>input</c-><c- p>,</c->               <c- c1>// 1</c->
                                 <c- n>std</c-><c- o>::</c-><c- n>span</c-><c- o>&lt;</c-><c- b>double</c-><c- o>></c-> <c- n>output</c-><c- p>,</c->                    <c- c1>// 1</c->
                                 <c- b>double</c-> <c- n>init</c-><c- p>,</c->                                 <c- c1>// 1</c->
                                 <c- n>std</c-><c- o>::</c-><c- b>size_t</c-> <c- n>tile_count</c-><c- p>)</c->                      <c- c1>// 3</c->
<c- p>{</c->
  <c- n>std</c-><c- o>::</c-><c- b>size_t</c-> <c- k>const</c-> <c- n>tile_size</c-> <c- o>=</c-> <c- p>(</c-><c- n>input</c-><c- p>.</c-><c- n>size</c-><c- p>()</c-> <c- o>+</c-> <c- n>tile_count</c-> <c- o>-</c-> <c- mi>1</c-><c- p>)</c-> <c- o>/</c-> <c- n>tile_count</c-><c- p>;</c->

  <c- n>std</c-><c- o>::</c-><c- n>vector</c-><c- o>&lt;</c-><c- b>double</c-><c- o>></c-> <c- n>partials</c-><c- p>(</c-><c- n>tile_count</c-> <c- o>+</c-> <c- mi>1</c-><c- p>);</c->                               <c- c1>// 4</c->
  <c- n>partials</c-><c- p>[</c-><c- mi>0</c-><c- p>]</c-> <c- o>=</c-> <c- n>init</c-><c- p>;</c->                                                         <c- c1>// 4</c->

  <c- k>return</c-> <c- n>just</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>partials</c-><c- p>))</c->                                            <c- c1>// 5</c->
       <c- o>|</c-> <c- n>transfer</c-><c- p>(</c-><c- n>sch</c-><c- p>)</c->
       <c- o>|</c-> <c- n>bulk</c-><c- p>(</c-><c- n>tile_count</c-><c- p>,</c->                                                     <c- c1>// 6</c->
           <c- p>[</c-> <c- o>=</c-> <c- p>](</c-><c- n>std</c-><c- o>::</c-><c- b>size_t</c-> <c- n>i</c-><c- p>,</c-> <c- n>std</c-><c- o>::</c-><c- n>vector</c-><c- o>&lt;</c-><c- b>double</c-><c- o>>&amp;</c-> <c- n>partials</c-><c- p>)</c-> <c- p>{</c->              <c- c1>// 7</c->
             <c- k>auto</c-> <c- n>start</c-> <c- o>=</c-> <c- n>i</c-> <c- o>*</c-> <c- n>tile_size</c-><c- p>;</c->                                      <c- c1>// 8</c->
             <c- k>auto</c-> <c- n>end</c->   <c- o>=</c-> <c- n>std</c-><c- o>::</c-><c- n>min</c-><c- p>(</c-><c- n>input</c-><c- p>.</c-><c- n>size</c-><c- p>(),</c-> <c- p>(</c-><c- n>i</c-> <c- o>+</c-> <c- mi>1</c-><c- p>)</c-> <c- o>*</c-> <c- n>tile_size</c-><c- p>);</c->        <c- c1>// 8</c->
             <c- n>partials</c-><c- p>[</c-><c- n>i</c-> <c- o>+</c-> <c- mi>1</c-><c- p>]</c-> <c- o>=</c-> <c- o>*--</c-><c- n>std</c-><c- o>::</c-><c- n>inclusive_scan</c-><c- p>(</c-><c- n>begin</c-><c- p>(</c-><c- n>input</c-><c- p>)</c-> <c- o>+</c-> <c- n>start</c-><c- p>,</c->   <c- c1>// 9</c->
                                                      <c- n>begin</c-><c- p>(</c-><c- n>input</c-><c- p>)</c-> <c- o>+</c-> <c- n>end</c-><c- p>,</c->     <c- c1>// 9</c->
                                                      <c- n>begin</c-><c- p>(</c-><c- n>output</c-><c- p>)</c-> <c- o>+</c-> <c- n>start</c-><c- p>);</c-> <c- c1>// 9</c->
           <c- p>})</c->                                                                 <c- c1>// 10</c->
       <c- o>|</c-> <c- n>then</c-><c- p>(</c->                                                                <c- c1>// 11</c->
           <c- p>[](</c-><c- n>std</c-><c- o>::</c-><c- n>vector</c-><c- o>&lt;</c-><c- b>double</c-><c- o>>&amp;&amp;</c-> <c- n>partials</c-><c- p>)</c-> <c- p>{</c->
             <c- n>std</c-><c- o>::</c-><c- n>inclusive_scan</c-><c- p>(</c-><c- n>begin</c-><c- p>(</c-><c- n>partials</c-><c- p>),</c-> <c- n>end</c-><c- p>(</c-><c- n>partials</c-><c- p>),</c->              <c- c1>// 12</c->
                                 <c- n>begin</c-><c- p>(</c-><c- n>partials</c-><c- p>));</c->                            <c- c1>// 12</c->
             <c- k>return</c-> <c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>partials</c-><c- p>);</c->                                      <c- c1>// 13</c->
           <c- p>})</c->
       <c- o>|</c-> <c- n>bulk</c-><c- p>(</c-><c- n>tile_count</c-><c- p>,</c->                                                     <c- c1>// 14</c->
           <c- p>[</c-> <c- o>=</c-> <c- p>](</c-><c- n>std</c-><c- o>::</c-><c- b>size_t</c-> <c- n>i</c-><c- p>,</c-> <c- n>std</c-><c- o>::</c-><c- n>vector</c-><c- o>&lt;</c-><c- b>double</c-><c- o>>&amp;</c-> <c- n>partials</c-><c- p>)</c-> <c- p>{</c->              <c- c1>// 14</c->
             <c- k>auto</c-> <c- n>start</c-> <c- o>=</c-> <c- n>i</c-> <c- o>*</c-> <c- n>tile_size</c-><c- p>;</c->                                      <c- c1>// 14</c->
             <c- k>auto</c-> <c- n>end</c->   <c- o>=</c-> <c- n>std</c-><c- o>::</c-><c- n>min</c-><c- p>(</c-><c- n>input</c-><c- p>.</c-><c- n>size</c-><c- p>(),</c-> <c- p>(</c-><c- n>i</c-> <c- o>+</c-> <c- mi>1</c-><c- p>)</c-> <c- o>*</c-> <c- n>tile_size</c-><c- p>);</c->        <c- c1>// 14</c->
             <c- n>std</c-><c- o>::</c-><c- n>for_each</c-><c- p>(</c-><c- n>begin</c-><c- p>(</c-><c- n>output</c-><c- p>)</c-> <c- o>+</c-> <c- n>start</c-><c- p>,</c-> <c- n>begin</c-><c- p>(</c-><c- n>output</c-><c- p>)</c-> <c- o>+</c-> <c- n>end</c-><c- p>,</c->        <c- c1>// 14</c->
               <c- p>[</c-><c- o>&amp;</c-><c- p>]</c-> <c- p>(</c-><c- b>double</c-><c- o>&amp;</c-> <c- n>e</c-><c- p>)</c-> <c- p>{</c-> <c- n>e</c-> <c- o>=</c-> <c- n>partials</c-><c- p>[</c-><c- n>i</c-><c- p>]</c-> <c- o>+</c-> <c- n>e</c-><c- p>;</c-> <c- p>}</c->                       <c- c1>// 14</c->
             <c- p>);</c->
           <c- p>})</c->
       <c- o>|</c-> <c- n>then</c-><c- p>(</c->                                                                <c- c1>// 15</c->
           <c- p>[</c-> <c- o>=</c-> <c- p>](</c-><c- n>std</c-><c- o>::</c-><c- n>vector</c-><c- o>&lt;</c-><c- b>double</c-><c- o>>&amp;&amp;</c-> <c- n>partials</c-><c- p>)</c-> <c- p>{</c->                            <c- c1>// 15</c->
             <c- k>return</c-> <c- n>output</c-><c- p>;</c->                                                   <c- c1>// 15</c->
           <c- p>});</c->                                                                <c- c1>// 15</c->
<c- p>}</c->
</pre>
   <p>This example builds an asynchronous computation of an inclusive scan:</p>
   <ol>
    <li data-md>
     <p>It scans a sequence of <code class="highlight"><c- b>double</c-></code>s (represented as the <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>span</c-><c- o>&lt;</c-><c- k>const</c-> <c- b>double</c-><c- o>></c-></code> <code class="highlight"><c- n>input</c-></code>) and stores the result in another sequence of <code class="highlight"><c- b>double</c-></code>s (represented as <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>span</c-><c- o>&lt;</c-><c- b>double</c-><c- o>></c-></code> <code class="highlight"><c- n>output</c-></code>).</p>
    <li data-md>
     <p>It takes a scheduler, which specifies what execution resource the scan should be launched on.</p>
    <li data-md>
     <p>It also takes a <code class="highlight"><c- n>tile_count</c-></code> parameter that controls the number of execution agents that will be spawned.</p>
    <li data-md>
     <p>First we need to allocate temporary storage needed for the algorithm, which we’ll do with a <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>vector</c-></code>, <code class="highlight"><c- n>partials</c-></code>. We need one <code class="highlight"><c- b>double</c-></code> of temporary storage for each execution agent we create.</p>
    <li data-md>
     <p>Next we’ll create our initial sender with <a href="#design-sender-factory-just">§ 4.19.2 execution::just</a> and <a href="#design-sender-adaptor-transfer">§ 4.20.1 execution::transfer</a>. These senders will send the temporary storage, which we’ve moved into the sender. The sender has a completion scheduler of <code class="highlight"><c- n>sch</c-></code>, which means the next item in the chain will use <code class="highlight"><c- n>sch</c-></code>.</p>
    <li data-md>
     <p>Senders and sender adaptors support composition via <code class="highlight"><c- k>operator</c-><c- o>|</c-></code>, similar to C++ ranges. We’ll use <code class="highlight"><c- k>operator</c-><c- o>|</c-></code> to attach the next piece of work, which will spawn <code class="highlight"><c- n>tile_count</c-></code> execution agents using <a href="#design-sender-adaptor-bulk">§ 4.20.9 execution::bulk</a> (see <a href="#design-pipeable">§ 4.12 Most sender adaptors are pipeable</a> for details).</p>
    <li data-md>
     <p>Each agent will call a <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>invocable</c-></code>, passing it two arguments. The first is the agent’s index (<code class="highlight"><c- n>i</c-></code>) in the <a href="#design-sender-adaptor-bulk">§ 4.20.9 execution::bulk</a> operation, in this case a unique integer in <code class="highlight"><c- p>[</c-><c- mi>0</c-><c- p>,</c-> <c- n>tile_count</c-><c- p>)</c-></code>. The second argument is what the input sender sent - the temporary storage.</p>
    <li data-md>
     <p>We start by computing the start and end of the range of input and output elements that this agent is responsible for, based on our agent index.</p>
    <li data-md>
     <p>Then we do a sequential <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>inclusive_scan</c-></code> over our elements. We store the scan result for our last element, which is the sum of all of our elements, in our temporary storage <code class="highlight"><c- n>partials</c-></code>.</p>
    <li data-md>
     <p>After all computation in that initial <a href="#design-sender-adaptor-bulk">§ 4.20.9 execution::bulk</a> pass has completed, every one of the spawned execution agents will have written the sum of its elements into its slot in <code class="highlight"><c- n>partials</c-></code>.</p>
    <li data-md>
     <p>Now we need to scan all of the values in <code class="highlight"><c- n>partials</c-></code>. We’ll do that with a single execution agent which will execute after the <a href="#design-sender-adaptor-bulk">§ 4.20.9 execution::bulk</a> completes. We create that execution agent with <a href="#design-sender-adaptor-then">§ 4.20.2 execution::then</a>.</p>
    <li data-md>
     <p><a href="#design-sender-adaptor-then">§ 4.20.2 execution::then</a> takes an input sender and an <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>invocable</c-></code> and calls the <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>invocable</c-></code> with the value sent by the input sender. Inside our <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>invocable</c-></code>, we call <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>inclusive_scan</c-></code> on <code class="highlight"><c- n>partials</c-></code>, which the input senders will send to us.</p>
    <li data-md>
     <p>Then we return <code class="highlight"><c- n>partials</c-></code>, which the next phase will need.</p>
    <li data-md>
     <p>Finally we do another <a href="#design-sender-adaptor-bulk">§ 4.20.9 execution::bulk</a> of the same shape as before. In this <a href="#design-sender-adaptor-bulk">§ 4.20.9 execution::bulk</a>, we will use the scanned values in <code class="highlight"><c- n>partials</c-></code> to integrate the sums from other tiles into our elements, completing the inclusive scan.</p>
    <li data-md>
     <p><code class="highlight"><c- n>async_inclusive_scan</c-></code> returns a sender that sends the output <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>span</c-><c- o>&lt;</c-><c- b>double</c-><c- o>></c-></code>. A consumer of the algorithm can chain additional work that uses the scan result. At the point at which <code class="highlight"><c- n>async_inclusive_scan</c-></code> returns, the computation may not have completed. In fact, it may not have even started.</p>
   </ol>
   <h4 class="heading settled" data-level="1.3.3" id="example-async-dynamically-sized-read"><span class="secno">1.3.3. </span><span class="content">Asynchronous dynamically-sized read</span><a class="self-link" href="#example-async-dynamically-sized-read"></a></h4>
<pre class="language-c++ highlight"><c- n>using</c-> <c- n>namespace</c-> <c- n>std</c-><c- o>::</c-><c- n>execution</c-><c- p>;</c->

<c- n>sender_of</c-><c- o>&lt;</c-><c- n>std</c-><c- o>::</c-><c- b>size_t</c-><c- o>></c-> <c- k>auto</c-> <c- n>async_read</c-><c- p>(</c->                                       <c- c1>// 1</c->
    <c- n>sender_of</c-><c- o>&lt;</c-><c- n>std</c-><c- o>::</c-><c- n>span</c-><c- o>&lt;</c-><c- n>std</c-><c- o>::</c-><c- n>byte</c-><c- o>>></c-> <c- k>auto</c-> <c- n>buffer</c-><c- p>,</c->                              <c- c1>// 1</c->
    <c- k>auto</c-> <c- n>handle</c-><c- p>);</c->                                                             <c- c1>// 1</c->

<c- k>struct</c-> <c- nc>dynamic_buffer</c-> <c- p>{</c->                                                       <c- c1>// 3</c->
  <c- n>std</c-><c- o>::</c-><c- n>unique_ptr</c-><c- o>&lt;</c-><c- n>std</c-><c- o>::</c-><c- n>byte</c-><c- p>[]</c-><c- o>></c-> <c- n>data</c-><c- p>;</c->                                          <c- c1>// 3</c->
  <c- n>std</c-><c- o>::</c-><c- b>size_t</c-> <c- n>size</c-><c- p>;</c->                                                           <c- c1>// 3</c->
<c- p>};</c->                                                                            <c- c1>// 3</c->

<c- n>sender_of</c-><c- o>&lt;</c-><c- n>dynamic_buffer</c-><c- o>></c-> <c- k>auto</c-> <c- n>async_read_array</c-><c- p>(</c-><c- k>auto</c-> <c- n>handle</c-><c- p>)</c-> <c- p>{</c->                <c- c1>// 2</c->
  <c- k>return</c-> <c- n>just</c-><c- p>(</c-><c- n>dynamic_buffer</c-><c- p>{})</c->                                               <c- c1>// 4</c->
       <c- o>|</c-> <c- n>let_value</c-><c- p>([</c-><c- n>handle</c-><c- p>]</c-> <c- p>(</c-><c- n>dynamic_buffer</c-><c- o>&amp;</c-> <c- n>buf</c-><c- p>)</c-> <c- p>{</c->                           <c- c1>// 5</c->
           <c- k>return</c-> <c- n>just</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>as_writeable_bytes</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>span</c-><c- p>(</c-><c- o>&amp;</c-><c- n>buf</c-><c- p>.</c-><c- n>size</c-><c- p>,</c-> <c- mi>1</c-><c- p>))</c->       <c- c1>// 6</c->
                <c- o>|</c-> <c- n>async_read</c-><c- p>(</c-><c- n>handle</c-><c- p>)</c->                                          <c- c1>// 7</c->
                <c- o>|</c-> <c- n>then</c-><c- p>(</c->                                                       <c- c1>// 8</c->
                    <c- p>[</c-><c- o>&amp;</c-><c- n>buf</c-><c- p>]</c-> <c- p>(</c-><c- n>std</c-><c- o>::</c-><c- b>size_t</c-> <c- n>bytes_read</c-><c- p>)</c-> <c- p>{</c->                         <c- c1>// 9</c->
                      <c- n>assert</c-><c- p>(</c-><c- n>bytes_read</c-> <c- o>==</c-> <c- k>sizeof</c-><c- p>(</c-><c- n>buf</c-><c- p>.</c-><c- n>size</c-><c- p>));</c->                 <c- c1>// 10</c->
                      <c- n>buf</c-><c- p>.</c-><c- n>data</c-> <c- o>=</c-> <c- n>std</c-><c- o>::</c-><c- n>make_unique</c-><c- o>&lt;</c-><c- n>std</c-><c- o>::</c-><c- n>byte</c-><c- p>[]</c-><c- o>></c-><c- p>(</c-><c- n>buf</c-><c- p>.</c-><c- n>size</c-><c- p>);</c->     <c- c1>// 11</c->
                      <c- k>return</c-> <c- n>std</c-><c- o>::</c-><c- n>span</c-><c- p>(</c-><c- n>buf</c-><c- p>.</c-><c- n>data</c-><c- p>.</c-><c- n>get</c-><c- p>(),</c-> <c- n>buf</c-><c- p>.</c-><c- n>size</c-><c- p>);</c->             <c- c1>// 12</c->
                    <c- p>})</c->
                <c- o>|</c-> <c- n>async_read</c-><c- p>(</c-><c- n>handle</c-><c- p>)</c->                                          <c- c1>// 13</c->
                <c- o>|</c-> <c- n>then</c-><c- p>(</c->
                    <c- p>[</c-><c- o>&amp;</c-><c- n>buf</c-><c- p>]</c-> <c- p>(</c-><c- n>std</c-><c- o>::</c-><c- b>size_t</c-> <c- n>bytes_read</c-><c- p>)</c-> <c- p>{</c->
                      <c- n>assert</c-><c- p>(</c-><c- n>bytes_read</c-> <c- o>==</c-> <c- n>buf</c-><c- p>.</c-><c- n>size</c-><c- p>);</c->                         <c- c1>// 14</c->
                      <c- k>return</c-> <c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>buf</c-><c- p>);</c->                                  <c- c1>// 15</c->
                    <c- p>});</c->
       <c- p>});</c->
<c- p>}</c->
</pre>
   <p>This example demonstrates a common asynchronous I/O pattern - reading a payload of a dynamic size by first reading the size, then reading the number of bytes specified by the size:</p>
   <ol>
    <li data-md>
     <p><code class="highlight"><c- n>async_read</c-></code> is a pipeable sender adaptor. It’s a customization point object, but this is what it’s call signature looks like. It takes a sender parameter which must send an input buffer in the form of a <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>span</c-><c- o>&lt;</c-><c- n>std</c-><c- o>::</c-><c- n>byte</c-><c- o>></c-></code>, and a handle to an I/O context. It will asynchronously read into the input buffer, up to the size of the <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>span</c-></code>. It returns a sender which will send the number of bytes read once the read completes.</p>
    <li data-md>
     <p><code class="highlight"><c- n>async_read_array</c-></code> takes an I/O handle and reads a size from it, and then a buffer of that many bytes. It returns a sender that sends a <code class="highlight"><c- n>dynamic_buffer</c-></code> object that owns the data that was sent.</p>
    <li data-md>
     <p><code class="highlight"><c- n>dynamic_buffer</c-></code> is an aggregate struct that contains a <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>unique_ptr</c-><c- o>&lt;</c-><c- n>std</c-><c- o>::</c-><c- n>byte</c-><c- p>[]</c-><c- o>></c-></code> and a size.</p>
    <li data-md>
     <p>The first thing we do inside of <code class="highlight"><c- n>async_read_array</c-></code> is create a sender that will send a new, empty <code class="highlight"><c- n>dynamic_array</c-></code> object using <a href="#design-sender-factory-just">§ 4.19.2 execution::just</a>. We can attach more work to the pipeline using <code class="highlight"><c- k>operator</c-><c- o>|</c-></code> composition (see <a href="#design-pipeable">§ 4.12 Most sender adaptors are pipeable</a> for details).</p>
    <li data-md>
     <p>We need the lifetime of this <code class="highlight"><c- n>dynamic_array</c-></code> object to last for the entire pipeline. So, we use <code class="highlight"><c- n>let_value</c-></code>, which takes an input sender and a <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>invocable</c-></code> that must return a sender itself (see <a href="#design-sender-adaptor-let">§ 4.20.4 execution::let_*</a> for details). <code class="highlight"><c- n>let_value</c-></code> sends the value from the input sender to the <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>invocable</c-></code>. Critically, the lifetime of the sent object will last until the sender returned by the <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>invocable</c-></code> completes.</p>
    <li data-md>
     <p>Inside of the <code class="highlight"><c- n>let_value</c-></code> <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>invocable</c-></code>, we have the rest of our logic. First, we want to initiate an <code class="highlight"><c- n>async_read</c-></code> of the buffer size. To do that, we need to send a <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>span</c-></code> pointing to <code class="highlight"><c- n>buf</c-><c- p>.</c-><c- n>size</c-></code>. We can do that with <a href="#design-sender-factory-just">§ 4.19.2 execution::just</a>.</p>
    <li data-md>
     <p>We chain the <code class="highlight"><c- n>async_read</c-></code> onto the <a href="#design-sender-factory-just">§ 4.19.2 execution::just</a> sender with <code class="highlight"><c- k>operator</c-><c- o>|</c-></code>.</p>
    <li data-md>
     <p>Next, we pipe a <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>invocable</c-></code> that will be invoked after the <code class="highlight"><c- n>async_read</c-></code> completes using <a href="#design-sender-adaptor-then">§ 4.20.2 execution::then</a>.</p>
    <li data-md>
     <p>That <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>invocable</c-></code> gets sent the number of bytes read.</p>
    <li data-md>
     <p>We need to check that the number of bytes read is what we expected.</p>
    <li data-md>
     <p>Now that we have read the size of the data, we can allocate storage for it.</p>
    <li data-md>
     <p>We return a <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>span</c-><c- o>&lt;</c-><c- n>std</c-><c- o>::</c-><c- n>byte</c-><c- o>></c-></code> to the storage for the data from the <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>invocable</c-></code>. This will be sent to the next recipient in the pipeline.</p>
    <li data-md>
     <p>And that recipient will be another <code class="highlight"><c- n>async_read</c-></code>, which will read the data.</p>
    <li data-md>
     <p>Once the data has been read, in another <a href="#design-sender-adaptor-then">§ 4.20.2 execution::then</a>, we confirm that we read the right number of bytes.</p>
    <li data-md>
     <p>Finally, we move out of and return our <code class="highlight"><c- n>dynamic_buffer</c-></code> object. It will get sent by the sender returned by <code class="highlight"><c- n>async_read_array</c-></code>. We can attach more things to that sender to use the data in the buffer.</p>
   </ol>
   <h3 class="heading settled" data-level="1.4" id="example-async-windows-socket-recv"><span class="secno">1.4. </span><span class="content">Asynchronous Windows socket <code class="highlight"><c- n>recv</c-></code></span><a class="self-link" href="#example-async-windows-socket-recv"></a></h3>
   <p>To get a better feel for how this interface might be used by low-level operations see this example implementation
of a cancellable <code class="highlight"><c- n>async_recv</c-><c- p>()</c-></code> operation for a Windows Socket.</p>
<pre class="language-c++ highlight"><c- k>struct</c-> <c- nc>operation_base</c-> <c- o>:</c-> <c- n>WSAOVERALAPPED</c-> <c- p>{</c->
    <c- n>using</c-> <c- n>completion_fn</c-> <c- o>=</c-> <c- b>void</c-><c- p>(</c-><c- n>operation_base</c-><c- o>*</c-> <c- n>op</c-><c- p>,</c-> <c- n>DWORD</c-> <c- n>bytesTransferred</c-><c- p>,</c-> <c- b>int</c-> <c- n>errorCode</c-><c- p>)</c-> <c- n>noexcept</c-><c- p>;</c->

    <c- c1>// Assume IOCP event loop will call this when this OVERLAPPED structure is dequeued.</c->
    <c- n>completion_fn</c-><c- o>*</c-> <c- n>completed</c-><c- p>;</c->
<c- p>};</c->

<c- n>template</c-><c- o>&lt;</c-><c- n>typename</c-> <c- n>Receiver</c-><c- o>></c->
<c- k>struct</c-> <c- nc>recv_op</c-> <c- o>:</c-> <c- n>operation_base</c-> <c- p>{</c->
    <c- n>recv_op</c-><c- p>(</c-><c- n>SOCKET</c-> <c- n>s</c-><c- p>,</c-> <c- b>void</c-><c- o>*</c-> <c- n>data</c-><c- p>,</c-> <c- b>size_t</c-> <c- n>len</c-><c- p>,</c-> <c- n>Receiver</c-> <c- n>r</c-><c- p>)</c->
    <c- o>:</c-> <c- n>receiver</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>r</c-><c- p>))</c->
    <c- p>,</c-> <c- n>sock</c-><c- p>(</c-><c- n>s</c-><c- p>)</c-> <c- p>{</c->
        <c- n>this</c-><c- o>-></c-><c- n>Internal</c-> <c- o>=</c-> <c- mi>0</c-><c- p>;</c->
        <c- n>this</c-><c- o>-></c-><c- n>InternalHigh</c-> <c- o>=</c-> <c- mi>0</c-><c- p>;</c->
        <c- n>this</c-><c- o>-></c-><c- n>Offset</c-> <c- o>=</c-> <c- mi>0</c-><c- p>;</c->
        <c- n>this</c-><c- o>-></c-><c- n>OffsetHigh</c-> <c- o>=</c-> <c- mi>0</c-><c- p>;</c->
        <c- n>this</c-><c- o>-></c-><c- n>hEvent</c-> <c- o>=</c-> NULL<c- p>;</c->
        <c- n>this</c-><c- o>-></c-><c- n>completed</c-> <c- o>=</c-> <c- o>&amp;</c-><c- n>recv_op</c-><c- o>::</c-><c- n>on_complete</c-><c- p>;</c->
        <c- n>buffer</c-><c- p>.</c-><c- n>len</c-> <c- o>=</c-> <c- n>len</c-><c- p>;</c->
        <c- n>buffer</c-><c- p>.</c-><c- n>buf</c-> <c- o>=</c-> <c- n>static_cast</c-><c- o>&lt;</c-><c- n>CHAR</c-><c- o>*></c-><c- p>(</c-><c- n>data</c-><c- p>);</c->
    <c- p>}</c->

    <c- n>friend</c-> <c- b>void</c-> <c- n>tag_invoke</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>execution</c-><c- o>::</c-><c- n>start_t</c-><c- p>,</c-> <c- n>recv_op</c-><c- o>&amp;</c-> <c- n>self</c-><c- p>)</c-> <c- n>noexcept</c-> <c- p>{</c->
        <c- c1>// Avoid even calling WSARecv() if operation already cancelled</c->
        <c- k>auto</c-> <c- n>st</c-> <c- o>=</c-> <c- n>std</c-><c- o>::</c-><c- n>execution</c-><c- o>::</c-><c- n>get_stop_token</c-><c- p>(</c->
          <c- n>std</c-><c- o>::</c-><c- n>execution</c-><c- o>::</c-><c- n>get_env</c-><c- p>(</c-><c- n>self</c-><c- p>.</c-><c- n>receiver</c-><c- p>));</c->
        <c- k>if</c-> <c- p>(</c-><c- n>st</c-><c- p>.</c-><c- n>stop_requested</c-><c- p>())</c-> <c- p>{</c->
            <c- n>std</c-><c- o>::</c-><c- n>execution</c-><c- o>::</c-><c- n>set_stopped</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>self</c-><c- p>.</c-><c- n>receiver</c-><c- p>));</c->
            <c- k>return</c-><c- p>;</c->
        <c- p>}</c->

        <c- c1>// Store and cache result here in case it changes during execution</c->
        <c- k>const</c-> <c- b>bool</c-> <c- n>stopPossible</c-> <c- o>=</c-> <c- n>st</c-><c- p>.</c-><c- n>stop_possible</c-><c- p>();</c->
        <c- k>if</c-> <c- p>(</c-><c- o>!</c-><c- n>stopPossible</c-><c- p>)</c-> <c- p>{</c->
            <c- n>self</c-><c- p>.</c-><c- n>ready</c-><c- p>.</c-><c- n>store</c-><c- p>(</c->true<c- p>,</c-> <c- n>std</c-><c- o>::</c-><c- n>memory_order_relaxed</c-><c- p>);</c->
        <c- p>}</c->

        <c- c1>// Launch the operation</c->
        <c- n>DWORD</c-> <c- n>bytesTransferred</c-> <c- o>=</c-> <c- mi>0</c-><c- p>;</c->
        <c- n>DWORD</c-> <c- n>flags</c-> <c- o>=</c-> <c- mi>0</c-><c- p>;</c->
        <c- b>int</c-> <c- n>result</c-> <c- o>=</c-> <c- n>WSARecv</c-><c- p>(</c-><c- n>self</c-><c- p>.</c-><c- n>sock</c-><c- p>,</c-> <c- o>&amp;</c-><c- n>self</c-><c- p>.</c-><c- n>buffer</c-><c- p>,</c-> <c- mi>1</c-><c- p>,</c-> <c- o>&amp;</c-><c- n>bytesTransferred</c-><c- p>,</c-> <c- o>&amp;</c-><c- n>flags</c-><c- p>,</c->
                             <c- n>static_cast</c-><c- o>&lt;</c-><c- n>WSAOVERLAPPED</c-><c- o>*></c-><c- p>(</c-><c- o>&amp;</c-><c- n>self</c-><c- p>),</c-> NULL<c- p>);</c->
        <c- k>if</c-> <c- p>(</c-><c- n>result</c-> <c- o>==</c-> <c- n>SOCKET_ERROR</c-><c- p>)</c-> <c- p>{</c->
            <c- b>int</c-> <c- n>errorCode</c-> <c- o>=</c-> <c- n>WSAGetLastError</c-><c- p>();</c->
            <c- k>if</c-> <c- p>(</c-><c- n>errorCode</c-> <c- o>!=</c-> <c- n>WSA_IO_PENDING</c-><c- p>)</c-> <c- p>{</c->
                <c- k>if</c-> <c- p>(</c-><c- n>errorCode</c-> <c- o>==</c-> <c- n>WSA_OPERATION_ABORTED</c-><c- p>)</c-> <c- p>{</c->
                    <c- n>std</c-><c- o>::</c-><c- n>execution</c-><c- o>::</c-><c- n>set_stopped</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>self</c-><c- p>.</c-><c- n>receiver</c-><c- p>));</c->
                <c- p>}</c-> <c- k>else</c-> <c- p>{</c->
                    <c- n>std</c-><c- o>::</c-><c- n>execution</c-><c- o>::</c-><c- n>set_error</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>self</c-><c- p>.</c-><c- n>receiver</c-><c- p>),</c->
                                              <c- n>std</c-><c- o>::</c-><c- n>error_code</c-><c- p>(</c-><c- n>errorCode</c-><c- p>,</c-> <c- n>std</c-><c- o>::</c-><c- n>system_category</c-><c- p>()));</c->
                <c- p>}</c->
                <c- k>return</c-><c- p>;</c->
            <c- p>}</c->
        <c- p>}</c-> <c- k>else</c-> <c- p>{</c->
            <c- c1>// Completed synchronously (assuming FILE_SKIP_COMPLETION_PORT_ON_SUCCESS has been set)</c->
            <c- n>execution</c-><c- o>::</c-><c- n>set_value</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>self</c-><c- p>.</c-><c- n>receiver</c-><c- p>),</c-> <c- n>bytesTransferred</c-><c- p>);</c->
            <c- k>return</c-><c- p>;</c->
        <c- p>}</c->

        <c- c1>// If we get here then operation has launched successfully and will complete asynchronously.</c->
        <c- c1>// May be completing concurrently on another thread already.</c->
        <c- k>if</c-> <c- p>(</c-><c- n>stopPossible</c-><c- p>)</c-> <c- p>{</c->
            <c- c1>// Register the stop callback</c->
            <c- n>self</c-><c- p>.</c-><c- n>stopCallback</c-><c- p>.</c-><c- n>emplace</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>st</c-><c- p>),</c-> <c- n>cancel_cb</c-><c- p>{</c-><c- n>self</c-><c- p>});</c->

            <c- c1>// Mark as 'completed'</c->
            <c- k>if</c-> <c- p>(</c-><c- n>self</c-><c- p>.</c-><c- n>ready</c-><c- p>.</c-><c- n>load</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>memory_order_acquire</c-><c- p>)</c-> <c- o>||</c->
                <c- n>self</c-><c- p>.</c-><c- n>ready</c-><c- p>.</c-><c- n>exchange</c-><c- p>(</c->true<c- p>,</c-> <c- n>std</c-><c- o>::</c-><c- n>memory_order_acq_rel</c-><c- p>))</c-> <c- p>{</c->
                <c- c1>// Already completed on another thread</c->
                <c- n>self</c-><c- p>.</c-><c- n>stopCallback</c-><c- p>.</c-><c- n>reset</c-><c- p>();</c->

                <c- n>BOOL</c-> <c- n>ok</c-> <c- o>=</c-> <c- n>WSAGetOverlappedResult</c-><c- p>(</c-><c- n>self</c-><c- p>.</c-><c- n>sock</c-><c- p>,</c-> <c- p>(</c-><c- n>WSAOVERLAPPED</c-><c- o>*</c-><c- p>)</c-><c- o>&amp;</c-><c- n>self</c-><c- p>,</c-> <c- o>&amp;</c-><c- n>bytesTransferred</c-><c- p>,</c-> <c- n>FALSE</c-><c- p>,</c-> <c- o>&amp;</c-><c- n>flags</c-><c- p>);</c->
                <c- k>if</c-> <c- p>(</c-><c- n>ok</c-><c- p>)</c-> <c- p>{</c->
                    <c- n>std</c-><c- o>::</c-><c- n>execution</c-><c- o>::</c-><c- n>set_value</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>self</c-><c- p>.</c-><c- n>receiver</c-><c- p>),</c-> <c- n>bytesTransferred</c-><c- p>);</c->
                <c- p>}</c-> <c- k>else</c-> <c- p>{</c->
                    <c- b>int</c-> <c- n>errorCode</c-> <c- o>=</c-> <c- n>WSAGetLastError</c-><c- p>();</c->
                    <c- n>std</c-><c- o>::</c-><c- n>execution</c-><c- o>::</c-><c- n>set_error</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>self</c-><c- p>.</c-><c- n>receiver</c-><c- p>),</c->
                                              <c- n>std</c-><c- o>::</c-><c- n>error_code</c-><c- p>(</c-><c- n>errorCode</c-><c- p>,</c-> <c- n>std</c-><c- o>::</c-><c- n>system_category</c-><c- p>()));</c->
                <c- p>}</c->
            <c- p>}</c->
        <c- p>}</c->
    <c- p>}</c->

    <c- k>struct</c-> <c- nc>cancel_cb</c-> <c- p>{</c->
        <c- n>recv_op</c-><c- o>&amp;</c-> <c- n>op</c-><c- p>;</c->

        <c- b>void</c-> <c- nf>operator</c-><c- p>()()</c-> <c- n>noexcept</c-> <c- p>{</c->
            <c- n>CancelIoEx</c-><c- p>((</c-><c- n>HANDLE</c-><c- p>)</c-><c- n>op</c-><c- p>.</c-><c- n>sock</c-><c- p>,</c-> <c- p>(</c-><c- n>OVERLAPPED</c-><c- o>*</c-><c- p>)(</c-><c- n>WSAOVERLAPPED</c-><c- o>*</c-><c- p>)</c-><c- o>&amp;</c-><c- n>op</c-><c- p>);</c->
        <c- p>}</c->
    <c- p>};</c->

    <c- k>static</c-> <c- b>void</c-> <c- nf>on_complete</c-><c- p>(</c-><c- n>operation_base</c-><c- o>*</c-> <c- n>op</c-><c- p>,</c-> <c- n>DWORD</c-> <c- n>bytesTransferred</c-><c- p>,</c-> <c- b>int</c-> <c- n>errorCode</c-><c- p>)</c-> <c- n>noexcept</c-> <c- p>{</c->
        <c- n>recv_op</c-><c- o>&amp;</c-> <c- n>self</c-> <c- o>=</c-> <c- o>*</c-><c- n>static_cast</c-><c- o>&lt;</c-><c- n>recv_op</c-><c- o>*></c-><c- p>(</c-><c- n>op</c-><c- p>);</c->

        <c- k>if</c-> <c- p>(</c-><c- n>ready</c-><c- p>.</c-><c- n>load</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>memory_order_acquire</c-><c- p>)</c-> <c- o>||</c->
            <c- n>ready</c-><c- p>.</c-><c- n>exchange</c-><c- p>(</c->true<c- p>,</c-> <c- n>std</c-><c- o>::</c-><c- n>memory_order_acq_rel</c-><c- p>))</c-> <c- p>{</c->
            <c- c1>// Unsubscribe any stop-callback so we know that CancelIoEx() is not accessing 'op'</c->
            <c- c1>// any more</c->
            <c- n>stopCallback</c-><c- p>.</c-><c- n>reset</c-><c- p>();</c->

            <c- k>if</c-> <c- p>(</c-><c- n>errorCode</c-> <c- o>==</c-> <c- mi>0</c-><c- p>)</c-> <c- p>{</c->
                <c- n>std</c-><c- o>::</c-><c- n>execution</c-><c- o>::</c-><c- n>set_value</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>receiver</c-><c- p>),</c-> <c- n>bytesTransferred</c-><c- p>);</c->
            <c- p>}</c-> <c- k>else</c-> <c- p>{</c->
                <c- n>std</c-><c- o>::</c-><c- n>execution</c-><c- o>::</c-><c- n>set_error</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>receiver</c-><c- p>),</c->
                                          <c- n>std</c-><c- o>::</c-><c- n>error_code</c-><c- p>(</c-><c- n>errorCode</c-><c- p>,</c-> <c- n>std</c-><c- o>::</c-><c- n>system_category</c-><c- p>()));</c->
            <c- p>}</c->
        <c- p>}</c->
    <c- p>}</c->

    <c- n>Receiver</c-> <c- n>receiver</c-><c- p>;</c->
    <c- n>SOCKET</c-> <c- n>sock</c-><c- p>;</c->
    <c- n>WSABUF</c-> <c- n>buffer</c-><c- p>;</c->
    <c- n>std</c-><c- o>::</c-><c- n>optional</c-><c- o>&lt;</c-><c- n>typename</c-> <c- n>stop_callback_type_t</c-><c- o>&lt;</c-><c- n>Receiver</c-><c- o>></c->
        <c- o>::</c-><c- n>template</c-> <c- n>callback_type</c-><c- o>&lt;</c-><c- n>cancel_cb</c-><c- o>>></c-> <c- n>stopCallback</c-><c- p>;</c->
    <c- n>std</c-><c- o>::</c-><c- n>atomic</c-><c- o>&lt;</c-><c- b>bool</c-><c- o>></c-> <c- n>ready</c-><c- p>{</c->false<c- p>};</c->
<c- p>};</c->

<c- k>struct</c-> <c- nc>recv_sender</c-> <c- p>{</c->
    <c- n>using</c-> <c- n>sender_concept</c-> <c- o>=</c-> <c- n>std</c-><c- o>::</c-><c- n>execution</c-><c- o>::</c-><c- n>sender_t</c-><c- p>;</c->
    <c- n>SOCKET</c-> <c- n>sock</c-><c- p>;</c->
    <c- b>void</c-><c- o>*</c-> <c- n>data</c-><c- p>;</c->
    <c- b>size_t</c-> <c- n>len</c-><c- p>;</c->

    <c- n>template</c-><c- o>&lt;</c-><c- n>typename</c-> <c- n>Receiver</c-><c- o>></c->
    <c- n>friend</c-> <c- n>recv_op</c-><c- o>&lt;</c-><c- n>Receiver</c-><c- o>></c-> <c- n>tag_invoke</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>execution</c-><c- o>::</c-><c- n>connect_t</c-><c- p>,</c->
                                        <c- k>const</c-> <c- n>recv_sender</c-><c- o>&amp;</c-> <c- n>s</c-><c- p>,</c->
                                        <c- n>Receiver</c-> <c- n>r</c-><c- p>)</c-> <c- p>{</c->
        <c- k>return</c-> <c- n>recv_op</c-><c- o>&lt;</c-><c- n>Receiver</c-><c- o>></c-><c- p>{</c-><c- n>s</c-><c- p>.</c-><c- n>sock</c-><c- p>,</c-> <c- n>s</c-><c- p>.</c-><c- n>data</c-><c- p>,</c-> <c- n>s</c-><c- p>.</c-><c- n>len</c-><c- p>,</c-> <c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>r</c-><c- p>)};</c->
    <c- p>}</c->
<c- p>};</c->

<c- n>recv_sender</c-> <c- nf>async_recv</c-><c- p>(</c-><c- n>SOCKET</c-> <c- n>s</c-><c- p>,</c-> <c- b>void</c-><c- o>*</c-> <c- n>data</c-><c- p>,</c-> <c- b>size_t</c-> <c- n>len</c-><c- p>)</c-> <c- p>{</c->
    <c- k>return</c-> <c- n>recv_sender</c-><c- p>{</c-><c- n>s</c-><c- p>,</c-> <c- n>data</c-><c- p>,</c-> <c- n>len</c-><c- p>};</c->
<c- p>}</c->
</pre>
   <h4 class="heading settled" data-level="1.4.1" id="example-moar"><span class="secno">1.4.1. </span><span class="content">More end-user examples</span><a class="self-link" href="#example-moar"></a></h4>
   <h5 class="heading settled" data-level="1.4.1.1" id="example-sudoku"><span class="secno">1.4.1.1. </span><span class="content">Sudoku solver</span><a class="self-link" href="#example-sudoku"></a></h5>
   <p>This example comes from Kirk Shoop, who ported an example from TBB’s documentation to sender/receiver in his fork of the libunifex repo. It is a Sudoku solver that uses a configurable number of threads to explore the search space for solutions.</p>
   <p>The sender/receiver-based Sudoku solver can be found <a href="https://github.com/kirkshoop/libunifex/blob/sudoku/examples/sudoku.cpp">here</a>. Some things that are worth noting about Kirk’s solution:</p>
   <ol>
    <li data-md>
     <p>Although it schedules asychronous work onto a thread pool, and each unit of work will schedule more work, its use of structured concurrency patterns make reference counting unnecessary. The solution does not make use of <code class="highlight"><c- n>shared_ptr</c-></code>.</p>
    <li data-md>
     <p>In addition to eliminating the need for reference counting, the use of structured concurrency makes it easy to ensure that resources are cleaned up on all code paths. In contrast, the TBB example that inspired this one <a href="https://github.com/oneapi-src/oneTBB/issues/568">leaks memory</a>.</p>
   </ol>
   <p>For comparison, the TBB-based Sudoku solver can be found <a href="https://github.com/oneapi-src/oneTBB/blob/40a9a1060069d37d5f66912c6ee4cf165144774b/examples/task_group/sudoku/sudoku.cpp">here</a>.</p>
   <h5 class="heading settled" data-level="1.4.1.2" id="example-file-copy"><span class="secno">1.4.1.2. </span><span class="content">File copy</span><a class="self-link" href="#example-file-copy"></a></h5>
   <p>This example also comes from Kirk Shoop which uses sender/receiver to recursively copy the files a directory tree. It demonstrates how sender/receiver can be used to do IO, using a scheduler that schedules work on Linux’s io_uring.</p>
   <p>As with the Sudoku example, this example obviates the need for reference counting by employing structured concurrency. It uses iteration with an upper limit to avoid having too many open file handles.</p>
   <p>You can find the example <a href="https://github.com/kirkshoop/libunifex/blob/filecopy/examples/file_copy.cpp">here</a>.</p>
   <h5 class="heading settled" data-level="1.4.1.3" id="example-echo-server"><span class="secno">1.4.1.3. </span><span class="content">Echo server</span><a class="self-link" href="#example-echo-server"></a></h5>
   <p>Dietmar Kuehl has a hobby project that implements networking APIs on top of sender/receiver. He recently implemented an echo server as a demo. His echo server code can be found <a href="https://github.com/dietmarkuehl/kuhllib/blob/main/src/examples/echo_server.cpp">here</a>.</p>
   <p>Below, I show the part of the echo server code. This code is executed for each client that connects to the echo server. In a loop, it reads input from a socket and echos the input back to the same socket. All of this, including the loop, is implemented with generic async algorithms.</p>
<pre class="highlight"><c- n>outstanding</c-><c- p>.</c-><c- n>start</c-><c- p>(</c->
    <c- n>EX</c-><c- o>::</c-><c- n>repeat_effect_until</c-><c- p>(</c->
          <c- n>EX</c-><c- o>::</c-><c- n>let_value</c-><c- p>(</c->
              <c- n>NN</c-><c- o>::</c-><c- n>async_read_some</c-><c- p>(</c-><c- n>ptr</c-><c- o>-></c-><c- n>d_socket</c-><c- p>,</c->
                                  <c- n>context</c-><c- p>.</c-><c- n>scheduler</c-><c- p>(),</c->
                                  <c- n>NN</c-><c- o>::</c-><c- n>buffer</c-><c- p>(</c-><c- n>ptr</c-><c- o>-></c-><c- n>d_buffer</c-><c- p>))</c->
        <c- o>|</c-> <c- n>EX</c-><c- o>::</c-><c- n>then</c-><c- p>([</c-><c- n>ptr</c-><c- p>](</c-><c- o>::</c-><c- n>std</c-><c- o>::</c-><c- b>size_t</c-> <c- n>n</c-><c- p>){</c->
            <c- o>::</c-><c- n>std</c-><c- o>::</c-><c- n>cout</c-> <c- o>&lt;&lt;</c-> <c- s>"read='"</c-> <c- o>&lt;&lt;</c-> <c- o>::</c-><c- n>std</c-><c- o>::</c-><c- n>string_view</c-><c- p>(</c-><c- n>ptr</c-><c- o>-></c-><c- n>d_buffer</c-><c- p>,</c-> <c- n>n</c-><c- p>)</c-> <c- o>&lt;&lt;</c-> <c- s>"'</c-><c- se>\n</c-><c- s>"</c-><c- p>;</c->
            <c- n>ptr</c-><c- o>-></c-><c- n>d_done</c-> <c- o>=</c-> <c- n>n</c-> <c- o>==</c-> <c- mi>0</c-><c- p>;</c->
            <c- k>return</c-> <c- n>n</c-><c- p>;</c->
        <c- p>}),</c->
          <c- p>[</c-><c- o>&amp;</c-><c- n>context</c-><c- p>,</c-> <c- n>ptr</c-><c- p>](</c-><c- o>::</c-><c- n>std</c-><c- o>::</c-><c- b>size_t</c-> <c- n>n</c-><c- p>){</c->
            <c- k>return</c-> <c- n>NN</c-><c- o>::</c-><c- n>async_write_some</c-><c- p>(</c-><c- n>ptr</c-><c- o>-></c-><c- n>d_socket</c-><c- p>,</c->
                                        <c- n>context</c-><c- p>.</c-><c- n>scheduler</c-><c- p>(),</c->
                                        <c- n>NN</c-><c- o>::</c-><c- n>buffer</c-><c- p>(</c-><c- n>ptr</c-><c- o>-></c-><c- n>d_buffer</c-><c- p>,</c-> <c- n>n</c-><c- p>));</c->
          <c- p>})</c->
        <c- o>|</c-> <c- n>EX</c-><c- o>::</c-><c- n>then</c-><c- p>([](</c-><c- k>auto</c-><c- o>&amp;&amp;</c-><c- p>...){})</c->
        <c- p>,</c-> <c- p>[</c-><c- n>owner</c-> <c- o>=</c-> <c- o>::</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>owner</c-><c- p>)]{</c-> <c- k>return</c-> <c- n>owner</c-><c- o>-></c-><c- n>d_done</c-><c- p>;</c-> <c- p>}</c->
    <c- p>)</c->
<c- p>);</c->
</pre>
   <p>In this code, <code class="highlight"><c- n>NN</c-><c- o>::</c-><c- n>async_read_some</c-></code> and <code class="highlight"><c- n>NN</c-><c- o>::</c-><c- n>async_write_some</c-></code> are asynchronous socket-based networking APIs that return senders. <code class="highlight"><c- n>EX</c-><c- o>::</c-><c- n>repeat_effect_until</c-></code>, <code class="highlight"><c- n>EX</c-><c- o>::</c-><c- n>let_value</c-></code>, and <code class="highlight"><c- n>EX</c-><c- o>::</c-><c- n>then</c-></code> are fully generic sender adaptor algorithms that accept and return senders.</p>
   <p>This is a good example of seamless composition of async IO functions with non-IO operations. And by composing the senders in this structured way, all the state for the composite operation -- the <code class="highlight"><c- n>repeat_effect_until</c-></code> expression and all its child operations -- is stored altogether in a single object.</p>
   <h3 class="heading settled" data-level="1.5" id="example-algorithm"><span class="secno">1.5. </span><span class="content">Examples: Algorithms</span><a class="self-link" href="#example-algorithm"></a></h3>
   <p>In this section we show a few simple sender/receiver-based algorithm implementations.</p>
   <h4 class="heading settled" data-level="1.5.1" id="example-then"><span class="secno">1.5.1. </span><span class="content"><code class="highlight"><c- n>then</c-></code></span><a class="self-link" href="#example-then"></a></h4>
<pre class="language-c++ highlight"><c- n>namespace</c-> <c- n>exec</c-> <c- o>=</c-> <c- n>std</c-><c- o>::</c-><c- n>execution</c-><c- p>;</c->

<c- n>template</c-><c- o>&lt;</c-><c- n>class</c-> <c- n>R</c-><c- p>,</c-> <c- n>class</c-> <c- n>F</c-><c- o>></c->
<c- n>class</c-> <c- n>_then_receiver</c->
    <c- o>:</c-> <c- n>exec</c-><c- o>::</c-><c- n>receiver_adaptor</c-><c- o>&lt;</c-><c- n>_then_receiver</c-><c- o>&lt;</c-><c- n>R</c-><c- p>,</c-> <c- n>F</c-><c- o>></c-><c- p>,</c-> <c- n>R</c-><c- o>></c-> <c- p>{</c->
  <c- n>friend</c-> <c- n>exec</c-><c- o>::</c-><c- n>receiver_adaptor</c-><c- o>&lt;</c-><c- n>_then_receiver</c-><c- p>,</c-> <c- n>R</c-><c- o>></c-><c- p>;</c->
  <c- n>F</c-> <c- n>f_</c-><c- p>;</c->

  <c- c1>// Customize set_value by invoking the callable and passing the result to the inner receiver</c->
  <c- n>template</c-><c- o>&lt;</c-><c- n>class</c-><c- p>...</c-> <c- n>As</c-><c- o>></c->
  <c- b>void</c-> <c- n>set_value</c-><c- p>(</c-><c- n>As</c-><c- o>&amp;&amp;</c-><c- p>...</c-> <c- n>as</c-><c- p>)</c-> <c- o>&amp;&amp;</c-> <c- n>noexcept</c-> <c- n>try</c-> <c- p>{</c->
    <c- n>exec</c-><c- o>::</c-><c- n>set_value</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- o>*</c-><c- n>this</c-><c- p>).</c-><c- n>base</c-><c- p>(),</c-> <c- n>std</c-><c- o>::</c-><c- n>invoke</c-><c- p>((</c-><c- n>F</c-><c- o>&amp;&amp;</c-><c- p>)</c-> <c- n>f_</c-><c- p>,</c-> <c- p>(</c-><c- n>As</c-><c- o>&amp;&amp;</c-><c- p>)</c-> <c- n>as</c-><c- p>...));</c->
  <c- p>}</c-> <c- n>catch</c-><c- p>(...)</c-> <c- p>{</c->
    <c- n>exec</c-><c- o>::</c-><c- n>set_error</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- o>*</c-><c- n>this</c-><c- p>).</c-><c- n>base</c-><c- p>(),</c-> <c- n>std</c-><c- o>::</c-><c- n>current_exception</c-><c- p>());</c->
  <c- p>}</c->

 <c- n>public</c-><c- o>:</c->
  <c- n>_then_receiver</c-><c- p>(</c-><c- n>R</c-> <c- n>r</c-><c- p>,</c-> <c- n>F</c-> <c- n>f</c-><c- p>)</c->
   <c- o>:</c-> <c- n>exec</c-><c- o>::</c-><c- n>receiver_adaptor</c-><c- o>&lt;</c-><c- n>_then_receiver</c-><c- p>,</c-> <c- n>R</c-><c- o>></c-><c- p>{</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>r</c-><c- p>)}</c->
   <c- p>,</c-> <c- n>f_</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>f</c-><c- p>))</c-> <c- p>{}</c->
<c- p>};</c->

<c- n>template</c-><c- o>&lt;</c-><c- n>exec</c-><c- o>::</c-><c- n>sender</c-> <c- n>S</c-><c- p>,</c-> <c- n>class</c-> <c- n>F</c-><c- o>></c->
<c- k>struct</c-> <c- nc>_then_sender</c-> <c- p>{</c->
  <c- n>using</c-> <c- n>sender_concept</c-> <c- o>=</c-> <c- n>exec</c-><c- o>::</c-><c- n>sender_t</c-><c- p>;</c->
  <c- n>S</c-> <c- n>s_</c-><c- p>;</c->
  <c- n>F</c-> <c- n>f_</c-><c- p>;</c->

  <c- n>template</c-> <c- o>&lt;</c-><c- n>class</c-><c- p>...</c-> <c- n>Args</c-><c- o>></c->
    <c- n>using</c-> <c- n>_set_value_t</c-> <c- o>=</c-> <c- n>exec</c-><c- o>::</c-><c- n>completion_signatures</c-><c- o>&lt;</c->
      <c- n>exec</c-><c- o>::</c-><c- n>set_value_t</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>invoke_result_t</c-><c- o>&lt;</c-><c- n>F</c-><c- p>,</c-> <c- n>Args</c-><c- p>...</c-><c- o>></c-><c- p>)</c-><c- o>></c-><c- p>;</c->

  <c- c1>// Compute the completion signatures</c->
  <c- n>template</c-><c- o>&lt;</c-><c- n>class</c-> <c- n>Env</c-><c- o>></c->
  <c- n>friend</c-> <c- k>auto</c-> <c- n>tag_invoke</c-><c- p>(</c-><c- n>exec</c-><c- o>::</c-><c- n>get_completion_signatures_t</c-><c- p>,</c-> <c- n>_then_sender</c-><c- o>&amp;&amp;</c-><c- p>,</c-> <c- n>Env</c-><c- p>)</c->
    <c- o>-></c-> <c- n>exec</c-><c- o>::</c-><c- n>transform_completion_signatures_of</c-><c- o>&lt;</c-><c- n>S</c-><c- p>,</c-> <c- n>Env</c-><c- p>,</c->
        <c- n>exec</c-><c- o>::</c-><c- n>completion_signatures</c-><c- o>&lt;</c-><c- n>exec</c-><c- o>::</c-><c- n>set_error_t</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>exception_ptr</c-><c- p>)</c-><c- o>></c-><c- p>,</c->
        <c- n>_set_value_t</c-><c- o>></c-><c- p>;</c->

  <c- c1>// Connect:</c->
  <c- n>template</c-><c- o>&lt;</c-><c- n>exec</c-><c- o>::</c-><c- n>receiver</c-> <c- n>R</c-><c- o>></c->
  <c- n>friend</c-> <c- k>auto</c-> <c- n>tag_invoke</c-><c- p>(</c-><c- n>exec</c-><c- o>::</c-><c- n>connect_t</c-><c- p>,</c-> <c- n>_then_sender</c-><c- o>&amp;&amp;</c-> <c- n>self</c-><c- p>,</c-> <c- n>R</c-> <c- n>r</c-><c- p>)</c->
    <c- o>-></c-> <c- n>exec</c-><c- o>::</c-><c- n>connect_result_t</c-><c- o>&lt;</c-><c- n>S</c-><c- p>,</c-> <c- n>_then_receiver</c-><c- o>&lt;</c-><c- n>R</c-><c- p>,</c-> <c- n>F</c-><c- o>>></c-> <c- p>{</c->
      <c- k>return</c-> <c- n>exec</c-><c- o>::</c-><c- n>connect</c-><c- p>(</c->
        <c- p>(</c-><c- n>S</c-><c- o>&amp;&amp;</c-><c- p>)</c-> <c- n>self</c-><c- p>.</c-><c- n>s_</c-><c- p>,</c-> <c- n>_then_receiver</c-><c- o>&lt;</c-><c- n>R</c-><c- p>,</c-> <c- n>F</c-><c- o>></c-><c- p>{(</c-><c- n>R</c-><c- o>&amp;&amp;</c-><c- p>)</c-> <c- n>r</c-><c- p>,</c-> <c- p>(</c-><c- n>F</c-><c- o>&amp;&amp;</c-><c- p>)</c-> <c- n>self</c-><c- p>.</c-><c- n>f_</c-><c- p>});</c->
  <c- p>}</c->

  <c- n>friend</c-> <c- n>decltype</c-><c- p>(</c-><c- k>auto</c-><c- p>)</c-> <c- n>tag_invoke</c-><c- p>(</c-><c- n>get_env_t</c-><c- p>,</c-> <c- k>const</c-> <c- n>_then_sender</c-><c- o>&amp;</c-> <c- n>self</c-><c- p>)</c-> <c- n>noexcept</c-> <c- p>{</c->
    <c- k>return</c-> <c- n>get_env</c-><c- p>(</c-><c- n>self</c-><c- p>.</c-><c- n>s_</c-><c- p>);</c->
  <c- p>}</c->
<c- p>};</c->

<c- n>template</c-><c- o>&lt;</c-><c- n>exec</c-><c- o>::</c-><c- n>sender</c-> <c- n>S</c-><c- p>,</c-> <c- n>class</c-> <c- n>F</c-><c- o>></c->
<c- n>exec</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>then</c-><c- p>(</c-><c- n>S</c-> <c- n>s</c-><c- p>,</c-> <c- n>F</c-> <c- n>f</c-><c- p>)</c-> <c- p>{</c->
  <c- k>return</c-> <c- n>_then_sender</c-><c- o>&lt;</c-><c- n>S</c-><c- p>,</c-> <c- n>F</c-><c- o>></c-><c- p>{(</c-><c- n>S</c-><c- o>&amp;&amp;</c-><c- p>)</c-> <c- n>s</c-><c- p>,</c-> <c- p>(</c-><c- n>F</c-><c- o>&amp;&amp;</c-><c- p>)</c-> <c- n>f</c-><c- p>};</c->
<c- p>}</c->
</pre>
   <p>This code builds a <code class="highlight"><c- n>then</c-></code> algorithm that transforms the value(s) from the input sender
with a transformation function. The result of the transformation becomes the new value.
The other receiver functions (<code class="highlight"><c- n>set_error</c-></code> and <code class="highlight"><c- n>set_stopped</c-></code>), as well as all receiver queries,
are passed through unchanged.</p>
   <p>In detail, it does the following:</p>
   <ol>
    <li data-md>
     <p>Defines a receiver in terms of <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>receiver_adaptor</c-></code> that aggregates
another receiver and an invocable that:</p>
     <ul>
      <li data-md>
       <p>Defines a constrained <code class="highlight"><c- n>tag_invoke</c-></code> overload for transforming the value
channel.</p>
      <li data-md>
       <p>Defines another constrained overload of <code class="highlight"><c- n>tag_invoke</c-></code> that passes all other
customizations through unchanged.</p>
     </ul>
     <p>The <code class="highlight"><c- n>tag_invoke</c-></code> overloads are actually implemented by <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>receiver_adaptor</c-></code>; they dispatch either to named members, as
shown above with <code class="highlight"><c- n>_then_receiver</c-><c- o>::</c-><c- n>set_value</c-></code>, or to the adapted receiver.</p>
    <li data-md>
     <p>Defines a sender that aggregates another sender and the invocable, which defines a <code class="highlight"><c- n>tag_invoke</c-></code> customization for <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>execution</c-><c- o>::</c-><c- n>connect</c-></code> that wraps the incoming receiver in the receiver from (1) and passes it and the incoming sender to <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>execution</c-><c- o>::</c-><c- n>connect</c-></code>, returning the result. It also defines a <code class="highlight"><c- n>tag_invoke</c-></code> customization of <code class="highlight"><c- n>get_completion_signatures</c-></code> that declares the sender’s completion signatures when executed within a particular environment.</p>
   </ol>
   <h4 class="heading settled" data-level="1.5.2" id="example-retry"><span class="secno">1.5.2. </span><span class="content"><code class="highlight"><c- n>retry</c-></code></span><a class="self-link" href="#example-retry"></a></h4>
<pre class="language-c++ highlight"><c- n>using</c-> <c- n>namespace</c-> <c- n>std</c-><c- p>;</c->
<c- n>namespace</c-> <c- n>exec</c-> <c- o>=</c-> <c- n>execution</c-><c- p>;</c->

<c- n>template</c-> <c- o>&lt;</c-><c- n>class</c-> <c- n>From</c-><c- p>,</c-> <c- n>class</c-> <c- n>To</c-><c- o>></c->
<c- n>concept</c-> <c- n>_decays_to</c-> <c- o>=</c-> <c- n>same_as</c-><c- o>&lt;</c-><c- n>decay_t</c-><c- o>&lt;</c-><c- n>From</c-><c- o>></c-><c- p>,</c-> <c- n>To</c-><c- o>></c-><c- p>;</c->

<c- c1>// _conv needed so we can emplace construct non-movable types into</c->
<c- c1>// a std::optional.</c->
<c- n>template</c-><c- o>&lt;</c-><c- n>invocable</c-> <c- n>F</c-><c- o>></c->
  <c- n>requires</c-> <c- n>is_nothrow_move_constructible_v</c-><c- o>&lt;</c-><c- n>F</c-><c- o>></c->
<c- k>struct</c-> <c- nc>_conv</c-> <c- p>{</c->
  <c- n>F</c-> <c- n>f_</c-><c- p>;</c->
  <c- n>explicit</c-> <c- nf>_conv</c-><c- p>(</c-><c- n>F</c-> <c- n>f</c-><c- p>)</c-> <c- nl>noexcept</c-> <c- p>:</c-> <c- n>f_</c-><c- p>((</c-><c- n>F</c-><c- o>&amp;&amp;</c-><c- p>)</c-> <c- n>f</c-><c- p>)</c-> <c- p>{}</c->
  <c- n>operator</c-> <c- n>invoke_result_t</c-><c- o>&lt;</c-><c- n>F</c-><c- o>></c-><c- p>()</c-> <c- o>&amp;&amp;</c-> <c- p>{</c->
    <c- k>return</c-> <c- p>((</c-><c- n>F</c-><c- o>&amp;&amp;</c-><c- p>)</c-> <c- n>f_</c-><c- p>)();</c->
  <c- p>}</c->
<c- p>};</c->

<c- n>template</c-><c- o>&lt;</c-><c- n>class</c-> <c- n>S</c-><c- p>,</c-> <c- n>class</c-> <c- n>R</c-><c- o>></c->
<c- k>struct</c-> <c- nc>_op</c-><c- p>;</c->

<c- c1>// pass through all customizations except set_error, which retries the operation.</c->
<c- n>template</c-><c- o>&lt;</c-><c- n>class</c-> <c- n>S</c-><c- p>,</c-> <c- n>class</c-> <c- n>R</c-><c- o>></c->
<c- k>struct</c-> <c- nc>_retry_receiver</c->
  <c- o>:</c-> <c- n>exec</c-><c- o>::</c-><c- n>receiver_adaptor</c-><c- o>&lt;</c-><c- n>_retry_receiver</c-><c- o>&lt;</c-><c- n>S</c-><c- p>,</c-> <c- n>R</c-><c- o>>></c-> <c- p>{</c->
  <c- n>_op</c-><c- o>&lt;</c-><c- n>S</c-><c- p>,</c-> <c- n>R</c-><c- o>>*</c-> <c- n>o_</c-><c- p>;</c->

  <c- n>R</c-><c- o>&amp;&amp;</c-> <c- nf>base</c-><c- p>()</c-> <c- o>&amp;&amp;</c-> <c- n>noexcept</c-> <c- p>{</c-> <c- k>return</c-> <c- p>(</c-><c- n>R</c-><c- o>&amp;&amp;</c-><c- p>)</c-> <c- n>o_</c-><c- o>-></c-><c- n>r_</c-><c- p>;</c-> <c- p>}</c->
  <c- k>const</c-> <c- n>R</c-><c- o>&amp;</c-> <c- nf>base</c-><c- p>()</c-> <c- k>const</c-> <c- o>&amp;</c-> <c- n>noexcept</c-> <c- p>{</c-> <c- k>return</c-> <c- n>o_</c-><c- o>-></c-><c- n>r_</c-><c- p>;</c-> <c- p>}</c->

  <c- n>explicit</c-> <c- nf>_retry_receiver</c-><c- p>(</c-><c- n>_op</c-><c- o>&lt;</c-><c- n>S</c-><c- p>,</c-> <c- n>R</c-><c- o>>*</c-> <c- n>o</c-><c- p>)</c-> <c- o>:</c-> <c- n>o_</c-><c- p>(</c-><c- n>o</c-><c- p>)</c-> <c- p>{}</c->

  <c- b>void</c-> <c- nf>set_error</c-><c- p>(</c-><c- k>auto</c-><c- o>&amp;&amp;</c-><c- p>)</c-> <c- o>&amp;&amp;</c-> <c- n>noexcept</c-> <c- p>{</c->
    <c- n>o_</c-><c- o>-></c-><c- n>_retry</c-><c- p>();</c-> <c- c1>// This causes the op to be retried</c->
  <c- p>}</c->
<c- p>};</c->

<c- c1>// Hold the nested operation state in an optional so we can</c->
<c- c1>// re-construct and re-start it if the operation fails.</c->
<c- n>template</c-><c- o>&lt;</c-><c- n>class</c-> <c- n>S</c-><c- p>,</c-> <c- n>class</c-> <c- n>R</c-><c- o>></c->
<c- k>struct</c-> <c- nc>_op</c-> <c- p>{</c->
  <c- n>S</c-> <c- n>s_</c-><c- p>;</c->
  <c- n>R</c-> <c- n>r_</c-><c- p>;</c->
  <c- n>optional</c-><c- o>&lt;</c->
      <c- n>exec</c-><c- o>::</c-><c- n>connect_result_t</c-><c- o>&lt;</c-><c- n>S</c-><c- o>&amp;</c-><c- p>,</c-> <c- n>_retry_receiver</c-><c- o>&lt;</c-><c- n>S</c-><c- p>,</c-> <c- n>R</c-><c- o>>>></c-> <c- n>o_</c-><c- p>;</c->

  <c- n>_op</c-><c- p>(</c-><c- n>S</c-> <c- n>s</c-><c- p>,</c-> <c- n>R</c-> <c- n>r</c-><c- p>)</c-><c- o>:</c-> <c- n>s_</c-><c- p>((</c-><c- n>S</c-><c- o>&amp;&amp;</c-><c- p>)</c-><c- n>s</c-><c- p>),</c-> <c- n>r_</c-><c- p>((</c-><c- n>R</c-><c- o>&amp;&amp;</c-><c- p>)</c-><c- n>r</c-><c- p>),</c-> <c- n>o_</c-><c- p>{</c-><c- n>_connect</c-><c- p>()}</c-> <c- p>{}</c->
  <c- n>_op</c-><c- p>(</c-><c- n>_op</c-><c- o>&amp;&amp;</c-><c- p>)</c-> <c- o>=</c-> <c- n>delete</c-><c- p>;</c->

  <c- k>auto</c-> <c- n>_connect</c-><c- p>()</c-> <c- n>noexcept</c-> <c- p>{</c->
    <c- k>return</c-> <c- n>_conv</c-><c- p>{[</c-><c- n>this</c-><c- p>]</c-> <c- p>{</c->
      <c- k>return</c-> <c- n>exec</c-><c- o>::</c-><c- n>connect</c-><c- p>(</c-><c- n>s_</c-><c- p>,</c-> <c- n>_retry_receiver</c-><c- o>&lt;</c-><c- n>S</c-><c- p>,</c-> <c- n>R</c-><c- o>></c-><c- p>{</c-><c- n>this</c-><c- p>});</c->
    <c- p>}};</c->
  <c- p>}</c->
  <c- b>void</c-> <c- n>_retry</c-><c- p>()</c-> <c- n>noexcept</c-> <c- n>try</c-> <c- p>{</c->
    <c- n>o_</c-><c- p>.</c-><c- n>emplace</c-><c- p>(</c-><c- n>_connect</c-><c- p>());</c-> <c- c1>// potentially-throwing</c->
    <c- n>exec</c-><c- o>::</c-><c- n>start</c-><c- p>(</c-><c- o>*</c-><c- n>o_</c-><c- p>);</c->
  <c- p>}</c-> <c- n>catch</c-><c- p>(...)</c-> <c- p>{</c->
    <c- n>exec</c-><c- o>::</c-><c- n>set_error</c-><c- p>((</c-><c- n>R</c-><c- o>&amp;&amp;</c-><c- p>)</c-> <c- n>r_</c-><c- p>,</c-> <c- n>std</c-><c- o>::</c-><c- n>current_exception</c-><c- p>());</c->
  <c- p>}</c->
  <c- n>friend</c-> <c- b>void</c-> <c- n>tag_invoke</c-><c- p>(</c-><c- n>exec</c-><c- o>::</c-><c- n>start_t</c-><c- p>,</c-> <c- n>_op</c-><c- o>&amp;</c-> <c- n>o</c-><c- p>)</c-> <c- n>noexcept</c-> <c- p>{</c->
    <c- n>exec</c-><c- o>::</c-><c- n>start</c-><c- p>(</c-><c- o>*</c-><c- n>o</c-><c- p>.</c-><c- n>o_</c-><c- p>);</c->
  <c- p>}</c->
<c- p>};</c->

<c- n>template</c-><c- o>&lt;</c-><c- n>class</c-> <c- n>S</c-><c- o>></c->
<c- k>struct</c-> <c- nc>_retry_sender</c-> <c- p>{</c->
  <c- n>using</c-> <c- n>sender_concept</c-> <c- o>=</c-> <c- n>exec</c-><c- o>::</c-><c- n>sender_t</c-><c- p>;</c->
  <c- n>S</c-> <c- n>s_</c-><c- p>;</c->
  <c- n>explicit</c-> <c- nf>_retry_sender</c-><c- p>(</c-><c- n>S</c-> <c- n>s</c-><c- p>)</c-> <c- o>:</c-> <c- n>s_</c-><c- p>((</c-><c- n>S</c-><c- o>&amp;&amp;</c-><c- p>)</c-> <c- n>s</c-><c- p>)</c-> <c- p>{}</c->

  <c- n>template</c-> <c- o>&lt;</c-><c- n>class</c-><c- p>...</c-> <c- n>Ts</c-><c- o>></c->
    <c- n>using</c-> <c- n>_value_t</c-> <c- o>=</c->
      <c- n>exec</c-><c- o>::</c-><c- n>completion_signatures</c-><c- o>&lt;</c-><c- n>exec</c-><c- o>::</c-><c- n>set_value_t</c-><c- p>(</c-><c- n>Ts</c-><c- p>...)</c-><c- o>></c-><c- p>;</c->
  <c- n>template</c-> <c- o>&lt;</c-><c- n>class</c-><c- o>></c->
    <c- n>using</c-> <c- n>_error_t</c-> <c- o>=</c-> <c- n>exec</c-><c- o>::</c-><c- n>completion_signatures</c-><c- o>&lt;></c-><c- p>;</c->

  <c- c1>// Declare the signatures with which this sender can complete</c->
  <c- n>template</c-> <c- o>&lt;</c-><c- n>class</c-> <c- n>Env</c-><c- o>></c->
  <c- n>friend</c-> <c- k>auto</c-> <c- n>tag_invoke</c-><c- p>(</c-><c- n>exec</c-><c- o>::</c-><c- n>get_completion_signatures_t</c-><c- p>,</c-> <c- k>const</c-> <c- n>_retry_sender</c-><c- o>&amp;</c-><c- p>,</c-> <c- n>Env</c-><c- p>)</c->
    <c- o>-></c-> <c- n>exec</c-><c- o>::</c-><c- n>transform_completion_signatures_of</c-><c- o>&lt;</c-><c- n>S</c-><c- o>&amp;</c-><c- p>,</c-> <c- n>Env</c-><c- p>,</c->
        <c- n>exec</c-><c- o>::</c-><c- n>completion_signatures</c-><c- o>&lt;</c-><c- n>exec</c-><c- o>::</c-><c- n>set_error_t</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>exception_ptr</c-><c- p>)</c-><c- o>></c-><c- p>,</c->
        <c- n>_value_t</c-><c- p>,</c-> <c- n>_error_t</c-><c- o>></c-><c- p>;</c->

  <c- n>template</c-><c- o>&lt;</c-><c- n>exec</c-><c- o>::</c-><c- n>receiver</c-> <c- n>R</c-><c- o>></c->
  <c- n>friend</c-> <c- n>_op</c-><c- o>&lt;</c-><c- n>S</c-><c- p>,</c-> <c- n>R</c-><c- o>></c-> <c- n>tag_invoke</c-><c- p>(</c-><c- n>exec</c-><c- o>::</c-><c- n>connect_t</c-><c- p>,</c-> <c- n>_retry_sender</c-><c- o>&amp;&amp;</c-> <c- n>self</c-><c- p>,</c-> <c- n>R</c-> <c- n>r</c-><c- p>)</c-> <c- p>{</c->
    <c- k>return</c-> <c- p>{(</c-><c- n>S</c-><c- o>&amp;&amp;</c-><c- p>)</c-> <c- n>self</c-><c- p>.</c-><c- n>s_</c-><c- p>,</c-> <c- p>(</c-><c- n>R</c-><c- o>&amp;&amp;</c-><c- p>)</c-> <c- n>r</c-><c- p>};</c->
  <c- p>}</c->

  <c- n>friend</c-> <c- n>decltype</c-><c- p>(</c-><c- k>auto</c-><c- p>)</c-> <c- n>tag_invoke</c-><c- p>(</c-><c- n>exec</c-><c- o>::</c-><c- n>get_env_t</c-><c- p>,</c-> <c- k>const</c-> <c- n>_retry_sender</c-><c- o>&amp;</c-> <c- n>self</c-><c- p>)</c-> <c- n>noexcept</c-> <c- p>{</c->
    <c- k>return</c-> <c- n>get_env</c-><c- p>(</c-><c- n>self</c-><c- p>.</c-><c- n>s_</c-><c- p>);</c->
  <c- p>}</c->
<c- p>};</c->

<c- n>template</c-><c- o>&lt;</c-><c- n>exec</c-><c- o>::</c-><c- n>sender</c-> <c- n>S</c-><c- o>></c->
<c- n>exec</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>retry</c-><c- p>(</c-><c- n>S</c-> <c- n>s</c-><c- p>)</c-> <c- p>{</c->
  <c- k>return</c-> <c- n>_retry_sender</c-><c- p>{(</c-><c- n>S</c-><c- o>&amp;&amp;</c-><c- p>)</c-> <c- n>s</c-><c- p>};</c->
<c- p>}</c->
</pre>
   <p>The <code class="highlight"><c- n>retry</c-></code> algorithm takes a multi-shot sender and causes it to repeat on error, passing
through values and stopped signals. Each time the input sender is restarted, a new receiver
is connected and the resulting operation state is stored in an <code class="highlight"><c- n>optional</c-></code>, which allows us
to reinitialize it multiple times.</p>
   <p>This example does the following:</p>
   <ol>
    <li data-md>
     <p>Defines a <code class="highlight"><c- n>_conv</c-></code> utility that takes advantage of C++17’s guaranteed copy elision to
emplace a non-movable type in a <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>optional</c-></code>.</p>
    <li data-md>
     <p>Defines a <code class="highlight"><c- n>_retry_receiver</c-></code> that holds a pointer back to the operation state. It passes
all customizations through unmodified to the inner receiver owned by the operation state
except for <code class="highlight"><c- n>set_error</c-></code>, which causes a <code class="highlight"><c- n>_retry</c-><c- p>()</c-></code> function to be called instead.</p>
    <li data-md>
     <p>Defines an operation state that aggregates the input sender and receiver, and declares
storage for the nested operation state in an <code class="highlight"><c- n>optional</c-></code>. Constructing the operation
state constructs a <code class="highlight"><c- n>_retry_receiver</c-></code> with a pointer to the (under construction) operation
state and uses it to connect to the aggregated sender.</p>
    <li data-md>
     <p>Starting the operation state dispatches to <code class="highlight"><c- n>start</c-></code> on the inner operation state.</p>
    <li data-md>
     <p>The <code class="highlight"><c- n>_retry</c-><c- p>()</c-></code> function reinitializes the inner operation state by connecting the sender
to a new receiver, holding a pointer back to the outer operation state as before.</p>
    <li data-md>
     <p>After reinitializing the inner operation state, <code class="highlight"><c- n>_retry</c-><c- p>()</c-></code> calls <code class="highlight"><c- n>start</c-></code> on it, causing
the failed operation to be rescheduled.</p>
    <li data-md>
     <p>Defines a <code class="highlight"><c- n>_retry_sender</c-></code> that implements the <code class="highlight"><c- n>connect</c-></code> customization point to return
an operation state constructed from the passed-in sender and receiver.</p>
    <li data-md>
     <p><code class="highlight"><c- n>_retry_sender</c-></code> also implements the <code class="highlight"><c- n>get_completion_signatures</c-></code> customization point to describe the ways this sender may complete when executed in a particular execution resource.</p>
   </ol>
   <h3 class="heading settled" data-level="1.6" id="example-schedulers"><span class="secno">1.6. </span><span class="content">Examples: Schedulers</span><a class="self-link" href="#example-schedulers"></a></h3>
   <p>In this section we look at some schedulers of varying complexity.</p>
   <h4 class="heading settled" data-level="1.6.1" id="example-schedulers-inline"><span class="secno">1.6.1. </span><span class="content">Inline scheduler</span><a class="self-link" href="#example-schedulers-inline"></a></h4>
<pre class="language-c++ highlight"><c- n>class</c-> <c- n>inline_scheduler</c-> <c- p>{</c->
  <c- n>template</c-> <c- o>&lt;</c-><c- n>class</c-> <c- n>R</c-><c- o>></c->
    <c- k>struct</c-> <c- nc>_op</c-> <c- p>{</c->
      <c- p>[[</c-><c- n>no_unique_address</c-><c- p>]]</c-> <c- n>R</c-> <c- n>rec_</c-><c- p>;</c->
      <c- n>friend</c-> <c- b>void</c-> <c- n>tag_invoke</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>execution</c-><c- o>::</c-><c- n>start_t</c-><c- p>,</c-> <c- n>_op</c-><c- o>&amp;</c-> <c- n>op</c-><c- p>)</c-> <c- n>noexcept</c-> <c- p>{</c->
        <c- n>std</c-><c- o>::</c-><c- n>execution</c-><c- o>::</c-><c- n>set_value</c-><c- p>((</c-><c- n>R</c-><c- o>&amp;&amp;</c-><c- p>)</c-> <c- n>op</c-><c- p>.</c-><c- n>rec_</c-><c- p>);</c->
      <c- p>}</c->
    <c- p>};</c->

  <c- k>struct</c-> <c- nc>_env</c-> <c- p>{</c->
    <c- n>template</c-> <c- o>&lt;</c-><c- n>class</c-> <c- n>Tag</c-><c- o>></c->
      <c- n>friend</c-> <c- n>inline_scheduler</c-> <c- n>tag_invoke</c-><c- p>(</c->
          <c- n>std</c-><c- o>::</c-><c- n>execution</c-><c- o>::</c-><c- n>get_completion_scheduler_t</c-><c- o>&lt;</c-><c- n>Tag</c-><c- o>></c-><c- p>,</c-> <c- n>_env</c-><c- p>)</c-> <c- n>noexcept</c-> <c- p>{</c->
        <c- k>return</c-> <c- p>{};</c->
      <c- p>}</c->
  <c- p>};</c->

  <c- k>struct</c-> <c- nc>_sender</c-> <c- p>{</c->
    <c- n>using</c-> <c- n>sender_concept</c-> <c- o>=</c-> <c- n>std</c-><c- o>::</c-><c- n>execution</c-><c- o>::</c-><c- n>sender_t</c-><c- p>;</c->
    <c- n>using</c-> <c- n>completion_signatures</c-> <c- o>=</c->
      <c- n>std</c-><c- o>::</c-><c- n>execution</c-><c- o>::</c-><c- n>completion_signatures</c-><c- o>&lt;</c-><c- n>std</c-><c- o>::</c-><c- n>execution</c-><c- o>::</c-><c- n>set_value_t</c-><c- p>()</c-><c- o>></c-><c- p>;</c->

    <c- n>template</c-> <c- o>&lt;</c-><c- n>class</c-> <c- n>R</c-><c- o>></c->
      <c- n>friend</c-> <c- k>auto</c-> <c- n>tag_invoke</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>execution</c-><c- o>::</c-><c- n>connect_t</c-><c- p>,</c-> <c- n>_sender</c-><c- p>,</c-> <c- n>R</c-><c- o>&amp;&amp;</c-> <c- n>rec</c-><c- p>)</c->
        <c- n>noexcept</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>is_nothrow_constructible_v</c-><c- o>&lt;</c-><c- n>std</c-><c- o>::</c-><c- n>remove_cvref_t</c-><c- o>&lt;</c-><c- n>R</c-><c- o>></c-><c- p>,</c-> <c- n>R</c-><c- o>></c-><c- p>)</c->
        <c- o>-></c-> <c- n>_op</c-><c- o>&lt;</c-><c- n>std</c-><c- o>::</c-><c- n>remove_cvref_t</c-><c- o>&lt;</c-><c- n>R</c-><c- o>>></c-> <c- p>{</c->
        <c- k>return</c-> <c- p>{(</c-><c- n>R</c-><c- o>&amp;&amp;</c-><c- p>)</c-> <c- n>rec</c-><c- p>};</c->
      <c- p>}</c->

    <c- n>friend</c-> <c- n>_env</c-> <c- n>tag_invoke</c-><c- p>(</c-><c- n>exec</c-><c- o>::</c-><c- n>get_env_t</c-><c- p>,</c-> <c- n>_sender</c-><c- p>)</c-> <c- n>noexcept</c-> <c- p>{</c->
      <c- k>return</c-> <c- p>{};</c->
    <c- p>}</c->
  <c- p>};</c->

  <c- n>friend</c-> <c- n>_sender</c-> <c- n>tag_invoke</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>execution</c-><c- o>::</c-><c- n>schedule_t</c-><c- p>,</c-> <c- k>const</c-> <c- n>inline_scheduler</c-><c- o>&amp;</c-><c- p>)</c-> <c- n>noexcept</c-> <c- p>{</c->
    <c- k>return</c-> <c- p>{};</c->
  <c- p>}</c->

 <c- n>public</c-><c- o>:</c->
  <c- n>inline_scheduler</c-><c- p>()</c-> <c- o>=</c-> <c- k>default</c-><c- p>;</c->
  <c- b>bool</c-> <c- n>operator</c-><c- o>==</c-><c- p>(</c-><c- k>const</c-> <c- n>inline_scheduler</c-><c- o>&amp;</c-><c- p>)</c-> <c- k>const</c-> <c- n>noexcept</c-> <c- o>=</c-> <c- k>default</c-><c- p>;</c->
<c- p>};</c->
</pre>
   <p>The inline scheduler is a trivial scheduler that completes immediately and synchronously on
the thread that calls <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>execution</c-><c- o>::</c-><c- n>start</c-></code> on the operation state produced by its sender.
In other words, <code class="highlight"><c- n>start</c-><c- p>(</c-><c- n>connect</c-><c- p>(</c-><c- n>schedule</c-><c- p>(</c-><i><c- kr>inline</c-><c- o>-</c-><c- n>scheduler</c-></i><c- p>),</c-> <c- n>receiver</c-><c- p>))</c-></code> is
just a fancy way of saying <code class="highlight"><c- n>set_value</c-><c- p>(</c-><c- n>receiver</c-><c- p>)</c-></code>, with the exception of the fact that <code class="highlight"><c- n>start</c-></code> wants to be passed an lvalue.</p>
   <p>Although not a particularly useful scheduler, it serves to illustrate the basics of
implementing one. The <code class="highlight"><c- n>inline_scheduler</c-></code>:</p>
   <ol>
    <li data-md>
     <p>Customizes <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>schedule</c-></code> to return an instance of the sender type <code class="highlight"><c- n>_sender</c-></code>.</p>
    <li data-md>
     <p>The <code class="highlight"><c- n>_sender</c-></code> type models the <code class="highlight"><c- n>sender</c-></code> concept and provides the metadata
needed to describe it as a sender of no values
and that never calls <code class="highlight"><c- n>set_error</c-></code> or <code class="highlight"><c- n>set_stopped</c-></code>. This
metadata is provided with the help of the <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>completion_signatures</c-></code> utility.</p>
    <li data-md>
     <p>The <code class="highlight"><c- n>_sender</c-></code> type customizes <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>connect</c-></code> to accept a receiver of no
values. It returns an instance of type <code class="highlight"><c- n>_op</c-></code> that holds the receiver by
value.</p>
    <li data-md>
     <p>The operation state customizes <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>execution</c-><c- o>::</c-><c- n>start</c-></code> to call <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>execution</c-><c- o>::</c-><c- n>set_value</c-></code> on the receiver.</p>
   </ol>
   <h4 class="heading settled" data-level="1.6.2" id="example-single-thread"><span class="secno">1.6.2. </span><span class="content">Single thread scheduler</span><a class="self-link" href="#example-single-thread"></a></h4>
   <p>This example shows how to create a scheduler for an execution resource that consists of a single
thread. It is implemented in terms of a lower-level execution resource called <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>execution</c-><c- o>::</c-><c- n>run_loop</c-></code>.</p>
<pre class="language-c++ highlight"><c- n>class</c-> <c- n>single_thread_context</c-> <c- p>{</c->
  <c- n>std</c-><c- o>::</c-><c- n>execution</c-><c- o>::</c-><c- n>run_loop</c-> <c- n>loop_</c-><c- p>;</c->
  <c- n>std</c-><c- o>::</c-><c- kr>thread</c-> <c- n>thread_</c-><c- p>;</c->

<c- n>public</c-><c- o>:</c->
  <c- n>single_thread_context</c-><c- p>()</c->
    <c- o>:</c-> <c- n>loop_</c-><c- p>()</c->
    <c- p>,</c-> <c- n>thread_</c-><c- p>([</c-><c- n>this</c-><c- p>]</c-> <c- p>{</c-> <c- n>loop_</c-><c- p>.</c-><c- n>run</c-><c- p>();</c-> <c- p>})</c->
  <c- p>{}</c->

  <c- o>~</c-><c- n>single_thread_context</c-><c- p>()</c-> <c- p>{</c->
    <c- n>loop_</c-><c- p>.</c-><c- n>finish</c-><c- p>();</c->
    <c- n>thread_</c-><c- p>.</c-><c- n>join</c-><c- p>();</c->
  <c- p>}</c->

  <c- k>auto</c-> <c- n>get_scheduler</c-><c- p>()</c-> <c- n>noexcept</c-> <c- p>{</c->
    <c- k>return</c-> <c- n>loop_</c-><c- p>.</c-><c- n>get_scheduler</c-><c- p>();</c->
  <c- p>}</c->

  <c- n>std</c-><c- o>::</c-><c- kr>thread</c-><c- o>::</c-><c- n>id</c-> <c- n>get_thread_id</c-><c- p>()</c-> <c- k>const</c-> <c- n>noexcept</c-> <c- p>{</c->
    <c- k>return</c-> <c- n>thread_</c-><c- p>.</c-><c- n>get_id</c-><c- p>();</c->
  <c- p>}</c->
<c- p>};</c->
</pre>
   <p>The <code class="highlight"><c- n>single_thread_context</c-></code> owns an event loop and a thread to drive it. In the destructor, it tells the event
loop to finish up what it’s doing and then joins the thread, blocking for the event loop to drain.</p>
   <p>The interesting bits are in the <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>run_loop</c-></code> context implementation. It
is slightly too long to include here, so we only provide <a href="https://github.com/NVIDIA/stdexec/blob/c2cdb2a2abe2b29a34cf277728319d6ca92ec0bb/include/stdexec/execution.hpp#L3916-L4101">a reference to
it</a>,
but there is one noteworthy detail about its implementation: It uses space in
its operation states to build an intrusive linked list of work items. In
structured concurrency patterns, the operation states of nested operations
compose statically, and in an algorithm like <code class="highlight"><c- n>this_thread</c-><c- o>::</c-><c- n>sync_wait</c-></code>, the
composite operation state lives on the stack for the duration of the operation.
The end result is that work can be scheduled onto this thread with zero
allocations.</p>
   <h3 class="heading settled" data-level="1.7" id="example-server"><span class="secno">1.7. </span><span class="content">Examples: Server theme</span><a class="self-link" href="#example-server"></a></h3>
   <p>In this section we look at some examples of how one would use senders to implement an HTTP server. The examples ignore the low-level details of the HTTP server and looks at how senders can be combined to achieve the goals of the project.</p>
   <p>General application context:</p>
   <ul>
    <li data-md>
     <p>server application that processes images</p>
    <li data-md>
     <p>execution resources:</p>
     <ul>
      <li data-md>
       <p>1 dedicated thread for network I/O</p>
      <li data-md>
       <p>N worker threads used for CPU-intensive work</p>
      <li data-md>
       <p>M threads for auxiliary I/O</p>
      <li data-md>
       <p>optional GPU context that may be used on some types of servers</p>
     </ul>
    <li data-md>
     <p>all parts of the applications can be asynchronous</p>
    <li data-md>
     <p>no locks shall be used in user code</p>
   </ul>
   <h4 class="heading settled" data-level="1.7.1" id="example-server-let"><span class="secno">1.7.1. </span><span class="content">Composability with <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>let_</c-><c- o>*</c-></code></span><a class="self-link" href="#example-server-let"></a></h4>
   <p>Example context:</p>
   <ul>
    <li data-md>
     <p>we are looking at the flow of processing an HTTP request and sending back the response</p>
    <li data-md>
     <p>show how one can break the (slightly complex) flow into steps with <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>let_</c-><c- o>*</c-></code> functions</p>
    <li data-md>
     <p>different phases of processing HTTP requests are broken down into separate concerns</p>
    <li data-md>
     <p>each part of the processing might use different execution resources (details not shown in this example)</p>
    <li data-md>
     <p>error handling is generic, regardless which component fails; we always send the right response to the clients</p>
   </ul>
   <p>Goals:</p>
   <ul>
    <li data-md>
     <p>show how one can break more complex flows into steps with let_* functions</p>
    <li data-md>
     <p>exemplify the use of <code class="highlight"><c- n>let_value</c-></code>, <code class="highlight"><c- n>let_error</c-></code>, <code class="highlight"><c- n>let_stopped</c-></code>, and <code class="highlight"><c- n>just</c-></code> algorithms</p>
   </ul>
<pre class="language-c++ highlight"><c- n>namespace</c-> <c- n>ex</c-> <c- o>=</c-> <c- n>std</c-><c- o>::</c-><c- n>execution</c-><c- p>;</c->

<c- c1>// Returns a sender that yields an http_request object for an incoming request</c->
<c- n>ex</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>schedule_request_start</c-><c- p>(</c-><c- n>read_requests_ctx</c-> <c- n>ctx</c-><c- p>)</c-> <c- p>{...}</c->
<c- c1>// Sends a response back to the client; yields a void signal on success</c->
<c- n>ex</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>send_response</c-><c- p>(</c-><c- k>const</c-> <c- n>http_response</c-><c- o>&amp;</c-> <c- n>resp</c-><c- p>)</c-> <c- p>{...}</c->
<c- c1>// Validate that the HTTP request is well-formed; forwards the request on success</c->
<c- n>ex</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>validate_request</c-><c- p>(</c-><c- k>const</c-> <c- n>http_request</c-><c- o>&amp;</c-> <c- n>req</c-><c- p>)</c-> <c- p>{...}</c->

<c- c1>// Handle the request; main application logic</c->
<c- n>ex</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>handle_request</c-><c- p>(</c-><c- k>const</c-> <c- n>http_request</c-><c- o>&amp;</c-> <c- n>req</c-><c- p>)</c-> <c- p>{</c->
  <c- c1>//...</c->
  <c- k>return</c-> <c- n>ex</c-><c- o>::</c-><c- n>just</c-><c- p>(</c-><c- n>http_response</c-><c- p>{</c-><c- mi>200</c-><c- p>,</c-> <c- n>result_body</c-><c- p>});</c->
<c- p>}</c->

<c- c1>// Transforms server errors into responses to be sent to the client</c->
<c- n>ex</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>error_to_response</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>exception_ptr</c-> <c- n>err</c-><c- p>)</c-> <c- p>{</c->
  <c- n>try</c-> <c- p>{</c->
    <c- n>std</c-><c- o>::</c-><c- n>rethrow_exception</c-><c- p>(</c-><c- n>err</c-><c- p>);</c->
  <c- p>}</c-> <c- n>catch</c-> <c- p>(</c-><c- k>const</c-> <c- n>std</c-><c- o>::</c-><c- n>invalid_argument</c-><c- o>&amp;</c-> <c- n>e</c-><c- p>)</c-> <c- p>{</c->
    <c- k>return</c-> <c- n>ex</c-><c- o>::</c-><c- n>just</c-><c- p>(</c-><c- n>http_response</c-><c- p>{</c-><c- mi>404</c-><c- p>,</c-> <c- n>e</c-><c- p>.</c-><c- n>what</c-><c- p>()});</c->
  <c- p>}</c-> <c- n>catch</c-> <c- p>(</c-><c- k>const</c-> <c- n>std</c-><c- o>::</c-><c- n>exception</c-><c- o>&amp;</c-> <c- n>e</c-><c- p>)</c-> <c- p>{</c->
    <c- k>return</c-> <c- n>ex</c-><c- o>::</c-><c- n>just</c-><c- p>(</c-><c- n>http_response</c-><c- p>{</c-><c- mi>500</c-><c- p>,</c-> <c- n>e</c-><c- p>.</c-><c- n>what</c-><c- p>()});</c->
  <c- p>}</c-> <c- n>catch</c-> <c- p>(...)</c-> <c- p>{</c->
    <c- k>return</c-> <c- n>ex</c-><c- o>::</c-><c- n>just</c-><c- p>(</c-><c- n>http_response</c-><c- p>{</c-><c- mi>500</c-><c- p>,</c-> <c- s>"Unknown server error"</c-><c- p>});</c->
  <c- p>}</c->
<c- p>}</c->
<c- c1>// Transforms cancellation of the server into responses to be sent to the client</c->
<c- n>ex</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>stopped_to_response</c-><c- p>()</c-> <c- p>{</c->
  <c- k>return</c-> <c- n>ex</c-><c- o>::</c-><c- n>just</c-><c- p>(</c-><c- n>http_response</c-><c- p>{</c-><c- mi>503</c-><c- p>,</c-> <c- s>"Service temporarily unavailable"</c-><c- p>});</c->
<c- p>}</c->
<c- c1>//...</c->
<c- c1>// The whole flow for transforming incoming requests into responses</c->
<c- n>ex</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>snd</c-> <c- o>=</c->
    <c- c1>// get a sender when a new request comes</c->
    <c- n>schedule_request_start</c-><c- p>(</c-><c- n>the_read_requests_ctx</c-><c- p>)</c->
    <c- c1>// make sure the request is valid; throw if not</c->
    <c- o>|</c-> <c- n>ex</c-><c- o>::</c-><c- n>let_value</c-><c- p>(</c-><c- n>validate_request</c-><c- p>)</c->
    <c- c1>// process the request in a function that may be using a different execution resource</c->
    <c- o>|</c-> <c- n>ex</c-><c- o>::</c-><c- n>let_value</c-><c- p>(</c-><c- n>handle_request</c-><c- p>)</c->
    <c- c1>// If there are errors transform them into proper responses</c->
    <c- o>|</c-> <c- n>ex</c-><c- o>::</c-><c- n>let_error</c-><c- p>(</c-><c- n>error_to_response</c-><c- p>)</c->
    <c- c1>// If the flow is cancelled, send back a proper response</c->
    <c- o>|</c-> <c- n>ex</c-><c- o>::</c-><c- n>let_stopped</c-><c- p>(</c-><c- n>stopped_to_response</c-><c- p>)</c->
    <c- c1>// write the result back to the client</c->
    <c- o>|</c-> <c- n>ex</c-><c- o>::</c-><c- n>let_value</c-><c- p>(</c-><c- n>send_response</c-><c- p>)</c->
    <c- c1>// done</c->
    <c- p>;</c->
<c- c1>// execute the whole flow asynchronously</c->
<c- n>ex</c-><c- o>::</c-><c- n>start_detached</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>snd</c-><c- p>));</c->
</pre>
   <p>The example shows how one can separate out the concerns for interpreting requests, validating requests, running the main logic for handling the request, generating error responses, handling cancellation and sending the response back to the client.
They are all different phases in the application, and can be joined together with the <code class="highlight"><c- n>let_</c-><c- o>*</c-></code> functions.</p>
   <p>All our functions return <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>sender</c-></code> objects, so that they can all generate success, failure and cancellation paths.
For example, regardless where an error is generated (reading request, validating request or handling the response), we would have one common block to handle the error, and following error flows is easy.</p>
   <p>Also, because of using <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>sender</c-></code> objects at any step, we might expect any of these steps to be completely asynchronous; the overall flow doesn’t care.
Regardless of the execution resource in which the steps, or part of the steps are executed in, the flow is still the same.</p>
   <h4 class="heading settled" data-level="1.7.2" id="example-server-on"><span class="secno">1.7.2. </span><span class="content">Moving between execution resources with <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>on</c-></code> and <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>transfer</c-></code></span><a class="self-link" href="#example-server-on"></a></h4>
   <p>Example context:</p>
   <ul>
    <li data-md>
     <p>reading data from the socket before processing the request</p>
    <li data-md>
     <p>reading of the data is done on the I/O context</p>
    <li data-md>
     <p>no processing of the data needs to be done on the I/O context</p>
   </ul>
   <p>Goals:</p>
   <ul>
    <li data-md>
     <p>show how one can change the execution resource</p>
    <li data-md>
     <p>exemplify the use of <code class="highlight"><c- n>on</c-></code> and <code class="highlight"><c- n>transfer</c-></code> algorithms</p>
   </ul>
<pre class="language-c++ highlight"><c- n>namespace</c-> <c- n>ex</c-> <c- o>=</c-> <c- n>std</c-><c- o>::</c-><c- n>execution</c-><c- p>;</c->

<c- b>size_t</c-> <c- nf>legacy_read_from_socket</c-><c- p>(</c-><c- b>int</c-> <c- n>sock</c-><c- p>,</c-> <c- b>char</c-><c- o>*</c-> <c- n>buffer</c-><c- p>,</c-> <c- b>size_t</c-> <c- n>buffer_len</c-><c- p>)</c-> <c- p>{}</c->
<c- b>void</c-> <c- nf>process_read_data</c-><c- p>(</c-><c- k>const</c-> <c- b>char</c-><c- o>*</c-> <c- n>read_data</c-><c- p>,</c-> <c- b>size_t</c-> <c- n>read_len</c-><c- p>)</c-> <c- p>{}</c->
<c- c1>//...</c->

<c- c1>// A sender that just calls the legacy read function</c->
<c- k>auto</c-> <c- n>snd_read</c-> <c- o>=</c-> <c- n>ex</c-><c- o>::</c-><c- n>just</c-><c- p>(</c-><c- n>sock</c-><c- p>,</c-> <c- n>buf</c-><c- p>,</c-> <c- n>buf_len</c-><c- p>)</c-> <c- o>|</c-> <c- n>ex</c-><c- o>::</c-><c- n>then</c-><c- p>(</c-><c- n>legacy_read_from_socket</c-><c- p>);</c->
<c- c1>// The entire flow</c->
<c- k>auto</c-> <c- n>snd</c-> <c- o>=</c->
    <c- c1>// start by reading data on the I/O thread</c->
    <c- n>ex</c-><c- o>::</c-><c- n>on</c-><c- p>(</c-><c- n>io_sched</c-><c- p>,</c-> <c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>snd_read</c-><c- p>))</c->
    <c- c1>// do the processing on the worker threads pool</c->
    <c- o>|</c-> <c- n>ex</c-><c- o>::</c-><c- n>transfer</c-><c- p>(</c-><c- n>work_sched</c-><c- p>)</c->
    <c- c1>// process the incoming data (on worker threads)</c->
    <c- o>|</c-> <c- n>ex</c-><c- o>::</c-><c- n>then</c-><c- p>([</c-><c- n>buf</c-><c- p>](</c-><c- b>int</c-> <c- n>read_len</c-><c- p>)</c-> <c- p>{</c-> <c- n>process_read_data</c-><c- p>(</c-><c- n>buf</c-><c- p>,</c-> <c- n>read_len</c-><c- p>);</c-> <c- p>})</c->
    <c- c1>// done</c->
    <c- p>;</c->
<c- c1>// execute the whole flow asynchronously</c->
<c- n>ex</c-><c- o>::</c-><c- n>start_detached</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>snd</c-><c- p>));</c->
</pre>
   <p>The example assume that we need to wrap some legacy code of reading sockets, and handle execution resource switching.
(This style of reading from socket may not be the most efficient one, but it’s working for our purposes.)
For performance reasons, the reading from the socket needs to be done on the I/O thread, and all the processing needs to happen on a work-specific execution resource (i.e., thread pool).</p>
   <p>Calling <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>on</c-></code> will ensure that the given sender will be started on the given scheduler.
In our example, <code class="highlight"><c- n>snd_read</c-></code> is going to be started on the I/O scheduler.
This sender will just call the legacy code.</p>
   <p>The completion-signal will be issued in the I/O execution resource, so we have to move it to the work thread pool.
This is achieved with the help of the <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>transfer</c-></code> algorithm.
The rest of the processing (in our case, the last call to <code class="highlight"><c- n>then</c-></code>) will happen in the work thread pool.</p>
   <p>The reader should notice the difference between <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>on</c-></code> and <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>transfer</c-></code>.
The <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>on</c-></code> algorithm will ensure that the given sender will start in the specified context, and doesn’t care where the completion-signal for that sender is sent.
The <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>transfer</c-></code> algorithm will not care where the given sender is going to be started, but will ensure that the completion-signal of will be transferred to the given context.</p>
   <h3 class="heading settled" data-level="1.8" id="intro-is-not"><span class="secno">1.8. </span><span class="content">What this proposal is <strong>not</strong></span><a class="self-link" href="#intro-is-not"></a></h3>
   <p>This paper is not a patch on top of <a data-link-type="biblio" href="https://wg21.link/p0443r14"><cite>A Unified Executors Proposal for C++</cite></a>; we are not asking to update the existing paper, we are asking to retire it in favor of this paper, which is already self-contained; any example code within this paper can be written in Standard C++, without the need
to standardize any further facilities.</p>
   <p>This paper is not an alternative design to <a data-link-type="biblio" href="https://wg21.link/p0443r14"><cite>A Unified Executors Proposal for C++</cite></a>; rather, we have taken the design in the current executors paper, and applied targeted fixes to allow it to fulfill the promises of the sender/receiver model, as well as provide all the facilities we consider
essential when writing user code using standard execution concepts; we have also applied the guidance of removing one-way executors from the paper entirely, and instead provided an algorithm based around senders that serves the same purpose.</p>
   <h3 class="heading settled" data-level="1.9" id="intro-compare"><span class="secno">1.9. </span><span class="content">Design changes from P0443</span><a class="self-link" href="#intro-compare"></a></h3>
   <ol>
    <li data-md>
     <p>The <code class="highlight"><c- n>executor</c-></code> concept has been removed and all of its proposed functionality
is now based on schedulers and senders, as per SG1 direction.</p>
    <li data-md>
     <p>Properties are not included in this paper. We see them as a possible future
extension, if the committee gets more comfortable with them.</p>
    <li data-md>
     <p>Senders now advertise what scheduler, if any, their evaluation will complete
on.</p>
    <li data-md>
     <p>The places of execution of user code in P0443 weren’t precisely defined,
whereas they are in this paper. See <a href="#design-propagation">§ 4.5 Senders can propagate completion schedulers</a>.</p>
    <li data-md>
     <p>P0443 did not propose a suite of sender algorithms necessary for writing
sender code; this paper does. See <a href="#design-sender-factories">§ 4.19 User-facing sender factories</a>, <a href="#design-sender-adaptors">§ 4.20 User-facing sender adaptors</a>, and <a href="#design-sender-consumers">§ 4.21 User-facing sender consumers</a>.</p>
    <li data-md>
     <p>P0443 did not specify the semantics of variously qualified <code class="highlight"><c- n>connect</c-></code> overloads; this paper does. See <a href="#design-shot">§ 4.7 Senders can be either multi-shot or single-shot</a>.</p>
    <li data-md>
     <p>This paper extends the sender traits/typed sender design to support typed
senders whose value/error types depend on type information provided late via
the receiver.</p>
    <li data-md>
     <p>Support for untyped senders is dropped; the <code class="highlight"><c- n>typed_sender</c-></code> concept is renamed <code class="highlight"><c- n>sender</c-></code>; <code class="highlight"><c- n>sender_traits</c-></code> is replaced with <code class="highlight"><c- n>completion_signatures_of_t</c-></code>.</p>
    <li data-md>
     <p>Specific type erasure facilities are omitted, as per LEWG direction. Type
erasure facilities can be built on top of this proposal, as discussed in <a href="#design-dispatch">§ 5.9 Ranges-style CPOs vs tag_invoke</a>.</p>
    <li data-md>
     <p>A specific thread pool implementation is omitted, as per LEWG direction.</p>
    <li data-md>
     <p>Some additional utilities are added:</p>
     <ul>
      <li data-md>
       <p><b><code class="highlight"><c- n>run_loop</c-></code></b>: An execution resource that provides a multi-producer,
single-consumer, first-in-first-out work queue.</p>
      <li data-md>
       <p><b><code class="highlight"><c- n>receiver_adaptor</c-></code></b>: A utility for algorithm authors for defining one
receiver type in terms of another.</p>
      <li data-md>
       <p><b><code class="highlight"><c- n>completion_signatures</c-></code></b> and <b><code class="highlight"><c- n>transform_completion_signatures</c-></code></b>:
Utilities for describing the ways in which a sender can complete in a
declarative syntax.</p>
     </ul>
   </ol>
   <h3 class="heading settled" data-level="1.10" id="intro-prior-art"><span class="secno">1.10. </span><span class="content">Prior art</span><a class="self-link" href="#intro-prior-art"></a></h3>
   <p>This proposal builds upon and learns from years of prior art with asynchronous and parallel programming frameworks in C++. In this section, we discuss async abstractions that have previously been suggested as a possible basis for asynchronous algorithms and why they fall short.</p>
   <h4 class="heading settled" data-level="1.10.1" id="intro-prior-art-futures"><span class="secno">1.10.1. </span><span class="content">Futures</span><a class="self-link" href="#intro-prior-art-futures"></a></h4>
   <p>A future is a handle to work that has already been scheduled for execution. It is one end of a communication channel; the other end is a promise, used to receive the result from the concurrent operation and to communicate it to the future.</p>
   <p>Futures, as traditionally realized, require the dynamic allocation and management of a shared state, synchronization, and typically type-erasure of work and continuation. Many of these costs are inherent in the nature of "future" as a handle to work that is already scheduled for execution. These expenses rule out the future abstraction for many uses and makes it a poor choice for a basis of a generic mechanism.</p>
   <h4 class="heading settled" data-level="1.10.2" id="intro-prior-art-coroutines"><span class="secno">1.10.2. </span><span class="content">Coroutines</span><a class="self-link" href="#intro-prior-art-coroutines"></a></h4>
   <p>C++20 coroutines are frequently suggested as a basis for asynchronous algorithms. It’s fair to ask why, if we added coroutines to C++, are we suggesting the addition of a library-based abstraction for asynchrony. Certainly, coroutines come with huge syntactic and semantic advantages over the alternatives.</p>
   <p>Although coroutines are lighter weight than futures, coroutines suffer many of the same problems. Since they typically start suspended, they can avoid synchronizing the chaining of dependent work. However in many cases, coroutine frames require an unavoidable dynamic allocation and indirect function calls. This is done to hide the layout of the coroutine frame from the C++ type system, which in turn makes possible the separate compilation of coroutines and certain compiler optimizations, such as optimization of the coroutine frame size.</p>
   <p>Those advantages come at a cost, though. Because of the dynamic allocation of coroutine frames, coroutines in embedded or heterogeneous environments, which often lack support for dynamic allocation, require great attention to detail. And the allocations and indirections tend to complicate the job of the inliner, often resulting in sub-optimal codegen.</p>
   <p>The coroutine language feature mitigates these shortcomings somewhat with the HALO optimization <a data-link-type="biblio" href="https://wg21.link/p0981r0"><cite>Halo: coroutine Heap Allocation eLision Optimization: the joint response</cite></a>, which leverages existing compiler optimizations such as allocation elision and devirtualization to inline the coroutine, completely eliminating the runtime overhead. However, HALO requires a sophisiticated compiler, and a fair number of stars need to align for the optimization to kick in. In our experience, more often than not in real-world code today’s compilers are not able to inline the coroutine, resulting in allocations and indirections in the generated code.</p>
   <p>In a suite of generic async algorithms that are expected to be callable from hot code paths, the extra allocations and indirections are a deal-breaker. It is for these reasons that we consider coroutines a poor choise for a basis of all standard async.</p>
   <h4 class="heading settled" data-level="1.10.3" id="intro-prior-art-callbacks"><span class="secno">1.10.3. </span><span class="content">Callbacks</span><a class="self-link" href="#intro-prior-art-callbacks"></a></h4>
   <p>Callbacks are the oldest, simplest, most powerful, and most efficient mechanism for creating chains of work, but suffer problems of their own. Callbacks must propagate either errors or values. This simple requirement yields many different interface possibilities. The lack of a standard callback shape obstructs generic design.</p>
   <p>Additionally, few of these possibilities accommodate cancellation signals when the user requests upstream work to stop and clean up.</p>
   <h3 class="heading settled" data-level="1.11" id="intro-field-experience"><span class="secno">1.11. </span><span class="content">Field experience</span><a class="self-link" href="#intro-field-experience"></a></h3>
   <h4 class="heading settled" data-level="1.11.1" id="intro-field-experience-libunifex"><span class="secno">1.11.1. </span><span class="content">libunifex</span><a class="self-link" href="#intro-field-experience-libunifex"></a></h4>
   <p>This proposal draws heavily from our field experience with <a href="https://github.com/facebookexperimental/libunifex">libunifex</a>. Libunifex implements all of the concepts and customization points defined in this paper (with slight variations -- the design of P2300 has evolved due to LEWG feedback), many of this paper’s algorithms (some under different names), and much more besides.</p>
   <p>Libunifex has several concrete schedulers in addition to the <code class="highlight"><c- n>run_loop</c-></code> suggested here (where it is called <code class="highlight"><c- n>manual_event_loop</c-></code>). It has schedulers that dispatch efficiently to epoll and io_uring on Linux and the Windows Thread Pool on Windows.</p>
   <p>In addition to the proposed interfaces and the additional schedulers, it has several important extensions to the facilities described in this paper, which demonstrate directions in which these abstractions may be evolved over time, including:</p>
   <ul>
    <li data-md>
     <p>Timed schedulers, which permit scheduling work on an execution resource at a particular time or after a particular duration has elapsed. In addition, it provides time-based algorithms.</p>
    <li data-md>
     <p>File I/O schedulers, which permit filesystem I/O to be scheduled.</p>
    <li data-md>
     <p>Two complementary abstractions for streams (asynchronous ranges), and a set of stream-based algorithms.</p>
   </ul>
   <p>Libunifex has seen heavy production use at Facebook. As of October 2021, it is currently used in production within the following applications and platforms:</p>
   <ul>
    <li data-md>
     <p>Facebook Messenger on iOS, Android, Windows, and macOS</p>
    <li data-md>
     <p>Instagram on iOS and Android</p>
    <li data-md>
     <p>Facebook on iOS and Android</p>
    <li data-md>
     <p>Portal</p>
    <li data-md>
     <p>An internal Facebook product that runs on Linux</p>
   </ul>
   <p>All of these applications are making direct use of the sender/receiver abstraction as presented in this paper. One product (Instagram on iOS) is making use of the sender/coroutine integration as presented. The monthly active users of these products number in the billions.</p>
   <h4 class="heading settled" data-level="1.11.2" id="intro-field-experience-other-implementations"><span class="secno">1.11.2. </span><span class="content">Other implementations</span><a class="self-link" href="#intro-field-experience-other-implementations"></a></h4>
   <p>The authors are aware of a number of other implementations of sender/receiver from this paper. These are presented here in perceived order of maturity and field experience.</p>
   <ul>
    <li data-md>
     <p><b><a data-link-type="biblio" href="https://doi.org/10.21105/joss.02352"><cite>HPX - The C++ Standard Library for Parallelism and Concurrency</cite></a></b></p>
     <p>HPX is a general purpose C++ runtime system for parallel and distributed applications that has been under active development since 2007. HPX exposes a uniform, standards-oriented API, and keeps abreast of the latest standards and proposals. It is used in a wide variety of high-performance applications.</p>
     <p>The sender/receiver implementation in HPX has been under active development since May 2020. It is used to erase the overhead of futures and to make it possible to write efficient generic asynchronous algorithms that are agnostic to their execution resource. In HPX, algorithms can migrate execution between execution resources, even to GPUs and back, using a uniform standard interface with sender/receiver.</p>
     <p>Far and away, the HPX team has the greatest usage experience outside Facebook. Mikael Simberg summarizes the experience as follows:</p>
     <blockquote>
      <p>Summarizing, for us the major benefits of sender/receiver compared to the old model are:</p>
      <ol>
       <li data-md>
        <p>Proper hooks for transitioning between execution resources.</p>
       <li data-md>
        <p>The adaptors. Things like <code class="highlight"><c- n>let_value</c-></code> are really nice additions.</p>
       <li data-md>
        <p>Separation of the error channel from the value channel (also cancellation, but we don’t have much use for it at the moment). Even from a teaching perspective having to explain that the future <code class="highlight"><c- n>f2</c-></code> in the continuation will always be ready here <code class="highlight"><c- n>f1</c-><c- p>.</c-><c- n>then</c-><c- p>([](</c-><c- n>future</c-><c- o>&lt;</c-><c- n>T</c-><c- o>></c-> <c- n>f2</c-><c- p>)</c-> <c- p>{...})</c-></code> is enough of a reason to separate the channels. All the other obvious reasons apply as well of course.</p>
       <li data-md>
        <p>For futures we have a thing called <code class="highlight"><c- n>hpx</c-><c- o>::</c-><c- n>dataflow</c-></code> which is an optimized version of <code class="highlight"><c- n>when_all</c-><c- p>(...).</c-><c- n>then</c-><c- p>(...)</c-></code> which avoids intermediate allocations. With the sender/receiver <code class="highlight"><c- n>when_all</c-><c- p>(...)</c-> <c- o>|</c-> <c- n>then</c-><c- p>(...)</c-></code> we get that "for free".</p>
      </ol>
     </blockquote>
    <li data-md>
     <p><b><a href="https://github.com/dietmarkuehl/kuhllib/">kuhllib</a> by Dietmar Kuehl</b></p>
     <p>This is a prototype Standard Template Library with an implementation of sender/receiver that has been under development since May, 2021. It is significant mostly for its support for sender/receiver-based networking interfaces.</p>
     <p>Here, Dietmar Kuehl speaks about the perceived complexity of sender/receiver:</p>
     <blockquote>
      <p>... and, also similar to STL: as I had tried to do things in that space before I recognize sender/receivers as being maybe complicated in one way but a huge simplification in another one: like with STL I think those who use it will benefit - if not from the algorithm from the clarity of abstraction: the separation of concerns of STL (the algorithm being detached from the details of the sequence representation) is a major leap. Here it is rather similar: the separation of the asynchronous algorithm from the details of execution. Sure, there is some glue to tie things back together but each of them is simpler than the combined result.</p>
     </blockquote>
     <p>Elsewhere, he said:</p>
     <blockquote>
      <p>... to me it feels like sender/receivers are like iterators when STL emerged: they are different from what everybody did in that space. However, everything people are already doing in that space isn’t right.</p>
     </blockquote>
     <p>Kuehl also has experience teaching sender/receiver at Bloomberg. About that experience he says:</p>
     <blockquote>
      <p>When I asked [my students] specifically about how complex they consider the sender/receiver stuff the feedback was quite unanimous that the sender/receiver parts aren’t trivial but not what contributes to the complexity.</p>
     </blockquote>
    <li data-md>
     <p><b><a href="https://github.com/NVIDIA/stdexec">The reference implementation</a></b></p>
     <p>This is a complete implementation written from the specification in this paper. Its primary purpose is to help find specification bugs and to harden the wording of the proposal. It is
fit for broad use and for contribution to libc++.</p>
     <p>It is current with R8 of this paper.</p>
    <li data-md>
     <p><b><a href="https://github.com/miscco/STL/tree/proposal/executors">Reference implementation for the Microsoft STL</a> by Michael Schellenberger Costa</b></p>
     <p>This is another reference implementation of this proposal, this time in a fork of the Mircosoft STL implementation. Michael Schellenberger Costa is not affiliated with Microsoft. He intends to contribute this implementation upstream when it is complete.</p>
   </ul>
   <h4 class="heading settled" data-level="1.11.3" id="intro-field-experience-inspirations"><span class="secno">1.11.3. </span><span class="content">Inspirations</span><a class="self-link" href="#intro-field-experience-inspirations"></a></h4>
   <p>This proposal also draws heavily from our experience with <a href="https://github.com/NVIDIA/thrust">Thrust</a> and <a href="https://github.com/agency-library/agency">Agency</a>. It is also inspired by the needs of countless other C++ frameworks for asynchrony, parallelism, and concurrency, including:</p>
   <ul>
    <li data-md>
     <p><a href="https://github.com/STEllAR-GROUP/hpx">HPX</a></p>
    <li data-md>
     <p><a href="https://github.com/facebook/folly/blob/master/folly/docs/Futures.md">Folly</a></p>
    <li data-md>
     <p><a href="https://stlab.cc/libraries/concurrency/">stlab</a></p>
   </ul>
   <h2 class="heading settled" data-level="2" id="revisions"><span class="secno">2. </span><span class="content">Revision history</span><a class="self-link" href="#revisions"></a></h2>
   <h3 class="heading settled" data-level="2.1" id="r8"><span class="secno">2.1. </span><span class="content">R8</span><a class="self-link" href="#r8"></a></h3>
   <p>The changes since R7 are as follows:</p>
   <p><b>Fixes:</b></p>
   <ul>
    <li data-md>
     <p><code class="highlight"><c- n>get_env</c-><c- p>(</c-><c- n>obj</c-><c- p>)</c-></code> is required to be nothrow.</p>
    <li data-md>
     <p><code class="highlight"><c- n>get_env</c-></code> and the associated environment utilities are moved back into <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>execution</c-></code> from <code class="highlight"><c- n>std</c-><c- o>::</c-></code>.</p>
    <li data-md>
     <p><code class="highlight"><c- n>make_completion_signatures</c-></code> is renamed <code class="highlight"><c- n>transform_completion_signatures_of</c-></code> and is expressed in terms of the new <code class="highlight"><c- n>transform_completion_signatures</c-></code>,
which takes an input set of completion signatures instead of a sender and an
environment.</p>
    <li data-md>
     <p>Add a requirement on queryable objects that if <code class="highlight"><c- n>tag_invoke</c-><c- p>(</c-><c- n>query</c-><c- p>,</c-> <c- n>env</c-><c- p>,</c-> <c- n>args</c-><c- p>...)</c-></code> is well-formed, then <code class="highlight"><c- n>query</c-><c- p>(</c-><c- n>env</c-><c- p>,</c-> <c- n>args</c-><c- p>...)</c-></code> is
expression-equivalent to it. This is necessary to properly specify how to
join two environments in the presence of queries that have defaults.</p>
    <li data-md>
     <p>The <code class="highlight"><c- n>sender_in</c-><c- o>&lt;</c-><c- n>Sndr</c-><c- p>,</c-> <c- n>Env</c-><c- o>></c-></code> concept requires that <code class="highlight"><c- n>E</c-></code> satisfies <code class="highlight"><c- n>queryable</c-></code>.</p>
    <li data-md>
     <p>Senders of more than one value are now <code class="highlight"><c- k>co_await</c-></code>-able in coroutines, the
result of which is a <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>tuple</c-></code> of the values (which is suitable as the
initializer of a structured binding).</p>
   </ul>
   <p><b>Enhancements:</b></p>
   <ul>
    <li data-md>
     <p>The exposition-only class template <code class="highlight"><i><c- n>basic</c-><c- o>-</c-><c- n>sender</c-></i></code> is greatly
enhanced, and the sender algorithms are respecified in term of it.</p>
    <li data-md>
     <p><code class="highlight"><c- n>enable_sender</c-></code> and <code class="highlight"><c- n>enable_receiver</c-></code> traits now have default
implementations that look for nested <code class="highlight"><c- n>sender_concept</c-></code> and <code class="highlight"><c- n>receiver_concept</c-></code> types, respectively.</p>
   </ul>
   <h3 class="heading settled" data-level="2.2" id="r7"><span class="secno">2.2. </span><span class="content">R7</span><a class="self-link" href="#r7"></a></h3>
   <p>The changes since R6 are as follows:</p>
   <p><b>Fixes:</b></p>
   <ul>
    <li data-md>
     <p>Make it valid to pass non-variadic templates to the exposition-only alias
template <code class="highlight"><i><c- n>gather</c-><c- o>-</c-><c- n>signatures</c-></i></code>, fixing the definitions of <code class="highlight"><c- n>value_types_of_t</c-></code>, <code class="highlight"><c- n>error_types_of_t</c-></code>, and the exposition-only alias
template <code class="highlight"><i><c- n>sync</c-><c- o>-</c-><c- n>wait</c-><c- o>-</c-><c- n>type</c-></i></code>.</p>
    <li data-md>
     <p>Removed the query forwarding from <code class="highlight"><c- n>receiver_adaptor</c-></code> that was
inadvertantly left over from a previous edit.</p>
    <li data-md>
     <p>When adapting a sender to an awaitable with <code class="highlight"><c- n>as_awaitable</c-></code>, the sender’s
value result datum is decayed before being stored in the exposition-only <code class="highlight"><c- n>variant</c-></code>.</p>
    <li data-md>
     <p>Correctly specify the completion signatures of the <code class="highlight"><c- n>schedule_from</c-></code> algorithm.</p>
    <li data-md>
     <p>The <code class="highlight"><c- n>sender_of</c-></code> concept no longer distinguishes between a sender of a
type <code class="highlight"><c- n>T</c-></code> and a sender of a type <code class="highlight"><c- n>T</c-><c- o>&amp;&amp;</c-></code>.</p>
    <li data-md>
     <p>The <code class="highlight"><c- n>just</c-></code> and <code class="highlight"><c- n>just_error</c-></code> sender factories now reject C-style arrays
instead of silently decaying them to pointers.</p>
   </ul>
   <p><b>Enhancements:</b></p>
   <ul>
    <li data-md>
     <p>The <code class="highlight"><c- n>sender</c-></code> and <code class="highlight"><c- n>receiver</c-></code> concepts get explicit opt-in traits called <code class="highlight"><c- n>enable_sender</c-></code> and <code class="highlight"><c- n>enable_receiver</c-></code>, respectively. The traits have
default implementations that look for nested <code class="highlight"><c- n>is_sender</c-></code> and <code class="highlight"><c- n>is_receiver</c-></code> types, respectively.</p>
    <li data-md>
     <p><code class="highlight"><c- n>get_attrs</c-></code> is removed and <code class="highlight"><c- n>get_env</c-></code> is used in its place.</p>
    <li data-md>
     <p>The exposition-only type <code class="highlight"><i><c- n>empty</c-><c- o>-</c-><c- n>env</c-></i></code> is made normative
and is renamed <code class="highlight"><c- n>empty_env</c-></code>.</p>
    <li data-md>
     <p><code class="highlight"><c- n>get_env</c-></code> gets a fall-back implementation that simply returns <code class="highlight"><c- n>empty_env</c-><c- p>{}</c-></code> if a <code class="highlight"><c- n>tag_invoke</c-></code> overload is not found.</p>
    <li data-md>
     <p><code class="highlight"><c- n>get_env</c-></code> is required to be insensitive to the cvref-qualification of its
argument.</p>
    <li data-md>
     <p><code class="highlight"><c- n>get_env</c-></code>, <code class="highlight"><c- n>empty_env</c-></code>, and <code class="highlight"><c- n>env_of_t</c-></code> are moved into the <code class="highlight"><c- n>std</c-><c- o>::</c-></code> namespace.</p>
    <li data-md>
     <p>Add a new subclause describing the async programming model of senders in
abstract terms. See <a href="#spec-execution-async.ops">§ 11.3 Asynchronous operations [async.ops]</a>.</p>
   </ul>
   <h3 class="heading settled" data-level="2.3" id="r6"><span class="secno">2.3. </span><span class="content">R6</span><a class="self-link" href="#r6"></a></h3>
   <p>The changes since R5 are as follows:</p>
   <p><b>Fixes:</b></p>
   <ul>
    <li data-md>
     <p>Fix typo in the specification of <code class="highlight"><c- n>in_place_stop_source</c-></code> about the relative
lifetimes of the tokens and the source that produced them.</p>
    <li data-md>
     <p><code class="highlight"><c- n>get_completion_signatures</c-></code> tests for awaitability with a promise type
similar to the one used by <code class="highlight"><c- n>connect</c-></code> for the sake of consistency.</p>
    <li data-md>
     <p>A coroutine promise type is an environment provider (that is, it implements <code class="highlight"><c- n>get_env</c-><c- p>()</c-></code>) rather than being directly queryable. The previous draft was
inconsistent about that.</p>
   </ul>
   <p><b>Enhancements:</b></p>
   <ul>
    <li data-md>
     <p>Sender queries are moved into a separate queryable "attributes" object
that is accessed by passing the sender to <code class="highlight"><c- n>get_attrs</c-><c- p>()</c-></code> (see below). The <code class="highlight"><c- n>sender</c-></code> concept is reexpressed to require <code class="highlight"><c- n>get_attrs</c-><c- p>()</c-></code> and separated
from a new <code class="highlight"><c- n>sender_in</c-><c- o>&lt;</c-><c- n>Snd</c-><c- p>,</c-> <c- n>Env</c-><c- o>></c-></code> concept for checking whether a type is
a sender within a particular execution environment.</p>
    <li data-md>
     <p>The placeholder types <code class="highlight"><c- n>no_env</c-></code> and <code class="highlight"><c- n>dependent_completion_signatures</c-><c- o>&lt;></c-></code> are no longer needed and are dropped.</p>
    <li data-md>
     <p><code class="highlight"><c- n>ensure_started</c-></code> and <code class="highlight"><c- n>split</c-></code> are changed to persist the result of
calling <code class="highlight"><c- n>get_attrs</c-><c- p>()</c-></code> on the input sender.</p>
    <li data-md>
     <p>Reorder constraints of the <code class="highlight"><c- n>scheduler</c-></code> and <code class="highlight"><c- n>receiver</c-></code> concepts to avoid constraint recursion
when used in tandem with poorly-constrained, implicitly convertible types.</p>
    <li data-md>
     <p>Re-express the <code class="highlight"><c- n>sender_of</c-></code> concept to be more ergonomic and general.</p>
    <li data-md>
     <p>Make the specification of the alias templates <code class="highlight"><c- n>value_types_of_t</c-></code> and <code class="highlight"><c- n>error_types_of_t</c-></code>, and the variable template <code class="highlight"><c- n>sends_done</c-></code> more concise by
expressing them in terms of a new exposition-only alias template <code class="highlight"><i><c- n>gather</c-><c- o>-</c-><c- n>signatures</c-></i></code>.</p>
   </ul>
   <h4 class="heading settled" data-level="2.3.1" id="environments-and-attributes"><span class="secno">2.3.1. </span><span class="content">Environments and attributes</span><a class="self-link" href="#environments-and-attributes"></a></h4>
   <p>In earlier revisions, receivers, senders, and schedulers all were directly
queryable. In R4, receiver queries were moved into a separate "environment"
object, obtainable from a receiver with a <code class="highlight"><c- n>get_env</c-></code> accessor. In R6, the
sender queries are given similar treatment, relocating to a "attributes"
object obtainable from a sender with a <code class="highlight"><c- n>get_attrs</c-></code> accessor. This was done
to solve a number of design problems with the <code class="highlight"><c- n>split</c-></code> and <code class="highlight"><c- n>ensure_started</c-></code> algorithms; _e.g._, see <a href="https://github.com/NVIDIA/stdexec/issues/466">NVIDIA/stdexec#466</a>.</p>
   <p>Schedulers, however, remain directly queryable. As lightweight handles
that are required to be movable and copyable, there is little reason to
want to dispose of a scheduler and yet persist the scheduler’s queries.</p>
   <p>This revision also makes operation states directly queryable, even though
there isn’t yet a use for such. Some early prototypes of cooperative bulk
parallel sender algorithms done at NVIDIA suggest the utility of
forwardable operation state queries. The authors chose to make opstates
directly queryable since the opstate object is itself required to be kept
alive for the duration of asynchronous operation.</p>
   <h3 class="heading settled" data-level="2.4" id="r5"><span class="secno">2.4. </span><span class="content">R5</span><a class="self-link" href="#r5"></a></h3>
   <p>The changes since R4 are as follows:</p>
   <p><b>Fixes:</b></p>
   <ul>
    <li data-md>
     <p><code class="highlight"><c- n>start_detached</c-></code> requires its argument to be a <code class="highlight"><c- b>void</c-></code> sender (sends no values
to <code class="highlight"><c- n>set_value</c-></code>).</p>
   </ul>
   <p><b>Enhancements:</b></p>
   <ul>
    <li data-md>
     <p>Receiver concepts refactored to no longer require an error channel for <code class="highlight"><c- n>exception_ptr</c-></code> or a stopped channel.</p>
    <li data-md>
     <p><code class="highlight"><c- n>sender_of</c-></code> concept and <code class="highlight"><c- n>connect</c-></code> customization point additionally require
that the receiver is capable of receiving all of the sender’s possible
completions.</p>
    <li data-md>
     <p><code class="highlight"><c- n>get_completion_signatures</c-></code> is now required to return an instance of either <code class="highlight"><c- n>completion_signatures</c-></code> or <code class="highlight"><c- n>dependent_completion_signatures</c-></code>.</p>
    <li data-md>
     <p><code class="highlight"><c- n>make_completion_signatures</c-></code> made more general.</p>
    <li data-md>
     <p><code class="highlight"><c- n>receiver_adaptor</c-></code> handles <code class="highlight"><c- n>get_env</c-></code> as it does the <code class="highlight"><c- n>set_</c-><c- o>*</c-></code> members; that is, <code class="highlight"><c- n>receiver_adaptor</c-></code> will look for a member named <code class="highlight"><c- n>get_env</c-><c- p>()</c-></code> in the derived
class, and if found dispatch the <code class="highlight"><c- n>get_env_t</c-></code> tag invoke customization to it.</p>
    <li data-md>
     <p><code class="highlight"><c- n>just</c-></code>, <code class="highlight"><c- n>just_error</c-></code>, <code class="highlight"><c- n>just_stopped</c-></code>, and <code class="highlight"><c- n>into_variant</c-></code> have been respecified
as customization point objects instead of functions, following LEWG guidance.</p>
   </ul>
   <h3 class="heading settled" data-level="2.5" id="r4"><span class="secno">2.5. </span><span class="content">R4</span><a class="self-link" href="#r4"></a></h3>
   <p>The changes since R3 are as follows:</p>
   <p><b>Fixes:</b></p>
   <ul>
    <li data-md>
     <p>Fix specification of <code class="highlight"><c- n>get_completion_scheduler</c-></code> on the <code class="highlight"><c- n>transfer</c-></code>, <code class="highlight"><c- n>schedule_from</c-></code> and <code class="highlight"><c- n>transfer_when_all</c-></code> algorithms; the completion scheduler cannot be guaranteed
for <code class="highlight"><c- n>set_error</c-></code>.</p>
    <li data-md>
     <p>The value of <code class="highlight"><c- n>sends_stopped</c-></code> for the default sender traits of types that are
generally awaitable was changed from <code class="highlight">false</code> to <code class="highlight">true</code> to acknowledge the
fact that some coroutine types are generally awaitable and may implement the <code class="highlight"><c- n>unhandled_stopped</c-><c- p>()</c-></code> protocol in their promise types.</p>
    <li data-md>
     <p>Fix the incorrect use of inline namespaces in the <code class="highlight"><c- o>&lt;</c-><c- n>execution</c-><c- o>></c-></code> header.</p>
    <li data-md>
     <p>Shorten the stable names for the sections.</p>
    <li data-md>
     <p><code class="highlight"><c- n>sync_wait</c-></code> now handles <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>error_code</c-></code> specially by throwing a <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>system_error</c-></code> on failure.</p>
    <li data-md>
     <p>Fix how ADL isolation from class template arguments is specified so it
doesn’t constrain implmentations.</p>
    <li data-md>
     <p>Properly expose the tag types in the header <code class="highlight"><c- o>&lt;</c-><c- n>execution</c-><c- o>></c-></code> synopsis.</p>
   </ul>
   <p><b>Enhancements:</b></p>
   <ul>
    <li data-md>
     <p>Support for "dependently-typed" senders, where the completion signatures -- and
thus the sender metadata -- depend on the type of the receiver connected
to it. See the section <a href="#dependently-typed-senders">dependently-typed
senders</a> below for more information.</p>
    <li data-md>
     <p>Add a <code class="highlight"><c- n>read</c-><c- p>(</c-><i><c- n>query</c-></i><c- p>)</c-></code> sender factory for issuing a query
against a receiver and sending the result through the value channel. (This is
a useful instance of a dependently-typed sender.)</p>
    <li data-md>
     <p>Add <code class="highlight"><c- n>completion_signatures</c-></code> utility for declaratively defining a typed
sender’s metadata.</p>
    <li data-md>
     <p>Add <code class="highlight"><c- n>make_completion_signatures</c-></code> utility for specifying a sender’s completion
signatures by adapting those of another sender.</p>
    <li data-md>
     <p>Drop support for untyped senders and rename <code class="highlight"><c- n>typed_sender</c-></code> to <code class="highlight"><c- n>sender</c-></code>.</p>
    <li data-md>
     <p><code class="highlight"><c- n>set_done</c-></code> is renamed to <code class="highlight"><c- n>set_stopped</c-></code>. All occurances of "<code class="highlight"><c- n>done</c-></code>" in
indentifiers replaced with "<code class="highlight"><c- n>stopped</c-></code>"</p>
    <li data-md>
     <p>Add customization points for controlling the forwarding of scheduler,
sender, receiver, and environment queries through layers of adaptors;
specify the behavior of the standard adaptors in terms of the new
customization points.</p>
    <li data-md>
     <p>Add <code class="highlight"><c- n>get_delegatee_scheduler</c-></code> query to forward a scheduler that can be used
by algorithms or by the scheduler to delegate work and forward progress.</p>
    <li data-md>
     <p>Add <code class="highlight"><c- n>schedule_result_t</c-></code> alias template.</p>
    <li data-md>
     <p>More precisely specify the sender algorithms, including precisely what their
completion signatures are.</p>
    <li data-md>
     <p><code class="highlight"><c- n>stopped_as_error</c-></code> respecified as a customization point object.</p>
    <li data-md>
     <p><code class="highlight"><c- n>tag_invoke</c-></code> respecified to improve diagnostics.</p>
   </ul>
   <h4 class="heading settled" data-level="2.5.1" id="dependently-typed-senders"><span class="secno">2.5.1. </span><span class="content">Dependently-typed senders</span><a class="self-link" href="#dependently-typed-senders"></a></h4>
   <p><strong>Background:</strong></p>
   <p>In the sender/receiver model, as with coroutines, contextual information about
the current execution is most naturally propagated from the consumer to the
producer. In coroutines, that means information like stop tokens, allocators and
schedulers are propagated from the calling coroutine to the callee. In
sender/receiver, that means that that contextual information is associated with
the receiver and is queried by the sender and/or operation state after the
sender and the receiver are <code class="highlight"><c- n>connect</c-></code>-ed.</p>
   <p><strong>Problem:</strong></p>
   <p>The implication of the above is that the sender alone does not have all the
information about the async computation it will ultimately initiate; some of
that information is provided late via the receiver. However, the <code class="highlight"><c- n>sender_traits</c-></code> mechanism, by which an algorithm can introspect the value and error types the
sender will propagate, <em>only</em> accepts a sender parameter. It does not take into
consideration the type information that will come in late via the receiver. The
effect of this is that some senders cannot be typed senders when they
otherwise could be.</p>
   <p><strong>Example:</strong></p>
   <p>To get concrete, consider the case of the "<code class="highlight"><c- n>get_scheduler</c-><c- p>()</c-></code>" sender: when <code class="highlight"><c- n>connect</c-></code>-ed and <code class="highlight"><c- n>start</c-></code>-ed, it queries the receiver for its associated
scheduler and passes it back to the receiver through the value channel. That
sender’s "value type" is the type of the <em>receiver’s</em> scheduler. What then
should <code class="highlight"><c- n>sender_traits</c-><c- o>&lt;</c-><c- n>get_scheduler_sender</c-><c- o>>::</c-><c- n>value_types</c-></code> report for the <code class="highlight"><c- n>get_scheduler</c-><c- p>()</c-></code>'s value type? It can’t answer because it doesn’t know.</p>
   <p>This causes knock-on problems since some important algorithms require a typed
sender, such as <code class="highlight"><c- n>sync_wait</c-></code>. To illustrate the problem, consider the following
code:</p>
<pre class="highlight"><c- k>namespace</c-> <c- nn>ex</c-> <c- o>=</c-> <c- nn>std</c-><c- o>::</c-><c- nn>execution</c-><c- p>;</c->

<c- n>ex</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>task</c-> <c- o>=</c->
  <c- n>ex</c-><c- o>::</c-><c- n>let_value</c-><c- p>(</c->
    <c- n>ex</c-><c- o>::</c-><c- n>get_scheduler</c-><c- p>(),</c-> <c- c1>// Fetches scheduler from receiver.</c->
    <c- p>[](</c-><c- k>auto</c-> <c- n>current_sched</c-><c- p>)</c-> <c- p>{</c->
      <c- c1>// Lauch some nested work on the current scheduler:</c->
      <c- k>return</c-> <c- n>ex</c-><c- o>::</c-><c- n>on</c-><c- p>(</c-><c- n>current_sched</c-><c- p>,</c-> <i><c- n>nested</c-> <c- n>work</c-><c- p>...</c-></i><c- p>);</c->
    <c- p>});</c->

<c- n>std</c-><c- o>::</c-><c- n>this_thread</c-><c- o>::</c-><c- n>sync_wait</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>task</c-><c- p>));</c->
</pre>
   <p>The code above is attempting to schedule some work onto the <code class="highlight"><c- n>sync_wait</c-></code>'s <code class="highlight"><c- n>run_loop</c-></code> execution resource. But <code class="highlight"><c- n>let_value</c-></code> only returns a typed sender when
the input sender is typed. As we explained above, <code class="highlight"><c- n>get_scheduler</c-><c- p>()</c-></code> is not
typed, so <code class="highlight"><c- n>task</c-></code> is likewise not typed. Since <code class="highlight"><c- n>task</c-></code> isn’t typed, it cannot be
passed to <code class="highlight"><c- n>sync_wait</c-></code> which is expecting a typed sender. The above code would
fail to compile.</p>
   <p><strong>Solution:</strong></p>
   <p>The solution is conceptually quite simple: extend the <code class="highlight"><c- n>sender_traits</c-></code> mechanism
to optionally accept a receiver in addition to the sender. The algorithms can
use <code class="highlight"><c- n>sender_traits</c-><c- o>&lt;</c-><i><c- n>Sender</c-></i><c- p>,</c-> <i><c- n>Receiver</c-></i><c- o>></c-></code> to inspect the
async operation’s completion-signals. The <code class="highlight"><c- n>typed_sender</c-></code> concept would also need
to take an optional receiver parameter. This is the simplest change, and it
would solve the immediate problem.</p>
   <p><strong>Design:</strong></p>
   <p>Using the receiver type to compute the sender traits turns out to have pitfalls
in practice. Many receivers make use of that type information in their
implementation. It is very easy to create cycles in the type system, leading to
inscrutible errors. The design pursued in R4 is to give receivers an associated <em>environment</em> object -- a bag of key/value pairs -- and to move the contextual
information (schedulers, etc) out of the receiver and into the environment. The <code class="highlight"><c- n>sender_traits</c-></code> template and the <code class="highlight"><c- n>typed_sender</c-></code> concept, rather than taking a
receiver, take an environment. This is a much more robust design.</p>
   <p>A further refinement of this design would be to separate the receiver and the
environment entirely, passing then as separate arguments along with the sender to <code class="highlight"><c- n>connect</c-></code>. This paper does not propose that change.</p>
   <p><strong>Impact:</strong></p>
   <p>This change, apart from increasing the expressive power of the sender/receiver abstraction, has the following impact:</p>
   <ul>
    <li data-md>
     <p>Typed senders become moderately more challenging to write. (The new <code class="highlight"><c- n>completion_signatures</c-></code> and <code class="highlight"><c- n>transform_completion_signatures</c-></code> utilities are added
to ease this extra burden.)</p>
    <li data-md>
     <p>Sender adaptor algorithms that previously constrained their sender arguments
to satisfy the <code class="highlight"><c- n>typed_sender</c-></code> concept can no longer do so as the receiver is
not available yet. This can result in type-checking that is done later, when <code class="highlight"><c- n>connect</c-></code> is ultimately called on the resulting sender adaptor.</p>
    <li data-md>
     <p>Operation states that own receivers that add to or change the environment
are typically larger by one pointer. It comes with the benefit of far fewer
indirections to evaluate queries.</p>
   </ul>
   <p><strong>"Has it been implemented?"</strong></p>
   <p>Yes, the reference implementation, which can be found at
https://github.com/NVIDIA/stdexec, has implemented this
design as well as some dependently-typed senders to confirm that it works.</p>
   <p><strong>Implementation experience</strong></p>
   <p>Although this change has not yet been made in libunifex, the most widely adopted sender/receiver implementation, a similar design can be found in Folly’s coroutine support library. In Folly.Coro, it is possible to await a special awaitable to obtain the current coroutine’s associated scheduler (called an executor in Folly).</p>
   <p>For instance, the following Folly code grabs the current executor, schedules a task for execution on that executor, and starts the resulting (scheduled) task by enqueueing it for execution.</p>
<pre class="language-c++ highlight"><c- c1>// From Facebook’s Folly open source library:</c->
<c- n>template</c-> <c- o>&lt;</c-><c- n>class</c-> <c- n>T</c-><c- o>></c->
<c- n>folly</c-><c- o>::</c-><c- n>coro</c-><c- o>::</c-><c- n>Task</c-><c- o>&lt;</c-><c- b>void</c-><c- o>></c-> <c- n>CancellableAsyncScope</c-><c- o>::</c-><c- n>co_schedule</c-><c- p>(</c-><c- n>folly</c-><c- o>::</c-><c- n>coro</c-><c- o>::</c-><c- n>Task</c-><c- o>&lt;</c-><c- n>T</c-><c- o>>&amp;&amp;</c-> <c- n>task</c-><c- p>)</c-> <c- p>{</c->
  <c- n>this</c-><c- o>-></c-><c- n>add</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>task</c-><c- p>).</c-><c- n>scheduleOn</c-><c- p>(</c-><c- n>co_await</c-> <c- n>co_current_executor</c-><c- p>));</c->
  <c- n>co_return</c-><c- p>;</c->
<c- p>}</c->
</pre>
   <p>Facebook relies heavily on this pattern in its coroutine code. But as described
above, this pattern doesn’t work with R3 of <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>execution</c-></code> because of the lack
of dependently-typed schedulers. The change to <code class="highlight"><c- n>sender_traits</c-></code> in R4 rectifies that.</p>
   <p><strong>Why now?</strong></p>
   <p>The authors are loathe to make any changes to the design, however small, at this
stage of the C++23 release cycle. But we feel that, for a relatively minor
design change -- adding an extra template parameter to <code class="highlight"><c- n>sender_traits</c-></code> and <code class="highlight"><c- n>typed_sender</c-></code> -- the returns are large enough to justify the change. And there
is no better time to make this change than as early as possible.</p>
   <p>One might wonder why this missing feature not been added to sender/receiver
before now. The designers of sender/receiver have long been aware of the need.
What was missing was a clean, robust, and simple design for the change, which we
now have.</p>
   <p><strong>Drive-by:</strong></p>
   <p>We took the opportunity to make an additional drive-by change: Rather than
providing the sender traits via a class template for users to specialize, we
changed it into a sender <em>query</em>: <code class="highlight"><c- n>get_completion_signatures</c-><c- p>(</c-><i><c- n>sender</c-></i><c- p>,</c-> <i><c- n>env</c-></i><c- p>)</c-></code>. That function’s return type is used as the sender’s traits.
The authors feel this leads to a more uniform design and gives sender authors a
straightforward way to make the value/error types dependent on the cv- and
ref-qualification of the sender if need be.</p>
   <p><strong>Details:</strong></p>
   <p>Below are the salient parts of the new support for dependently-typed senders in
R4:</p>
   <ul>
    <li data-md>
     <p>Receiver queries have been moved from the receiver into a separate environment
object.</p>
    <li data-md>
     <p>Receivers have an associated environment. The new <code class="highlight"><c- n>get_env</c-></code> CPO retrieves a
receiver’s environment. If a receiver doesn’t implement <code class="highlight"><c- n>get_env</c-></code>, it returns
an unspecified "empty" environment -- an empty struct.</p>
    <li data-md>
     <p><code class="highlight"><c- n>sender_traits</c-></code> now takes an optional <code class="highlight"><c- n>Env</c-></code> parameter that is used to
determine the error/value types.</p>
    <li data-md>
     <p>The primary <code class="highlight"><c- n>sender_traits</c-></code> template is replaced with a <code class="highlight"><c- n>completion_signatures_of_t</c-></code> alias implemented in terms of a new <code class="highlight"><c- n>get_completion_signatures</c-></code> CPO that dispatches
with <code class="highlight"><c- n>tag_invoke</c-></code>. <code class="highlight"><c- n>get_completion_signatures</c-></code> takes a sender and an optional
environment. A sender can customize this to specify its value/error types.</p>
    <li data-md>
     <p>Support for untyped senders is dropped. The <code class="highlight"><c- n>typed_sender</c-></code> concept has been
renamed to <code class="highlight"><c- n>sender</c-></code> and now takes an optional environment.</p>
    <li data-md>
     <p>The environment argument to the <code class="highlight"><c- n>sender</c-></code> concept and the <code class="highlight"><c- n>get_completion_signatures</c-></code> CPO defaults to <code class="highlight"><c- n>no_env</c-></code>. All environment queries fail (are ill-formed) when
passed an instance of <code class="highlight"><c- n>no_env</c-></code>.</p>
    <li data-md>
     <p>A type <code class="highlight"><c- n>S</c-></code> is required to satisfy <code class="highlight"><c- n>sender</c-><c- o>&lt;</c-><i><c- n>S</c-></i><c- o>></c-></code> to be
considered a sender. If it doesn’t know what types it will complete with
independent of an environment, it returns an instance of the placeholder
traits <code class="highlight"><c- n>dependent_completion_signatures</c-></code>.</p>
    <li data-md>
     <p>If a sender satisfies both <code class="highlight"><c- n>sender</c-><c- o>&lt;</c-><i><c- n>S</c-></i><c- o>></c-></code> and <code class="highlight"><c- n>sender</c-><c- o>&lt;</c-><i><c- n>S</c-></i><c- p>,</c-> <i><c- n>Env</c-></i><c- o>></c-></code>, then the completion signatures
for the two cannot be different in any way. It is possible for an
implementation to enforce this statically, but not required.</p>
    <li data-md>
     <p>All of the algorithms and examples have been updated to work with
dependently-typed senders.</p>
   </ul>
   <h3 class="heading settled" data-level="2.6" id="r3"><span class="secno">2.6. </span><span class="content">R3</span><a class="self-link" href="#r3"></a></h3>
   <p>The changes since R2 are as follows:</p>
   <p><b>Fixes:</b></p>
   <ul>
    <li data-md>
     <p>Fix specification of the <code class="highlight"><c- n>on</c-></code> algorithm to clarify lifetimes of
intermediate operation states and properly scope the <code class="highlight"><c- n>get_scheduler</c-></code> query.</p>
    <li data-md>
     <p>Fix a memory safety bug in the implementation of <code class="highlight"><i><c- n>connect</c-><c- o>-</c-><c- n>awaitable</c-></i></code>.</p>
    <li data-md>
     <p>Fix recursive definition of the <code class="highlight"><c- n>scheduler</c-></code> concept.</p>
   </ul>
   <p><b>Enhancements:</b></p>
   <ul>
    <li data-md>
     <p>Add <code class="highlight"><c- n>run_loop</c-></code> execution resource.</p>
    <li data-md>
     <p>Add <code class="highlight"><c- n>receiver_adaptor</c-></code> utility to simplify writing receivers.</p>
    <li data-md>
     <p>Require a scheduler’s sender to model <code class="highlight"><c- n>sender_of</c-></code> and provide a completion scheduler.</p>
    <li data-md>
     <p>Specify the cancellation scope of the <code class="highlight"><c- n>when_all</c-></code> algorithm.</p>
    <li data-md>
     <p>Make <code class="highlight"><c- n>as_awaitable</c-></code> a customization point.</p>
    <li data-md>
     <p>Change <code class="highlight"><c- n>connect</c-></code>'s handling of awaitables to consider those types that are awaitable owing to customization of <code class="highlight"><c- n>as_awaitable</c-></code>.</p>
    <li data-md>
     <p>Add <code class="highlight"><c- n>value_types_of_t</c-></code> and <code class="highlight"><c- n>error_types_of_t</c-></code> alias templates; rename <code class="highlight"><c- n>stop_token_type_t</c-></code> to <code class="highlight"><c- n>stop_token_of_t</c-></code>.</p>
    <li data-md>
     <p>Add a design rationale for the removal of the possibly eager algorithms.</p>
    <li data-md>
     <p>Expand the section on field experience.</p>
   </ul>
   <h3 class="heading settled" data-level="2.7" id="r2"><span class="secno">2.7. </span><span class="content">R2</span><a class="self-link" href="#r2"></a></h3>
   <p>The changes since R1 are as follows:</p>
   <ul>
    <li data-md>
     <p>Remove the eagerly executing sender algorithms.</p>
    <li data-md>
     <p>Extend the <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>connect</c-></code> customization point and the <code class="highlight"><c- n>sender_traits</c-><c- o>&lt;></c-></code> template to recognize awaitables as <code class="highlight"><c- n>typed_sender</c-></code>s.</p>
    <li data-md>
     <p>Add utilities <code class="highlight"><c- n>as_awaitable</c-><c- p>()</c-></code> and <code class="highlight"><c- n>with_awaitable_senders</c-><c- o>&lt;></c-></code> so a coroutine type can trivially make senders awaitable with a coroutine.</p>
    <li data-md>
     <p>Add a section describing the design of the sender/awaitable interactions.</p>
    <li data-md>
     <p>Add a section describing the design of the cancellation support in sender/receiver.</p>
    <li data-md>
     <p>Add a section showing examples of simple sender adaptor algorithms.</p>
    <li data-md>
     <p>Add a section showing examples of simple schedulers.</p>
    <li data-md>
     <p>Add a few more examples: a sudoku solver, a parallel recursive file copy, and an echo server.</p>
    <li data-md>
     <p>Refined the forward progress guarantees on the <code class="highlight"><c- n>bulk</c-></code> algorithm.</p>
    <li data-md>
     <p>Add a section describing how to use a range of senders to represent async sequences.</p>
    <li data-md>
     <p>Add a section showing how to use senders to represent partial success.</p>
    <li data-md>
     <p>Add sender factories <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>just_error</c-></code> and <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>just_stopped</c-></code>.</p>
    <li data-md>
     <p>Add sender adaptors <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>stopped_as_optional</c-></code> and <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>stopped_as_error</c-></code>.</p>
    <li data-md>
     <p>Document more production uses of sender/receiver at scale.</p>
    <li data-md>
     <p>Various fixes of typos and bugs.</p>
   </ul>
   <h3 class="heading settled" data-level="2.8" id="r1"><span class="secno">2.8. </span><span class="content">R1</span><a class="self-link" href="#r1"></a></h3>
   <p>The changes since R0 are as follows:</p>
   <ul>
    <li data-md>
     <p>Added a new concept, <code class="highlight"><c- n>sender_of</c-></code>.</p>
    <li data-md>
     <p>Added a new scheduler query, <code class="highlight"><c- n>this_thread</c-><c- o>::</c-><c- n>execute_may_block_caller</c-></code>.</p>
    <li data-md>
     <p>Added a new scheduler query, <code class="highlight"><c- n>get_forward_progress_guarantee</c-></code>.</p>
    <li data-md>
     <p>Removed the <code class="highlight"><c- n>unschedule</c-></code> adaptor.</p>
    <li data-md>
     <p>Various fixes of typos and bugs.</p>
   </ul>
   <h3 class="heading settled" data-level="2.9" id="r0"><span class="secno">2.9. </span><span class="content">R0</span><a class="self-link" href="#r0"></a></h3>
   <p>Initial revision.</p>
   <h2 class="heading settled" data-level="3" id="design-intro"><span class="secno">3. </span><span class="content">Design - introduction</span><a class="self-link" href="#design-intro"></a></h2>
   <p>The following three sections describe the entirety of the proposed design.</p>
   <ul>
    <li data-md>
     <p><a href="#design-intro">§ 3 Design - introduction</a> describes the conventions used through the rest of the
design sections, as well as an example illustrating how we envision code will
be written using this proposal.</p>
    <li data-md>
     <p><a href="#design-user">§ 4 Design - user side</a> describes all the functionality from the perspective we
intend for users: it describes the various concepts they will interact with,
and what their programming model is.</p>
    <li data-md>
     <p><a href="#design-implementer">§ 5 Design - implementer side</a> describes the machinery that allows for that
programming model to function, and the information contained there is
necessary for people implementing senders and sender algorithms (including the
standard library ones) - but is not necessary to use senders productively.</p>
   </ul>
   <h3 class="heading settled" data-level="3.1" id="design-conventions"><span class="secno">3.1. </span><span class="content">Conventions</span><a class="self-link" href="#design-conventions"></a></h3>
   <p>The following conventions are used throughout the design section:</p>
   <ol>
    <li data-md>
     <p>The namespace proposed in this paper is the same as in <a data-link-type="biblio" href="https://wg21.link/p0443r14"><cite>A Unified Executors Proposal for C++</cite></a>: <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>execution</c-></code>; however, for brevity, the <code class="highlight"><c- n>std</c-><c- o>::</c-></code> part of this name is
  omitted. When you see <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>foo</c-></code>, treat that as <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>execution</c-><c- o>::</c-><c- n>foo</c-></code>.</p>
    <li data-md>
     <p>Universal references and explicit calls to <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>move</c-></code>/<code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>forward</c-></code> are
  omitted in code samples and signatures for simplicity; assume universal
  references and perfect forwarding unless stated otherwise.</p>
    <li data-md>
     <p>None of the names proposed here are names that we are particularly attached
  to; consider the names to be reasonable placeholders that can freely be
  changed, should the committee want to do so.</p>
   </ol>
   <h3 class="heading settled" data-level="3.2" id="design-queries-and-algorithms"><span class="secno">3.2. </span><span class="content">Queries and algorithms</span><a class="self-link" href="#design-queries-and-algorithms"></a></h3>
   <p>A <strong>query</strong> is a callable that takes some set of objects (usually one) as
parameters and returns facts about those objects without modifying them. Queries
are usually customization point objects, but in some cases may be functions.</p>
   <p>An <strong>algorithm</strong> is a callable that takes some set of objects as parameters and
causes those objects to do something. Algorithms are usually customization point
objects, but in some cases may be functions.</p>
   <h2 class="heading settled" data-level="4" id="design-user"><span class="secno">4. </span><span class="content">Design - user side</span><a class="self-link" href="#design-user"></a></h2>
   <h3 class="heading settled" data-level="4.1" id="design-contexts"><span class="secno">4.1. </span><span class="content">Execution resources describe the place of execution</span><a class="self-link" href="#design-contexts"></a></h3>
   <p>An <a data-link-type="dfn" href="#execution-resource" id="ref-for-execution-resource">execution resource</a> is a resource that represents the <em>place</em> where
execution will happen. This could be a concrete resource - like a specific
thread pool object, or a GPU - or a more abstract one, like the current thread
of execution. Execution contexts don’t need to have a representation in code;
they are simply a term describing certain properties of execution of a function.</p>
   <h3 class="heading settled" data-level="4.2" id="design-schedulers"><span class="secno">4.2. </span><span class="content">Schedulers represent execution resources</span><a class="self-link" href="#design-schedulers"></a></h3>
   <p>A <a data-link-type="dfn" href="#scheduler" id="ref-for-scheduler">scheduler</a> is a lightweight handle that represents a strategy for
scheduling work onto an execution resource. Since execution resources don’t
necessarily manifest in C++ code, it’s not possible to program directly against
their API. A scheduler is a solution to that problem: the scheduler concept is
defined by a single sender algorithm, <code class="highlight"><c- n>schedule</c-></code>, which returns a sender that
will complete on an execution resource determined by the scheduler. Logic that
you want to run on that context can be placed in the receiver’s
completion-signalling method.</p>
<pre class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>scheduler</c-> <c- k>auto</c-> <c- n>sch</c-> <c- o>=</c-> <c- n>thread_pool</c-><c- p>.</c-><c- n>scheduler</c-><c- p>();</c->
<c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>snd</c-> <c- o>=</c-> <c- n>execution</c-><c- o>::</c-><c- n>schedule</c-><c- p>(</c-><c- n>sch</c-><c- p>);</c->
<c- c1>// snd is a sender (see below) describing the creation of a new execution resource</c->
<c- c1>// on the execution resource associated with sch</c->
</pre>
   <p>Note that a particular scheduler type may provide other kinds of scheduling operations
which are supported by its associated execution resource. It is not limited to scheduling
purely using the <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>schedule</c-></code> API.</p>
   <p>Future papers will propose additional scheduler concepts that extend <code class="highlight"><c- n>scheduler</c-></code> to add other capabilities. For example:</p>
   <ul>
    <li data-md>
     <p>A <code class="highlight"><c- n>time_scheduler</c-></code> concept that extends <code class="highlight"><c- n>scheduler</c-></code> to support time-based
scheduling. Such a concept might provide access to <code class="highlight"><c- n>schedule_after</c-><c- p>(</c-><c- n>sched</c-><c- p>,</c-> <c- n>duration</c-><c- p>)</c-></code>, <code class="highlight"><c- n>schedule_at</c-><c- p>(</c-><c- n>sched</c-><c- p>,</c-> <c- n>time_point</c-><c- p>)</c-></code> and <code class="highlight"><c- n>now</c-><c- p>(</c-><c- n>sched</c-><c- p>)</c-></code> APIs.</p>
    <li data-md>
     <p>Concepts that extend <code class="highlight"><c- n>scheduler</c-></code> to support opening, reading and writing files
asynchronously.</p>
    <li data-md>
     <p>Concepts that extend <code class="highlight"><c- n>scheduler</c-></code> to support connecting, sending data and
receiving data over the network asynchronously.</p>
   </ul>
   <h3 class="heading settled" data-level="4.3" id="design-senders"><span class="secno">4.3. </span><span class="content">Senders describe work</span><a class="self-link" href="#design-senders"></a></h3>
   <p>A <a data-link-type="dfn" href="#sender" id="ref-for-sender">sender</a> is an object that describes work. Senders are similar to futures in
existing asynchrony designs, but unlike futures, the work that is being done to
arrive at the values they will <em>send</em> is also directly described by the sender
object itself. A sender is said to <em>send</em> some values if a receiver connected
(see <a href="#design-connect">§ 5.3 execution::connect</a>) to that sender will eventually <em>receive</em> said values.</p>
   <p>The primary defining sender algorithm is <a href="#design-connect">§ 5.3 execution::connect</a>; this function,
however, is not a user-facing API; it is used to facilitate communication
between senders and various sender algorithms, but end user code is not expected
to invoke it directly.</p>
   <p>The way user code is expected to interact with senders is by using <a data-link-type="dfn" href="#sender-algorithm" id="ref-for-sender-algorithm">sender
algorithms</a>. This paper proposes an initial set of such sender algorithms,
which are described in <a href="#design-composable">§ 4.4 Senders are composable through sender algorithms</a>, <a href="#design-sender-factories">§ 4.19 User-facing sender factories</a>, <a href="#design-sender-adaptors">§ 4.20 User-facing sender adaptors</a>, and <a href="#design-sender-consumers">§ 4.21 User-facing sender consumers</a>. For example, here
is how a user can create a new sender on a scheduler, attach a continuation to
it, and then wait for execution of the continuation to complete:</p>
<pre class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>scheduler</c-> <c- k>auto</c-> <c- n>sch</c-> <c- o>=</c-> <c- n>thread_pool</c-><c- p>.</c-><c- n>scheduler</c-><c- p>();</c->
<c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>snd</c-> <c- o>=</c-> <c- n>execution</c-><c- o>::</c-><c- n>schedule</c-><c- p>(</c-><c- n>sch</c-><c- p>);</c->
<c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>cont</c-> <c- o>=</c-> <c- n>execution</c-><c- o>::</c-><c- n>then</c-><c- p>(</c-><c- n>snd</c-><c- p>,</c-> <c- p>[]{</c->
    <c- n>std</c-><c- o>::</c-><c- n>fstream</c-> <c- n>file</c-><c- p>{</c-> <c- s>"result.txt"</c-> <c- p>};</c->
    <c- n>file</c-> <c- o>&lt;&lt;</c-> <c- n>compute_result</c-><c- p>;</c->
<c- p>});</c->

<c- n>this_thread</c-><c- o>::</c-><c- n>sync_wait</c-><c- p>(</c-><c- n>cont</c-><c- p>);</c->
<c- c1>// at this point, cont has completed execution</c->
</pre>
   <h3 class="heading settled" data-level="4.4" id="design-composable"><span class="secno">4.4. </span><span class="content">Senders are composable through sender algorithms</span><a class="self-link" href="#design-composable"></a></h3>
   <p>Asynchronous programming often departs from traditional code structure and control flow that we are familiar with.
A successful asynchronous framework must provide an intuitive story for composition of asynchronous work: expressing dependencies, passing objects, managing object lifetimes, etc.</p>
   <p>The true power and utility of senders is in their composability.
With senders, users can describe generic execution pipelines and graphs, and then run them on and across a variety of different schedulers.
Senders are composed using <a data-link-type="dfn" href="#sender-algorithm" id="ref-for-sender-algorithm①">sender algorithms</a>:</p>
   <ul>
    <li data-md>
     <p><a data-link-type="dfn" href="#sender-factory" id="ref-for-sender-factory">sender factories</a>, algorithms that take no senders and return a sender.</p>
    <li data-md>
     <p><a data-link-type="dfn" href="#sender-adaptor" id="ref-for-sender-adaptor">sender adaptors</a>, algorithms that take (and potentially <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>connect</c-></code>) senders and return a sender.</p>
    <li data-md>
     <p><a data-link-type="dfn" href="#sender-consumer" id="ref-for-sender-consumer">sender consumers</a>, algorithms that take (and potentially <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>connect</c-></code>) senders and do not return a sender.</p>
   </ul>
   <h3 class="heading settled" data-level="4.5" id="design-propagation"><span class="secno">4.5. </span><span class="content">Senders can propagate completion schedulers</span><a class="self-link" href="#design-propagation"></a></h3>
   <p>One of the goals of executors is to support a diverse set of execution resources, including traditional thread pools, task and fiber frameworks (like <a href="https://github.com/STEllAR-GROUP/hpx">HPX</a> and <a href="https://github.com/StanfordLegion/legion">Legion</a>), and GPUs and other accelerators (managed by runtimes such as CUDA or SYCL).
On many of these systems, not all execution agents are created equal and not all functions can be run on all execution agents.
Having precise control over the execution resource used for any given function call being submitted is important on such systems, and the users of standard execution facilities will expect to be able to express such requirements.</p>
   <p><a data-link-type="biblio" href="https://wg21.link/p0443r14"><cite>A Unified Executors Proposal for C++</cite></a> was not always clear about the <i>place of execution</i> of any given piece of code.
Precise control was present in the two-way execution API present in earlier executor designs, but it has so far been missing from the senders design. There has been a proposal (<a data-link-type="biblio" href="https://wg21.link/p1897r3"><cite>Towards C++23 executors: A proposal for an initial set of algorithms</cite></a>) to provide a number of sender algorithms that would enforce certain rules on the places of execution
of the work described by a sender, but we have found those sender algorithms to be insufficient for achieving the best performance on all platforms that are of interest to us. The implementation strategies that we are aware of result in one of the following situations:</p>
   <ol>
    <li data-md>
     <p>trying to submit work to one execution resource (such as a CPU thread pool) from another execution resource (such as a GPU or a task framework), which assumes that all execution agents are as capable as a <code class="highlight"><c- n>std</c-><c- o>::</c-><c- kr>thread</c-></code> (which they aren’t).</p>
    <li data-md>
     <p>forcibly interleaving two adjacent execution graph nodes that are both executing on one execution resource (such as a GPU) with glue code that runs on another execution resource (such as a CPU), which is prohibitively expensive for some execution resources (such as CUDA or SYCL).</p>
    <li data-md>
     <p>having to customise most or all sender algorithms to support an execution resource, so that you can avoid problems described in 1. and 2, which we believe is impractical and brittle based on months of field experience attempting this in <a href="https://github.com/agency-library/agency">Agency</a>.</p>
   </ol>
   <p>None of these implementation strategies are acceptable for many classes of parallel runtimes, such as task frameworks (like <a href="https://github.com/STEllAR-GROUP/hpx">HPX</a>) or accelerator runtimes (like CUDA or SYCL).</p>
   <p>Therefore, in addition to the <code class="highlight"><c- n>on</c-></code> sender algorithm from <a data-link-type="biblio" href="https://wg21.link/p1897r3"><cite>Towards C++23 executors: A proposal for an initial set of algorithms</cite></a>, we are proposing a way for senders to advertise what scheduler (and by extension what execution resource) they will complete on.
Any given sender <b>may</b> have <a data-link-type="dfn" href="#completion-scheduler" id="ref-for-completion-scheduler">completion schedulers</a> for some or all of the signals (value, error, or stopped) it completes with (for more detail on the completion-signals, see <a href="#design-receivers">§ 5.1 Receivers serve as glue between senders</a>).
When further work is attached to that sender by invoking sender algorithms, that work will also complete on an appropriate completion scheduler.</p>
   <h4 class="heading settled" data-level="4.5.1" id="design-sender-query-get_completion_scheduler"><span class="secno">4.5.1. </span><span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>get_completion_scheduler</c-></code></span><a class="self-link" href="#design-sender-query-get_completion_scheduler"></a></h4>
   <p><code class="highlight"><c- n>get_completion_scheduler</c-></code> is a query that retrieves the completion scheduler for a specific completion-signal from a sender’s environment.
For a sender that lacks a completion scheduler query for a given signal, calling <code class="highlight"><c- n>get_completion_scheduler</c-></code> is ill-formed.
If a sender advertises a completion scheduler for a signal in this way, that sender <b>must</b> ensure that it <a data-link-type="dfn" href="#send" id="ref-for-send">sends</a> that signal on an execution agent belonging to an execution resource represented by a scheduler returned from this function.
See <a href="#design-propagation">§ 4.5 Senders can propagate completion schedulers</a> for more details.</p>
<pre class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>scheduler</c-> <c- k>auto</c-> <c- n>cpu_sched</c-> <c- o>=</c-> <c- n>new_thread_scheduler</c-><c- p>{};</c->
<c- n>execution</c-><c- o>::</c-><c- n>scheduler</c-> <c- k>auto</c-> <c- n>gpu_sched</c-> <c- o>=</c-> <c- n>cuda</c-><c- o>::</c-><c- n>scheduler</c-><c- p>();</c->

<c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>snd0</c-> <c- o>=</c-> <c- n>execution</c-><c- o>::</c-><c- n>schedule</c-><c- p>(</c-><c- n>cpu_sched</c-><c- p>);</c->
<c- n>execution</c-><c- o>::</c-><c- n>scheduler</c-> <c- k>auto</c-> <c- n>completion_sch0</c-> <c- o>=</c->
  <c- n>execution</c-><c- o>::</c-><c- n>get_completion_scheduler</c-><c- o>&lt;</c-><c- n>execution</c-><c- o>::</c-><c- n>set_value_t</c-><c- o>></c-><c- p>(</c-><c- n>get_env</c-><c- p>(</c-><c- n>snd0</c-><c- p>));</c->
<c- c1>// completion_sch0 is equivalent to cpu_sched</c->

<c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>snd1</c-> <c- o>=</c-> <c- n>execution</c-><c- o>::</c-><c- n>then</c-><c- p>(</c-><c- n>snd0</c-><c- p>,</c-> <c- p>[]{</c->
    <c- n>std</c-><c- o>::</c-><c- n>cout</c-> <c- o>&lt;&lt;</c-> <c- s>"I am running on cpu_sched!</c-><c- se>\n</c-><c- s>"</c-><c- p>;</c->
<c- p>});</c->
<c- n>execution</c-><c- o>::</c-><c- n>scheduler</c-> <c- k>auto</c-> <c- n>completion_sch1</c-> <c- o>=</c->
  <c- n>execution</c-><c- o>::</c-><c- n>get_completion_scheduler</c-><c- o>&lt;</c-><c- n>execution</c-><c- o>::</c-><c- n>set_value_t</c-><c- o>></c-><c- p>(</c-><c- n>get_env</c-><c- p>(</c-><c- n>snd1</c-><c- p>));</c->
<c- c1>// completion_sch1 is equivalent to cpu_sched</c->

<c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>snd2</c-> <c- o>=</c-> <c- n>execution</c-><c- o>::</c-><c- n>transfer</c-><c- p>(</c-><c- n>snd1</c-><c- p>,</c-> <c- n>gpu_sched</c-><c- p>);</c->
<c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>snd3</c-> <c- o>=</c-> <c- n>execution</c-><c- o>::</c-><c- n>then</c-><c- p>(</c-><c- n>snd2</c-><c- p>,</c-> <c- p>[]{</c->
    <c- n>std</c-><c- o>::</c-><c- n>cout</c-> <c- o>&lt;&lt;</c-> <c- s>"I am running on gpu_sched!</c-><c- se>\n</c-><c- s>"</c-><c- p>;</c->
<c- p>});</c->
<c- n>execution</c-><c- o>::</c-><c- n>scheduler</c-> <c- k>auto</c-> <c- n>completion_sch3</c-> <c- o>=</c->
  <c- n>execution</c-><c- o>::</c-><c- n>get_completion_scheduler</c-><c- o>&lt;</c-><c- n>execution</c-><c- o>::</c-><c- n>set_value_t</c-><c- o>></c-><c- p>(</c-><c- n>get_env</c-><c- p>(</c-><c- n>snd3</c-><c- p>));</c->
<c- c1>// completion_sch3 is equivalent to gpu_sched</c->
</pre>
   <h3 class="heading settled" data-level="4.6" id="design-transitions"><span class="secno">4.6. </span><span class="content">Execution resource transitions are explicit</span><a class="self-link" href="#design-transitions"></a></h3>
   <p><a data-link-type="biblio" href="https://wg21.link/p0443r14"><cite>A Unified Executors Proposal for C++</cite></a> does not contain any mechanisms for performing an execution resource transition. The only sender algorithm that can create a sender that will move execution to a <em>specific</em> execution resource is <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>schedule</c-></code>, which does not take an input sender.
That means that there’s no way to construct sender chains that traverse different execution resources. This is necessary to fulfill the promise of senders being able to replace two-way executors, which had this capability.</p>
   <p>We propose that, for senders advertising their <a data-link-type="dfn" href="#completion-scheduler" id="ref-for-completion-scheduler①">completion scheduler</a>, all execution resource transitions <b>must</b> be explicit; running user code anywhere but where they defined it to run <b>must</b> be considered a bug.</p>
   <p>The <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>transfer</c-></code> sender adaptor performs a transition from one execution resource to another:</p>
<pre class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>scheduler</c-> <c- k>auto</c-> <c- n>sch1</c-> <c- o>=</c-> <c- p>...;</c->
<c- n>execution</c-><c- o>::</c-><c- n>scheduler</c-> <c- k>auto</c-> <c- n>sch2</c-> <c- o>=</c-> <c- p>...;</c->

<c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>snd1</c-> <c- o>=</c-> <c- n>execution</c-><c- o>::</c-><c- n>schedule</c-><c- p>(</c-><c- n>sch1</c-><c- p>);</c->
<c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>then1</c-> <c- o>=</c-> <c- n>execution</c-><c- o>::</c-><c- n>then</c-><c- p>(</c-><c- n>snd1</c-><c- p>,</c-> <c- p>[]{</c->
    <c- n>std</c-><c- o>::</c-><c- n>cout</c-> <c- o>&lt;&lt;</c-> <c- s>"I am running on sch1!</c-><c- se>\n</c-><c- s>"</c-><c- p>;</c->
<c- p>});</c->

<c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>snd2</c-> <c- o>=</c-> <c- n>execution</c-><c- o>::</c-><c- n>transfer</c-><c- p>(</c-><c- n>then1</c-><c- p>,</c-> <c- n>sch2</c-><c- p>);</c->
<c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>then2</c-> <c- o>=</c-> <c- n>execution</c-><c- o>::</c-><c- n>then</c-><c- p>(</c-><c- n>snd2</c-><c- p>,</c-> <c- p>[]{</c->
    <c- n>std</c-><c- o>::</c-><c- n>cout</c-> <c- o>&lt;&lt;</c-> <c- s>"I am running on sch2!</c-><c- se>\n</c-><c- s>"</c-><c- p>;</c->
<c- p>});</c->

<c- n>this_thread</c-><c- o>::</c-><c- n>sync_wait</c-><c- p>(</c-><c- n>then2</c-><c- p>);</c->
</pre>
   <h3 class="heading settled" data-level="4.7" id="design-shot"><span class="secno">4.7. </span><span class="content">Senders can be either multi-shot or single-shot</span><a class="self-link" href="#design-shot"></a></h3>
   <p>Some senders may only support launching their operation a single time, while others may be repeatable
and support being launched multiple times. Executing the operation may consume resources owned by the
sender.</p>
   <p>For example, a sender may contain a <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>unique_ptr</c-></code> that it will be transferring ownership of to the
operation-state returned by a call to <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>connect</c-></code> so that the operation has access to
this resource. In such a sender, calling <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>connect</c-></code> consumes the sender such that after
the call the input sender is no longer valid. Such a sender will also typically be move-only so that
it can maintain unique ownership of that resource.</p>
   <p>A <dfn data-dfn-type="dfn" data-export id="single-shot-sender">single-shot sender<a class="self-link" href="#single-shot-sender"></a></dfn> can only be connected to a receiver
at most once. Its implementation of <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>connect</c-></code> only has overloads for
an rvalue-qualified sender. Callers must pass the sender as an rvalue to the
call to <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>connect</c-></code>, indicating that the call consumes the sender.</p>
   <p>A <dfn data-dfn-type="dfn" data-export id="multi-shot-sender">multi-shot sender<a class="self-link" href="#multi-shot-sender"></a></dfn> can be connected to multiple
receivers and can be launched multiple times. Multi-shot senders customise <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>connect</c-></code> to accept an lvalue reference to the sender. Callers can
indicate that they want the sender to remain valid after the call to <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>connect</c-></code> by passing an lvalue reference to the sender to call these
overloads. Multi-shot senders should also define overloads of <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>connect</c-></code> that accept rvalue-qualified senders to allow the sender to
be also used in places where only a single-shot sender is required.</p>
   <p>If the user of a sender does not require the sender to remain valid after connecting it to a
receiver then it can pass an rvalue-reference to the sender to the call to <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>connect</c-></code>.
Such usages should be able to accept either single-shot or multi-shot senders.</p>
   <p>If the caller does wish for the sender to remain valid after the call then it can pass an lvalue-qualified sender
to the call to <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>connect</c-></code>. Such usages will only accept multi-shot senders.</p>
   <p>Algorithms that accept senders will typically either decay-copy an input sender and store it somewhere
for later usage (for example as a data-member of the returned sender) or will immediately call <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>connect</c-></code> on the input sender, such as in <code class="highlight"><c- n>this_thread</c-><c- o>::</c-><c- n>sync_wait</c-></code> or <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>start_detached</c-></code>.</p>
   <p>Some multi-use sender algorithms may require that an input sender be copy-constructible but will only call <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>connect</c-></code> on an rvalue of each copy, which still results in effectively executing the operation multiple times.
Other multi-use sender algorithms may require that the sender is move-constructible but will invoke <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>connect</c-></code> on an lvalue reference to the sender.</p>
   <p>For a sender to be usable in both multi-use scenarios, it will generally be required to be both copy-constructible and lvalue-connectable.</p>
   <h3 class="heading settled" data-level="4.8" id="design-forkable"><span class="secno">4.8. </span><span class="content">Senders are forkable</span><a class="self-link" href="#design-forkable"></a></h3>
   <p>Any non-trivial program will eventually want to fork a chain of senders into independent streams of work, regardless of whether they are single-shot or multi-shot.
For instance, an incoming event to a middleware system may be required to trigger events on more than one downstream system.
This requires that we provide well defined mechanisms for making sure that connecting a sender multiple times is possible and correct.</p>
   <p>The <code class="highlight"><c- n>split</c-></code> sender adaptor facilitates connecting to a sender multiple times, regardless of whether it is single-shot or multi-shot:</p>
<pre class="highlight"><c- k>auto</c-> <c- n>some_algorithm</c-><c- p>(</c-><c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-><c- o>&amp;&amp;</c-> <c- n>input</c-><c- p>)</c-> <c- p>{</c->
    <c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>multi_shot</c-> <c- o>=</c-> <c- n>split</c-><c- p>(</c-><c- n>input</c-><c- p>);</c->
    <c- c1>// "multi_shot" is guaranteed to be multi-shot,</c->
    <c- c1>// regardless of whether "input" was multi-shot or not</c->

    <c- k>return</c-> <c- n>when_all</c-><c- p>(</c->
      <c- n>then</c-><c- p>(</c-><c- n>multi_shot</c-><c- p>,</c-> <c- p>[]</c-> <c- p>{</c-> <c- n>std</c-><c- o>::</c-><c- n>cout</c-> <c- o>&lt;&lt;</c-> <c- s>"First continuation</c-><c- se>\n</c-><c- s>"</c-><c- p>;</c-> <c- p>}),</c->
      <c- n>then</c-><c- p>(</c-><c- n>multi_shot</c-><c- p>,</c-> <c- p>[]</c-> <c- p>{</c-> <c- n>std</c-><c- o>::</c-><c- n>cout</c-> <c- o>&lt;&lt;</c-> <c- s>"Second continuation</c-><c- se>\n</c-><c- s>"</c-><c- p>;</c-> <c- p>})</c->
    <c- p>);</c->
<c- p>}</c->
</pre>
   <h3 class="heading settled" data-level="4.9" id="design-cancellation"><span class="secno">4.9. </span><span class="content">Senders support cancellation</span><a class="self-link" href="#design-cancellation"></a></h3>
   <p>Senders are often used in scenarios where the application may be concurrently executing
multiple strategies for achieving some program goal. When one of these strategies succeeds
(or fails) it may not make sense to continue pursuing the other strategies as their results
are no longer useful.</p>
   <p>For example, we may want to try to simultaneously connect to multiple network servers and use
whichever server responds first. Once the first server responds we no longer need to continue
trying to connect to the other servers.</p>
   <p>Ideally, in these scenarios, we would somehow be able to request that those other strategies
stop executing promptly so that their resources (e.g. cpu, memory, I/O bandwidth) can be
released and used for other work.</p>
   <p>While the design of senders has support for cancelling an operation before it starts
by simply destroying the sender or the operation-state returned from <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>connect</c-><c- p>()</c-></code> before calling <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>start</c-><c- p>()</c-></code>, there also needs to be a standard, generic mechanism
to ask for an already-started operation to complete early.</p>
   <p>The ability to be able to cancel in-flight operations is fundamental to supporting some kinds
of generic concurrency algorithms.</p>
   <p>For example:</p>
   <ul>
    <li data-md>
     <p>a <code class="highlight"><c- n>when_all</c-><c- p>(</c-><c- n>ops</c-><c- p>...)</c-></code> algorithm should cancel other operations as soon as one operation fails</p>
    <li data-md>
     <p>a <code class="highlight"><c- n>first_successful</c-><c- p>(</c-><c- n>ops</c-><c- p>...)</c-></code> algorithm should cancel the other operations as soon as one operation completes successfuly</p>
    <li data-md>
     <p>a generic <code class="highlight"><c- n>timeout</c-><c- p>(</c-><c- n>src</c-><c- p>,</c-> <c- n>duration</c-><c- p>)</c-></code> algorithm needs to be able to cancel the <code class="highlight"><c- n>src</c-></code> operation after the timeout duration has elapsed.</p>
    <li data-md>
     <p>a <code class="highlight"><c- n>stop_when</c-><c- p>(</c-><c- n>src</c-><c- p>,</c-> <c- n>trigger</c-><c- p>)</c-></code> algorithm should cancel <code class="highlight"><c- n>src</c-></code> if <code class="highlight"><c- n>trigger</c-></code> completes first and cancel <code class="highlight"><c- n>trigger</c-></code> if <code class="highlight"><c- n>src</c-></code> completes first</p>
   </ul>
   <p>The mechanism used for communcating cancellation-requests, or stop-requests, needs to have a uniform interface
so that generic algorithms that compose sender-based operations, such as the ones listed above, are able to
communicate these cancellation requests to senders that they don’t know anything about.</p>
   <p>The design is intended to be composable so that cancellation of higher-level operations can propagate
those cancellation requests through intermediate layers to lower-level operations that need to actually
respond to the cancellation requests.</p>
   <p>For example, we can compose the algorithms mentioned above so that child operations
are cancelled when any one of the multiple cancellation conditions occurs:</p>
<pre class="highlight"><c- n>sender</c-> <c- k>auto</c-> <c- n>composed_cancellation_example</c-><c- p>(</c-><c- k>auto</c-> <c- n>query</c-><c- p>)</c-> <c- p>{</c->
  <c- k>return</c-> <c- n>stop_when</c-><c- p>(</c->
    <c- n>timeout</c-><c- p>(</c->
      <c- n>when_all</c-><c- p>(</c->
        <c- n>first_successful</c-><c- p>(</c->
          <c- n>query_server_a</c-><c- p>(</c-><c- n>query</c-><c- p>),</c->
          <c- n>query_server_b</c-><c- p>(</c-><c- n>query</c-><c- p>)),</c->
        <c- n>load_file</c-><c- p>(</c-><c- s>"some_file.jpg"</c-><c- p>)),</c->
      <c- mi>5</c-><c- n>s</c-><c- p>),</c->
    <c- n>cancelButton</c-><c- p>.</c-><c- n>on_click</c-><c- p>());</c->
<c- p>}</c->
</pre>
   <p>In this example, if we take the operation returned by <code class="highlight"><c- n>query_server_b</c-><c- p>(</c-><c- n>query</c-><c- p>)</c-></code>, this operation will
receive a stop-request when any of the following happens:</p>
   <ul>
    <li data-md>
     <p><code class="highlight"><c- n>first_successful</c-></code> algorithm will send a stop-request if <code class="highlight"><c- n>query_server_a</c-><c- p>(</c-><c- n>query</c-><c- p>)</c-></code> completes successfully</p>
    <li data-md>
     <p><code class="highlight"><c- n>when_all</c-></code> algorithm will send a stop-request if the <code class="highlight"><c- n>load_file</c-><c- p>(</c-><c- s>"some_file.jpg"</c-><c- p>)</c-></code> operation completes with an error or stopped result.</p>
    <li data-md>
     <p><code class="highlight"><c- n>timeout</c-></code> algorithm will send a stop-request if the operation does not complete within 5 seconds.</p>
    <li data-md>
     <p><code class="highlight"><c- n>stop_when</c-></code> algorithm will send a stop-request if the user clicks on the "Cancel" button in the user-interface.</p>
    <li data-md>
     <p>The parent operation consuming the <code class="highlight"><c- n>composed_cancellation_example</c-><c- p>()</c-></code> sends a stop-request</p>
   </ul>
   <p>Note that within this code there is no explicit mention of cancellation, stop-tokens, callbacks, etc.
yet the example fully supports and responds to the various cancellation sources.</p>
   <p>The intent of the design is that the common usage of cancellation in sender/receiver-based code is
primarily through use of concurrency algorithms that manage the detailed plumbing of cancellation
for you. Much like algorithms that compose senders relieve the user from having to write their own
receiver types, algorithms that introduce concurrency and provide higher-level cancellation semantics
relieve the user from having to deal with low-level details of cancellation.</p>
   <h4 class="heading settled" data-level="4.9.1" id="design-cancellation-summary"><span class="secno">4.9.1. </span><span class="content">Cancellation design summary</span><a class="self-link" href="#design-cancellation-summary"></a></h4>
   <p>The design of cancellation described in this paper is built on top of and extends the <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>stop_token</c-></code>-based
cancellation facilities added in C++20, first proposed in <a data-link-type="biblio" href="https://wg21.link/p2175r0"><cite>Composable cancellation for sender-based async operations</cite></a>.</p>
   <p>At a high-level, the facilities proposed by this paper for supporting cancellation include:</p>
   <ul>
    <li data-md>
     <p>Add <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>stoppable_token</c-></code> and <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>stoppable_token_for</c-></code> concepts that generalise the interface of <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>stop_token</c-></code> type to allow other types with different implementation strategies.</p>
    <li data-md>
     <p>Add <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>unstoppable_token</c-></code> concept for detecting whether a <code class="highlight"><c- n>stoppable_token</c-></code> can never receive a stop-request.</p>
    <li data-md>
     <p>Add <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>in_place_stop_token</c-></code>, <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>in_place_stop_source</c-></code> and <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>in_place_stop_callback</c-><c- o>&lt;</c-><c- n>CB</c-><c- o>></c-></code> types that provide a more efficient implementation of a stop-token for use in structured concurrency situations.</p>
    <li data-md>
     <p>Add <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>never_stop_token</c-></code> for use in places where you never want to issue a stop-request</p>
    <li data-md>
     <p>Add <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>execution</c-><c- o>::</c-><c- n>get_stop_token</c-><c- p>()</c-></code> CPO for querying the stop-token to use for an operation from its receiver’s execution environment.</p>
    <li data-md>
     <p>Add <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>execution</c-><c- o>::</c-><c- n>stop_token_of_t</c-><c- o>&lt;</c-><c- n>T</c-><c- o>></c-></code> for querying the type of a stop-token returned from <code class="highlight"><c- n>get_stop_token</c-><c- p>()</c-></code></p>
   </ul>
   <p>In addition, there are requirements added to some of the algorithms to specify what their cancellation
behaviour is and what the requirements of customisations of those algorithms are with respect to
cancellation.</p>
   <p>The key component that enables generic cancellation within sender-based operations is the <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>get_stop_token</c-><c- p>()</c-></code> CPO.
This CPO takes a single parameter, which is the execution environment of the receiver passed to <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>connect</c-></code>, and returns a <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>stoppable_token</c-></code> that the operation can use to check for stop-requests for that operation.</p>
   <p>As the caller of <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>connect</c-></code> typically has control over the receiver
type it passes, it is able to customise the <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>execution</c-><c- o>::</c-><c- n>get_env</c-><c- p>()</c-></code> CPO for that
receiver to return an execution environment that hooks the <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>get_stop_token</c-><c- p>()</c-></code> CPO to return a stop-token that the receiver has
control over and that it can use to communicate a stop-request to the operation
once it has started.</p>
   <h4 class="heading settled" data-level="4.9.2" id="design-cancellation-optional"><span class="secno">4.9.2. </span><span class="content">Support for cancellation is optional</span><a class="self-link" href="#design-cancellation-optional"></a></h4>
   <p>Support for cancellation is optional, both on part of the author of the receiver and on part of the author of the sender.</p>
   <p>If the receiver’s execution environment does not customise the <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>get_stop_token</c-><c- p>()</c-></code> CPO then invoking the CPO on that receiver’s
environment will invoke the default implementation which returns <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>never_stop_token</c-></code>. This is a special <code class="highlight"><c- n>stoppable_token</c-></code> type that is
statically known to always return <code class="highlight">false</code> from the <code class="highlight"><c- n>stop_possible</c-><c- p>()</c-></code> method.</p>
   <p>Sender code that tries to use this stop-token will in general result in code that handles stop-requests being
compiled out and having little to no run-time overhead.</p>
   <p>If the sender doesn’t call <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>get_stop_token</c-><c- p>()</c-></code>, for example because the operation does not support
cancellation, then it will simply not respond to stop-requests from the caller.</p>
   <p>Note that stop-requests are generally racy in nature as there is often a race betwen an operation completing
naturally and the stop-request being made. If the operation has already completed or past the point at which
it can be cancelled when the stop-request is sent then the stop-request may just be ignored. An application
will typically need to be able to cope with senders that might ignore a stop-request anyway.</p>
   <h4 class="heading settled" data-level="4.9.3" id="design-cancellation-racy"><span class="secno">4.9.3. </span><span class="content">Cancellation is inherently racy</span><a class="self-link" href="#design-cancellation-racy"></a></h4>
   <p>Usually, an operation will attach a stop-callback at some point inside the call to <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>start</c-><c- p>()</c-></code> so that
a subsequent stop-request will interrupt the logic.</p>
   <p>A stop-request can be issued concurrently from another thread. This means the implementation of <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>start</c-><c- p>()</c-></code> needs to be careful to ensure that, once a stop-callback has been registered, that there are no data-races between
a potentially concurrently-executing stop-callback and the rest of the <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>start</c-><c- p>()</c-></code> implementation.</p>
   <p>An implementation of <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>start</c-><c- p>()</c-></code> that supports cancellation will generally need to perform (at least)
two separate steps: launch the operation, subscribe a stop-callback to the receiver’s stop-token. Care needs
to be taken depending on the order in which these two steps are performed.</p>
   <p>If the stop-callback is subscribed first and then the operation is launched, care needs to be taken to ensure
that a stop-request that invokes the stop-callback on another thread after the stop-callback is registered
but before the operation finishes launching does not either result in a missed cancellation request or a
data-race. e.g. by performing an atomic write after the launch has finished executing</p>
   <p>If the operation is launched first and then the stop-callback is subscribed, care needs to be taken to ensure
that if the launched operation completes concurrently on another thread that it does not destroy the operation-state
until after the stop-callback has been registered. e.g. by having the <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>start</c-></code> implementation write to
an atomic variable once it has finished registering the stop-callback and having the concurrent completion handler
check that variable and either call the completion-signalling operation or store the result and defer calling the
receiver’s completion-signalling operation to the <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>start</c-><c- p>()</c-></code> call (which is still executing).</p>
   <p>For an example of an implementation strategy for solving these data-races see <a href="#example-async-windows-socket-recv">§ 1.4 Asynchronous Windows socket recv</a>.</p>
   <h4 class="heading settled" data-level="4.9.4" id="design-cancellation-status"><span class="secno">4.9.4. </span><span class="content">Cancellation design status</span><a class="self-link" href="#design-cancellation-status"></a></h4>
   <p>This paper currently includes the design for cancellation as proposed in <a data-link-type="biblio" href="https://wg21.link/p2175r0"><cite>Composable cancellation for sender-based async operations</cite></a> - "Composable cancellation for sender-based async operations".
P2175R0 contains more details on the background motivation and prior-art and design rationale of this design.</p>
   <p>It is important to note, however, that initial review of this design in the SG1 concurrency subgroup raised some concerns
related to runtime overhead of the design in single-threaded scenarios and these concerns are still being investigated.</p>
   <p>The design of P2175R0 has been included in this paper for now, despite its potential to change, as we believe that
support for cancellation is a fundamental requirement for an async model and is required in some form to be able to
talk about the semantics of some of the algorithms proposed in this paper.</p>
   <p>This paper will be updated in the future with any changes that arise from the investigations into P2175R0.</p>
   <h3 class="heading settled" data-level="4.10" id="design-lazy-algorithms"><span class="secno">4.10. </span><span class="content">Sender factories and adaptors are lazy</span><a class="self-link" href="#design-lazy-algorithms"></a></h3>
   <p>In an earlier revision of this paper, some of the proposed algorithms supported
executing their logic eagerly; <i>i.e.</i>, before the returned sender has been
connected to a receiver and started. These algorithms were removed because eager
execution has a number of negative semantic and performance implications.</p>
   <p>We have originally included this functionality in the paper because of a long-standing
belief that eager execution is a mandatory feature to be included in the standard Executors
facility for that facility to be acceptable for accelerator vendors. A particular concern
was that we must be able to write generic algorithms that can run either eagerly or lazily,
depending on the kind of an input sender or scheduler that have been passed into them as
arguments. We considered this a requirement, because the _latency_ of launching work on an
accelerator can sometimes be considerable.</p>
   <p>However, in the process of working on this paper and implementations of the features
proposed within, our set of requirements has shifted, as we understood the different
implementation strategies that are available for the feature set of this paper better,
and, after weighting the earlier concerns against the points presented below, we
have arrived at the conclusion that a purely lazy model is enough for most algorithms,
and users who intend to launch work earlier may use an algorithm such as <code class="highlight"><c- n>ensure_started</c-></code> to achieve that goal. We have also come to deeply appreciate the fact that a purely
lazy model allows both the implementation and the compiler to have a much better
understanding of what the complete graph of tasks looks like, allowing them to better
optimize the code - also when targetting accelerators.</p>
   <h4 class="heading settled" data-level="4.10.1" id="design-lazy-algorithms-detached"><span class="secno">4.10.1. </span><span class="content">Eager execution leads to detached work or worse</span><a class="self-link" href="#design-lazy-algorithms-detached"></a></h4>
   <p>One of the questions that arises with APIs that can potentially return
eagerly-executing senders is "What happens when those senders are destructed
without a call to <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>connect</c-></code>?" or similarly, "What happens if a call
to <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>connect</c-></code> is made, but the returned operation state is destroyed
before <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>start</c-></code> is called on that operation state"?</p>
   <p>In these cases, the operation represented by the sender is potentially executing
concurrently in another thread at the time that the destructor of the sender
and/or operation-state is running. In the case that the operation has not
completed executing by the time that the destructor is run we need to decide
what the semantics of the destructor is.</p>
   <p>There are three main strategies that can be adopted here, none of which is
particularly satisfactory:</p>
   <ol>
    <li data-md>
     <p>Make this undefined-behaviour - the caller must ensure that any
eagerly-executing sender is always joined by connecting and starting that
sender. This approach is generally pretty hostile to programmers,
particularly in the presence of exceptions, since it complicates the ability
to compose these operations.</p>
     <p>Eager operations typically need to acquire resources when they are first
called in order to start the operation early. This makes eager algorithms
prone to failure. Consider, then, what might happen in an expression such as <code class="highlight"><c- n>when_all</c-><c- p>(</c-><c- n>eager_op_1</c-><c- p>(),</c-> <c- n>eager_op_2</c-><c- p>())</c-></code>. Imagine <code class="highlight"><c- n>eager_op_1</c-><c- p>()</c-></code> starts an
asynchronous operation successfully, but then <code class="highlight"><c- n>eager_op_2</c-><c- p>()</c-></code> throws. For
lazy senders, that failure happens in the context of the <code class="highlight"><c- n>when_all</c-></code> algorithm, which handles the failure and ensures that async work joins on
all code paths. In this case though -- the eager case -- the child operation
has failed even before <code class="highlight"><c- n>when_all</c-></code> has been called.</p>
     <p>It then becomes the responsibility, not of the algorithm, but of the end
user to handle the exception and ensure that <code class="highlight"><c- n>eager_op_1</c-><c- p>()</c-></code> is joined before
allowing the exception to propagate. If they fail to do that, they incur
undefined behavior.</p>
    <li data-md>
     <p>Detach from the computation - let the operation continue in the background -
like an implicit call to <code class="highlight"><c- n>std</c-><c- o>::</c-><c- kr>thread</c-><c- o>::</c-><c- n>detach</c-><c- p>()</c-></code>. While this approach can
work in some circumstances for some kinds of applications, in general it is
also pretty user-hostile; it makes it difficult to reason about the safe
destruction of resources used by these eager operations. In general,
detached work necessitates some kind of garbage collection; <i>e.g.</i>, <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>shared_ptr</c-></code>, to ensure resources are kept alive until the operations
complete, and can make clean shutdown nigh impossible.</p>
    <li data-md>
     <p>Block in the destructor until the operation completes. This approach is
probably the safest to use as it preserves the structured nature of the
concurrent operations, but also introduces the potential for deadlocking the
application if the completion of the operation depends on the current thread
making forward progress.</p>
     <p>The risk of deadlock might occur, for example, if a thread-pool with a
small number of threads is executing code that creates a sender representing
an eagerly-executing operation and then calls the destructor of that sender
without joining it (e.g. because an exception was thrown). If the current
thread blocks waiting for that eager operation to complete and that eager
operation cannot complete until some entry enqueued to the thread-pool’s
queue of work is run then the thread may wait for an indefinite amount of
time. If all threads of the thread-pool are simultaneously performing such
blocking operations then deadlock can result.</p>
   </ol>
   <p>There are also minor variations on each of these choices. For example:</p>
   <ol start="4">
    <li data-md>
     <p>A variation of (1): Call <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>terminate</c-></code> if an eager sender is destructed
without joining it. This is the approach that <code class="highlight"><c- n>std</c-><c- o>::</c-><c- kr>thread</c-></code> destructor
takes.</p>
    <li data-md>
     <p>A variation of (2): Request cancellation of the operation before detaching.
This reduces the chances of operations continuing to run indefinitely in the
background once they have been detached but does not solve the
lifetime- or shutdown-related challenges.</p>
    <li data-md>
     <p>A variation of (3): Request cancellation of the operation before blocking on
its completion. This is the strategy that <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>jthread</c-></code> uses for its
destructor. It reduces the risk of deadlock but does not eliminate it.</p>
   </ol>
   <h4 class="heading settled" data-level="4.10.2" id="design-lazy-algorithms-complexity"><span class="secno">4.10.2. </span><span class="content">Eager senders complicate algorithm implementations</span><a class="self-link" href="#design-lazy-algorithms-complexity"></a></h4>
   <p>Algorithms that can assume they are operating on senders with strictly lazy
semantics are able to make certain optimizations that are not available if
senders can be potentially eager. With lazy senders, an algorithm can safely
assume that a call to <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>start</c-></code> on an operation state strictly happens
before the execution of that async operation. This frees the algorithm from
needing to resolve potential race conditions. For example, consider an algorithm <code class="highlight"><c- n>sequence</c-></code> that puts async operations in sequence by starting an operation only
after the preceding one has completed. In an expression like <code class="highlight"><c- n>sequence</c-><c- p>(</c-><c- n>a</c-><c- p>(),</c-> <c- n>then</c-><c- p>(</c-><c- n>src</c-><c- p>,</c-> <c- p>[]</c-> <c- p>{</c-> <c- n>b</c-><c- p>();</c-> <c- p>}),</c-> <c- n>c</c-><c- p>())</c-></code>, one may reasonably assume that <code class="highlight"><c- n>a</c-><c- p>()</c-></code>, <code class="highlight"><c- n>b</c-><c- p>()</c-></code> and <code class="highlight"><c- n>c</c-><c- p>()</c-></code> are sequenced and therefore do not need synchronisation. Eager algorithms
break that assumption.</p>
   <p>When an algorithm needs to deal with potentially eager senders, the potential
race conditions can be resolved one of two ways, neither of which is desirable:</p>
   <ol>
    <li data-md>
     <p>Assume the worst and implement the algorithm defensively, assuming all
senders are eager. This obviously has overheads both at runtime and in
algorithm complexity. Resolving race conditions is hard.</p>
    <li data-md>
     <p>Require senders to declare whether they are eager or not with a query.
Algorithms can then implement two different implementation strategies, one
for strictly lazy senders and one for potentially eager senders. This
addresses the performance problem of (1) while compounding the complexity
problem.</p>
   </ol>
   <h4 class="heading settled" data-level="4.10.3" id="design-lazy-algorithms-runtime"><span class="secno">4.10.3. </span><span class="content">Eager senders incur cancellation-related overhead</span><a class="self-link" href="#design-lazy-algorithms-runtime"></a></h4>
   <p>Another implication of the use of eager operations is with regards to
cancellation. The eagerly executing operation will not have access to the
caller’s stop token until the sender is connected to a receiver. If we still
want to be able to cancel the eager operation then it will need to create a new
stop source and pass its associated stop token down to child operations. Then
when the returned sender is eventually connected it will register a stop
callback with the receiver’s stop token that will request stop on the eager
sender’s stop source.</p>
   <p>As the eager operation does not know at the time that it is launched what the
type of the receiver is going to be, and thus whether or not the stop token
returned from <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>get_stop_token</c-></code> is an <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>unstoppable_token</c-></code> or not,
the eager operation is going to need to assume it might be later connected to a
receiver with a stop token that might actually issue a stop request. Thus it
needs to declare space in the operation state for a type-erased stop callback
and incur the runtime overhead of supporting cancellation, even if cancellation
will never be requested by the caller.</p>
   <p>The eager operation will also need to do this to support sending a stop request
to the eager operation in the case that the sender representing the eager work
is destroyed before it has been joined (assuming strategy (5) or (6) listed
above is chosen).</p>
   <h4 class="heading settled" data-level="4.10.4" id="design-lazy-algorithms-context"><span class="secno">4.10.4. </span><span class="content">Eager senders cannot access execution resource from the receiver</span><a class="self-link" href="#design-lazy-algorithms-context"></a></h4>
   <p>In sender/receiver, contextual information is passed from parent operations to
their children by way of receivers. Information like stop tokens, allocators,
current scheduler, priority, and deadline are propagated to child operations
with custom receivers at the time the operation is connected. That way, each
operation has the contextual information it needs before it is started.</p>
   <p>But if the operation is started before it is connected to a receiver, then there
isn’t a way for a parent operation to communicate contextual information to its
child operations, which may complete before a receiver is ever attached.</p>
   <h3 class="heading settled" data-level="4.11" id="design-fpg"><span class="secno">4.11. </span><span class="content">Schedulers advertise their forward progress guarantees</span><a class="self-link" href="#design-fpg"></a></h3>
   <p>To decide whether a scheduler (and its associated execution resource) is sufficient for a specific task, it may be necessary to know what kind of forward progress guarantees it provides for the execution agents it creates. The C++ Standard defines the following
forward progress guarantees:</p>
   <ul>
    <li data-md>
     <p><i>concurrent</i>, which requires that a thread makes progress <i>eventually</i>;</p>
    <li data-md>
     <p><i>parallel</i>, which requires that a thread makes progress once it executes a step; and</p>
    <li data-md>
     <p><i>weakly parallel</i>, which does not require that the thread makes progress.</p>
   </ul>
   <p>This paper introduces a scheduler query function, <code class="highlight"><c- n>get_forward_progress_guarantee</c-></code>, which returns one of the enumerators of a new <code class="highlight"><c- k>enum</c-></code> type, <code class="highlight"><c- n>forward_progress_guarantee</c-></code>. Each enumerator of <code class="highlight"><c- n>forward_progress_guarantee</c-></code> corresponds to one of the aforementioned
guarantees.</p>
   <h3 class="heading settled" data-level="4.12" id="design-pipeable"><span class="secno">4.12. </span><span class="content">Most sender adaptors are pipeable</span><a class="self-link" href="#design-pipeable"></a></h3>
   <p>To facilitate an intuitive syntax for composition, most sender adaptors are <dfn data-dfn-type="dfn" data-export id="pipeable">pipeable<a class="self-link" href="#pipeable"></a></dfn>; they can be composed (<dfn data-dfn-type="dfn" data-export id="piped">piped<a class="self-link" href="#piped"></a></dfn>) together with <code class="highlight"><c- k>operator</c-><c- o>|</c-></code>.
This mechanism is similar to the <code class="highlight"><c- k>operator</c-><c- o>|</c-></code> composition that C++ range adaptors support and draws inspiration from piping in *nix shells.
Pipeable sender adaptors take a sender as their first parameter and have no other sender parameters.</p>
   <p><code class="highlight"><c- n>a</c-> <c- o>|</c-> <c- n>b</c-></code> will pass the sender <code class="highlight"><c- n>a</c-></code> as the first argument to the pipeable sender adaptor <code class="highlight"><c- n>b</c-></code>. Pipeable sender adaptors support partial application of the parameters after the first. For example, all of the following are equivalent:</p>
<pre class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>bulk</c-><c- p>(</c-><c- n>snd</c-><c- p>,</c-> <c- n>N</c-><c- p>,</c-> <c- p>[]</c-> <c- p>(</c-><c- n>std</c-><c- o>::</c-><c- b>size_t</c-> <c- n>i</c-><c- p>,</c-> <c- k>auto</c-> <c- n>d</c-><c- p>)</c-> <c- p>{});</c->
<c- n>execution</c-><c- o>::</c-><c- n>bulk</c-><c- p>(</c-><c- n>N</c-><c- p>,</c-> <c- p>[]</c-> <c- p>(</c-><c- n>std</c-><c- o>::</c-><c- b>size_t</c-> <c- n>i</c-><c- p>,</c-> <c- k>auto</c-> <c- n>d</c-><c- p>)</c-> <c- p>{})(</c-><c- n>snd</c-><c- p>);</c->
<c- n>snd</c-> <c- o>|</c-> <c- n>execution</c-><c- o>::</c-><c- n>bulk</c-><c- p>(</c-><c- n>N</c-><c- p>,</c-> <c- p>[]</c-> <c- p>(</c-><c- n>std</c-><c- o>::</c-><c- b>size_t</c-> <c- n>i</c-><c- p>,</c-> <c- k>auto</c-> <c- n>d</c-><c- p>)</c-> <c- p>{});</c->
</pre>
   <p>Piping enables you to compose together senders with a linear syntax.
Without it, you’d have to use either nested function call syntax, which would cause a syntactic inversion of the direction of control flow, or you’d have to introduce a temporary variable for each stage of the pipeline.
Consider the following example where we want to execute first on a CPU thread pool, then on a CUDA GPU, then back on the CPU thread pool:</p>
   <table>
    <tbody>
     <tr>
      <th>Syntax Style 
      <th>Example 
     <tr>
      <th>Function call <br> (nested) 
      <td>
<pre class="highlight"><c- k>auto</c-> <c- n>snd</c-> <c- o>=</c-> <c- n>execution</c-><c- o>::</c-><c- n>then</c-><c- p>(</c->
             <c- n>execution</c-><c- o>::</c-><c- n>transfer</c-><c- p>(</c->
               <c- n>execution</c-><c- o>::</c-><c- n>then</c-><c- p>(</c->
                 <c- n>execution</c-><c- o>::</c-><c- n>transfer</c-><c- p>(</c->
                   <c- n>execution</c-><c- o>::</c-><c- n>then</c-><c- p>(</c->
                     <c- n>execution</c-><c- o>::</c-><c- n>schedule</c-><c- p>(</c-><c- n>thread_pool</c-><c- p>.</c-><c- n>scheduler</c-><c- p>())</c->
                     <c- p>[]{</c-> <c- k>return</c-> <c- mi>123</c-><c- p>;</c-> <c- p>}),</c->
                   <c- n>cuda</c-><c- o>::</c-><c- n>new_stream_scheduler</c-><c- p>()),</c->
                 <c- p>[](</c-><c- b>int</c-> <c- n>i</c-><c- p>){</c-> <c- k>return</c-> <c- mi>123</c-> <c- o>*</c-> <c- mi>5</c-><c- p>;</c-> <c- p>}),</c->
               <c- n>thread_pool</c-><c- p>.</c-><c- n>scheduler</c-><c- p>()),</c->
             <c- p>[](</c-><c- b>int</c-> <c- n>i</c-><c- p>){</c-> <c- k>return</c-> <c- n>i</c-> <c- o>-</c-> <c- mi>5</c-><c- p>;</c-> <c- p>});</c->
<c- k>auto</c-> <c- p>[</c-><c- n>result</c-><c- p>]</c-> <c- o>=</c-> <c- n>this_thread</c-><c- o>::</c-><c- n>sync_wait</c-><c- p>(</c-><c- n>snd</c-><c- p>).</c-><c- n>value</c-><c- p>();</c->
<c- c1>// result == 610</c->
</pre>
     <tr>
      <th>Function call <br> (named temporaries) 
      <td>
<pre class="highlight"><c- k>auto</c-> <c- n>snd0</c-> <c- o>=</c-> <c- n>execution</c-><c- o>::</c-><c- n>schedule</c-><c- p>(</c-><c- n>thread_pool</c-><c- p>.</c-><c- n>scheduler</c-><c- p>());</c->
<c- k>auto</c-> <c- n>snd1</c-> <c- o>=</c-> <c- n>execution</c-><c- o>::</c-><c- n>then</c-><c- p>(</c-><c- n>snd0</c-><c- p>,</c-> <c- p>[]{</c-> <c- k>return</c-> <c- mi>123</c-><c- p>;</c-> <c- p>});</c->
<c- k>auto</c-> <c- n>snd2</c-> <c- o>=</c-> <c- n>execution</c-><c- o>::</c-><c- n>transfer</c-><c- p>(</c-><c- n>snd1</c-><c- p>,</c-> <c- n>cuda</c-><c- o>::</c-><c- n>new_stream_scheduler</c-><c- p>());</c->
<c- k>auto</c-> <c- n>snd3</c-> <c- o>=</c-> <c- n>execution</c-><c- o>::</c-><c- n>then</c-><c- p>(</c-><c- n>snd2</c-><c- p>,</c-> <c- p>[](</c-><c- b>int</c-> <c- n>i</c-><c- p>){</c-> <c- k>return</c-> <c- mi>123</c-> <c- o>*</c-> <c- mi>5</c-><c- p>;</c-> <c- p>})</c->
<c- k>auto</c-> <c- n>snd4</c-> <c- o>=</c-> <c- n>execution</c-><c- o>::</c-><c- n>transfer</c-><c- p>(</c-><c- n>snd3</c-><c- p>,</c-> <c- n>thread_pool</c-><c- p>.</c-><c- n>scheduler</c-><c- p>())</c->
<c- k>auto</c-> <c- n>snd5</c-> <c- o>=</c-> <c- n>execution</c-><c- o>::</c-><c- n>then</c-><c- p>(</c-><c- n>snd4</c-><c- p>,</c-> <c- p>[](</c-><c- b>int</c-> <c- n>i</c-><c- p>){</c-> <c- k>return</c-> <c- n>i</c-> <c- o>-</c-> <c- mi>5</c-><c- p>;</c-> <c- p>});</c->
<c- k>auto</c-> <c- p>[</c-><c- n>result</c-><c- p>]</c-> <c- o>=</c-> <c- o>*</c-><c- n>this_thread</c-><c- o>::</c-><c- n>sync_wait</c-><c- p>(</c-><c- n>snd4</c-><c- p>);</c->
<c- c1>// result == 610</c->
</pre>
     <tr>
      <th>Pipe 
      <td>
<pre class="highlight"><c- k>auto</c-> <c- n>snd</c-> <c- o>=</c-> <c- n>execution</c-><c- o>::</c-><c- n>schedule</c-><c- p>(</c-><c- n>thread_pool</c-><c- p>.</c-><c- n>scheduler</c-><c- p>())</c->
         <c- o>|</c-> <c- n>execution</c-><c- o>::</c-><c- n>then</c-><c- p>([]{</c-> <c- k>return</c-> <c- mi>123</c-><c- p>;</c-> <c- p>})</c->
         <c- o>|</c-> <c- n>execution</c-><c- o>::</c-><c- n>transfer</c-><c- p>(</c-><c- n>cuda</c-><c- o>::</c-><c- n>new_stream_scheduler</c-><c- p>())</c->
         <c- o>|</c-> <c- n>execution</c-><c- o>::</c-><c- n>then</c-><c- p>([](</c-><c- b>int</c-> <c- n>i</c-><c- p>){</c-> <c- k>return</c-> <c- mi>123</c-> <c- o>*</c-> <c- mi>5</c-><c- p>;</c-> <c- p>})</c->
         <c- o>|</c-> <c- n>execution</c-><c- o>::</c-><c- n>transfer</c-><c- p>(</c-><c- n>thread_pool</c-><c- p>.</c-><c- n>scheduler</c-><c- p>())</c->
         <c- o>|</c-> <c- n>execution</c-><c- o>::</c-><c- n>then</c-><c- p>([](</c-><c- b>int</c-> <c- n>i</c-><c- p>){</c-> <c- k>return</c-> <c- n>i</c-> <c- o>-</c-> <c- mi>5</c-><c- p>;</c-> <c- p>});</c->
<c- k>auto</c-> <c- p>[</c-><c- n>result</c-><c- p>]</c-> <c- o>=</c-> <c- n>this_thread</c-><c- o>::</c-><c- n>sync_wait</c-><c- p>(</c-><c- n>snd</c-><c- p>).</c-><c- n>value</c-><c- p>();</c->
<c- c1>// result == 610</c->
</pre>
   </table>
   <p>Certain sender adaptors are not pipeable, because using the pipeline syntax can result in confusion of the semantics of the adaptors involved. Specifically, the following sender adaptors are not pipeable.</p>
   <ul>
    <li data-md>
     <p><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>when_all</c-></code> and <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>when_all_with_variant</c-></code>: Since this sender adaptor takes a variadic pack of senders, a partially applied form would be ambiguous with a non partially applied form with an arity of one less.</p>
    <li data-md>
     <p><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>on</c-></code>: This sender adaptor changes how the sender passed to it is executed, not what happens to its result, but allowing it in a pipeline makes it read as if it performed a function more similar to <code class="highlight"><c- n>transfer</c-></code>.</p>
   </ul>
   <p>Sender consumers could be made pipeable, but we have chosen to not do so.
However, since these are terminal nodes in a pipeline and nothing can be piped after them, we believe a pipe syntax may be confusing as well as unnecessary, as consumers cannot be chained.
We believe sender consumers read better with function call syntax.</p>
   <h3 class="heading settled" data-level="4.13" id="design-range-of-senders"><span class="secno">4.13. </span><span class="content">A range of senders represents an async sequence of data</span><a class="self-link" href="#design-range-of-senders"></a></h3>
   <p>Senders represent a single unit of asynchronous work. In many cases though, what is being modelled is a sequence of data arriving asynchronously, and you want computation to happen on demand, when each element arrives. This requires nothing more than what is in this paper and the range support in C++20. A range of senders would allow you to model such input as keystrikes, mouse movements, sensor readings, or network requests.</p>
   <p>Given some expression <code class="highlight"><i><c- n>R</c-></i></code> that is a range of senders, consider the following in a coroutine that returns an async generator type:</p>
<pre class="highlight"><c- k>for</c-> <c- p>(</c-><c- k>auto</c-> <c- n>snd</c-> <c- o>:</c-> <i><c- n>R</c-></i><c- p>)</c-> <c- p>{</c->
  <c- k>if</c-> <c- p>(</c-><c- k>auto</c-> <c- n>opt</c-> <c- o>=</c-> <c- k>co_await</c-> <c- n>execution</c-><c- o>::</c-><c- n>stopped_as_optional</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>snd</c-><c- p>)))</c->
    <c- k>co_yield</c-> <c- n>fn</c-><c- p>(</c-><c- o>*</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>opt</c-><c- p>));</c->
  <c- k>else</c->
    <c- k>break</c-><c- p>;</c->
<c- p>}</c->
</pre>
   <p>This transforms each element of the asynchronous sequence <code class="highlight"><i><c- n>R</c-></i></code> with the function <code class="highlight"><c- n>fn</c-></code> on demand, as the data arrives. The result is a new asynchronous sequence of the transformed values.</p>
   <p>Now imagine that <code class="highlight"><i><c- n>R</c-></i></code> is the simple expression <code class="highlight"><c- n>views</c-><c- o>::</c-><c- n>iota</c-><c- p>(</c-><c- mi>0</c-><c- p>)</c-> <c- o>|</c-> <c- n>views</c-><c- o>::</c-><c- n>transform</c-><c- p>(</c-><c- n>execution</c-><c- o>::</c-><c- n>just</c-><c- p>)</c-></code>. This creates a lazy range of senders, each of which completes immediately with monotonically increasing integers. The above code churns through the range, generating a new infine asynchronous range of values [<code class="highlight"><c- n>fn</c-><c- p>(</c-><c- mi>0</c-><c- p>)</c-></code>, <code class="highlight"><c- n>fn</c-><c- p>(</c-><c- mi>1</c-><c- p>)</c-></code>, <code class="highlight"><c- n>fn</c-><c- p>(</c-><c- mi>2</c-><c- p>)</c-></code>, ...].</p>
   <p>Far more interesting would be if <code class="highlight"><i><c- n>R</c-></i></code> were a range of senders representing, say, user actions in a UI. The above code gives a simple way to respond to user actions on demand.</p>
   <h3 class="heading settled" data-level="4.14" id="design-partial-success"><span class="secno">4.14. </span><span class="content">Senders can represent partial success</span><a class="self-link" href="#design-partial-success"></a></h3>
   <p>Receivers have three ways they can complete: with success, failure, or cancellation. This begs the question of how they can be used to represent async operations that <em>partially</em> succeed. For example, consider an API that reads from a socket. The connection could drop after the API has filled in some of the buffer. In cases like that, it makes sense to want to report both that the connection dropped and that some data has been successfully read.</p>
   <p>Often in the case of partial success, the error condition is not fatal nor does it mean the API has failed to satisfy its post-conditions. It is merely an extra piece of information about the nature of the completion. In those cases, "partial success" is another way of saying "success". As a result, it is sensible to pass both the error code and the result (if any) through the value channel, as shown below:</p>
<pre class="highlight"><c- c1>// Capture a buffer for read_socket_async to fill in</c->
<c- n>execution</c-><c- o>::</c-><c- n>just</c-><c- p>(</c-><c- n>array</c-><c- o>&lt;</c-><c- n>byte</c-><c- p>,</c-> <c- mi>1024</c-><c- o>></c-><c- p>{})</c->
  <c- o>|</c-> <c- n>execution</c-><c- o>::</c-><c- n>let_value</c-><c- p>([</c-><c- n>socket</c-><c- p>](</c-><c- n>array</c-><c- o>&lt;</c-><c- n>byte</c-><c- p>,</c-> <c- mi>1024</c-><c- o>>&amp;</c-> <c- n>buff</c-><c- p>)</c-> <c- p>{</c->
      <c- c1>// read_socket_async completes with two values: an error_code and</c->
      <c- c1>// a count of bytes:</c->
      <c- k>return</c-> <c- n>read_socket_async</c-><c- p>(</c-><c- n>socket</c-><c- p>,</c-> <c- n>span</c-><c- p>{</c-><c- n>buff</c-><c- p>})</c->
          <c- c1>// For success (partial and full), specify the next action:</c->
        <c- o>|</c-> <c- n>execution</c-><c- o>::</c-><c- n>let_value</c-><c- p>([](</c-><c- n>error_code</c-> <c- n>err</c-><c- p>,</c-> <c- b>size_t</c-> <c- n>bytes_read</c-><c- p>)</c-> <c- p>{</c->
            <c- k>if</c-> <c- p>(</c-><c- n>err</c-> <c- o>!=</c-> <c- mi>0</c-><c- p>)</c-> <c- p>{</c->
              <c- c1>// OK, partial success. Decide how to deal with the partial results</c->
            <c- p>}</c-> <c- k>else</c-> <c- p>{</c->
              <c- c1>// OK, full success here.</c->
            <c- p>}</c->
          <c- p>});</c->
    <c- p>})</c->
</pre>
   <p>In other cases, the partial success is more of a partial <em>failure</em>. That happens when the error condition indicates that in some way the function failed to satisfy its post-conditions. In those cases, sending the error through the value channel loses valuable contextual information. It’s possible that bundling the error and the incomplete results into an object and passing it through the error channel makes more sense. In that way, generic algorithms will not miss the fact that a post-condition has not been met and react inappropriately.</p>
   <p>Another possibility is for an async API to return a <em>range</em> of senders: if the API completes with full success, full error, or cancellation, the returned range contains just one sender with the result. Otherwise, if the API partially fails (doesn’t satisfy its post-conditions, but some incomplete result is available), the returned range would have <em>two</em> senders: the first containing the partial result, and the second containing the error. Such an API might be used in a coroutine as follows:</p>
<pre class="highlight"><c- c1>// Declare a buffer for read_socket_async to fill in</c->
<c- n>array</c-><c- o>&lt;</c-><c- n>byte</c-><c- p>,</c-> <c- mi>1024</c-><c- o>></c-> <c- n>buff</c-><c- p>;</c->

<c- k>for</c-> <c- p>(</c-><c- k>auto</c-> <c- n>snd</c-> <c- o>:</c-> <c- n>read_socket_async</c-><c- p>(</c-><c- n>socket</c-><c- p>,</c-> <c- n>span</c-><c- p>{</c-><c- n>buff</c-><c- p>}))</c-> <c- p>{</c->
  <c- k>try</c-> <c- p>{</c->
    <c- k>if</c-> <c- p>(</c-><c- n>optional</c-><c- o>&lt;</c-><c- b>size_t</c-><c- o>></c-> <c- n>bytes_read</c-> <c- o>=</c->
          <c- k>co_await</c-> <c- n>execution</c-><c- o>::</c-><c- n>stopped_as_optional</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>snd</c-><c- p>)))</c-> <c- p>{</c->
      <c- c1>// OK, we read some bytes into buff. Process them here....</c->
    <c- p>}</c-> <c- k>else</c-> <c- p>{</c->
      <c- c1>// The socket read was cancelled and returned no data. React</c->
      <c- c1>// appropriately.</c->
    <c- p>}</c->
  <c- p>}</c-> <c- k>catch</c-> <c- p>(...)</c-> <c- p>{</c->
    <c- c1>// read_socket_async failed to meet its post-conditions.</c->
    <c- c1>// Do some cleanup and propagate the error...</c->
  <c- p>}</c->
<c- p>}</c->
</pre>
   <p>Finally, it’s possible to combine these two approaches when the API can both partially succeed (meeting its post-conditions) and partially fail (not meeting its post-conditions).</p>
   <h3 class="heading settled" data-level="4.15" id="design-awaitables-are-senders"><span class="secno">4.15. </span><span class="content">All awaitables are senders</span><a class="self-link" href="#design-awaitables-are-senders"></a></h3>
   <p>Since C++20 added coroutines to the standard, we expect that coroutines and awaitables will be how a great many will choose to express their asynchronous code. However, in this paper, we are proposing to add a suite of asynchronous algorithms that accept senders, not awaitables. One might wonder whether and how these algorithms will be accessible to those who choose coroutines instead of senders.</p>
   <p>In truth there will be no problem because all generally awaitable types
automatically model the <code class="highlight"><c- n>sender</c-></code> concept. The adaptation is transparent and
happens in the sender customization points, which are aware of awaitables. (By
"generally awaitable" we mean types that don’t require custom <code class="highlight"><c- n>await_transform</c-></code> trickery from a promise type to make them awaitable.)</p>
   <p>For an example, imagine a coroutine type called <code class="highlight"><c- n>task</c-><c- o>&lt;</c-><c- n>T</c-><c- o>></c-></code> that knows nothing
about senders. It doesn’t implement any of the sender customization points.
Despite that fact, and despite the fact that the <code class="highlight"><c- n>this_thread</c-><c- o>::</c-><c- n>sync_wait</c-></code> algorithm is constrained with the <code class="highlight"><c- n>sender</c-></code> concept, the following would compile
and do what the user wants:</p>
<pre class="language-c++ highlight"><c- n>task</c-><c- o>&lt;</c-><c- b>int</c-><c- o>></c-> <c- n>doSomeAsyncWork</c-><c- p>();</c->

<c- b>int</c-> <c- nf>main</c-><c- p>()</c-> <c- p>{</c->
  <c- c1>// OK, awaitable types satisfy the requirements for senders:</c->
  <c- k>auto</c-> <c- n>o</c-> <c- o>=</c-> <c- n>this_thread</c-><c- o>::</c-><c- n>sync_wait</c-><c- p>(</c-><c- n>doSomeAsyncWork</c-><c- p>());</c->
<c- p>}</c->
</pre>
   <p>Since awaitables are senders, writing a sender-based asynchronous algorithm is trivial if you have a coroutine task type: implement the algorithm as a coroutine. If you are not bothered by the possibility of allocations and indirections as a result of using coroutines, then there is no need to ever write a sender, a receiver, or an operation state.</p>
   <h3 class="heading settled" data-level="4.16" id="design-senders-are-awaitable"><span class="secno">4.16. </span><span class="content">Many senders can be trivially made awaitable</span><a class="self-link" href="#design-senders-are-awaitable"></a></h3>
   <p>If you choose to implement your sender-based algorithms as coroutines, you’ll run into the issue of how to retrieve results from a passed-in sender. This is not a problem. If the coroutine type opts in to sender support -- trivial with the <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>with_awaitable_senders</c-></code> utility -- then a large class of senders are transparently awaitable from within the coroutine.</p>
   <p>For example, consider the following trivial implementation of the sender-based <code class="highlight"><c- n>retry</c-></code> algorithm:</p>
<pre class="highlight"><c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>S</c-><c- o>></c->
  <c- k>requires</c-> <i><c- n>single</c-><c- o>-</c-><c- n>sender</c-></i><c- o>&lt;</c-><c- n>S</c-><c- o>&amp;></c-> <c- c1>// see </c-><a href="#spec-execution.coro_utils.as_awaitable"><c- c1>[exec.as.awaitable]</c-></a>
<c- n>task</c-><c- o>&lt;</c-><i><c- n>single</c-><c- o>-</c-><c- n>sender</c-><c- o>-</c-><c- n>value</c-><c- o>-</c-><c- n>type</c-></i><c- o>&lt;</c-><c- n>S</c-><c- o>>></c-> <c- n>retry</c-><c- p>(</c-><c- n>S</c-> <c- n>s</c-><c- p>)</c-> <c- p>{</c->
  <c- k>for</c-> <c- p>(;;)</c-> <c- p>{</c->
    <c- k>try</c-> <c- p>{</c->
      <c- k>co_return</c-> <c- k>co_await</c-> <c- n>s</c-><c- p>;</c->
    <c- p>}</c-> <c- k>catch</c-><c- p>(...)</c-> <c- p>{</c->
    <c- p>}</c->
  <c- p>}</c->
<c- p>}</c->
</pre>
   <p>Only <em>some</em> senders can be made awaitable directly because of the fact that callbacks are more expressive than coroutines. An awaitable expression has a single type: the result value of the async operation. In contrast, a callback can accept multiple arguments as the result of an operation. What’s more, the callback can have overloaded function call signatures that take different sets of arguments. There is no way to automatically map such senders into awaitables. The <code class="highlight"><c- n>with_awaitable_senders</c-></code> utility recognizes as awaitables those senders that send a single value of a single type. To await another kind of sender, a user would have to first map its value channel into a single value of a single type -- say, with the <code class="highlight"><c- n>into_variant</c-></code> sender algorithm -- before <code class="highlight"><c- k>co_await</c-></code>-ing that sender.</p>
   <h3 class="heading settled" data-level="4.17" id="design-native-coro-unwind"><span class="secno">4.17. </span><span class="content">Cancellation of a sender can unwind a stack of coroutines</span><a class="self-link" href="#design-native-coro-unwind"></a></h3>
   <p>When looking at the sender-based <code class="highlight"><c- n>retry</c-></code> algorithm in the previous section, we can see that the value and error cases are correctly handled. But what about cancellation? What happens to a coroutine that is suspended awaiting a sender that completes by calling <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_stopped</c-></code>?</p>
   <p>When your task type’s promise inherits from <code class="highlight"><c- n>with_awaitable_senders</c-></code>, what happens is this: the coroutine behaves as if an <em>uncatchable exception</em> had been thrown from the <code class="highlight"><c- k>co_await</c-></code> expression. (It is not really an exception, but it’s helpful to think of it that way.) Provided that the promise types of the calling coroutines also inherit from <code class="highlight"><c- n>with_awaitable_senders</c-></code>, or more generally implement a member function called <code class="highlight"><c- n>unhandled_stopped</c-></code>, the exception unwinds the chain of coroutines as if an exception were thrown except that it bypasses <code class="highlight"><c- k>catch</c-><c- p>(...)</c-></code> clauses.</p>
   <p>In order to "catch" this uncatchable stopped exception, one of the calling coroutines in the stack would have to await a sender that maps the stopped channel into either a value or an error. That is achievable with the <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>let_stopped</c-></code>, <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>upon_stopped</c-></code>, <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>stopped_as_optional</c-></code>, or <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>stopped_as_error</c-></code> sender adaptors. For instance, we can use <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>stopped_as_optional</c-></code> to "catch" the stopped signal and map it into an empty optional as shown below:</p>
<pre class="language-c++ highlight"><c- k>if</c-> <c- p>(</c-><c- k>auto</c-> <c- n>opt</c-> <c- o>=</c-> <c- n>co_await</c-> <c- n>execution</c-><c- o>::</c-><c- n>stopped_as_optional</c-><c- p>(</c-><c- n>some_sender</c-><c- p>))</c-> <c- p>{</c->
  <c- c1>// OK, some_sender completed successfully, and opt contains the result.</c->
<c- p>}</c-> <c- k>else</c-> <c- p>{</c->
  <c- c1>// some_sender completed with a cancellation signal.</c->
<c- p>}</c->
</pre>
   <p>As described in the section <a href="#design-awaitables-are-senders">"All awaitables are senders"</a>, the sender customization points recognize awaitables and adapt them transparently to model the sender concept. When <code class="highlight"><c- n>connect</c-></code>-ing an awaitable and a receiver, the adaptation layer awaits the awaitable within a coroutine that implements <code class="highlight"><c- n>unhandled_stopped</c-></code> in its promise type. The effect of this is that an "uncatchable" stopped exception propagates seamlessly out of awaitables, causing <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_stopped</c-></code> to be called on the receiver.</p>
   <p>Obviously, <code class="highlight"><c- n>unhandled_stopped</c-></code> is a library extension of the coroutine promise interface. Many promise types will not implement <code class="highlight"><c- n>unhandled_stopped</c-></code>. When an uncatchable stopped exception tries to propagate through such a coroutine, it is treated as an unhandled exception and <code class="highlight"><c- n>terminate</c-></code> is called. The solution, as described above, is to use a sender adaptor to handle the stopped exception before awaiting it. It goes without saying that any future Standard Library coroutine types ought to implement <code class="highlight"><c- n>unhandled_stopped</c-></code>. The author of <a data-link-type="biblio" href="https://wg21.link/p1056r1"><cite>Add lazy coroutine (coroutine task) type</cite></a>, which proposes a standard coroutine task type, is in agreement.</p>
   <h3 class="heading settled" data-level="4.18" id="design-parallel-algorithms"><span class="secno">4.18. </span><span class="content">Composition with parallel algorithms</span><a class="self-link" href="#design-parallel-algorithms"></a></h3>
   <p>The C++ Standard Library provides a large number of algorithms that offer the potential for non-sequential execution via the use of execution policies. The set of algorithms with execution policy overloads are often referred to as "parallel algorithms", although
additional policies are available.</p>
   <p>Existing policies, such as <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>par</c-></code>, give the implementation permission to execute the algorithm in parallel. However, the choice of execution resources used to perform the work is left to the implementation.</p>
   <p>We will propose a customization point for combining schedulers with policies in order to provide control over where work will execute.</p>
<pre class="highlight"><c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>ExecutionPolicy</c-><c- o>></c->
<i><c- n>unspecified</c-></i> <c- n>executing_on</c-><c- p>(</c->
    <c- n>execution</c-><c- o>::</c-><c- n>scheduler</c-> <c- k>auto</c-> <c- n>scheduler</c-><c- p>,</c->
    <c- n>ExecutionPolicy</c-> <c- o>&amp;&amp;</c-> <c- n>policy</c->
<c- p>);</c->
</pre>
   <p>This function would return an object of an unspecified type which can be used in place of an execution policy as the first argument to one of the parallel algorithms. The overload selected by that object should execute its computation as requested by <code class="highlight"><c- n>policy</c-></code> while using <code class="highlight"><c- n>scheduler</c-></code> to create any work to be run. The expression may be ill-formed if <code class="highlight"><c- n>scheduler</c-></code> is not able to support the given policy.</p>
   <p>The existing parallel algorithms are synchronous; all of the effects performed by the computation are complete before the algorithm returns to its caller. This remains unchanged with the <code class="highlight"><c- n>executing_on</c-></code> customization point.</p>
   <p>In the future, we expect additional papers will propose asynchronous forms of the parallel algorithms which (1) return senders rather than values or <code class="highlight"><c- b>void</c-></code> and (2) where a customization point pairing a sender with an execution policy would similarly be used to
obtain an object of unspecified type to be provided as the first argument to the algorithm.</p>
   <h3 class="heading settled" data-level="4.19" id="design-sender-factories"><span class="secno">4.19. </span><span class="content">User-facing sender factories</span><a class="self-link" href="#design-sender-factories"></a></h3>
   <p>A <a data-link-type="dfn" href="#sender-factory" id="ref-for-sender-factory①">sender factory</a> is an algorithm that takes no senders as parameters and returns a sender.</p>
   <h4 class="heading settled" data-level="4.19.1" id="design-sender-factory-schedule"><span class="secno">4.19.1. </span><span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>schedule</c-></code></span><a class="self-link" href="#design-sender-factory-schedule"></a></h4>
<pre class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>schedule</c-><c- p>(</c->
    <c- n>execution</c-><c- o>::</c-><c- n>scheduler</c-> <c- k>auto</c-> <c- n>scheduler</c->
<c- p>);</c->
</pre>
   <p>Returns a sender describing the start of a task graph on the provided scheduler. See <a href="#design-schedulers">§ 4.2 Schedulers represent execution resources</a>.</p>
<pre class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>scheduler</c-> <c- k>auto</c-> <c- n>sch1</c-> <c- o>=</c-> <c- n>get_system_thread_pool</c-><c- p>().</c-><c- n>scheduler</c-><c- p>();</c->

<c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>snd1</c-> <c- o>=</c-> <c- n>execution</c-><c- o>::</c-><c- n>schedule</c-><c- p>(</c-><c- n>sch1</c-><c- p>);</c->
<c- c1>// snd1 describes the creation of a new task on the system thread pool</c->
</pre>
   <h4 class="heading settled" data-level="4.19.2" id="design-sender-factory-just"><span class="secno">4.19.2. </span><span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>just</c-></code></span><a class="self-link" href="#design-sender-factory-just"></a></h4>
<pre class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>just</c-><c- p>(</c->
    <c- k>auto</c-> <c- p>...</c-><c- o>&amp;&amp;</c-> <c- n>values</c->
<c- p>);</c->
</pre>
   <p>Returns a sender with no <a data-link-type="dfn" href="#completion-scheduler" id="ref-for-completion-scheduler②">completion schedulers</a>, which <a data-link-type="dfn" href="#send" id="ref-for-send①">sends</a> the provided values. The input values are decay-copied into the returned sender. When the returned sender is connected to a receiver, the values are moved into the operation state if the sender is an rvalue; otherwise, they are copied. Then xvalues referencing the values in the operation state are passed to the receiver’s <code class="highlight"><c- n>set_value</c-></code>.</p>
<pre class="language-c++ highlight"><c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>snd1</c-> <c- o>=</c-> <c- n>execution</c-><c- o>::</c-><c- n>just</c-><c- p>(</c-><c- mf>3.14</c-><c- p>);</c->
<c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>then1</c-> <c- o>=</c-> <c- n>execution</c-><c- o>::</c-><c- n>then</c-><c- p>(</c-><c- n>snd1</c-><c- p>,</c-> <c- p>[]</c-> <c- p>(</c-><c- b>double</c-> <c- n>d</c-><c- p>)</c-> <c- p>{</c->
  <c- n>std</c-><c- o>::</c-><c- n>cout</c-> <c- o>&lt;&lt;</c-> <c- n>d</c-> <c- o>&lt;&lt;</c-> <c- s>"</c-><c- se>\n</c-><c- s>"</c-><c- p>;</c->
<c- p>});</c->

<c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>snd2</c-> <c- o>=</c-> <c- n>execution</c-><c- o>::</c-><c- n>just</c-><c- p>(</c-><c- mf>3.14</c-><c- p>,</c-> <c- mi>42</c-><c- p>);</c->
<c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>then2</c-> <c- o>=</c-> <c- n>execution</c-><c- o>::</c-><c- n>then</c-><c- p>(</c-><c- n>snd2</c-><c- p>,</c-> <c- p>[]</c-> <c- p>(</c-><c- b>double</c-> <c- n>d</c-><c- p>,</c-> <c- b>int</c-> <c- n>i</c-><c- p>)</c-> <c- p>{</c->
  <c- n>std</c-><c- o>::</c-><c- n>cout</c-> <c- o>&lt;&lt;</c-> <c- n>d</c-> <c- o>&lt;&lt;</c-> <c- s>", "</c-> <c- o>&lt;&lt;</c-> <c- n>i</c-> <c- o>&lt;&lt;</c-> <c- s>"</c-><c- se>\n</c-><c- s>"</c-><c- p>;</c->
<c- p>});</c->

<c- n>std</c-><c- o>::</c-><c- n>vector</c-> <c- n>v3</c-><c- p>{</c-><c- mi>1</c-><c- p>,</c-> <c- mi>2</c-><c- p>,</c-> <c- mi>3</c-><c- p>,</c-> <c- mi>4</c-><c- p>,</c-> <c- mi>5</c-><c- p>};</c->
<c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>snd3</c-> <c- o>=</c-> <c- n>execution</c-><c- o>::</c-><c- n>just</c-><c- p>(</c-><c- n>v3</c-><c- p>);</c->
<c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>then3</c-> <c- o>=</c-> <c- n>execution</c-><c- o>::</c-><c- n>then</c-><c- p>(</c-><c- n>snd3</c-><c- p>,</c-> <c- p>[]</c-> <c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>vector</c-><c- o>&lt;</c-><c- b>int</c-><c- o>>&amp;&amp;</c-> <c- n>v3copy</c-><c- p>)</c-> <c- p>{</c->
  <c- k>for</c-> <c- p>(</c-><c- k>auto</c-><c- o>&amp;&amp;</c-> <c- n>e</c-> <c- o>:</c-> <c- n>v3copy</c-><c- p>)</c-> <c- p>{</c-> <c- n>e</c-> <c- o>*=</c-> <c- mi>2</c-><c- p>;</c-> <c- p>}</c->
  <c- k>return</c-> <c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>v3copy</c-><c- p>);</c->
<c- p>}</c->
<c- k>auto</c-><c- o>&amp;&amp;</c-> <c- p>[</c-><c- n>v3copy</c-><c- p>]</c-> <c- o>=</c-> <c- n>this_thread</c-><c- o>::</c-><c- n>sync_wait</c-><c- p>(</c-><c- n>then3</c-><c- p>).</c-><c- n>value</c-><c- p>();</c->
<c- c1>// v3 contains {1, 2, 3, 4, 5}; v3copy will contain {2, 4, 6, 8, 10}.</c->

<c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>snd4</c-> <c- o>=</c-> <c- n>execution</c-><c- o>::</c-><c- n>just</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>vector</c-><c- p>{</c-><c- mi>1</c-><c- p>,</c-> <c- mi>2</c-><c- p>,</c-> <c- mi>3</c-><c- p>,</c-> <c- mi>4</c-><c- p>,</c-> <c- mi>5</c-><c- p>});</c->
<c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>then4</c-> <c- o>=</c-> <c- n>execution</c-><c- o>::</c-><c- n>then</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>snd4</c-><c- p>),</c-> <c- p>[]</c-> <c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>vector</c-><c- o>&lt;</c-><c- b>int</c-><c- o>>&amp;&amp;</c-> <c- n>v4</c-><c- p>)</c-> <c- p>{</c->
  <c- k>for</c-> <c- p>(</c-><c- k>auto</c-><c- o>&amp;&amp;</c-> <c- n>e</c-> <c- o>:</c-> <c- n>v4</c-><c- p>)</c-> <c- p>{</c-> <c- n>e</c-> <c- o>*=</c-> <c- mi>2</c-><c- p>;</c-> <c- p>}</c->
  <c- k>return</c-> <c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>v4</c-><c- p>);</c->
<c- p>});</c->
<c- k>auto</c-><c- o>&amp;&amp;</c-> <c- p>[</c-><c- n>v4</c-><c- p>]</c-> <c- o>=</c-> <c- n>this_thread</c-><c- o>::</c-><c- n>sync_wait</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>then4</c-><c- p>)).</c-><c- n>value</c-><c- p>();</c->
<c- c1>// v4 contains {2, 4, 6, 8, 10}. No vectors were copied in this example.</c->
</pre>
   <h4 class="heading settled" data-level="4.19.3" id="design-sender-factory-just_error"><span class="secno">4.19.3. </span><span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>just_error</c-></code></span><a class="self-link" href="#design-sender-factory-just_error"></a></h4>
<pre class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>just_error</c-><c- p>(</c->
    <c- k>auto</c-> <c- o>&amp;&amp;</c-> <c- n>error</c->
<c- p>);</c->
</pre>
   <p>Returns a sender with no <a data-link-type="dfn" href="#completion-scheduler" id="ref-for-completion-scheduler③">completion schedulers</a>, which completes with the specified error. If the provided error is an lvalue reference, a copy is made inside the returned sender and a non-const lvalue reference to the copy is sent to the receiver’s <code class="highlight"><c- n>set_error</c-></code>. If the provided value is an rvalue reference, it is moved into the returned sender and an rvalue reference to it is sent to the receiver’s <code class="highlight"><c- n>set_error</c-></code>.</p>
   <h4 class="heading settled" data-level="4.19.4" id="design-sender-factory-just_stopped"><span class="secno">4.19.4. </span><span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>just_stopped</c-></code></span><a class="self-link" href="#design-sender-factory-just_stopped"></a></h4>
<pre class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>just_stopped</c-><c- p>();</c->
</pre>
   <p>Returns a sender with no <a data-link-type="dfn" href="#completion-scheduler" id="ref-for-completion-scheduler④">completion schedulers</a>, which completes immediately by calling the receiver’s <code class="highlight"><c- n>set_stopped</c-></code>.</p>
   <h4 class="heading settled" data-level="4.19.5" id="design-sender-factory-read"><span class="secno">4.19.5. </span><span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>read</c-></code></span><a class="self-link" href="#design-sender-factory-read"></a></h4>
<pre class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>read</c-><c- p>(</c-><c- k>auto</c-> <c- n>tag</c-><c- p>);</c->

<c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>get_scheduler</c-><c- p>()</c-> <c- p>{</c->
  <c- k>return</c-> <c- n>read</c-><c- p>(</c-><c- n>execution</c-><c- o>::</c-><c- n>get_scheduler</c-><c- p>);</c->
<c- p>}</c->
<c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>get_delegatee_scheduler</c-><c- p>()</c-> <c- p>{</c->
  <c- k>return</c-> <c- n>read</c-><c- p>(</c-><c- n>execution</c-><c- o>::</c-><c- n>get_delegatee_scheduler</c-><c- p>);</c->
<c- p>}</c->
<c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>get_allocator</c-><c- p>()</c-> <c- p>{</c->
  <c- k>return</c-> <c- n>read</c-><c- p>(</c-><c- n>execution</c-><c- o>::</c-><c- n>get_allocator</c-><c- p>);</c->
<c- p>}</c->
<c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>get_stop_token</c-><c- p>()</c-> <c- p>{</c->
  <c- k>return</c-> <c- n>read</c-><c- p>(</c-><c- n>execution</c-><c- o>::</c-><c- n>get_stop_token</c-><c- p>);</c->
<c- p>}</c->
</pre>
   <p>Returns a sender that reaches into a receiver’s environment and pulls out the current value associated with the customization point denoted by <code class="highlight"><c- n>Tag</c-></code>. It then sends the value read back to the receiver through the value channel. For instance, <code class="highlight"><c- n>get_scheduler</c-><c- p>()</c-></code> (with no arguments) is a sender that asks the receiver for the currently suggested <code class="highlight"><c- n>scheduler</c-></code> and passes it to the receiver’s <code class="highlight"><c- n>set_value</c-></code> completion-signal.</p>
   <p>This can be useful when scheduling nested dependent work. The following sender pulls the current schduler into the value channel and then schedules more work onto it.</p>
<pre class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>task</c-> <c- o>=</c->
  <c- n>execution</c-><c- o>::</c-><c- n>get_scheduler</c-><c- p>()</c->
    <c- o>|</c-> <c- n>execution</c-><c- o>::</c-><c- n>let_value</c-><c- p>([](</c-><c- k>auto</c-> <c- n>sched</c-><c- p>)</c-> <c- p>{</c->
        <c- k>return</c-> <c- n>execution</c-><c- o>::</c-><c- n>on</c-><c- p>(</c-><c- n>sched</c-><c- p>,</c-> <i><c- n>some</c-> <c- n>nested</c-> <c- n>work</c-> <c- n>here</c-></i><c- p>);</c->
    <c- p>});</c->

<c- n>this_thread</c-><c- o>::</c-><c- n>sync_wait</c-><c- p>(</c-> <c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>task</c-><c- p>)</c-> <c- p>);</c-> <c- c1>// wait for it to finish</c->
</pre>
   <p>This code uses the fact that <code class="highlight"><c- n>sync_wait</c-></code> associates a scheduler with the receiver that it connects with <code class="highlight"><c- n>task</c-></code>. <code class="highlight"><c- n>get_scheduler</c-><c- p>()</c-></code> reads that scheduler out of the receiver, and passes it to <code class="highlight"><c- n>let_value</c-></code>'s receiver’s <code class="highlight"><c- n>set_value</c-></code> function, which in turn passes it to the lambda. That lambda returns a new sender that uses the scheduler to schedule some nested work onto <code class="highlight"><c- n>sync_wait</c-></code>'s scheduler.</p>
   <h3 class="heading settled" data-level="4.20" id="design-sender-adaptors"><span class="secno">4.20. </span><span class="content">User-facing sender adaptors</span><a class="self-link" href="#design-sender-adaptors"></a></h3>
   <p>A <a data-link-type="dfn" href="#sender-adaptor" id="ref-for-sender-adaptor①">sender adaptor</a> is an algorithm that takes one or more senders, which it may <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>connect</c-></code>, as parameters, and returns a sender, whose completion is related to the sender arguments it has received.</p>
   <p>Sender adaptors are <i>lazy</i>, that is, they are never allowed to submit any work for execution prior to the returned sender being <a data-link-type="dfn" href="#start" id="ref-for-start">started</a> later on, and are also guaranteed to not start any input senders passed into them. Sender consumers
such as <a href="#design-sender-consumer-start_detached">§ 4.21.1 execution::start_detached</a> and <a href="#design-sender-consumer-sync_wait">§ 4.21.2 this_thread::sync_wait</a> start senders.</p>
   <p>For more implementer-centric description of starting senders, see <a href="#design-laziness">§ 5.5 Sender adaptors are lazy</a>.</p>
   <h4 class="heading settled" data-level="4.20.1" id="design-sender-adaptor-transfer"><span class="secno">4.20.1. </span><span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>transfer</c-></code></span><a class="self-link" href="#design-sender-adaptor-transfer"></a></h4>
<pre class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>transfer</c-><c- p>(</c->
    <c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>input</c-><c- p>,</c->
    <c- n>execution</c-><c- o>::</c-><c- n>scheduler</c-> <c- k>auto</c-> <c- n>scheduler</c->
<c- p>);</c->
</pre>
   <p>Returns a sender describing the transition from the execution agent of the input sender to the execution agent of the target scheduler. See <a href="#design-transitions">§ 4.6 Execution resource transitions are explicit</a>.</p>
<pre class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>scheduler</c-> <c- k>auto</c-> <c- n>cpu_sched</c-> <c- o>=</c-> <c- n>get_system_thread_pool</c-><c- p>().</c-><c- n>scheduler</c-><c- p>();</c->
<c- n>execution</c-><c- o>::</c-><c- n>scheduler</c-> <c- k>auto</c-> <c- n>gpu_sched</c-> <c- o>=</c-> <c- n>cuda</c-><c- o>::</c-><c- n>scheduler</c-><c- p>();</c->

<c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>cpu_task</c-> <c- o>=</c-> <c- n>execution</c-><c- o>::</c-><c- n>schedule</c-><c- p>(</c-><c- n>cpu_sched</c-><c- p>);</c->
<c- c1>// cpu_task describes the creation of a new task on the system thread pool</c->

<c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>gpu_task</c-> <c- o>=</c-> <c- n>execution</c-><c- o>::</c-><c- n>transfer</c-><c- p>(</c-><c- n>cpu_task</c-><c- p>,</c-> <c- n>gpu_sched</c-><c- p>);</c->
<c- c1>// gpu_task describes the transition of the task graph described by cpu_task to the gpu</c->
</pre>
   <h4 class="heading settled" data-level="4.20.2" id="design-sender-adaptor-then"><span class="secno">4.20.2. </span><span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>then</c-></code></span><a class="self-link" href="#design-sender-adaptor-then"></a></h4>
<pre class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>then</c-><c- p>(</c->
    <c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>input</c-><c- p>,</c->
    <c- n>std</c-><c- o>::</c-><c- n>invocable</c-><c- o>&lt;</c-><i><c- n>values</c-><c- o>-</c-><c- n>sent</c-><c- o>-</c-><c- n>by</c-><c- p>(</c-><c- n>input</c-><c- p>)</c-></i><c- p>...</c-><c- o>></c-> <c- n>function</c->
<c- p>);</c->
</pre>
   <p><code class="highlight"><c- n>then</c-></code> returns a sender describing the task graph described by the input sender, with an added node of invoking the provided function with the values <a data-link-type="dfn" href="#send" id="ref-for-send②">sent</a> by the input sender as arguments.</p>
   <p><code class="highlight"><c- n>then</c-></code> is <strong>guaranteed</strong> to not begin executing <code class="highlight"><c- n>function</c-></code> until the returned sender is started.</p>
<pre class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>input</c-> <c- o>=</c-> <c- n>get_input</c-><c- p>();</c->
<c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>snd</c-> <c- o>=</c-> <c- n>execution</c-><c- o>::</c-><c- n>then</c-><c- p>(</c-><c- n>input</c-><c- p>,</c-> <c- p>[](</c-><c- k>auto</c-><c- p>...</c-> <c- n>args</c-><c- p>)</c-> <c- p>{</c->
    <c- n>std</c-><c- o>::</c-><c- n>print</c-><c- p>(</c-><c- n>args</c-><c- p>...);</c->
<c- p>});</c->
<c- c1>// snd describes the work described by pred</c->
<c- c1>// followed by printing all of the values sent by pred</c->
</pre>
   <p>This adaptor is included as it is necessary for writing any sender code that actually performs a useful function.</p>
   <h4 class="heading settled" data-level="4.20.3" id="design-sender-adaptor-upon"><span class="secno">4.20.3. </span><span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>upon_</c-><c- o>*</c-></code></span><a class="self-link" href="#design-sender-adaptor-upon"></a></h4>
<pre class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>upon_error</c-><c- p>(</c->
    <c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>input</c-><c- p>,</c->
    <c- n>std</c-><c- o>::</c-><c- n>invocable</c-><c- o>&lt;</c-><i><c- n>errors</c-><c- o>-</c-><c- n>sent</c-><c- o>-</c-><c- n>by</c-><c- p>(</c-><c- n>input</c-><c- p>)</c-></i><c- p>...</c-><c- o>></c-> <c- n>function</c->
<c- p>);</c->

<c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>upon_stopped</c-><c- p>(</c->
    <c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>input</c-><c- p>,</c->
    <c- n>std</c-><c- o>::</c-><c- n>invocable</c-> <c- k>auto</c-> <c- n>function</c->
<c- p>);</c->
</pre>
   <p><code class="highlight"><c- n>upon_error</c-></code> and <code class="highlight"><c- n>upon_stopped</c-></code> are similar to <code class="highlight"><c- n>then</c-></code>, but where <code class="highlight"><c- n>then</c-></code> works with values sent by the input sender, <code class="highlight"><c- n>upon_error</c-></code> works with errors, and <code class="highlight"><c- n>upon_stopped</c-></code> is invoked when the "stopped" signal is sent.</p>
   <h4 class="heading settled" data-level="4.20.4" id="design-sender-adaptor-let"><span class="secno">4.20.4. </span><span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>let_</c-><c- o>*</c-></code></span><a class="self-link" href="#design-sender-adaptor-let"></a></h4>
<pre class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>let_value</c-><c- p>(</c->
    <c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>input</c-><c- p>,</c->
    <c- n>std</c-><c- o>::</c-><c- n>invocable</c-><c- o>&lt;</c-><i><c- n>values</c-><c- o>-</c-><c- n>sent</c-><c- o>-</c-><c- n>by</c-><c- p>(</c-><c- n>input</c-><c- p>)</c-></i><c- p>...</c-><c- o>></c-> <c- n>function</c->
<c- p>);</c->

<c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>let_error</c-><c- p>(</c->
    <c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>input</c-><c- p>,</c->
    <c- n>std</c-><c- o>::</c-><c- n>invocable</c-><c- o>&lt;</c-><i><c- n>errors</c-><c- o>-</c-><c- n>sent</c-><c- o>-</c-><c- n>by</c-><c- p>(</c-><c- n>input</c-><c- p>)</c-></i><c- p>...</c-><c- o>></c-> <c- n>function</c->
<c- p>);</c->

<c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>let_stopped</c-><c- p>(</c->
    <c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>input</c-><c- p>,</c->
    <c- n>std</c-><c- o>::</c-><c- n>invocable</c-> <c- k>auto</c-> <c- n>function</c->
<c- p>);</c->
</pre>
   <p><code class="highlight"><c- n>let_value</c-></code> is very similar to <code class="highlight"><c- n>then</c-></code>: when it is started, it invokes the provided function with the values <a data-link-type="dfn" href="#send" id="ref-for-send③">sent</a> by the input sender as arguments. However, where the sender returned from <code class="highlight"><c- n>then</c-></code> sends exactly what that function ends up returning - <code class="highlight"><c- n>let_value</c-></code> requires that the function return a sender, and the sender returned by <code class="highlight"><c- n>let_value</c-></code> sends the values sent by the sender returned from the callback. This is similar to the notion of "future unwrapping" in future/promise-based frameworks.</p>
   <p><code class="highlight"><c- n>let_value</c-></code> is <strong>guaranteed</strong> to not begin executing <code class="highlight"><c- n>function</c-></code> until the returned sender is started.</p>
   <p><code class="highlight"><c- n>let_error</c-></code> and <code class="highlight"><c- n>let_stopped</c-></code> are similar to <code class="highlight"><c- n>let_value</c-></code>, but where <code class="highlight"><c- n>let_value</c-></code> works with values sent by the input sender, <code class="highlight"><c- n>let_error</c-></code> works with errors, and <code class="highlight"><c- n>let_stopped</c-></code> is invoked when the "stopped" signal is sent.</p>
   <h4 class="heading settled" data-level="4.20.5" id="design-sender-adaptor-on"><span class="secno">4.20.5. </span><span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>on</c-></code></span><a class="self-link" href="#design-sender-adaptor-on"></a></h4>
<pre class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>on</c-><c- p>(</c->
    <c- n>execution</c-><c- o>::</c-><c- n>scheduler</c-> <c- k>auto</c-> <c- n>sched</c-><c- p>,</c->
    <c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>snd</c->
<c- p>);</c->
</pre>
   <p>Returns a sender which, when started, will start the provided sender on an execution agent belonging to the execution resource associated with the provided scheduler. This returned sender has no <a data-link-type="dfn" href="#completion-scheduler" id="ref-for-completion-scheduler⑤">completion schedulers</a>.</p>
   <h4 class="heading settled" data-level="4.20.6" id="design-sender-adaptor-into_variant"><span class="secno">4.20.6. </span><span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>into_variant</c-></code></span><a class="self-link" href="#design-sender-adaptor-into_variant"></a></h4>
<pre class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>into_variant</c-><c- p>(</c->
    <c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>snd</c->
<c- p>);</c->
</pre>
   <p>Returns a sender which sends a variant of tuples of all the possible sets of types sent by the input sender. Senders can send multiple sets of values depending on runtime conditions; this is a helper function that turns them into a single variant value.</p>
   <h4 class="heading settled" data-level="4.20.7" id="design-sender-adaptor-stopped_as_optional"><span class="secno">4.20.7. </span><span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>stopped_as_optional</c-></code></span><a class="self-link" href="#design-sender-adaptor-stopped_as_optional"></a></h4>
<pre class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>stopped_as_optional</c-><c- p>(</c->
    <i><c- n>single</c-><c- o>-</c-><c- n>sender</c-></i> <c- k>auto</c-> <c- n>snd</c->
<c- p>);</c->
</pre>
   <p>Returns a sender that maps the value channel from a <code class="highlight"><c- n>T</c-></code> to an <code class="highlight"><c- n>optional</c-><c- o>&lt;</c-><c- n>decay_t</c-><c- o>&lt;</c-><c- n>T</c-><c- o>>></c-></code>, and maps the stopped channel to a value of an empty <code class="highlight"><c- n>optional</c-><c- o>&lt;</c-><c- n>decay_t</c-><c- o>&lt;</c-><c- n>T</c-><c- o>>></c-></code>.</p>
   <h4 class="heading settled" data-level="4.20.8" id="design-sender-adaptor-stopped_as_error"><span class="secno">4.20.8. </span><span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>stopped_as_error</c-></code></span><a class="self-link" href="#design-sender-adaptor-stopped_as_error"></a></h4>
<pre class="highlight"><c- k>template</c-><c- o>&lt;</c-><c- n>move_constructible</c-> <c- n>Error</c-><c- o>></c->
<c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>stopped_as_error</c-><c- p>(</c->
    <c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>snd</c-><c- p>,</c->
    <c- n>Error</c-> <c- n>err</c->
<c- p>);</c->
</pre>
   <p>Returns a sender that maps the stopped channel to an error of <code class="highlight"><c- n>err</c-></code>.</p>
   <h4 class="heading settled" data-level="4.20.9" id="design-sender-adaptor-bulk"><span class="secno">4.20.9. </span><span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>bulk</c-></code></span><a class="self-link" href="#design-sender-adaptor-bulk"></a></h4>
<pre class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>bulk</c-><c- p>(</c->
    <c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>input</c-><c- p>,</c->
    <c- n>std</c-><c- o>::</c-><c- n>integral</c-> <c- k>auto</c-> <c- n>shape</c-><c- p>,</c->
    <c- n>invocable</c-><c- o>&lt;</c-><c- k>decltype</c-><c- p>(</c-><c- n>size</c-><c- p>),</c-> <i><c- n>values</c-><c- o>-</c-><c- n>sent</c-><c- o>-</c-><c- n>by</c-><c- p>(</c-><c- n>input</c-><c- p>)</c-></i><c- p>...</c-><c- o>></c-> <c- n>function</c->
<c- p>);</c->
</pre>
   <p>Returns a sender describing the task of invoking the provided function with every index in the provided shape along with the values sent by the input sender. The returned sender completes once all invocations have completed, or an error has occurred. If it completes
by sending values, they are equivalent to those sent by the input sender.</p>
   <p>No instance of <code class="highlight"><c- n>function</c-></code> will begin executing until the returned sender is started. Each invocation of <code class="highlight"><c- n>function</c-></code> runs in an execution agent whose forward progress guarantees are determined by the scheduler on which they are run. All agents created by a single use
of <code class="highlight"><c- n>bulk</c-></code> execute with the same guarantee. The number of execution agents used by <code class="highlight"><c- n>bulk</c-></code> is not specified. This allows a scheduler to execute some invocations of the <code class="highlight"><c- n>function</c-></code> in parallel.</p>
   <p>In this proposal, only integral types are used to specify the shape of the bulk section. We expect that future papers may wish to explore extensions of the interface to explore additional kinds of shapes, such as multi-dimensional grids, that are commonly used for
parallel computing tasks.</p>
   <h4 class="heading settled" data-level="4.20.10" id="design-sender-adaptor-split"><span class="secno">4.20.10. </span><span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>split</c-></code></span><a class="self-link" href="#design-sender-adaptor-split"></a></h4>
<pre class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>split</c-><c- p>(</c-><c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>sender</c-><c- p>);</c->
</pre>
   <p>If the provided sender is a multi-shot sender, returns that sender. Otherwise, returns a multi-shot sender which sends values equivalent to the values sent by the provided sender. See <a href="#design-shot">§ 4.7 Senders can be either multi-shot or single-shot</a>.</p>
   <h4 class="heading settled" data-level="4.20.11" id="design-sender-adaptor-when_all"><span class="secno">4.20.11. </span><span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>when_all</c-></code></span><a class="self-link" href="#design-sender-adaptor-when_all"></a></h4>
<pre class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>when_all</c-><c- p>(</c->
    <c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- p>...</c-><c- n>inputs</c->
<c- p>);</c->

<c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>when_all_with_variant</c-><c- p>(</c->
    <c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- p>...</c-><c- n>inputs</c->
<c- p>);</c->
</pre>
   <p><code class="highlight"><c- n>when_all</c-></code> returns a sender that completes once all of the input senders have completed. It is constrained to only accept senders that can complete with a single set of values (_i.e._, it only calls one overload of <code class="highlight"><c- n>set_value</c-></code> on its receiver). The values sent by this sender are the values sent by each of the input senders, in order of the arguments passed to <code class="highlight"><c- n>when_all</c-></code>. It completes inline on the execution resource on which the last input sender completes, unless stop is requested before <code class="highlight"><c- n>when_all</c-></code> is started, in which case it completes inline within the call to <code class="highlight"><c- n>start</c-></code>.</p>
   <p><code class="highlight"><c- n>when_all_with_variant</c-></code> does the same, but it adapts all the input senders using <code class="highlight"><c- n>into_variant</c-></code>, and so it does not constrain the input arguments as <code class="highlight"><c- n>when_all</c-></code> does.</p>
   <p>The returned sender has no <a data-link-type="dfn" href="#completion-scheduler" id="ref-for-completion-scheduler⑥">completion schedulers</a>.</p>
<pre class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>scheduler</c-> <c- k>auto</c-> <c- n>sched</c-> <c- o>=</c-> <c- n>thread_pool</c-><c- p>.</c-><c- n>scheduler</c-><c- p>();</c->

<c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>sends_1</c-> <c- o>=</c-> <c- p>...;</c->
<c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>sends_abc</c-> <c- o>=</c-> <c- p>...;</c->

<c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>both</c-> <c- o>=</c-> <c- n>execution</c-><c- o>::</c-><c- n>when_all</c-><c- p>(</c-><c- n>sched</c-><c- p>,</c->
    <c- n>sends_1</c-><c- p>,</c->
    <c- n>sends_abc</c->
<c- p>);</c->

<c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- k>final</c-> <c- o>=</c-> <c- n>execution</c-><c- o>::</c-><c- n>then</c-><c- p>(</c-><c- n>both</c-><c- p>,</c-> <c- p>[](</c-><c- k>auto</c-><c- p>...</c-> <c- n>args</c-><c- p>){</c->
    <c- n>std</c-><c- o>::</c-><c- n>cout</c-> <c- o>&lt;&lt;</c-> <c- n>std</c-><c- o>::</c-><c- n>format</c-><c- p>(</c-><c- s>"the two args: {}, {}"</c-><c- p>,</c-> <c- n>args</c-><c- p>...);</c->
<c- p>});</c->
<c- c1>// when final executes, it will print "the two args: 1, abc"</c->
</pre>
   <h4 class="heading settled" data-level="4.20.12" id="design-sender-adaptor-ensure_started"><span class="secno">4.20.12. </span><span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>ensure_started</c-></code></span><a class="self-link" href="#design-sender-adaptor-ensure_started"></a></h4>
<pre class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>ensure_started</c-><c- p>(</c->
    <c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>sender</c->
<c- p>);</c->
</pre>
   <p>Once <code class="highlight"><c- n>ensure_started</c-></code> returns, it is known that the provided sender has been <a data-link-type="dfn" href="#connect" id="ref-for-connect">connected</a> and <code class="highlight"><c- n>start</c-></code> has been called on the resulting operation state (see <a href="#design-states">§ 5.2 Operation states represent work</a>); in other words, the work described by the provided sender has been submitted
for execution on the appropriate execution resources. Returns a sender which completes when the provided sender completes and sends values equivalent to those of the provided sender.</p>
   <p>If the returned sender is destroyed before <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>connect</c-><c- p>()</c-></code> is called, or if <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>connect</c-><c- p>()</c-></code> is called but the
returned operation-state is destroyed before <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>start</c-><c- p>()</c-></code> is called, then a stop-request is sent to the eagerly launched
operation and the operation is detached and will run to completion in the background. Its result will be discarded when it
eventually completes.</p>
   <p>Note that the application will need to make sure that resources are kept alive in the case that the operation detaches.
e.g. by holding a <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>shared_ptr</c-></code> to those resources or otherwise having some out-of-band way to signal completion of
the operation so that resource release can be sequenced after the completion.</p>
   <h3 class="heading settled" data-level="4.21" id="design-sender-consumers"><span class="secno">4.21. </span><span class="content">User-facing sender consumers</span><a class="self-link" href="#design-sender-consumers"></a></h3>
   <p>A <a data-link-type="dfn" href="#sender-consumer" id="ref-for-sender-consumer①">sender consumer</a> is an algorithm that takes one or more senders, which it may <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>connect</c-></code>, as parameters, and does not return a sender.</p>
   <h4 class="heading settled" data-level="4.21.1" id="design-sender-consumer-start_detached"><span class="secno">4.21.1. </span><span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>start_detached</c-></code></span><a class="self-link" href="#design-sender-consumer-start_detached"></a></h4>
<pre class="highlight"><c- b>void</c-> <c- nf>start_detached</c-><c- p>(</c->
    <c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>sender</c->
<c- p>);</c->
</pre>
   <p>Like <code class="highlight"><c- n>ensure_started</c-></code>, but does not return a value; if the provided sender sends an error instead of a value, <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>terminate</c-></code> is called.</p>
   <h4 class="heading settled" data-level="4.21.2" id="design-sender-consumer-sync_wait"><span class="secno">4.21.2. </span><span class="content"><code class="highlight"><c- n>this_thread</c-><c- o>::</c-><c- n>sync_wait</c-></code></span><a class="self-link" href="#design-sender-consumer-sync_wait"></a></h4>
<pre class="highlight"><c- k>auto</c-> <c- n>sync_wait</c-><c- p>(</c->
    <c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>sender</c->
<c- p>)</c-> <c- k>requires</c-> <c- p>(</c-><i><c- n>always</c-><c- o>-</c-><c- n>sends</c-><c- o>-</c-><c- n>same</c-><c- o>-</c-><c- n>values</c-></i><c- p>(</c-><c- n>sender</c-><c- p>))</c->
    <c- o>-></c-> <c- n>std</c-><c- o>::</c-><c- n>optional</c-><c- o>&lt;</c-><c- n>std</c-><c- o>::</c-><c- n>tuple</c-><c- o>&lt;</c-><i><c- n>values</c-><c- o>-</c-><c- n>sent</c-><c- o>-</c-><c- n>by</c-></i><c- p>(</c-><c- n>sender</c-><c- p>)</c-><c- o>>></c-><c- p>;</c->
</pre>
   <p><code class="highlight"><c- n>this_thread</c-><c- o>::</c-><c- n>sync_wait</c-></code> is a sender consumer that submits the work described by the provided sender for execution, similarly to <code class="highlight"><c- n>ensure_started</c-></code>, except that it blocks <b>the current <code class="highlight"><c- n>std</c-><c- o>::</c-><c- kr>thread</c-></code> or thread of <code class="highlight"><c- n>main</c-></code></b> until the work is completed, and returns
an optional tuple of values that were sent by the provided sender on its completion of work. Where <a href="#design-sender-factory-schedule">§ 4.19.1 execution::schedule</a> and <a href="#design-sender-factory-just">§ 4.19.2 execution::just</a> are meant to <i>enter</i> the domain of senders, <code class="highlight"><c- n>sync_wait</c-></code> is meant to <i>exit</i> the domain of
senders, retrieving the result of the task graph.</p>
   <p>If the provided sender sends an error instead of values, <code class="highlight"><c- n>sync_wait</c-></code> throws that error as an exception, or rethrows the original exception if the error is of type <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>exception_ptr</c-></code>.</p>
   <p>If the provided sender sends the "stopped" signal instead of values, <code class="highlight"><c- n>sync_wait</c-></code> returns an empty optional.</p>
   <p>For an explanation of the <code class="highlight"><c- k>requires</c-></code> clause, see <a href="#design-typed">§ 5.8 All senders are typed</a>. That clause also explains another sender consumer, built on top of <code class="highlight"><c- n>sync_wait</c-></code>: <code class="highlight"><c- n>sync_wait_with_variant</c-></code>.</p>
   <p class="note" role="note"><span>Note:</span> This function is specified inside <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>this_thread</c-></code>, and not inside <code class="highlight"><c- n>execution</c-></code>. This is because <code class="highlight"><c- n>sync_wait</c-></code> has to block the <i>current</i> execution agent, but determining what the current execution agent is is not reliable. Since the standard
does not specify any functions on the current execution agent other than those in <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>this_thread</c-></code>, this is the flavor of this function that is being proposed. If C++ ever obtains fibers, for instance, we expect that a variant of this function called <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>this_fiber</c-><c- o>::</c-><c- n>sync_wait</c-></code> would be provided. We also expect that runtimes with execution agents that use different synchronization mechanisms than <code class="highlight"><c- n>std</c-><c- o>::</c-><c- kr>thread</c-></code>'s will provide their own flavors of <code class="highlight"><c- n>sync_wait</c-></code> as well (assuming their execution agents have the means
to block in a non-deadlock manner).</p>
   <h3 class="heading settled" data-level="4.22" id="design-execute"><span class="secno">4.22. </span><span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>execute</c-></code></span><a class="self-link" href="#design-execute"></a></h3>
   <p>In addition to the three categories of functions presented above, we also propose to include a convenience function for fire-and-forget eager one-way submission of an invocable to a scheduler, to fulfil the role of one-way executors from P0443.</p>
<pre class="highlight"><c- b>void</c-> <c- nf>execution::execute</c-><c- p>(</c->
    <c- n>execution</c-><c- o>::</c-><c- n>schedule</c-> <c- k>auto</c-> <c- n>sched</c-><c- p>,</c->
    <c- n>std</c-><c- o>::</c-><c- n>invocable</c-><void> <c- k>auto</c-> <c- n>fn</c->
<c- p>);</c->
</void></pre>
   <p>Submits the provided function for execution on the provided scheduler, as-if by:</p>
<pre class="highlight"><c- k>auto</c-> <c- n>snd</c-> <c- o>=</c-> <c- n>execution</c-><c- o>::</c-><c- n>schedule</c-><c- p>(</c-><c- n>sched</c-><c- p>);</c->
<c- k>auto</c-> <c- n>work</c-> <c- o>=</c-> <c- n>execution</c-><c- o>::</c-><c- n>then</c-><c- p>(</c-><c- n>snd</c-><c- p>,</c-> <c- n>fn</c-><c- p>);</c->
<c- n>execution</c-><c- o>::</c-><c- n>start_detached</c-><c- p>(</c-><c- n>work</c-><c- p>);</c->
</pre>
   <h2 class="heading settled" data-level="5" id="design-implementer"><span class="secno">5. </span><span class="content">Design - implementer side</span><a class="self-link" href="#design-implementer"></a></h2>
   <h3 class="heading settled" data-level="5.1" id="design-receivers"><span class="secno">5.1. </span><span class="content">Receivers serve as glue between senders</span><a class="self-link" href="#design-receivers"></a></h3>
   <p>A <a data-link-type="dfn" href="#receiver" id="ref-for-receiver">receiver</a> is a callback that supports more than one channel. In fact, it supports three of them:</p>
   <ul>
    <li data-md>
     <p><code class="highlight"><c- n>set_value</c-></code>, which is the moral equivalent of an <code class="highlight"><c- k>operator</c-><c- p>()</c-></code> or a function
call, which signals successful completion of the operation its execution
depends on;</p>
    <li data-md>
     <p><code class="highlight"><c- n>set_error</c-></code>, which signals that an error has happened during scheduling of the
current work, executing the current work, or at some earlier point in the
sender chain; and</p>
    <li data-md>
     <p><code class="highlight"><c- n>set_stopped</c-></code>, which signals that the operation completed without succeeding
(<code class="highlight"><c- n>set_value</c-></code>) and without failing (<code class="highlight"><c- n>set_error</c-></code>). This result is often used
to indicate that the operation stopped early, typically because it was asked
to do so because the result is no longer needed.</p>
   </ul>
   <p>Once an async operation has been started exactly one of these functions must be invoked
on a receiver before it is destroyed.</p>
   <p>While the receiver interface may look novel, it is in fact very similar to the
interface of <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>promise</c-></code>, which provides the first two signals as <code class="highlight"><c- n>set_value</c-></code> and <code class="highlight"><c- n>set_exception</c-></code>, and it’s possible to emulate the third channel with
lifetime management of the promise.</p>
   <p>Receivers are not a part of the end-user-facing API of this proposal; they are necessary to allow unrelated senders communicate with each other, but the only users who will interact with receivers directly are authors of senders.</p>
   <p>Receivers are what is passed as the second argument to <a href="#design-connect">§ 5.3 execution::connect</a>.</p>
   <h3 class="heading settled" data-level="5.2" id="design-states"><span class="secno">5.2. </span><span class="content">Operation states represent work</span><a class="self-link" href="#design-states"></a></h3>
   <p>An <a data-link-type="dfn" href="#operation-state" id="ref-for-operation-state">operation state</a> is an object that represents work. Unlike senders, it is not a chaining mechanism; instead, it is a concrete object that packages the work described by a full sender chain, ready to be executed. An operation state is neither movable nor
copyable, and its interface consists of a single algorithm: <code class="highlight"><c- n>start</c-></code>, which serves as the submission point of the work represented by a given operation state.</p>
   <p>Operation states are not a part of the user-facing API of this proposal; they are necessary for implementing sender consumers like <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>ensure_started</c-></code> and <code class="highlight"><c- n>this_thread</c-><c- o>::</c-><c- n>sync_wait</c-></code>, and the knowledge of them is necessary to implement senders, so the only users who will
interact with operation states directly are authors of senders and authors of sender algorithms.</p>
   <p>The return value of <a href="#design-connect">§ 5.3 execution::connect</a> must satisfy the operation state concept.</p>
   <h3 class="heading settled" data-level="5.3" id="design-connect"><span class="secno">5.3. </span><span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>connect</c-></code></span><a class="self-link" href="#design-connect"></a></h3>
   <p><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>connect</c-></code> is a customization point which <a data-link-type="dfn" href="#connect" id="ref-for-connect①">connects</a> senders with receivers, resulting in an operation state that will ensure that if <code class="highlight"><c- n>start</c-></code> is called that one of the completion operations will be called on the receiver passed to <code class="highlight"><c- n>connect</c-></code>.</p>
<pre class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>snd</c-> <c- o>=</c-> <i><c- n>some</c-> <c- n>input</c-> <c- n>sender</c-></i><c- p>;</c->
<c- n>execution</c-><c- o>::</c-><c- n>receiver</c-> <c- k>auto</c-> <c- n>rcv</c-> <c- o>=</c-> <i><c- n>some</c-> <c- n>receiver</c-></i><c- p>;</c->
<c- n>execution</c-><c- o>::</c-><c- n>operation_state</c-> <c- k>auto</c-> <c- n>state</c-> <c- o>=</c-> <c- n>execution</c-><c- o>::</c-><c- n>connect</c-><c- p>(</c-><c- n>snd</c-><c- p>,</c-> <c- n>rcv</c-><c- p>);</c->

<c- n>execution</c-><c- o>::</c-><c- n>start</c-><c- p>(</c-><c- n>state</c-><c- p>);</c->
<c- c1>// at this point, it is guaranteed that the work represented by state has been submitted</c->
<c- c1>// to an execution resource, and that execution resource will eventually call one of the</c->
<c- c1>// completion operations on rcv</c->

<c- c1>// operation states are not movable, and therefore this operation state object must be</c->
<c- c1>// kept alive until the operation finishes</c->
</pre>
   <h3 class="heading settled" data-level="5.4" id="design-customization"><span class="secno">5.4. </span><span class="content">Sender algorithms are customizable</span><a class="self-link" href="#design-customization"></a></h3>
   <p>Senders being able to advertise what their <a data-link-type="dfn" href="#completion-scheduler" id="ref-for-completion-scheduler⑦">completion schedulers</a> are fulfills one of the promises of senders: that of being able to customize an implementation of a sender algorithm based on what scheduler any work it depends on will complete on.</p>
   <p>The simple way to provide customizations for functions like <code class="highlight"><c- n>then</c-></code>, that is for <a data-link-type="dfn" href="#sender-adaptor" id="ref-for-sender-adaptor②">sender adaptors</a> and <a data-link-type="dfn" href="#sender-consumer" id="ref-for-sender-consumer②">sender consumers</a>, is to follow the customization scheme that has been adopted for C++20 ranges library; to do that, we would define
the expression <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>then</c-><c- p>(</c-><c- n>sender</c-><c- p>,</c-> <c- n>invocable</c-><c- p>)</c-></code> to be equivalent to:</p>
   <ol>
    <li data-md>
     <p><code class="highlight"><c- n>sender</c-><c- p>.</c-><c- n>then</c-><c- p>(</c-><c- n>invocable</c-><c- p>)</c-></code>, if that expression is well-formed; otherwise</p>
    <li data-md>
     <p><code class="highlight"><c- n>then</c-><c- p>(</c-><c- n>sender</c-><c- p>,</c-> <c- n>invocable</c-><c- p>)</c-></code>, performed in a context where this call always performs ADL, if that expression is well-formed; otherwise</p>
    <li data-md>
     <p>a default implementation of <code class="highlight"><c- n>then</c-></code>, which returns a sender adaptor, and then define the exact semantics of said adaptor.</p>
   </ol>
   <p>However, this definition is problematic. Imagine another sender adaptor, <code class="highlight"><c- n>bulk</c-></code>, which is a structured abstraction for a loop over an index space. Its default implementation is just a for loop. However, for accelerator runtimes like CUDA, we would like sender algorithms
like <code class="highlight"><c- n>bulk</c-></code> to have specialized behavior, which invokes a kernel of more than one thread (with its size defined by the call to <code class="highlight"><c- n>bulk</c-></code>); therefore, we would like to customize <code class="highlight"><c- n>bulk</c-></code> for CUDA senders to achieve this. However, there’s no reason for CUDA kernels to
necessarily customize the <code class="highlight"><c- n>then</c-></code> sender adaptor, as the generic implementation is perfectly sufficient. This creates a problem, though; consider the following snippet:</p>
<pre class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>scheduler</c-> <c- k>auto</c-> <c- n>cuda_sch</c-> <c- o>=</c-> <c- n>cuda_scheduler</c-><c- p>{};</c->

<c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>initial</c-> <c- o>=</c-> <c- n>execution</c-><c- o>::</c-><c- n>schedule</c-><c- p>(</c-><c- n>cuda_sch</c-><c- p>);</c->
<c- c1>// the type of initial is a type defined by the cuda_scheduler</c->
<c- c1>// let’s call it cuda::schedule_sender&lt;></c->

<c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>next</c-> <c- o>=</c-> <c- n>execution</c-><c- o>::</c-><c- n>then</c-><c- p>(</c-><c- n>cuda_sch</c-><c- p>,</c-> <c- p>[]{</c-> <c- k>return</c-> <c- mi>1</c-><c- p>;</c-> <c- p>});</c->
<c- c1>// the type of next is a standard-library unspecified sender adaptor</c->
<c- c1>// that wraps the cuda sender</c->
<c- c1>// let’s call it execution::then_sender_adaptor&lt;cuda::schedule_sender&lt;>></c->

<c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>kernel_sender</c-> <c- o>=</c-> <c- n>execution</c-><c- o>::</c-><c- n>bulk</c-><c- p>(</c-><c- n>next</c-><c- p>,</c-> <c- n>shape</c-><c- p>,</c-> <c- p>[](</c-><c- b>int</c-> <c- n>i</c-><c- p>){</c-> <c- p>...</c-> <c- p>});</c->
</pre>
   <p>How can we specialize the <code class="highlight"><c- n>bulk</c-></code> sender adaptor for our wrapped <code class="highlight"><c- n>schedule_sender</c-></code>? Well, here’s one possible approach, taking advantage of ADL (and the fact that the definition of "associated namespace" also recursively enumerates the associated namespaces of all template
parameters of a type):</p>
<pre class="highlight"><c- k>namespace</c-> <c- nn>cuda</c-><c- o>::</c-><c- nn>for_adl_purposes</c-> <c- p>{</c->
<c- k>template</c-><c- o>&lt;</c-><c- k>typename</c-><c- p>...</c-> <c- n>SentValues</c-><c- o>></c->
<c- k>class</c-> <c- nc>schedule_sender</c-> <c- p>{</c->
    <c- n>execution</c-><c- o>::</c-><c- n>operation_state</c-> <c- k>auto</c-> <c- n>connect</c-><c- p>(</c-><c- n>execution</c-><c- o>::</c-><c- n>receiver</c-> <c- k>auto</c-> <c- n>rcv</c-><c- p>);</c->
    <c- n>execution</c-><c- o>::</c-><c- n>scheduler</c-> <c- k>auto</c-> <c- n>get_completion_scheduler</c-><c- p>()</c-> <c- k>const</c-><c- p>;</c->
<c- p>};</c->

<c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>bulk</c-><c- p>(</c->
    <c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- o>&amp;&amp;</c-> <c- n>input</c-><c- p>,</c->
    <c- n>execution</c-><c- o>::</c-><c- n>shape</c-> <c- k>auto</c-> <c- o>&amp;&amp;</c-> <c- n>shape</c-><c- p>,</c->
    <c- n>invocable</c-><c- o>%</c-><c- n>lt</c-><c- p>;</c-><i><c- n>sender</c-><c- o>-</c-><c- n>values</c-><c- p>(</c-><c- n>input</c-><c- p>)</c-></i><c- o>></c-> <c- k>auto</c-> <c- o>&amp;&amp;</c-> <c- n>fn</c-><c- p>)</c->
<c- p>{</c->
    <c- c1>// return a cuda sender representing a bulk kernel launch</c->
<c- p>}</c->
<c- p>}</c-> <c- c1>// namespace cuda::for_adl_purposes</c->
</pre>
   <p>However, if the input sender is not just a <code class="highlight"><c- n>then_sender_adaptor</c-></code> like in the example above, but another sender that overrides <code class="highlight"><c- n>bulk</c-></code> by itself, as a member function, because its author believes they know an optimization for bulk - the specialization above will no
longer be selected, because a member function of the first argument is a better match than the ADL-found overload.</p>
   <p>This means that well-meant specialization of sender algorithms that are entirely scheduler-agnostic can have negative consequences.
The scheduler-specific specialization - which is essential for good performance on platforms providing specialized ways to launch certain sender algorithms - would not be selected in such cases.
But it’s really the scheduler that should control the behavior of sender algorithms when a non-default implementation exists, not the sender. Senders merely describe work; schedulers, however, are the handle to the
runtime that will eventually execute said work, and should thus have the final say in <em>how</em> the work is going to be executed.</p>
   <p>Therefore, we are proposing the following customization scheme (also modified to take <a href="#design-dispatch">§ 5.9 Ranges-style CPOs vs tag_invoke</a> into account): the expression <code class="highlight"><c- n>execution</c-><c- o>::&lt;</c-><c- n>sender</c-><c- o>-</c-><c- n>algorithm</c-><c- o>></c-><c- p>(</c-><c- n>sender</c-><c- p>,</c-> <c- n>args</c-><c- p>...)</c-></code>, for any given sender algorithm that accepts a sender as its first argument, should be
equivalent to:</p>
   <ol>
    <li data-md>
     <p><code class="highlight"><c- n>tag_invoke</c-><c- p>(</c-><c- o>&lt;</c-><c- n>sender</c-><c- o>-</c-><c- n>algorithm</c-><c- o>></c-><c- p>,</c-> <c- n>get_completion_scheduler</c-><c- o>&lt;</c-><i><c- n>Tag</c-></i><c- o>></c-><c- p>(</c-><c- n>get_env</c-><c- p>(</c-><c- n>sender</c-><c- p>)),</c-> <c- n>sender</c-><c- p>,</c-> <c- n>args</c-><c- p>...)</c-></code>, if that expression is well-formed; otherwise</p>
    <li data-md>
     <p><code class="highlight"><c- n>tag_invoke</c-><c- p>(</c-><c- o>&lt;</c-><c- n>sender</c-><c- o>-</c-><c- n>algorithm</c-><c- o>></c-><c- p>,</c-> <c- n>sender</c-><c- p>,</c-> <c- n>args</c-><c- p>...)</c-></code>, if that expression is well-formed; otherwise</p>
    <li data-md>
     <p>a default implementation, if there exists a default implementation of the given sender algorithm.</p>
   </ol>
   <p>where <code class="highlight"><i><c- n>Tag</c-></i></code> is one of <code class="highlight"><c- n>set_value</c-></code>, <code class="highlight"><c- n>set_error</c-></code>, or <code class="highlight"><c- n>set_stopped</c-></code>. For most sender algorithms, the completion scheduler for <code class="highlight"><c- n>set_value</c-></code> would be used, but for some (like <code class="highlight"><c- n>upon_error</c-></code> or <code class="highlight"><c- n>let_stopped</c-></code>), one of the others would be used.</p>
   <p>For sender algorithms which accept concepts other than <code class="highlight"><c- n>sender</c-></code> as their first argument, we propose that the customization scheme remains as it has been in <a data-link-type="biblio" href="https://wg21.link/p0443r14"><cite>A Unified Executors Proposal for C++</cite></a> so far, except it should also use <code class="highlight"><c- n>tag_invoke</c-></code>.</p>
   <h3 class="heading settled" data-level="5.5" id="design-laziness"><span class="secno">5.5. </span><span class="content">Sender adaptors are lazy</span><a class="self-link" href="#design-laziness"></a></h3>
   <p>Contrary to early revisions of this paper, we propose to make all sender adaptors perform strictly lazy submission, unless specified otherwise (the one notable exception in this paper is <a href="#design-sender-adaptor-ensure_started">§ 4.20.12 execution::ensure_started</a>, whose sole purpose is to start an
input sender).</p>
   <p><dfn data-dfn-type="dfn" data-export id="strictly-lazy-submission">Strictly lazy submission<a class="self-link" href="#strictly-lazy-submission"></a></dfn> means that there is a guarantee that no work is submitted to an execution resource before a receiver is connected to a sender, and <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>start</c-></code> is called on the resulting operation state.</p>
   <h3 class="heading settled" data-level="5.6" id="design-fusion"><span class="secno">5.6. </span><span class="content">Lazy senders provide optimization opportunities</span><a class="self-link" href="#design-fusion"></a></h3>
   <p>Because lazy senders fundamentally <em>describe</em> work, instead of describing or representing the submission of said work to an execution resource, and thanks to the flexibility of the customization of most sender algorithms, they provide an opportunity for fusing
multiple algorithms in a sender chain together, into a single function that can later be submitted for execution by an execution resource. There are two ways this can happen.</p>
   <p>The first (and most common) way for such optimizations to happen is thanks to the structure of the implementation: because all the work is done within callbacks invoked on the completion of an earlier sender, recursively up to the original source of computation,
the compiler is able to see a chain of work described using senders as a tree of tail calls, allowing for inlining and removal of most of the sender machinery. In fact, when work is not submitted to execution resources outside of the current thread of execution,
compilers are capable of removing the senders abstraction entirely, while still allowing for composition of functions across different parts of a program.</p>
   <p>The second way for this to occur is when a sender algorithm is specialized for a specific set of arguments. For instance, we expect that, for senders which are known to have been started already, <a href="#design-sender-adaptor-ensure_started">§ 4.20.12 execution::ensure_started</a> will be an identity transformation,
because the sender algorithm will be specialized for such senders. Similarly, an implementation could recognize two subsequent <a href="#design-sender-adaptor-bulk">§ 4.20.9 execution::bulk</a>s of compatible shapes, and merge them together into a single submission of a GPU kernel.</p>
   <h3 class="heading settled" data-level="5.7" id="design-transition-details"><span class="secno">5.7. </span><span class="content">Execution resource transitions are two-step</span><a class="self-link" href="#design-transition-details"></a></h3>
   <p>Because <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>transfer</c-></code> takes a sender as its first argument, it is not actually directly customizable by the target scheduler. This is by design: the target scheduler may not know how to transition <i>from</i> a scheduler such as a CUDA scheduler;
transitioning away from a GPU in an efficient manner requires making runtime calls that are specific to the GPU in question, and the same is usually true for other kinds of accelerators too (or for scheduler running on remote systems). To avoid this problem,
specialized schedulers like the ones mentioned here can still hook into the transition mechanism, and inject a sender which will perform a transition to the regular CPU execution resource, so that any sender can be attached to it.</p>
   <p>This, however, is a problem: because customization of sender algorithms must be controlled by the scheduler they will run on (see <a href="#design-customization">§ 5.4 Sender algorithms are customizable</a>), the type of the sender returned from <code class="highlight"><c- n>transfer</c-></code> must be controllable by the target scheduler. Besides, the target
scheduler may itself represent a specialized execution resource, which requires additional work to be performed to transition <i>to</i> it. GPUs and remote node schedulers are once again good examples of such schedulers: executing code on their execution resources
requires making runtime API calls for work submission, and quite possibly for the data movement of the values being sent by the input sender passed into <code class="highlight"><c- n>transfer</c-></code>.</p>
   <p>To allow for such customization from both ends, we propose the inclusion of a secondary transitioning sender adaptor, called <code class="highlight"><c- n>schedule_from</c-></code>. This adaptor is a form of <code class="highlight"><c- n>schedule</c-></code>, but takes an additional, second argument: the input sender. This adaptor is not
meant to be invoked manually by the end users; they are always supposed to invoke <code class="highlight"><c- n>transfer</c-></code>, to ensure that both schedulers have a say in how the transitions are made. Any scheduler that specializes <code class="highlight"><c- n>transfer</c-><c- p>(</c-><c- n>snd</c-><c- p>,</c-> <c- n>sch</c-><c- p>)</c-></code> shall ensure that the
return value of their customization is equivalent to <code class="highlight"><c- n>schedule_from</c-><c- p>(</c-><c- n>sch</c-><c- p>,</c-> <c- n>snd2</c-><c- p>)</c-></code>, where <code class="highlight"><c- n>snd2</c-></code> is a successor of <code class="highlight"><c- n>snd</c-></code> that sends values equivalent to those sent by <code class="highlight"><c- n>snd</c-></code>.</p>
   <p>The default implementation of <code class="highlight"><c- n>transfer</c-><c- p>(</c-><c- n>snd</c-><c- p>,</c-> <c- n>sched</c-><c- p>)</c-></code> is <code class="highlight"><c- n>schedule_from</c-><c- p>(</c-><c- n>sched</c-><c- p>,</c-> <c- n>snd</c-><c- p>)</c-></code>.</p>
   <h3 class="heading settled" data-level="5.8" id="design-typed"><span class="secno">5.8. </span><span class="content">All senders are typed</span><a class="self-link" href="#design-typed"></a></h3>
   <p>All senders must advertise the types they will <a data-link-type="dfn" href="#send" id="ref-for-send④">send</a> when they complete.
This is necessary for a number of features, and writing code in a way that’s
agnostic of whether an input sender is typed or not in common sender adaptors
such as <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>then</c-></code> is hard.</p>
   <p>The mechanism for this advertisement is similar to the one in <a data-link-type="biblio" href="https://wg21.link/p0443r14"><cite>A Unified Executors Proposal for C++</cite></a>; the
way to query the types is through <code class="highlight"><c- n>completion_signatures_of_t</c-><c- o>&lt;</c-><c- n>S</c-><c- p>,</c-> <c- p>[</c-><c- n>Env</c-><c- p>]</c-><c- o>>::</c-><c- n>value_types</c-><c- o>&lt;</c-><c- n>tuple_like</c-><c- p>,</c-> <c- n>variant_like</c-><c- o>></c-></code>.</p>
   <p><code class="highlight"><c- n>completion_signatures_of_t</c-><c- o>::</c-><c- n>value_types</c-></code> is a template that takes two
arguments: one is a tuple-like template, the other is a variant-like template.
The tuple-like argument is required to represent senders sending more than one
value (such as <code class="highlight"><c- n>when_all</c-></code>). The variant-like argument is required to represent
senders that choose which specific values to send at runtime.</p>
   <p>There’s a choice made in the specification of <a href="#design-sender-consumer-sync_wait">§ 4.21.2 this_thread::sync_wait</a>: it returns a tuple of values sent by the
sender passed to it, wrapped in <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>optional</c-></code> to handle the <code class="highlight"><c- n>set_stopped</c-></code> signal. However, this assumes that those values can be represented as a tuple,
like here:</p>
<pre class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>sends_1</c-> <c- o>=</c-> <c- p>...;</c->
<c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>sends_2</c-> <c- o>=</c-> <c- p>...;</c->
<c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>sends_3</c-> <c- o>=</c-> <c- p>...;</c->

<c- k>auto</c-> <c- p>[</c-><c- n>a</c-><c- p>,</c-> <c- n>b</c-><c- p>,</c-> <c- n>c</c-><c- p>]</c-> <c- o>=</c-> <c- n>this_thread</c-><c- o>::</c-><c- n>sync_wait</c-><c- p>(</c->
    <c- n>execution</c-><c- o>::</c-><c- n>when_all</c-><c- p>(</c->
        <c- n>sends_1</c-><c- p>,</c->
        <c- n>sends_2</c-><c- p>,</c->
        <c- n>sends_3</c-><c- p>)</c->
    <c- o>|</c-> <c- n>execution</c-><c- o>::</c-><c- n>transfer</c-><c- p>(</c->
        <c- n>execution</c-><c- o>::</c-><c- n>get_completion_scheduler</c-><c- o>&lt;</c-><c- n>execution</c-><c- o>::</c-><c- n>set_value_t</c-><c- o>></c-><c- p>(</c-><c- n>get_env</c-><c- p>(</c-><c- n>sends_1</c-><c- p>))),</c->
    <c- p>).</c-><c- n>value</c-><c- p>();</c->
<c- c1>// a == 1</c->
<c- c1>// b == 2</c->
<c- c1>// c == 3</c->
</pre>
   <p>This works well for senders that always send the same set of arguments. If we ignore the possibility of having a sender that sends different sets of arguments into a receiver, we can specify the "canonical" (i.e. required to be followed by all senders) form of <code class="highlight"><c- n>value_types</c-></code> of a sender which sends <code class="highlight"><c- n>Types</c-><c- p>...</c-></code> to be as follows:</p>
<pre class="highlight"><c- k>template</c-><c- o>&lt;</c-><c- k>template</c-><c- o>&lt;</c-><c- k>typename</c-> <c- p>...</c-><c- o>></c-> <c- k>typename</c-> <c- nc>TupleLike</c-><c- o>></c->
<c- k>using</c-> <c- n>value_types</c-> <c- o>=</c-> <c- n>TupleLike</c-><types...><c- p>;</c->
</types...></pre>
   <p>If senders could only ever send one specific set of values, this would probably need to be the required form of <code class="highlight"><c- n>value_types</c-></code> for all senders; defining it otherwise would cause very weird results and should be considered a bug.</p>
   <p>This matter is somewhat complicated by the fact that (1) <code class="highlight"><c- n>set_value</c-></code> for receivers can be overloaded and accept different sets of arguments, and (2) senders are allowed to send multiple different sets of values, depending on runtime conditions, the data they
consumed, and so on. To accomodate this, <a data-link-type="biblio" href="https://wg21.link/p0443r14"><cite>A Unified Executors Proposal for C++</cite></a> also includes a second template parameter to <code class="highlight"><c- n>value_types</c-></code>, one that represents a variant-like type. If we permit such senders, we would almost certainly need to require that the canonical form of <code class="highlight"><c- n>value_types</c-></code> for <em>all</em> senders (to ensure consistency in how they are handled, and to avoid accidentally interpreting a user-provided variant as a sender-provided one) sending the different sets of arguments <code class="highlight"><c- n>Types1</c-><c- p>...</c-></code>, <code class="highlight"><c- n>Types2</c-><c- p>...</c-></code>, ..., <code class="highlight"><c- n>TypesN</c-><c- p>...</c-></code> to be as follows:</p>
<pre class="highlight"><c- k>template</c-><c- o>&lt;</c->
    <c- k>template</c-><c- o>&lt;</c-><c- k>typename</c-> <c- p>...</c-><c- o>></c-> <c- k>typename</c-> <c- nc>TupleLike</c-><c- p>,</c->
    <c- k>template</c-><c- o>&lt;</c-><c- k>typename</c-> <c- p>...</c-><c- o>></c-> <c- k>typename</c-> <c- nc>VariantLike</c->
<c- o>></c->
<c- k>using</c-> <c- n>value_types</c-> <c- o>=</c-> <c- n>VariantLike</c-><c- o>&lt;</c->
    <c- n>TupleLike</c-><c- o>&lt;</c-><c- n>Types1</c-><c- p>...</c-><c- o>></c-><c- p>,</c->
    <c- n>TupleLike</c-><c- o>&lt;</c-><c- n>Types2</c-><c- p>...</c-><c- o>></c-><c- p>,</c->
    <c- p>...,</c->
    <c- n>TupleLike</c-><c- o>&lt;</c-><c- n>Types3</c-><c- p>...</c-><c- o>></c->
<c- o>></c-><c- p>;</c->
</pre>
   <p>This, however, introduces a couple of complications:</p>
   <ol>
    <li data-md>
     <p>A <code class="highlight"><c- n>just</c-><c- p>(</c-><c- mi>1</c-><c- p>)</c-></code> sender would also need to follow this structure, so the correct type for storing the value sent by it would be <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>variant</c-><c- o>&lt;</c-><c- n>std</c-><c- o>::</c-><c- n>tuple</c-><c- o>&lt;</c-><c- b>int</c-><c- o>>></c-></code> or some such. This introduces a lot of compile time overhead for the simplest senders, and this overhead
effectively exists in all places in the code where <code class="highlight"><c- n>value_types</c-></code> is queried, regardless of the tuple-like and variant-like templates passed to it. Such overhead does exist if only the tuple-like parameter exists, but is made much worse by adding this second
wrapping layer.</p>
    <li data-md>
     <p>As a consequence of (1): because <code class="highlight"><c- n>sync_wait</c-></code> needs to store the above type, it can no longer return just a <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>tuple</c-><c- o>&lt;</c-><c- b>int</c-><c- o>></c-></code> for <code class="highlight"><c- n>just</c-><c- p>(</c-><c- mi>1</c-><c- p>)</c-></code>; it has to return <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>variant</c-><c- o>&lt;</c-><c- n>std</c-><c- o>::</c-><c- n>tuple</c-><c- o>&lt;</c-><c- b>int</c-><c- o>>></c-></code>. C++ currently does not have an easy way to destructure this; it may get
less awkward with pattern matching, but even then it seems extremely heavyweight to involve variants in this API, and for the purpose of generic code, the kind of the return type of <code class="highlight"><c- n>sync_wait</c-></code> must be the same across all sender types.</p>
   </ol>
   <p>One possible solution to (2) above is to place a requirement on <code class="highlight"><c- n>sync_wait</c-></code> that it can only accept senders which send only a single set of values, therefore removing the need for <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>variant</c-></code> to appear in its API; because of this, we propose to expose both <code class="highlight"><c- n>sync_wait</c-></code>, which is a simple, user-friendly version of the sender consumer, but requires that <code class="highlight"><c- n>value_types</c-></code> have only one possible variant, and <code class="highlight"><c- n>sync_wait_with_variant</c-></code>, which accepts any sender, but returns an optional whose value type is the variant of all the
possible tuples sent by the input sender:</p>
<pre class="highlight"><c- k>auto</c-> <c- n>sync_wait_with_variant</c-><c- p>(</c->
    <c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>sender</c->
<c- p>)</c-> <c- o>-></c-> <c- n>std</c-><c- o>::</c-><c- n>optional</c-><c- o>&lt;</c-><c- n>std</c-><c- o>::</c-><c- n>variant</c-><c- o>&lt;</c->
        <c- n>std</c-><c- o>::</c-><c- n>tuple</c-><c- o>&lt;</c-><i><c- n>values</c-><i><sub><c- n>0</c-></sub></i><c- o>-</c-><c- n>sent</c-><c- o>-</c-><c- n>by</c-></i><c- p>(</c-><c- n>sender</c-><c- p>)</c-><c- o>></c-><c- p>,</c->
        <c- n>std</c-><c- o>::</c-><c- n>tuple</c-><c- o>&lt;</c-><i><c- n>values</c-><i><sub><c- n>1</c-></sub></i><c- o>-</c-><c- n>sent</c-><c- o>-</c-><c- n>by</c-></i><c- p>(</c-><c- n>sender</c-><c- p>)</c-><c- o>></c-><c- p>,</c->
        <c- p>...,</c->
        <c- n>std</c-><c- o>::</c-><c- n>tuple</c-><c- o>&lt;</c-><i><c- n>values</c-><i><sub><c- n>n</c-></sub></i><c- o>-</c-><c- n>sent</c-><c- o>-</c-><c- n>by</c-></i><c- p>(</c-><c- n>sender</c-><c- p>)</c-><c- o>></c->
    <c- o>>></c-><c- p>;</c->

<c- k>auto</c-> <c- n>sync_wait</c-><c- p>(</c->
    <c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>sender</c->
<c- p>)</c-> <c- k>requires</c-> <c- p>(</c-><i><c- n>always</c-><c- o>-</c-><c- n>sends</c-><c- o>-</c-><c- n>same</c-><c- o>-</c-><c- n>values</c-></i><c- p>(</c-><c- n>sender</c-><c- p>))</c->
    <c- o>-></c-> <c- n>std</c-><c- o>::</c-><c- n>optional</c-><c- o>&lt;</c-><c- n>std</c-><c- o>::</c-><c- n>tuple</c-><c- o>&lt;</c-><i><c- n>values</c-><c- o>-</c-><c- n>sent</c-><c- o>-</c-><c- n>by</c-></i><c- p>(</c-><c- n>sender</c-><c- p>)</c-><c- o>>></c-><c- p>;</c->
</pre>
   <h3 class="heading settled" data-level="5.9" id="design-dispatch"><span class="secno">5.9. </span><span class="content">Ranges-style CPOs vs <code class="highlight"><c- n>tag_invoke</c-></code></span><a class="self-link" href="#design-dispatch"></a></h3>
   <p>The contemporary technique for customization in the Standard Library is customization point objects. A customization point object, will it look for member functions and then for nonmember functions with the same name as the customization point, and calls those if
they match. This is the technique used by the C++20 ranges library, and previous executors proposals (<a data-link-type="biblio" href="https://wg21.link/p0443r14"><cite>A Unified Executors Proposal for C++</cite></a> and <a data-link-type="biblio" href="https://wg21.link/p1897r3"><cite>Towards C++23 executors: A proposal for an initial set of algorithms</cite></a>) intended to use it as well. However, it has several unfortunate consequences:</p>
   <ol>
    <li data-md>
     <p>It does not allow for easy propagation of customization points unknown to the adaptor to a wrapped object, which makes writing universal adapter types much harder - and this proposal uses quite a lot of those.</p>
    <li data-md>
     <p>It effectively reserves names globally. Because neither member names nor ADL-found functions can be qualified with a namespace, every customization point object that uses the ranges scheme reserves the name for all types in all namespaces. This is unfortunate
due to the sheer number of customization points already in the paper, but also ones that we are envisioning in the future. It’s also a big problem for one of the operations being proposed already: <code class="highlight"><c- n>sync_wait</c-></code>. We imagine that if, in the future, C++ was to
gain fibers support, we would want to also have <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>this_fiber</c-><c- o>::</c-><c- n>sync_wait</c-></code>, in addition to <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>this_thread</c-><c- o>::</c-><c- n>sync_wait</c-></code>. However, because we would want the names to be the same in both cases, we would need to make the names of the customizations not match the
names of the customization points. This is undesirable.</p>
   </ol>
   <p>This paper proposes to instead use the mechanism described in <a data-link-type="biblio" href="https://wg21.link/p1895r0"><cite>tag_invoke: A general pattern for supporting customisable functions</cite></a>: <code class="highlight"><c- n>tag_invoke</c-></code>; the wording for <code class="highlight"><c- n>tag_invoke</c-></code> has been incorporated into the proposed specification in this paper.</p>
   <p>In short, instead of using globally reserved names, <code class="highlight"><c- n>tag_invoke</c-></code> uses the <i>type</i> of the customization point object itself as the mechanism to find customizations. It globally reserves only a single name - <code class="highlight"><c- n>tag_invoke</c-></code> - which itself is used the same way that
ranges-style customization points are used. All other customization points are defined in terms of <code class="highlight"><c- n>tag_invoke</c-></code>. For example, the customization for <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>this_thread</c-><c- o>::</c-><c- n>sync_wait</c-><c- p>(</c-><c- n>s</c-><c- p>)</c-></code> will call <code class="highlight"><c- n>tag_invoke</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>this_thread</c-><c- o>::</c-><c- n>sync_wait</c-><c- p>,</c-> <c- n>s</c-><c- p>)</c-></code>, instead of attempting
to invoke <code class="highlight"><c- n>s</c-><c- p>.</c-><c- n>sync_wait</c-><c- p>()</c-></code>, and then <code class="highlight"><c- n>sync_wait</c-><c- p>(</c-><c- n>s</c-><c- p>)</c-></code> if the member call is not valid.</p>
   <p>Using <code class="highlight"><c- n>tag_invoke</c-></code> has the following benefits:</p>
   <ol>
    <li data-md>
     <p>It reserves only a single global name, instead of reserving a global name for every customization point object we define.</p>
    <li data-md>
     <p>It is possible to propagate customizations to a subobject, because the information of which customization point is being resolved is in the type of an argument, and not in the name of the function:</p>
<pre class="highlight"><c- c1>// forward most customizations to a subobject</c->
<c- k>template</c-><c- o>&lt;</c-><c- k>typename</c-> <c- nc>Tag</c-><c- p>,</c-> <c- k>typename</c-> <c- p>...</c-><c- n>Args</c-><c- o>></c->
<c- k>friend</c-> <c- k>auto</c-> <c- n>tag_invoke</c-><c- p>(</c-><c- n>Tag</c-> <c- o>&amp;&amp;</c-> <c- n>tag</c-><c- p>,</c-> <c- n>wrapper</c-> <c- o>&amp;</c-> <c- n>self</c-><c- p>,</c-> <c- n>Args</c-> <c- o>&amp;&amp;</c-><c- p>...</c-> <c- n>args</c-><c- p>)</c-> <c- p>{</c->
    <c- k>return</c-> <c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>Tag</c-><c- o>></c-><c- p>(</c-><c- n>tag</c-><c- p>)(</c-><c- n>self</c-><c- p>.</c-><c- n>subobject</c-><c- p>,</c-> <c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>Args</c-><c- o>></c-><c- p>(</c-><c- n>args</c-><c- p>)...);</c->
<c- p>}</c->

<c- c1>// but override one of them with a specific value</c->
<c- k>friend</c-> <c- k>auto</c-> <c- n>tag_invoke</c-><c- p>(</c-><c- n>specific_customization_point_t</c-><c- p>,</c-> <c- n>wrapper</c-> <c- o>&amp;</c-> <c- n>self</c-><c- p>)</c-> <c- p>{</c->
    <c- k>return</c-> <c- n>self</c-><c- p>.</c-><c- n>some_value</c-><c- p>;</c->
<c- p>}</c->
</pre>
    <li data-md>
     <p>It is possible to pass those as template arguments to types, because the information of which customization point is being resolved is in the type. Similarly to how <a data-link-type="biblio" href="https://wg21.link/p0443r14"><cite>A Unified Executors Proposal for C++</cite></a> defines a polymorphic executor wrapper which accepts a list of properties it
supports, we can imagine scheduler and sender wrappers that accept a list of queries and operations they support. That list can contain the types of the customization point objects, and the polymorphic wrappers can then specialize those customization points on
themselves using <code class="highlight"><c- n>tag_invoke</c-></code>, dispatching to manually constructed vtables containing pointers to specialized implementations for the wrapped objects. For an example of such a polymorphic wrapper, see <code class="highlight"><a href="https://github.com/facebookexperimental/libunifex/blob/1a6fbfc9cc3829356ccbdcf9e8d1f3cc33a6d9e0/include/unifex/any_unique.hpp"><c- n>unifex</c-><c- o>::</c-><c- n>any_unique</c-></a></code> (<a href="https://github.com/facebookexperimental/libunifex/blob/1a6fbfc9cc3829356ccbdcf9e8d1f3cc33a6d9e0/examples/any_unique.cpp">example</a>).</p>
   </ol>
   <h2 class="heading settled" data-level="6" id="spec"><span class="secno">6. </span><span class="content">Specification</span><a class="self-link" href="#spec"></a></h2>
   <p>Much of this wording follows the wording of <a data-link-type="biblio" href="https://wg21.link/p0443r14"><cite>A Unified Executors Proposal for C++</cite></a>.</p>
   <p><a href="#spec-library">§ 8 Library introduction [library]</a> is meant to be a diff relative to the wording of the <b>[library]</b> clause of <a data-link-type="biblio" href="https://wg21.link/n4885"><cite>Working Draft, Standard for Programming Language C++</cite></a>.</p>
   <p><a href="#spec-utilities">§ 9 General utilities library [utilities]</a> is meant to be a diff relative to the wording of the <b>[utilities]</b> clause of <a data-link-type="biblio" href="https://wg21.link/n4885"><cite>Working Draft, Standard for Programming Language C++</cite></a>. This diff applies changes from <a data-link-type="biblio" href="https://wg21.link/p1895r0"><cite>tag_invoke: A general pattern for supporting customisable functions</cite></a>.</p>
   <p><a href="#spec-thread">§ 10 Thread support library [thread]</a> is meant to be a diff relative to the wording of the <b>[thread]</b> clause of <a data-link-type="biblio" href="https://wg21.link/n4885"><cite>Working Draft, Standard for Programming Language C++</cite></a>. This diff applies changes from <a data-link-type="biblio" href="https://wg21.link/p2175r0"><cite>Composable cancellation for sender-based async operations</cite></a>.</p>
   <p><a href="#spec-execution">§ 11 Execution control library [exec]</a> is meant to be added as a new library clause to the working draft of C++.</p>
   <h2 class="heading settled" data-level="7" id="spec-except"><span class="secno">7. </span><span class="content">Exception handling [except]</span><a class="self-link" href="#spec-except"></a></h2>
   <h3 class="heading settled" data-level="7.1" id="spec-except.special"><span class="secno">7.1. </span><span class="content">Special functions [except.special]</span><a class="self-link" href="#spec-except.special"></a></h3>
   <h4 class="heading settled" data-level="7.1.1" id="spec-except.special.general"><span class="secno">7.1.1. </span><span class="content">General [except.special.general]</span><a class="self-link" href="#spec-except.special.general"></a></h4>
   <h5 class="heading settled" data-level="7.1.1.1" id="spec-except.terminate"><span class="secno">7.1.1.1. </span><span class="content">The <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>terminate</c-></code> function [except.terminate]</span><a class="self-link" href="#spec-except.terminate"></a></h5>
   <div class="ed-note">At the end of the bulleted list in the Note in paragraph 1, add a new bullet as follows:</div>
   <ins>
    <blockquote>
     <ul>
      <li data-md>
       <p>when a callback invocation exits via an exception when requesting stop on a <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>stop_source</c-></code> or a <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>in_place_stop_source</c-></code> ([stopsource.mem], [stopsource.inplace.mem]), or in
the constructor of <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>stop_callback</c-></code> or <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>in_place_stop_callback</c-></code> ([stopcallback.cons], [stopcallback.inplace.cons]) when a callback invocation exits
via an exception.</p>
     </ul>
    </blockquote>
   </ins>
   <h2 class="heading settled" data-level="8" id="spec-library"><span class="secno">8. </span><span class="content">Library introduction <b>[library]</b></span><a class="self-link" href="#spec-library"></a></h2>
   <div class="ed-note">Add the header <code class="highlight"><c- o>&lt;</c-><c- n>execution</c-><c- o>></c-></code> to Table 23: C++ library
headers [tab:headers.cpp]</div>
   <div class="ed-note">At the end of [expos.only.entity], add the following:</div>
   <ins>
    <blockquote>
     <ol start="3">
      <li data-md>
       <p>An object <code class="highlight"><c- n>dst</c-></code> is said to be <dfn data-dfn-type="dfn" data-export id="decay-copied-from">decay-copied from<a class="self-link" href="#decay-copied-from"></a></dfn> a
subexpression <code class="highlight"><c- n>src</c-></code> if the type of <code class="highlight"><c- n>dst</c-></code> is <code class="highlight"><c- n>decay_t</c-><c- o>&lt;</c-><c- k>decltype</c-><c- p>((</c-><c- n>src</c-><c- p>))</c-><c- o>></c-></code>,
and <code class="highlight"><c- n>dst</c-></code> is copy-initialized from <code class="highlight"><c- n>src</c-></code>.</p>
     </ol>
    </blockquote>
   </ins>
   <div class="ed-note">In subclause [conforming], after [lib.types.movedfrom],
add the following new subclause with suggested stable name [lib.tmpl-heads].</div>
   <ins>
    <blockquote>
      <strong>16.4.6.17  Class template-heads</strong> 
     <ol>
      <li data-md>
       <p>If a class template’s template-head is marked with "<em>arguments are not
associated entities</em>"", any template arguments do not contribute to the
associated entities ([basic.lookup.argdep]) of a function call where a
specialization of the class template is an associated entity. In such a case,
the class template can be implemented as an alias template referring to a
templated class, or as a class template where the template arguments
themselves are templated classes.</p>
      <li data-md>
       <p>[<em>Example:</em></p>
<pre class="highlight"><c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>T</c-><c- o>></c-> <c- c1>// arguments are not associated entities</c->
<c- k>struct</c-> <c- nc>S</c-> <c- p>{};</c->

<c- k>namespace</c-> <c- nn>N</c-> <c- p>{</c->
  <c- b>int</c-> <c- nf>f</c-><c- p>(</c-><c- k>auto</c-><c- p>);</c->
  <c- k>struct</c-> <c- nc>A</c-> <c- p>{};</c->
<c- p>}</c->

<c- b>int</c-> <c- n>x</c-> <c- o>=</c-> <c- n>f</c-><c- p>(</c-><c- n>S</c-><c- o>&lt;</c-><c- n>N</c-><c- o>::</c-><c- n>A</c-><c- o>></c-><c- p>{});</c->  <c- c1>// error: N::f not a candidate</c->
</pre>
       <p>The template <code class="highlight"><c- n>S</c-></code> specified above can be implemented as</p>
<pre class="highlight"><c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>T</c-><c- o>></c->
<c- k>struct</c-> <i><c- nc>s</c-><c- o>-</c-><c- n>impl</c-></i> <c- p>{</c->
  <c- k>struct</c-> <c- nc>type</c-> <c- p>{</c-> <c- p>};</c->
<c- p>};</c->

<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>T</c-><c- o>></c->
<c- k>using</c-> <c- n>S</c-> <c- o>=</c-> <i><c- n>s</c-><c- o>-</c-><c- n>impl</c-></i><c- o>&lt;</c-><c- n>T</c-><c- o>>::</c-><c- n>type</c-><c- p>;</c->
</pre>
       <p>or as</p>
<pre class="highlight"><c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>T</c-><c- o>></c->
<c- k>struct</c-> <i><c- nc>hidden</c-></i> <c- p>{</c->
  <c- k>using</c-> <c- n>type</c-> <c- o>=</c-> <c- k>struct</c-> <c- nc>_</c-> <c- p>{</c->
    <c- k>using</c-> <c- n>type</c-> <c- o>=</c-> <c- n>T</c-><c- p>;</c->
  <c- p>};</c->
<c- p>};</c->

<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>HiddenT</c-><c- o>></c->
<c- k>struct</c-> <i><c- nc>s</c-><c- o>-</c-><c- n>impl</c-></i> <c- p>{</c->
  <c- k>using</c-> <c- n>T</c-> <c- o>=</c-> <c- n>HiddenT</c-><c- o>::</c-><c- n>type</c-><c- p>;</c->
<c- p>};</c->

<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>T</c-><c- o>></c->
<c- k>using</c-> <c- n>S</c-> <c- o>=</c-> <i><c- n>s</c-><c- o>-</c-><c- n>impl</c-></i><c- o>&lt;</c-><c- k>typename</c-> <i><c- nc>hidden</c-></i><c- o>&lt;</c-><c- n>T</c-><c- o>>::</c-><c- n>type</c-><c- o>></c-><c- p>;</c->
</pre>
       <p>-- <i>end example</i>]</p>
     </ol>
    </blockquote>
   </ins>
   <h2 class="heading settled" data-level="9" id="spec-utilities"><span class="secno">9. </span><span class="content">General utilities library <b>[utilities]</b></span><a class="self-link" href="#spec-utilities"></a></h2>
   <h3 class="heading settled" data-level="9.1" id="spec-function.objects"><span class="secno">9.1. </span><span class="content">Function objects <b>[function.objects]</b></span><a class="self-link" href="#spec-function.objects"></a></h3>
   <h4 class="heading settled" data-level="9.1.1" id="spec-functional.syn"><span class="secno">9.1.1. </span><span class="content">Header <code class="highlight"><c- o>&lt;</c-><c- n>functional</c-><c- o>></c-></code> synopsis <b>[functional.syn]</b></span><a class="self-link" href="#spec-functional.syn"></a></h4>
   <p>At the end of this subclause, insert the following declarations into the synopsis within <code class="highlight"><c- k>namespace</c-> <c- nn>std</c-></code>:</p>
   <ins>
    <blockquote>
<pre class="highlight"><i><c- c1>// expositon only:</c-></i>
<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Fn</c-><c- p>,</c-> <c- k>class</c-><c- p>...</c-> <c- n>Args</c-><c- o>></c->
  <c- k>concept</c-> <i><c- nc>callable</c-></i> <c- o>=</c->
    <c- k>requires</c-> <c- p>(</c-><c- n>Fn</c-><c- o>&amp;&amp;</c-> <c- n>fn</c-><c- p>,</c-> <c- n>Args</c-><c- o>&amp;&amp;</c-><c- p>...</c-> <c- n>args</c-><c- p>)</c-> <c- p>{</c->
      <c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>Fn</c-><c- o>></c-><c- p>(</c-><c- n>fn</c-><c- p>)(</c-><c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>Args</c-><c- o>></c-><c- p>(</c-><c- n>args</c-><c- p>)...);</c->
    <c- p>};</c->
<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Fn</c-><c- p>,</c-> <c- k>class</c-><c- p>...</c-> <c- n>Args</c-><c- o>></c->
  <c- k>concept</c-> <i><c- nc>nothrow</c-><c- o>-</c-><c- n>callable</c-></i> <c- o>=</c->
    <i><c- n>callable</c-></i><c- o>&lt;</c-><c- n>Fn</c-><c- p>,</c-> <c- n>Args</c-><c- p>...</c-><c- o>></c-> <c- o>&amp;&amp;</c->
    <c- k>requires</c-> <c- p>(</c-><c- n>Fn</c-><c- o>&amp;&amp;</c-> <c- n>fn</c-><c- p>,</c-> <c- n>Args</c-><c- o>&amp;&amp;</c-><c- p>...</c-> <c- n>args</c-><c- p>)</c-> <c- p>{</c->
      <c- p>{</c-> <c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>Fn</c-><c- o>></c-><c- p>(</c-><c- n>fn</c-><c- p>)(</c-><c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>Args</c-><c- o>></c-><c- p>(</c-><c- n>args</c-><c- p>)...)</c-> <c- p>}</c-> <c- k>noexcept</c-><c- p>;</c->
    <c- p>};</c->
<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Fn</c-><c- p>,</c-> <c- k>class</c-><c- p>...</c-> <c- n>Args</c-><c- o>></c->
  <c- k>using</c-> <i><c- n>call</c-><c- o>-</c-><c- n>result</c-><c- o>-</c-><c- n>t</c-></i> <c- o>=</c-> <c- k>decltype</c-><c- p>(</c-><c- n>declval</c-><c- o>&lt;</c-><c- n>Fn</c-><c- o>></c-><c- p>()(</c-><c- n>declval</c-><c- o>&lt;</c-><c- n>Args</c-><c- o>></c-><c- p>()...));</c->

<c- c1>// [func.tag_invoke], tag_invoke</c->
<c- k>namespace</c-> <i><c- nn>tag</c-><c- o>-</c-><c- nn>invoke</c-></i> <c- p>{</c-> <i><c- c1>// exposition only</c-></i>
  <c- b>void</c-> <c- nf>tag_invoke</c-><c- p>();</c->

  <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Tag</c-><c- p>,</c-> <c- k>class</c-><c- p>...</c-> <c- n>Args</c-><c- o>></c->
    <c- k>concept</c-> <c- nc>tag_invocable</c-> <c- o>=</c->
      <c- k>requires</c-> <c- p>(</c-><c- n>Tag</c-><c- o>&amp;&amp;</c-> <c- n>tag</c-><c- p>,</c-> <c- n>Args</c-><c- o>&amp;&amp;</c-><c- p>...</c-> <c- n>args</c-><c- p>)</c-> <c- p>{</c->
        <c- n>tag_invoke</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>Tag</c-><c- o>></c-><c- p>(</c-><c- n>tag</c-><c- p>),</c-> <c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>Args</c-><c- o>></c-><c- p>(</c-><c- n>args</c-><c- p>)...);</c->
      <c- p>};</c->

  <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Tag</c-><c- p>,</c-> <c- k>class</c-><c- p>...</c-> <c- n>Args</c-><c- o>></c->
    <c- k>concept</c-> <c- nc>nothrow_tag_invocable</c-> <c- o>=</c->
      <c- n>tag_invocable</c-><c- o>&lt;</c-><c- n>Tag</c-><c- p>,</c-> <c- n>Args</c-><c- p>...</c-><c- o>></c-> <c- o>&amp;&amp;</c->
      <c- k>requires</c-> <c- p>(</c-><c- n>Tag</c-><c- o>&amp;&amp;</c-> <c- n>tag</c-><c- p>,</c-> <c- n>Args</c-><c- o>&amp;&amp;</c-><c- p>...</c-> <c- n>args</c-><c- p>)</c-> <c- p>{</c->
        <c- p>{</c-> <c- n>tag_invoke</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>Tag</c-><c- o>></c-><c- p>(</c-><c- n>tag</c-><c- p>),</c-> <c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>Args</c-><c- o>></c-><c- p>(</c-><c- n>args</c-><c- p>)...)</c-> <c- p>}</c-> <c- k>noexcept</c-><c- p>;</c->
      <c- p>};</c->

  <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Tag</c-><c- p>,</c-> <c- k>class</c-><c- p>...</c-> <c- n>Args</c-><c- o>></c->
    <c- k>using</c-> <c- n>tag_invoke_result_t</c-> <c- o>=</c->
      <c- k>decltype</c-><c- p>(</c-><c- n>tag_invoke</c-><c- p>(</c-><c- n>declval</c-><c- o>&lt;</c-><c- n>Tag</c-><c- o>></c-><c- p>(),</c-> <c- n>declval</c-><c- o>&lt;</c-><c- n>Args</c-><c- o>></c-><c- p>()...));</c->

  <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Tag</c-><c- p>,</c-> <c- k>class</c-><c- p>...</c-> <c- n>Args</c-><c- o>></c->
    <c- k>struct</c-> <c- nc>tag_invoke_result</c-><c- o>&lt;</c-><c- n>Tag</c-><c- p>,</c-> <c- n>Args</c-><c- p>...</c-><c- o>></c-> <c- p>{</c->
      <c- k>using</c-> <c- n>type</c-> <c- o>=</c->
        <c- n>tag_invoke_result_t</c-><c- o>&lt;</c-><c- n>Tag</c-><c- p>,</c-> <c- n>Args</c-><c- p>...</c-><c- o>></c-><c- p>;</c-> <i><c- c1>// present if and only if tag_invocable&lt;Tag, Args...> is true</c-></i>
    <c- p>};</c->

  <c- k>struct</c-> <i><c- nc>tag</c-></i><c- p>;</c-> <i><c- c1>// exposition only</c-></i>
<c- p>}</c->
<c- kr>inline</c-> <c- k>constexpr</c-> <i><c- n>tag</c-><c- o>-</c-><c- n>invoke</c-></i><c- o>::</c-><i><c- n>tag</c-></i> <c- n>tag_invoke</c-> <c- p>{};</c->
<c- k>using</c-> <i><c- n>tag</c-><c- o>-</c-><c- n>invoke</c-></i><c- o>::</c-><c- n>tag_invocable</c-><c- p>;</c->
<c- k>using</c-> <i><c- n>tag</c-><c- o>-</c-><c- n>invoke</c-></i><c- o>::</c-><c- n>nothrow_tag_invocable</c-><c- p>;</c->
<c- k>using</c-> <i><c- n>tag</c-><c- o>-</c-><c- n>invoke</c-></i><c- o>::</c-><c- n>tag_invoke_result_t</c-><c- p>;</c->
<c- k>using</c-> <i><c- n>tag</c-><c- o>-</c-><c- n>invoke</c-></i><c- o>::</c-><c- n>tag_invoke_result</c-><c- p>;</c->

<c- k>template</c-><c- o>&lt;</c-><c- k>auto</c-><c- o>&amp;</c-> <c- n>Tag</c-><c- o>></c->
  <c- k>using</c-> <c- n>tag_t</c-> <c- o>=</c-> <c- k>decltype</c-><c- p>(</c-><c- k>auto</c-><c- p>(</c-><c- n>Tag</c-><c- p>));</c->
</pre>
    </blockquote>
   </ins>
   <h4 class="heading settled" data-level="9.1.2" id="spec-func.tag_invoke"><span class="secno">9.1.2. </span><span class="content"><code class="highlight"><c- n>tag_invoke</c-></code> <b>[func.tag_invoke]</b></span><a class="self-link" href="#spec-func.tag_invoke"></a></h4>
   <p>Insert this subclause as a new subclause, between Searchers <b>[func.search]</b> and Class template <code class="highlight"><c- n>hash</c-></code> <b>[unord.hash]</b>.</p>
   <ins>
    <blockquote>
     <ol>
      <li data-md>
       <p>Given a subexpression <code class="highlight"><c- n>E</c-></code>, let <code class="highlight"><i><c- n>REIFY</c-></i><c- p>(</c-><c- n>E</c-><c- p>)</c-></code> be expression-equivalent to
a glvalue with the same type and value as <code class="highlight"><c- n>E</c-></code> as if by <code class="highlight"><c- n>identity</c-><c- p>()(</c-><c- n>E</c-><c- p>)</c-></code>.</p>
      <li data-md>
       <p>The name <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>tag_invoke</c-></code> denotes a customization point object [customization.point.object].
Given subexpressions <code class="highlight"><c- n>T</c-></code> and <code class="highlight"><c- n>A</c-><c- p>...</c-></code>, the expression <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>tag_invoke</c-><c- p>(</c-><c- n>T</c-><c- p>,</c-> <c- n>A</c-><c- p>...)</c-></code> is
expression-equivalent [defns.expression-equivalent] to <code class="highlight"><c- n>tag_invoke</c-><c- p>(</c-><i><c- n>REIFY</c-></i><c- p>(</c-><c- n>T</c-><c- p>),</c-> <i><c- n>REIFY</c-></i><c- p>(</c-><c- n>A</c-><c- p>)...)</c-></code> with overload resolution performed in a context in which unqualified lookup for <code class="highlight"><c- n>tag_invoke</c-></code> finds only the declaration</p>
<pre class="language-c++ highlight"><c- b>void</c-> <c- nf>tag_invoke</c-><c- p>();</c->
</pre>
      <li data-md>
       <p>[Note: Diagnosable ill-formed cases above result in substitution failure when <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>tag_invoke</c-><c- p>(</c-><c- n>T</c-><c- p>,</c-> <c- n>A</c-><c- p>...)</c-></code> appears in the immediate context of a template instantiation. —end note]</p>
     </ol>
    </blockquote>
   </ins>
   <h2 class="heading settled" data-level="10" id="spec-thread"><span class="secno">10. </span><span class="content">Thread support library <b>[thread]</b></span><a class="self-link" href="#spec-thread"></a></h2>
   <h3 class="heading settled" data-level="10.1" id="spec-thread.stoptoken"><span class="secno">10.1. </span><span class="content">Stop tokens <b>[thread.stoptoken]</b></span><a class="self-link" href="#spec-thread.stoptoken"></a></h3>
   <h4 class="heading settled" data-level="10.1.1" id="spec-thread.stoptoken.syn"><span class="secno">10.1.1. </span><span class="content">Header <code class="highlight"><c- o>&lt;</c-><c- n>stop_token</c-><c- o>></c-></code> synopsis <b>[thread.stoptoken.syn]</b></span><a class="self-link" href="#spec-thread.stoptoken.syn"></a></h4>
   <p>At the beginning of this subclause, insert the following declarations into the synopsis within <code class="highlight"><c- k>namespace</c-> <c- nn>std</c-></code>:</p>
   <ins>
    <blockquote>
<pre class="highlight"><c- k>template</c-><c- o>&lt;</c-><c- k>template</c-><c- o>&lt;</c-><c- k>class</c-><c- o>></c-> <c- k>class</c-><c- o>></c->
  <c- k>struct</c-> <i><c- nc>check</c-><c- o>-</c-><c- n>type</c-><c- o>-</c-><c- n>alias</c-><c- o>-</c-><c- n>exists</c-></i><c- p>;</c-> <c- c1>// exposition-only</c->

<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>T</c-><c- o>></c->
  <c- k>concept</c-> <c- nc>stoppable_token</c-> <c- o>=</c-> <i><c- n>see</c-> <c- n>below</c-></i><c- p>;</c->

<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>T</c-><c- p>,</c-> <c- k>class</c-> <c- nc>CB</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Initializer</c-> <c- o>=</c-> <c- n>CB</c-><c- o>></c->
  <c- k>concept</c-> <c- nc>stoppable_token_for</c-> <c- o>=</c-> <i><c- n>see</c-> <c- n>below</c-></i><c- p>;</c->

<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>T</c-><c- o>></c->
  <c- k>concept</c-> <c- nc>unstoppable_token</c-> <c- o>=</c-> <i><c- n>see</c-> <c- n>below</c-></i><c- p>;</c->
</pre>
    </blockquote>
   </ins>
   <p>At the end of this subclause, insert the following declarations into the synopsis of within <code class="highlight"><c- k>namespace</c-> <c- nn>std</c-></code>:</p>
   <ins>
    <blockquote>
<pre class="highlight"><c- c1>// [stoptoken.never], class never_stop_token</c->
<c- k>class</c-> <c- nc>never_stop_token</c-><c- p>;</c->

<c- c1>// [stoptoken.inplace], class in_place_stop_token</c->
<c- k>class</c-> <c- nc>in_place_stop_token</c-><c- p>;</c->

<c- c1>// [stopsource.inplace], class in_place_stop_source</c->
<c- k>class</c-> <c- nc>in_place_stop_source</c-><c- p>;</c->

<c- c1>// [stopcallback.inplace], class template in_place_stop_callback</c->
<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>CB</c-><c- o>></c->
  <c- k>class</c-> <c- nc>in_place_stop_callback</c-><c- p>;</c->

<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>T</c-><c- p>,</c-> <c- k>class</c-> <c- nc>CB</c-><c- o>></c->
  <c- k>using</c-> <c- n>stop_callback_for_t</c-> <c- o>=</c-> <c- n>T</c-><c- o>::</c-><c- k>template</c-> <c- n>callback_type</c-><c- o>&lt;</c-><c- n>CB</c-><c- o>></c-><c- p>;</c->
</pre>
    </blockquote>
   </ins>
   <h4 class="heading settled" data-level="10.1.2" id="spec-thread.stoptoken.concepts"><span class="secno">10.1.2. </span><span class="content">Stop token concepts <b>[thread.stoptoken.concepts]</b></span><a class="self-link" href="#spec-thread.stoptoken.concepts"></a></h4>
   <p>Insert this subclause as a new subclause between Header <code class="highlight"><c- o>&lt;</c-><c- n>stop_token</c-><c- o>></c-></code> synopsis <b>[thread.stoptoken.syn]</b> and Class <code class="highlight"><c- n>stop_token</c-></code> <b>[stoptoken]</b>.</p>
   <ins>
    <blockquote>
     <ol>
      <li data-md>
       <p>The <code class="highlight"><c- n>stoppable_token</c-></code> concept checks for the basic interface of a stop token
that is copyable and allows polling to see if stop has been requested and
also whether a stop request is possible. For a stop token type <code class="highlight"><c- n>T</c-></code> and a type <code class="highlight"><c- n>CB</c-></code> that is callable with no arguments, the type <code class="highlight"><c- n>T</c-><c- o>::</c-><c- n>callback_type</c-><c- o>&lt;</c-><c- n>CB</c-><c- o>></c-></code> is
valid and denotes the stop callback type to use to register a callback
to be executed if a stop request is ever made on a <code class="highlight"><c- n>stoppable_token</c-></code> of type <code class="highlight"><c- n>T</c-></code>. The <code class="highlight"><c- n>stoppable_token_for</c-></code> concept checks for a stop token type compatible
with a given callback type. The <code class="highlight"><c- n>unstoppable_token</c-></code> concept checks for a stop
token type that does not allow stopping.</p>
     </ol>
<pre class="highlight"><c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>T</c-><c- o>></c->
  <c- k>concept</c-> <c- nc>stoppable_token</c-> <c- o>=</c->
    <c- n>copyable</c-><c- o>&lt;</c-><c- n>T</c-><c- o>></c-> <c- o>&amp;&amp;</c->
    <c- n>equality_comparable</c-><c- o>&lt;</c-><c- n>T</c-><c- o>></c-> <c- o>&amp;&amp;</c->
    <c- k>requires</c-> <c- p>(</c-><c- k>const</c-> <c- n>T</c-> <c- n>t</c-><c- p>)</c-> <c- p>{</c->
      <c- p>{</c-> <c- n>T</c-><c- p>(</c-><c- n>t</c-><c- p>)</c-> <c- p>}</c-> <c- k>noexcept</c-><c- p>;</c-> <c- c1>// </c-><i><c- c1>see implicit expression variations ([concepts.equality])</c-></i>
      <c- p>{</c-> <c- n>t</c-><c- p>.</c-><c- n>stop_requested</c-><c- p>()</c-> <c- p>}</c-> <c- k>noexcept</c-> <c- o>-></c-> <c- n>same_as</c-><c- o>&lt;</c-><c- b>bool</c-><c- o>></c-><c- p>;</c->
      <c- p>{</c-> <c- n>t</c-><c- p>.</c-><c- n>stop_possible</c-><c- p>()</c-> <c- p>}</c-> <c- k>noexcept</c-> <c- o>-></c-> <c- n>same_as</c-><c- o>&lt;</c-><c- b>bool</c-><c- o>></c-><c- p>;</c->
      <c- k>typename</c-> <i><c- nc>check</c-><c- o>-</c-><c- n>type</c-><c- o>-</c-><c- n>alias</c-><c- o>-</c-><c- n>exists</c-></i><c- o>&lt;</c-><c- n>T</c-><c- o>::</c-><c- k>template</c-> <c- n>callback_type</c-><c- o>></c-><c- p>;</c->
    <c- p>};</c->

<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>T</c-><c- p>,</c-> <c- k>class</c-> <c- nc>CB</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Initializer</c-> <c- o>=</c-> <c- n>CB</c-><c- o>></c->
  <c- k>concept</c-> <c- nc>stoppable_token_for</c-> <c- o>=</c->
    <c- n>stoppable_token</c-><c- o>&lt;</c-><c- n>T</c-><c- o>></c-> <c- o>&amp;&amp;</c->
    <c- n>invocable</c-><c- o>&lt;</c-><c- n>CB</c-><c- o>></c-> <c- o>&amp;&amp;</c->
    <c- n>constructible_from</c-><c- o>&lt;</c-><c- n>CB</c-><c- p>,</c-> <c- n>Initializer</c-><c- o>></c-> <c- o>&amp;&amp;</c->
    <c- k>requires</c-> <c- p>{</c-> <c- k>typename</c-> <c- nc>stop_callback_for_t</c-><c- o>&lt;</c-><c- n>T</c-><c- p>,</c-> <c- n>CB</c-><c- o>></c-><c- p>;</c-> <c- p>}</c-> <c- o>&amp;&amp;</c->
    <c- n>constructible_from</c-><c- o>&lt;</c-><c- n>stop_callback_for_t</c-><c- o>&lt;</c-><c- n>T</c-><c- p>,</c-> <c- n>CB</c-><c- o>></c-><c- p>,</c-> <c- k>const</c-> <c- n>T</c-><c- o>&amp;</c-><c- p>,</c-> <c- n>Initializer</c-><c- o>></c-><c- p>;</c->

<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>T</c-><c- o>></c->
  <c- k>concept</c-> <c- nc>unstoppable_token</c-> <c- o>=</c->
    <c- n>stoppable_token</c-><c- o>&lt;</c-><c- n>T</c-><c- o>></c-> <c- o>&amp;&amp;</c->
    <c- k>requires</c-> <c- p>{</c->
      <c- p>{</c-> <c- n>bool_constant</c-><c- o>&lt;</c-><c- n>T</c-><c- o>::</c-><c- n>stop_possible</c-><c- p>()</c-><c- o>></c-><c- p>{}</c-> <c- p>}</c-> <c- o>-></c-> <c- n>same_as</c-><c- o>&lt;</c-><c- n>false_type</c-><c- o>></c-><c- p>;</c->
    <c- p>};</c->
</pre>
     <div class="ed-note">
      LWG directed me to replace <code class="highlight"><c- n>T</c-><c- o>::</c-><c- n>stop_possible</c-><c- p>()</c-></code> with <code class="highlight"><c- n>t</c-><c- p>.</c-><c- n>stop_possible</c-><c- p>()</c-></code> because
of the recent <code class="highlight"><c- k>constexpr</c-></code> changes in <a data-link-type="biblio" href="https://wg21.link/p2280r2">P2280R2</a>. However, even with those changes, a nested
requirement like <code class="highlight"><c- k>requires</c-> <c- p>(</c-><c- o>!</c-><c- n>t</c-><c- p>.</c-><c- n>stop_possible</c-><c- p>())</c-></code>, where <code class="highlight"><c- n>t</c-></code> is an argument in the requirement-parameter-list, is ill-formed according to <a href="http://eel.is/c++draft/expr.prim.req#nested-2.sentence-1">[expr.prim.req.nested/p2]</a>: 
      <blockquote>
       <p>A local parameter shall only appear as an unevaluated operand within the constraint-expression.</p>
      </blockquote>
      <p>This is the subject of core issue <a data-link-type="biblio" href="https://wg21.link/cwg2517">2517</a>.</p>
     </div>
     <ol start="2">
      <li data-md>
       <p>Let <code class="highlight"><c- n>t</c-></code> and <code class="highlight"><c- n>u</c-></code> be distinct, valid objects of type <code class="highlight"><c- n>T</c-></code>. The type <code class="highlight"><c- n>T</c-></code> models <code class="highlight"><c- n>stoppable_token</c-></code> only if:</p>
       <ol>
        <li data-md>
         <p>If <code class="highlight"><c- n>t</c-><c- p>.</c-><c- n>stop_possible</c-><c- p>()</c-></code> evaluates to <code class="highlight">false</code> then, if <code class="highlight"><c- n>t</c-></code> and <code class="highlight"><c- n>u</c-></code> reference the same logical shared stop state, <code class="highlight"><c- n>u</c-><c- p>.</c-><c- n>stop_possible</c-><c- p>()</c-></code> shall also subsequently evaluate to <code class="highlight">false</code> and <code class="highlight"><c- n>u</c-><c- p>.</c-><c- n>stop_requested</c-><c- p>()</c-></code> shall also subsequently evaluate to <code class="highlight">false</code>.</p>
        <li data-md>
         <p>If <code class="highlight"><c- n>t</c-><c- p>.</c-><c- n>stop_requested</c-><c- p>()</c-></code> evaluates to <code class="highlight">true</code> then, if <code class="highlight"><c- n>t</c-></code> and <code class="highlight"><c- n>u</c-></code> reference the same logical shared stop state, <code class="highlight"><c- n>u</c-><c- p>.</c-><c- n>stop_requested</c-><c- p>()</c-></code> shall also subsequently evaluate to <code class="highlight">true</code> and <code class="highlight"><c- n>u</c-><c- p>.</c-><c- n>stop_possible</c-><c- p>()</c-></code> shall also subsequently evaluate to <code class="highlight">true</code>.</p>
       </ol>
      <li data-md>
       <p>Let <code class="highlight"><c- n>t</c-></code> and <code class="highlight"><c- n>u</c-></code> be distinct, valid objects of type <code class="highlight"><c- n>T</c-></code> and let <code class="highlight"><c- n>init</c-></code> be an
object of type <code class="highlight"><c- n>Initializer</c-></code>. Then for some type <code class="highlight"><c- n>CB</c-></code>, the type <code class="highlight"><c- n>T</c-></code> models <code class="highlight"><c- n>stoppable_token_for</c-><c- o>&lt;</c-><c- n>CB</c-><c- p>,</c-> <c- n>Initializer</c-><c- o>></c-></code> only if:</p>
       <ol>
        <li data-md>
         <p>The type <code class="highlight"><c- n>T</c-><c- o>::</c-><c- n>callback_type</c-><c- o>&lt;</c-><c- n>CB</c-><c- o>></c-></code> models:</p>
<pre class="language-c++ highlight"><c- n>constructible_from</c-><c- o>&lt;</c-><c- n>T</c-><c- p>,</c-> <c- n>Initializer</c-><c- o>></c-> <c- o>&amp;&amp;</c->
<c- n>constructible_from</c-><c- o>&lt;</c-><c- n>T</c-><c- o>&amp;</c-><c- p>,</c-> <c- n>Initializer</c-><c- o>></c-> <c- o>&amp;&amp;</c->
<c- n>constructible_from</c-><c- o>&lt;</c-><c- k>const</c-> <c- n>T</c-><c- p>,</c-> <c- n>Initializer</c-><c- o>></c->
</pre>
        <li data-md>
         <p>Direct non-list initializing an object <code class="highlight"><c- n>cb</c-></code> of type <code class="highlight"><c- n>T</c-><c- o>::</c-><c- n>callback_type</c-><c- o>&lt;</c-><c- n>CB</c-><c- o>></c-></code> from <code class="highlight"><c- n>t</c-><c- p>,</c-> <c- n>init</c-></code> shall, if <code class="highlight"><c- n>t</c-><c- p>.</c-><c- n>stop_possible</c-><c- p>()</c-></code> is <code class="highlight">true</code>, construct an
instance, <code class="highlight"><c- n>callback</c-></code>, of type <code class="highlight"><c- n>CB</c-></code>, direct-initialized with <code class="highlight"><c- n>init</c-></code>,
and register callback with <code class="highlight"><c- n>t</c-></code>'s shared stop state such that <code class="highlight"><c- n>callback</c-></code> will be invoked with an empty argument list if a stop request is made
on the shared stop state.</p>
         <ol>
          <li data-md>
           <p>If <code class="highlight"><c- n>t</c-><c- p>.</c-><c- n>stop_requested</c-><c- p>()</c-></code> evaluates to <code class="highlight">true</code> at the time <code class="highlight"><c- n>callback</c-></code> is
registered then <code class="highlight"><c- n>callback</c-></code> can be invoked on the thread executing <code class="highlight"><c- n>cb</c-></code>'s constructor.</p>
          <li data-md>
           <p>If <code class="highlight"><c- n>callback</c-></code> is invoked then, if <code class="highlight"><c- n>t</c-></code> and <code class="highlight"><c- n>u</c-></code> reference the same shared stop
state, an evaluation of <code class="highlight"><c- n>u</c-><c- p>.</c-><c- n>stop_requested</c-><c- p>()</c-></code> will be <code class="highlight">true</code> if the beginning of the invocation of <code class="highlight"><c- n>callback</c-></code> strongly-happens-before the evaluation of <code class="highlight"><c- n>u</c-><c- p>.</c-><c- n>stop_requested</c-><c- p>()</c-></code>.</p>
          <li data-md>
           <p>[<em>Note:</em> If <code class="highlight"><c- n>t</c-><c- p>.</c-><c- n>stop_possible</c-><c- p>()</c-></code> evaluates to <code class="highlight">false</code> then the construction of <code class="highlight"><c- n>cb</c-></code> is not required to construct and initialize <code class="highlight"><c- n>callback</c-></code>. <em>--end note</em>]</p>
         </ol>
        <li data-md>
         <p>Construction of a <code class="highlight"><c- n>T</c-><c- o>::</c-><c- n>callback_type</c-><c- o>&lt;</c-><c- n>CB</c-><c- o>></c-></code> instance shall only throw exceptions thrown by the initialization of the <code class="highlight"><c- n>CB</c-></code> instance from the value of type <code class="highlight"><c- n>Initializer</c-></code>.</p>
        <li data-md>
         <p>Destruction of the <code class="highlight"><c- n>T</c-><c- o>::</c-><c- n>callback_type</c-><c- o>&lt;</c-><c- n>CB</c-><c- o>></c-></code> object, <code class="highlight"><c- n>cb</c-></code>, removes <code class="highlight"><c- n>callback</c-></code> from the shared stop state such that <code class="highlight"><c- n>callback</c-></code> will not be invoked after the destructor returns.</p>
         <ol>
          <li data-md>
           <p>If <code class="highlight"><c- n>callback</c-></code> is currently being invoked on another thread then the destructor of <code class="highlight"><c- n>cb</c-></code> will block until the invocation of <code class="highlight"><c- n>callback</c-></code> returns such that the return from the invocation of <code class="highlight"><c- n>callback</c-></code> strongly-happens-before the destruction of <code class="highlight"><c- n>callback</c-></code>.</p>
          <li data-md>
           <p>Destruction of a callback <code class="highlight"><c- n>cb</c-></code> shall not block on the completion of the invocation of some other callback registered with the same shared stop state.</p>
         </ol>
       </ol>
     </ol>
    </blockquote>
   </ins>
   <h4 class="heading settled" data-level="10.1.3" id="spec-stoptoken"><span class="secno">10.1.3. </span><span class="content">Class <code class="highlight"><c- n>stop_token</c-></code> <b>[stoptoken]</b></span><a class="self-link" href="#spec-stoptoken"></a></h4>
   <h5 class="heading settled" data-level="10.1.3.1" id="spec-stoptoken.general"><span class="secno">10.1.3.1. </span><span class="content">General <b>[stoptoken.general]</b></span><a class="self-link" href="#spec-stoptoken.general"></a></h5>
   <p>Modify the synopsis of class <code class="highlight"><c- n>stop_token</c-></code> in subclause General <b>[stoptoken.general]</b> as follows:</p>
<pre class="highlight"><c- k>namespace</c-> <c- nn>std</c-> <c- p>{</c->
  <c- k>class</c-> <c- nc>stop_token</c-> <c- p>{</c->
  <c- k>public</c-><c- o>:</c->
<ins>    <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>T</c-><c- o>></c->
      <c- k>using</c-> <c- n>callback_type</c-> <c- o>=</c-> <c- n>stop_callback</c-><c- o>&lt;</c-><c- n>T</c-><c- o>></c-><c- p>;</c-></ins>

    <c- c1>// [stoptoken.cons], constructors, copy, and assignment</c->
    <c- n>stop_token</c-><c- p>()</c-> <c- k>noexcept</c-><c- p>;</c->

    <c- c1>// ...</c->
</pre>
   <h4 class="heading settled" data-level="10.1.4" id="spec-stoptoken.never"><span class="secno">10.1.4. </span><span class="content">Class <code class="highlight"><c- n>never_stop_token</c-></code> <b>[stoptoken.never]</b></span><a class="self-link" href="#spec-stoptoken.never"></a></h4>
   <p>Insert a new subclause, Class <code class="highlight"><c- n>never_stop_token</c-></code> <b>[stoptoken.never]</b>, after subclause Class template <code class="highlight"><c- n>stop_callback</c-></code> <b>[stopcallback]</b>, as a new subclause of Stop tokens <b>[thread.stoptoken]</b>.</p>
   <h5 class="heading settled" data-level="10.1.4.1" id="spec-stoptoken.never.general"><span class="secno">10.1.4.1. </span><span class="content">General <b>[stoptoken.never.general]</b></span><a class="self-link" href="#spec-stoptoken.never.general"></a></h5>
   <ol>
    <li data-md>
     <p>The class <code class="highlight"><c- n>never_stop_token</c-></code> provides an implementation of the <code class="highlight"><c- n>unstoppable_token</c-></code> concept. It provides a stop token interface, but also provides static information that a stop is never possible nor requested.</p>
   </ol>
<pre class="highlight"><c- k>namespace</c-> <c- nn>std</c->
<c- p>{</c->
  <c- k>class</c-> <c- nc>never_stop_token</c-> <c- p>{</c->
    <i><c- c1>// exposition only</c-></i>
    <c- k>struct</c-> <i><c- nc>callback</c-></i> <c- p>{</c->
      <c- k>explicit</c-> <i><c- n>callback</c-></i><c- p>(</c-><c- n>never_stop_token</c-><c- p>,</c-> <c- k>auto</c-><c- o>&amp;&amp;</c-><c- p>)</c-> <c- k>noexcept</c-> <c- p>{}</c->
    <c- p>};</c->
  <c- k>public</c-><c- o>:</c->
    <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-><c- o>></c->
      <c- k>using</c-> <c- n>callback_type</c-> <c- o>=</c-> <i><c- n>callback</c-></i><c- p>;</c->

    <c- p>[[</c-><c- n>nodiscard</c-><c- p>]]</c-> <c- k>static</c-> <c- k>constexpr</c-> <c- b>bool</c-> <c- n>stop_requested</c-><c- p>()</c-> <c- k>noexcept</c-> <c- p>{</c-> <c- k>return</c-> false<c- p>;</c-> <c- p>}</c->
    <c- p>[[</c-><c- n>nodiscard</c-><c- p>]]</c-> <c- k>static</c-> <c- k>constexpr</c-> <c- b>bool</c-> <c- n>stop_possible</c-><c- p>()</c-> <c- k>noexcept</c-> <c- p>{</c-> <c- k>return</c-> false<c- p>;</c-> <c- p>}</c->

    <c- p>[[</c-><c- n>nodiscard</c-><c- p>]]</c-> <c- k>friend</c-> <c- b>bool</c-> <c- k>operator</c-><c- o>==</c-><c- p>(</c-><c- k>const</c-> <c- n>never_stop_token</c-><c- o>&amp;</c-><c- p>,</c-> <c- k>const</c-> <c- n>never_stop_token</c-><c- o>&amp;</c-><c- p>)</c-> <c- k>noexcept</c-> <c- o>=</c-> <c- k>default</c-><c- p>;</c->
  <c- p>};</c->
<c- p>}</c->
</pre>
   <h4 class="heading settled" data-level="10.1.5" id="spec-stoptoken.inplace"><span class="secno">10.1.5. </span><span class="content">Class <code class="highlight"><c- n>in_place_stop_token</c-></code> <b>[stoptoken.inplace]</b></span><a class="self-link" href="#spec-stoptoken.inplace"></a></h4>
   <p>Insert a new subclause, Class <code class="highlight"><c- n>in_place_stop_token</c-></code> <b>[stoptoken.inplace]</b>, after the subclause added above, as a new subclause of Stop tokens <b>[thread.stoptoken]</b>.</p>
   <h5 class="heading settled" data-level="10.1.5.1" id="spec-stoptoken.inplace.general"><span class="secno">10.1.5.1. </span><span class="content">General <b>[stoptoken.inplace.general]</b></span><a class="self-link" href="#spec-stoptoken.inplace.general"></a></h5>
   <ol>
    <li data-md>
     <p>The class <code class="highlight"><c- n>in_place_stop_token</c-></code> provides an interface for querying whether a stop request has been made (<code class="highlight"><c- n>stop_requested</c-></code>) or can ever be made (<code class="highlight"><c- n>stop_possible</c-></code>) using an associated <code class="highlight"><c- n>in_place_stop_source</c-></code> object ([stopsource.inplace]).
An <code class="highlight"><c- n>in_place_stop_token</c-></code> can also be passed to an <code class="highlight"><c- n>in_place_stop_callback</c-></code> ([stopcallback.inplace]) constructor to register a callback to be called when a stop request has been made from an associated <code class="highlight"><c- n>in_place_stop_source</c-></code>.</p>
   </ol>
<pre class="highlight"><c- k>namespace</c-> <c- nn>std</c-> <c- p>{</c->
  <c- k>class</c-> <c- nc>in_place_stop_token</c-> <c- p>{</c->
  <c- k>public</c-><c- o>:</c->
    <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>CB</c-><c- o>></c->
      <c- k>using</c-> <c- n>callback_type</c-> <c- o>=</c-> <c- n>in_place_stop_callback</c-><c- o>&lt;</c-><c- n>CB</c-><c- o>></c-><c- p>;</c->

    <c- c1>// [stoptoken.inplace.cons], constructors, copy, and assignment</c->
    <c- n>in_place_stop_token</c-><c- p>()</c-> <c- k>noexcept</c-><c- p>;</c->
    <c- o>~</c-><c- n>in_place_stop_token</c-><c- p>();</c->
    <c- b>void</c-> <c- nf>swap</c-><c- p>(</c-><c- n>in_place_stop_token</c-><c- o>&amp;</c-><c- p>)</c-> <c- k>noexcept</c-><c- p>;</c->

    <c- c1>// [stoptoken.inplace.mem], stop handling</c->
    <c- p>[[</c-><c- n>nodiscard</c-><c- p>]]</c-> <c- b>bool</c-> <c- n>stop_requested</c-><c- p>()</c-> <c- k>const</c-> <c- k>noexcept</c-><c- p>;</c->
    <c- p>[[</c-><c- n>nodiscard</c-><c- p>]]</c-> <c- b>bool</c-> <c- n>stop_possible</c-><c- p>()</c-> <c- k>const</c-> <c- k>noexcept</c-><c- p>;</c->

    <c- p>[[</c-><c- n>nodiscard</c-><c- p>]]</c-> <c- k>friend</c-> <c- b>bool</c-> <c- k>operator</c-><c- o>==</c-><c- p>(</c-><c- k>const</c-> <c- n>in_place_stop_token</c-><c- o>&amp;</c-><c- p>,</c-> <c- k>const</c-> <c- n>in_place_stop_token</c-><c- o>&amp;</c-><c- p>)</c-> <c- k>noexcept</c-> <c- o>=</c-> <c- k>default</c-><c- p>;</c->
    <c- k>friend</c-> <c- b>void</c-> <c- nf>swap</c-><c- p>(</c-><c- n>in_place_stop_token</c-><c- o>&amp;</c-> <c- n>lhs</c-><c- p>,</c-> <c- n>in_place_stop_token</c-><c- o>&amp;</c-> <c- n>rhs</c-><c- p>)</c-> <c- k>noexcept</c-><c- p>;</c->

  <c- k>private</c-><c- o>:</c->
    <c- k>const</c-> <c- n>in_place_stop_source</c-><c- o>*</c-> <i><c- n>source_</c-></i><c- p>;</c-> <c- c1>// exposition only</c->
  <c- p>};</c->
<c- p>}</c->
</pre>
   <h5 class="heading settled" data-level="10.1.5.2" id="spec-stoptoken.inplace.cons"><span class="secno">10.1.5.2. </span><span class="content">Constructors, copy, and assignment <b>[stoptoken.inplace.cons]</b></span><a class="self-link" href="#spec-stoptoken.inplace.cons"></a></h5>
<pre class="highlight"><c- n>in_place_stop_token</c-><c- p>()</c-> <c- k>noexcept</c-><c- p>;</c->
</pre>
   <ol>
    <li data-md>
     <p><em>Effects</em>: initializes <code class="highlight"><i><c- n>source_</c-></i></code> with <code class="highlight"><c- k>nullptr</c-></code>.</p>
   </ol>
<pre class="highlight"><c- b>void</c-> <c- nf>swap</c-><c- p>(</c-><c- n>stop_token</c-><c- o>&amp;</c-> <c- n>rhs</c-><c- p>)</c-> <c- k>noexcept</c-><c- p>;</c->
</pre>
   <ol start="2">
    <li data-md>
     <p><em>Effects</em>: Exchanges the values of <code class="highlight"><i><c- n>source_</c-></i></code> and <code class="highlight"><c- n>rhs</c-><c- p>.</c-><i><c- n>source_</c-></i></code>.</p>
   </ol>
   <h5 class="heading settled" data-level="10.1.5.3" id="spec-stoptoken.inplace.mem"><span class="secno">10.1.5.3. </span><span class="content">Members <b>[stoptoken.inplace.mem]</b></span><a class="self-link" href="#spec-stoptoken.inplace.mem"></a></h5>
<pre class="highlight"><c- p>[[</c-><c- n>nodiscard</c-><c- p>]]</c-> <c- b>bool</c-> <c- n>stop_requested</c-><c- p>()</c-> <c- k>const</c-> <c- k>noexcept</c-><c- p>;</c->
</pre>
   <ol>
    <li data-md>
     <p><em>Effects</em>: Equivalent to: <code class="highlight"><c- k>return</c-> <i><c- n>source_</c-></i> <c- o>!=</c-> <c- k>nullptr</c-> <c- o>&amp;&amp;</c-> <i><c- n>source_</c-></i><c- o>-></c-><c- n>stop_requested</c-><c- p>();</c-></code></p>
    <li data-md>
     <p>[<em>Note</em>: The behavior of <code class="highlight"><c- n>stop_requested</c-><c- p>()</c-></code> is undefined unless the call
strongly happens before the start of the destructor of the associated <code class="highlight"><c- n>in_place_stop_source</c-></code>, if any ([basic.life]). --<em>end note</em>]</p>
   </ol>
<pre class="highlight"><c- p>[[</c-><c- n>nodiscard</c-><c- p>]]</c-> <c- b>bool</c-> <c- n>stop_possible</c-><c- p>()</c-> <c- k>const</c-> <c- k>noexcept</c-><c- p>;</c->
</pre>
   <ol start="3">
    <li data-md>
     <p><em>Effects</em>: Equivalent to: <code class="highlight"><c- k>return</c-> <i><c- n>source_</c-></i> <c- o>!=</c-> <c- k>nullptr</c-><c- p>;</c-></code></p>
    <li data-md>
     <p>[<em>Note</em>: The behavior of <code class="highlight"><c- n>stop_possible</c-><c- p>()</c-></code> is implementation-defined unless
the call strongly happens before the end of the storage duration of the
associated <code class="highlight"><c- n>in_place_stop_source</c-></code> object, if any ([basic.stc.general]). --<em>end note</em>]</p>
   </ol>
   <h5 class="heading settled" data-level="10.1.5.4" id="spec-stoptoken.inplace.nonmembers"><span class="secno">10.1.5.4. </span><span class="content">Non-member functions <b>[stoptoken.inplace.nonmembers]</b></span><a class="self-link" href="#spec-stoptoken.inplace.nonmembers"></a></h5>
<pre class="highlight"><c- k>friend</c-> <c- b>void</c-> <c- nf>swap</c-><c- p>(</c-><c- n>in_place_stop_token</c-><c- o>&amp;</c-> <c- n>x</c-><c- p>,</c-> <c- n>in_place_stop_token</c-><c- o>&amp;</c-> <c- n>y</c-><c- p>)</c-> <c- k>noexcept</c-><c- p>;</c->
</pre>
   <ol start="2">
    <li data-md>
     <p><em>Effects</em>: Equivalent to: <code class="highlight"><c- n>x</c-><c- p>.</c-><c- n>swap</c-><c- p>(</c-><c- n>y</c-><c- p>)</c-></code>.</p>
   </ol>
   <h4 class="heading settled" data-level="10.1.6" id="spec-stopsource.inplace"><span class="secno">10.1.6. </span><span class="content">Class <code class="highlight"><c- n>in_place_stop_source</c-></code> <b>[stopsource.inplace]</b></span><a class="self-link" href="#spec-stopsource.inplace"></a></h4>
   <p>Insert a new subclause, Class <code class="highlight"><c- n>in_place_stop_source</c-></code> <b>[stopsource.inplace]</b>, after the subclause added above, as a new subclause of Stop tokens <b>[thread.stoptoken]</b>.</p>
   <h5 class="heading settled" data-level="10.1.6.1" id="spec-stopsource.inplace.general"><span class="secno">10.1.6.1. </span><span class="content">General <b>[stopsource.inplace.general]</b></span><a class="self-link" href="#spec-stopsource.inplace.general"></a></h5>
   <ol>
    <li data-md>
     <p>The class <code class="highlight"><c- n>in_place_stop_source</c-></code> implements the semantics of making a stop request, without the need for a dynamic allocation of a shared state.
A stop request made on a <code class="highlight"><c- n>in_place_stop_source</c-></code> object is visible to all associated <code class="highlight"><c- n>in_place_stop_token</c-></code> ([stoptoken.inplace]) objects.
Once a stop request has been made it cannot be withdrawn (a subsequent stop request has no effect).
All uses of <code class="highlight"><c- n>in_place_stop_token</c-></code> objects associated with a given <code class="highlight"><c- n>in_place_stop_source</c-></code> object must happen before the start of the destructor of that <code class="highlight"><c- n>in_place_stop_source</c-></code> object.</p>
   </ol>
<pre class="highlight"><c- k>namespace</c-> <c- nn>std</c-> <c- p>{</c->
  <c- k>class</c-> <c- nc>in_place_stop_source</c-> <c- p>{</c->
  <c- k>public</c-><c- o>:</c->
    <c- c1>// [stopsource.inplace.cons], constructors, copy, and assignment</c->
    <c- n>in_place_stop_source</c-><c- p>()</c-> <c- k>noexcept</c-><c- p>;</c->

    <c- n>in_place_stop_source</c-><c- p>(</c-><c- n>in_place_stop_source</c-><c- o>&amp;&amp;</c-><c- p>)</c-> <c- k>noexcept</c-> <c- o>=</c-> <c- k>delete</c-><c- p>;</c->
    <c- o>~</c-><c- n>in_place_stop_source</c-><c- p>();</c->

    <c- c1>//[stopsource.inplace.mem], stop handling</c->
    <c- p>[[</c-><c- n>nodiscard</c-><c- p>]]</c-> <c- n>in_place_stop_token</c-> <c- n>get_token</c-><c- p>()</c-> <c- k>const</c-> <c- k>noexcept</c-><c- p>;</c->
    <c- p>[[</c-><c- n>nodiscard</c-><c- p>]]</c-> <c- k>static</c-> <c- k>constexpr</c-> <c- b>bool</c-> <c- n>stop_possible</c-><c- p>()</c-> <c- k>noexcept</c-> <c- p>{</c-> <c- k>return</c-> true<c- p>;</c-> <c- p>}</c->
    <c- p>[[</c-><c- n>nodiscard</c-><c- p>]]</c-> <c- b>bool</c-> <c- n>stop_requested</c-><c- p>()</c-> <c- k>const</c-> <c- k>noexcept</c-><c- p>;</c->
    <c- b>bool</c-> <c- nf>request_stop</c-><c- p>()</c-> <c- k>noexcept</c-><c- p>;</c->
  <c- p>};</c->
<c- p>}</c->
</pre>
   <ol start="2">
    <li data-md>
     <p>An instance of <code class="highlight"><c- n>in_place_stop_source</c-></code> maintains a list of registered callback invocations.
The registration of a callback invocation either succeeds or fails. When an invocation
of a callback is registered, the following happens atomically:</p>
     <ul>
      <li data-md>
       <p>The stop state is checked. If stop has not been requested, the callback invocation is
added to the list of registered callback invocations, and registration has succeeded.</p>
      <li data-md>
       <p>Otherwise, registration has failed.</p>
     </ul>
     <p>When an invocation of a callback is unregistered, the invocation is atomically removed
from the list of registered callback invocations. The removal is not blocked by the concurrent
execution of another callback invocation in the list. If the callback invocation
being unregistered is currently executing, then:</p>
     <ul>
      <li data-md>
       <p>If the execution of the callback invocation is happening concurrently on another thread,
the completion of the execution strongly happens before ([intro.races]) the end of the
callback’s lifetime.</p>
      <li data-md>
       <p>Otherwise, the execution is happening on the current thread. Removal of the
callback invocation does not block waiting for the execution to complete.</p>
     </ul>
   </ol>
   <h5 class="heading settled" data-level="10.1.6.2" id="spec-stopsource.inplace.cons"><span class="secno">10.1.6.2. </span><span class="content">Constructors, copy, and assignment <b>[stopsource.inplace.cons]</b></span><a class="self-link" href="#spec-stopsource.inplace.cons"></a></h5>
<pre class="highlight"><c- n>in_place_stop_source</c-><c- p>()</c-> <c- k>noexcept</c-><c- p>;</c->
</pre>
   <ol>
    <li data-md>
     <p><em>Effects</em>: Initializes a new stop state inside <code class="highlight"><c- o>*</c-><c- k>this</c-></code>.</p>
    <li data-md>
     <p><em>Postconditions</em>: <code class="highlight"><c- n>stop_requested</c-><c- p>()</c-></code> is <code class="highlight">false</code>.</p>
   </ol>
   <h5 class="heading settled" data-level="10.1.6.3" id="spec-stopsource.inplace.mem"><span class="secno">10.1.6.3. </span><span class="content">Members <b>[stopsource.inplace.mem]</b></span><a class="self-link" href="#spec-stopsource.inplace.mem"></a></h5>
<pre class="highlight"><c- p>[[</c-><c- n>nodiscard</c-><c- p>]]</c-> <c- n>in_place_stop_token</c-> <c- n>get_token</c-><c- p>()</c-> <c- k>const</c-> <c- k>noexcept</c-><c- p>;</c->
</pre>
   <ol>
    <li data-md>
     <p><em>Returns</em>: A new associated <code class="highlight"><c- n>in_place_stop_token</c-></code> object.</p>
   </ol>
<pre class="highlight"><c- p>[[</c-><c- n>nodiscard</c-><c- p>]]</c-> <c- b>bool</c-> <c- n>stop_requested</c-><c- p>()</c-> <c- k>const</c-> <c- k>noexcept</c-><c- p>;</c->
</pre>
   <ol start="3">
    <li data-md>
     <p><em>Returns</em>: <code class="highlight">true</code> if the stop state inside <code class="highlight"><c- o>*</c-><c- k>this</c-></code> has received a stop request; otherwise, <code class="highlight">false</code>.</p>
   </ol>
<pre class="highlight"><c- b>bool</c-> <c- nf>request_stop</c-><c- p>()</c-> <c- k>noexcept</c-><c- p>;</c->
</pre>
   <ol start="4">
    <li data-md>
     <p><em>Effects</em>: Atomically determines whether the stop state inside <code class="highlight"><c- o>*</c-><c- k>this</c-></code> has received a stop request, and if not, makes a stop request.
The determination and making of the stop request are an atomic read-modify-write operation ([intro.races]).
If the request was made, the registered invocations are executed and the evaluations of the invocations are indeterminately sequenced.
If an invocation of a callback exits via an exception then <code class="highlight"><c- n>terminate</c-></code> is invoked ([except.terminate]).</p>
    <li data-md>
     <p><em>Postconditions</em>: <code class="highlight"><c- n>stop_requested</c-><c- p>()</c-></code> is <code class="highlight">true</code>.</p>
    <li data-md>
     <p><em>Returns</em>: <code class="highlight">true</code> if this call made a stop request; otherwise <code class="highlight">false</code>.</p>
   </ol>
   <h4 class="heading settled" data-level="10.1.7" id="spec-stopcallback.inplace"><span class="secno">10.1.7. </span><span class="content">Class template <code class="highlight"><c- n>in_place_stop_callback</c-></code> <b>[stopcallback.inplace]</b></span><a class="self-link" href="#spec-stopcallback.inplace"></a></h4>
   <p>Insert a new subclause, Class template <code class="highlight"><c- n>in_place_stop_callback</c-></code> <b>[stopcallback.inplace]</b>, after the subclause added above, as a new subclause of Stop tokens <b>[thread.stoptoken]</b>.</p>
   <h5 class="heading settled" data-level="10.1.7.1" id="spec-stopcallback.inplace.general"><span class="secno">10.1.7.1. </span><span class="content">General <b>[stopcallback.inplace.general]</b></span><a class="self-link" href="#spec-stopcallback.inplace.general"></a></h5>
   <ol>
    <li data-md>
<pre class="highlight"><c- k>namespace</c-> <c- nn>std</c-> <c- p>{</c->
  <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Callback</c-><c- o>></c->
  <c- k>class</c-> <c- nc>in_place_stop_callback</c-> <c- p>{</c->
  <c- k>public</c-><c- o>:</c->
    <c- k>using</c-> <c- n>callback_type</c-> <c- o>=</c-> <c- n>Callback</c-><c- p>;</c->

    <c- c1>// [stopcallback.inplace.cons], constructors and destructor</c->
    <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>C</c-><c- o>></c->
      <c- k>explicit</c-> <c- n>in_place_stop_callback</c-><c- p>(</c-><c- n>in_place_stop_token</c-> <c- n>st</c-><c- p>,</c-> <c- n>C</c-><c- o>&amp;&amp;</c-> <c- n>cb</c-><c- p>)</c->
        <c- k>noexcept</c-><c- p>(</c-><c- n>is_nothrow_constructible_v</c-><c- o>&lt;</c-><c- n>Callback</c-><c- p>,</c-> <c- n>C</c-><c- o>></c-><c- p>);</c->
    <c- o>~</c-><c- n>in_place_stop_callback</c-><c- p>();</c->

    <c- n>in_place_stop_callback</c-><c- p>(</c-><c- n>in_place_stop_callback</c-><c- o>&amp;&amp;</c-><c- p>)</c-> <c- o>=</c-> <c- k>delete</c-><c- p>;</c->

  <c- k>private</c-><c- o>:</c->
    <c- n>Callback</c-> <i><c- n>callback_</c-></i><c- p>;</c->      <i><c- c1>// exposition only</c-></i>
  <c- p>};</c->

  <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Callback</c-><c- o>></c->
    <c- n>in_place_stop_callback</c-><c- p>(</c-><c- n>in_place_stop_token</c-><c- p>,</c-> <c- n>Callback</c-><c- p>)</c->
      <c- o>-></c-> <c- n>in_place_stop_callback</c-><c- o>&lt;</c-><c- n>Callback</c-><c- o>></c-><c- p>;</c->
<c- p>}</c->
</pre>
    <li data-md>
     <p><em>Mandates</em>: <code class="highlight"><c- n>in_place_stop_callback</c-></code> is instantiated with an argument for the template parameter <code class="highlight"><c- n>Callback</c-></code> that satisfies both <code class="highlight"><c- n>invocable</c-></code> and <code class="highlight"><c- n>destructible</c-></code>.</p>
    <li data-md>
     <p><em>Preconditions</em>: <code class="highlight"><c- n>in_place_stop_callback</c-></code> is instantiated with an argument for the template parameter <code class="highlight"><c- n>Callback</c-></code> that models both <code class="highlight"><c- n>invocable</c-></code> and <code class="highlight"><c- n>destructible</c-></code>.</p>
    <li data-md>
     <p><em>Recommended practice</em>: Implementations should use the storage of the <code class="highlight"><c- n>in_place_stop_callback</c-></code> objects to store the state necessary for their association with an <code class="highlight"><c- n>in_place_stop_source</c-></code> object.</p>
   </ol>
   <h5 class="heading settled" data-level="10.1.7.2" id="spec-stopcallback.inplace.cons"><span class="secno">10.1.7.2. </span><span class="content">Constructors and destructor <b>[stopcallback.inplace.cons]</b></span><a class="self-link" href="#spec-stopcallback.inplace.cons"></a></h5>
<pre class="highlight"><c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>C</c-><c- o>></c->
  <c- k>explicit</c-> <c- n>in_place_stop_callback</c-><c- p>(</c-><c- n>in_place_stop_token</c-> <c- n>st</c-><c- p>,</c-> <c- n>C</c-><c- o>&amp;&amp;</c-> <c- n>cb</c-><c- p>)</c->
    <c- k>noexcept</c-><c- p>(</c-><c- n>is_nothrow_constructible_v</c-><c- o>&lt;</c-><c- n>Callback</c-><c- p>,</c-> <c- n>C</c-><c- o>></c-><c- p>);</c->
</pre>
   <ol>
    <li data-md>
     <p><em>Constraints</em>: <code class="highlight"><c- n>Callback</c-></code> and <code class="highlight"><c- n>C</c-></code> satisfy <code class="highlight"><c- n>constructible_from</c-><c- o>&lt;</c-><c- n>Callback</c-><c- p>,</c-> <c- n>C</c-><c- o>></c-></code>.</p>
    <li data-md>
     <p><em>Preconditions</em>: <code class="highlight"><c- n>Callback</c-></code> and <code class="highlight"><c- n>C</c-></code> model <code class="highlight"><c- n>constructible_from</c-><c- o>&lt;</c-><c- n>Callback</c-><c- p>,</c-> <c- n>C</c-><c- o>></c-></code>.</p>
    <li data-md>
     <p><em>Effects</em>: Initializes <code class="highlight"><i><c- n>callback_</c-></i></code> with <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>C</c-><c- o>></c-><c- p>(</c-><c- n>cb</c-><c- p>)</c-></code>.
Any <code class="highlight"><c- n>in_place_stop_source</c-></code> associated with <code class="highlight"><c- n>st</c-></code> becomes associated with <code class="highlight"><c- o>*</c-><c- k>this</c-></code>.
Registers ([stopsource.inplace.general]) the callback invocation <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>Callback</c-><c- o>></c-><c- p>(</c-><i><c- n>callback_</c-></i><c- p>)()</c-></code> with the associated <code class="highlight"><c- n>in_place_stop_source</c-></code>, if any. If the registration fails, evaluates
the callback invocation.</p>
    <li data-md>
     <p><em>Throws</em>: Any exception thrown by the initialization of <code class="highlight"><i><c- n>callback_</c-></i></code>.</p>
    <li data-md>
     <p><em>Remarks</em>: If evaluating <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>Callback</c-><c- o>></c-><c- p>(</c-><i><c- n>callback_</c-></i><c- p>)()</c-></code> exits via an exception, then <code class="highlight"><c- n>terminate</c-></code> is invoked ([except.terminate]).</p>
   </ol>
<pre class="highlight"><c- o>~</c-><c- n>in_place_stop_callback</c-><c- p>();</c->
</pre>
   <ol start="6">
    <li data-md>
     <p><em>Effects</em>: Unregisters ([stopsource.inplace.general]) the callback invocation from
the associated <code class="highlight"><c- n>in_place_stop_source</c-></code> object, if any.</p>
    <li data-md>
     <p><em>Remarks</em>: A program has undefined behavior if the start of this destructor does
not strongly happen before the start of the destructor of the associated <code class="highlight"><c- n>in_place_stop_source</c-></code> object, if any.</p>
   </ol>
   <h2 class="heading settled" data-level="11" id="spec-execution"><span class="secno">11. </span><span class="content">Execution control library <b>[exec]</b></span><a class="self-link" href="#spec-execution"></a></h2>
   <h3 class="heading settled" data-level="11.1" id="spec-execution.general"><span class="secno">11.1. </span><span class="content">General <b>[exec.general]</b></span><a class="self-link" href="#spec-execution.general"></a></h3>
   <ol>
    <li data-md>
     <p>This Clause describes components supporting execution of function objects
[function.objects].</p>
    <li data-md>
     <p>The following subclauses describe the requirements, concepts, and components
for execution control primitives as summarized in Table 1.</p>
   </ol>
   <table>
    <caption>Table <i>N</i>: Execution control library summary <b>[tab:execution.summary]</b></caption>
    <tbody>
     <tr>
      <th>
      <td>Subclause
      <td>Header
     <tr style="border-bottom-style: hidden;">
      <td><a href="#spec-execution.schedulers">[exec.sched]</a>
      <td>Schedulers
      <td><code class="highlight"><c- o>&lt;</c-><c- n>execution</c-><c- o>></c-></code>
     <tr style="border-bottom-style: hidden;">
      <td><a href="#spec-execution.receivers">[exec.recv]</a>
      <td>Receivers
      <td>
     <tr style="border-bottom-style: hidden;">
      <td><a href="#spec-execution.opstate">[exec.opstate]</a>
      <td>Operation states
      <td>
     <tr style="border-bottom-style: hidden;">
      <td><a href="#spec-execution.senders">[exec.snd]</a>
      <td>Senders
      <td>
     <tr>
      <td><a href="#spec-execution.execute">[exec.execute]</a>
      <td>One-way execution
      <td>
   </table>
   <ol start="3">
    <li data-md>
     <p>[<i>Note:</i> A large number of execution control primitives are
customization point objects. For an object one might define multiple types of
customization point objects, for which different rules apply. Table 2 shows
the types of customization point objects used in the execution control
library:</p>
   </ol>
   <table>
    <caption>Table <i>N+1</i>: Types of customization point objects in the execution control library <b>[tab:execution.cpos]</b></caption>
    <tbody>
     <tr>
      <th>Customization point object type
      <th>Purpose
      <th>Examples
     <tr>
      <td>core
      <td>provide core execution functionality, and connection between core components
      <td><code class="highlight"><c- n>connect</c-></code>, <code class="highlight"><c- n>start</c-></code>, <code class="highlight"><c- n>execute</c-></code>
     <tr>
      <td>completion functions
      <td>called by senders to announce the completion of the work (success, error, or cancellation)
      <td><code class="highlight"><c- n>set_value</c-></code>, <code class="highlight"><c- n>set_error</c-></code>, <code class="highlight"><c- n>set_stopped</c-></code>
     <tr>
      <td><a href="#spec-execution.senders">senders</a>
      <td>allow the specialization of the provided sender algorithms
      <td>
       <ul>
        <li>sender factories (<code class="highlight"><c- n>schedule</c-></code>, <code class="highlight"><c- n>just</c-></code>, <code class="highlight"><c- n>read</c-></code>, ...)
        <li>sender adaptors (<code class="highlight"><c- n>transfer</c-></code>, <code class="highlight"><c- n>then</c-></code>, <code class="highlight"><c- n>let_value</c-></code>, ...)
        <li>sender consumers (<code class="highlight"><c- n>start_detached</c-></code>, <code class="highlight"><c- n>sync_wait</c-></code>)
       </ul>
     <tr>
      <td><a href="#spec-execution.queries">queries</a>
      <td>allow querying different properties of objects
      <td>
       <ul>
        <li>general queries (<code class="highlight"><c- n>get_allocator</c-></code>, <code class="highlight"><c- n>get_stop_token</c-></code>, ...)
        <li>environment queries (<code class="highlight"><c- n>get_scheduler</c-></code>, <code class="highlight"><c- n>get_delegatee_scheduler</c-></code>, ...)
        <li>scheduler queries (<code class="highlight"><c- n>get_forward_progress_guarantee</c-></code>, <code class="highlight"><c- n>execute_may_block_caller</c-></code>, ...)
        <li>sender attribute queries (<code class="highlight"><c- n>get_completion_scheduler</c-></code>)
       </ul>
   </table>
   <p>-- <i>end note</i>]</p>
   <ol start="4">
    <li data-md>
     <p>This clause makes use of the following exposition-only entities:</p>
     <ol>
      <li data-md>
<pre class="highlight"><c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Fn</c-><c- p>,</c-> <c- k>class</c-><c- p>...</c-> <c- n>Args</c-><c- o>></c->
    <c- k>requires</c-> <i><c- n>callable</c-></i><c- o>&lt;</c-><c- n>Fn</c-><c- p>,</c-> <c- n>Args</c-><c- p>...</c-><c- o>></c->
  <c- k>constexpr</c-> <c- k>auto</c-> <i><c- n>mandate</c-><c- o>-</c-><c- n>nothrow</c-><c- o>-</c-><c- n>call</c-></i><c- p>(</c-><c- n>Fn</c-><c- o>&amp;&amp;</c-> <c- n>fn</c-><c- p>,</c-> <c- n>Args</c-><c- o>&amp;&amp;</c-><c- p>...</c-> <c- n>args</c-><c- p>)</c-> <c- k>noexcept</c->
    <c- o>-></c-> <i><c- n>call</c-><c- o>-</c-><c- n>result</c-><c- o>-</c-><c- n>t</c-></i><c- o>&lt;</c-><c- n>Fn</c-><c- p>,</c-> <c- n>Args</c-><c- p>...</c-><c- o>></c-> <c- p>{</c->
    <c- k>return</c-> <c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>Fn</c-><c- o>></c-><c- p>(</c-><c- n>fn</c-><c- p>)(</c-><c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>Args</c-><c- o>></c-><c- p>(</c-><c- n>args</c-><c- p>)...);</c->
  <c- p>}</c->
</pre>
       <ul>
        <li data-md>
         <p><i>Mandates:</i> <code class="highlight"><i><c- n>nothrow</c-><c- o>-</c-><c- n>callable</c-></i><c- o>&lt;</c-><c- n>Fn</c-><c- p>,</c-> <c- n>Args</c-><c- p>...</c-><c- o>></c-></code> is <code class="highlight">true</code>.</p>
       </ul>
      <li data-md>
<pre class="highlight"><c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>T</c-><c- o>></c->
  <c- k>concept</c-> <i><c- nc>movable</c-><c- o>-</c-><c- n>value</c-></i> <c- o>=</c->
    <c- n>move_constructible</c-><c- o>&lt;</c-><c- n>decay_t</c-><c- o>&lt;</c-><c- n>T</c-><c- o>>></c-> <c- o>&amp;&amp;</c->
    <c- n>constructible_from</c-><c- o>&lt;</c-><c- n>decay_t</c-><c- o>&lt;</c-><c- n>T</c-><c- o>></c-><c- p>,</c-> <c- n>T</c-><c- o>></c-> <c- o>&amp;&amp;</c->
    <c- p>(</c-><c- o>!</c-><c- n>is_array_v</c-><c- o>&lt;</c-><c- n>remove_cvref_t</c-><c- o>&lt;</c-><c- n>T</c-><c- o>>></c-><c- p>);</c->
</pre>
      <li data-md>
       <p>For function types <code class="highlight"><c- n>F1</c-></code> and <code class="highlight"><c- n>F2</c-></code> denoting <code class="highlight"><c- n>R1</c-><c- p>(</c-><c- n>Args1</c-><c- p>...)</c-></code> and <code class="highlight"><c- n>R2</c-><c- p>(</c-><c- n>Args2</c-><c- p>...)</c-></code> respectively, <code class="highlight"><i><c- n>MATCHING</c-><c- o>-</c-><c- n>SIG</c-></i><c- p>(</c-><c- n>F1</c-><c- p>,</c-> <c- n>F2</c-><c- p>)</c-></code> is <code class="highlight">true</code> if and only if <code class="highlight"><c- n>same_as</c-><c- o>&lt;</c-><c- n>R1</c-><c- p>(</c-><c- n>Args</c-><c- o>&amp;&amp;</c-><c- p>...),</c-> <c- n>R2</c-><c- p>(</c-><c- n>Args2</c-><c- o>&amp;&amp;</c-><c- p>...)</c-><c- o>></c-></code> is <code class="highlight">true</code>.</p>
     </ol>
   </ol>
   <h3 class="heading settled" data-level="11.2" id="spec-execution.queryable"><span class="secno">11.2. </span><span class="content">Queries and queryables <b>[exec.queryable]</b></span><a class="self-link" href="#spec-execution.queryable"></a></h3>
   <h4 class="heading settled" data-level="11.2.1" id="spec-execution.queryable.general"><span class="secno">11.2.1. </span><span class="content">General <b>[exec.queryable.general]</b></span><a class="self-link" href="#spec-execution.queryable.general"></a></h4>
   <ol>
    <li data-md>
     <p>A <dfn data-dfn-type="dfn" data-export id="queryable-object">queryable object<a class="self-link" href="#queryable-object"></a></dfn> is a read-only collection of
key/value pairs where each key is a customization point object known as a <dfn data-dfn-type="dfn" data-export id="query-object">query object<a class="self-link" href="#query-object"></a></dfn>. A <dfn data-dfn-type="dfn" data-export id="query">query<a class="self-link" href="#query"></a></dfn> is an invocation of a query object with a queryable
object as its first argument and a (possibly empty) set of additional
arguments. The result of a query expression is valid as long as the
queryable object is valid. <span class="wg21note">A query imposes syntactic
and semantic requirements on its invocations.</span></p>
    <li data-md>
     <p>Given a subexpression <code class="highlight"><c- n>env</c-></code> that refers to a queryable object <code class="highlight"><c- n>o</c-></code>, a query
object <code class="highlight"><i><c- n>q</c-></i></code>, and a (possibly empty) pack of subexpressions <code class="highlight"><c- n>args</c-></code>, the expression <code class="highlight"><i><c- n>q</c-></i><c- p>(</c-><c- n>env</c-><c- p>,</c-> <c- n>args</c-><c- p>...)</c-></code> is equal to
([concepts.equality]) the expression <code class="highlight"><i><c- n>q</c-></i><c- p>(</c-><c- n>c</c-><c- p>,</c-> <c- n>args</c-><c- p>...)</c-></code> where <code class="highlight"><c- n>c</c-></code> is a <code class="highlight"><c- k>const</c-></code> lvalue reference to <code class="highlight"><c- n>o</c-></code>.</p>
    <li data-md>
     <p>The type of a query expression can not be <code class="highlight"><c- b>void</c-></code>.</p>
    <li data-md>
     <p>The expression <code class="highlight"><i><c- n>q</c-></i><c- p>(</c-><c- n>env</c-><c- p>,</c-> <c- n>args</c-><c- p>...)</c-></code> is equality-preserving
([concepts.equality]) and does not modify the function object or the
arguments.</p>
    <li data-md>
     <p>If <code class="highlight"><c- n>tag_invoke</c-><c- p>(</c-><i><c- n>q</c-></i><c- p>,</c-> <c- n>env</c-><c- p>,</c-> <c- n>args</c-><c- p>...)</c-></code> is well-formed, then <code class="highlight"><i><c- n>q</c-></i><c- p>(</c-><c- n>env</c-><c- p>,</c-> <c- n>args</c-><c- p>...)</c-></code> is expression-equivalent to <code class="highlight"><c- n>tag_invoke</c-><c- p>(</c-><i><c- n>q</c-></i><c- p>,</c-> <c- n>env</c-><c- p>,</c-> <c- n>args</c-><c- p>...)</c-></code>.</p>
    <li data-md>
     <p>Unless otherwise specified, the value returned by the expression <code class="highlight"><i><c- n>q</c-></i><c- p>(</c-><c- n>env</c-><c- p>,</c-> <c- n>args</c-><c- p>...)</c-></code> is valid as long as <code class="highlight"><c- n>env</c-></code> is valid.</p>
   </ol>
   <h4 class="heading settled" data-level="11.2.2" id="spec-execution.queryable.concept"><span class="secno">11.2.2. </span><span class="content"><code class="highlight"><c- n>queryable</c-></code> concept <b>[exec.queryable.concept]</b></span><a class="self-link" href="#spec-execution.queryable.concept"></a></h4>
<pre class="highlight"><c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>T</c-><c- o>></c->
  <c- k>concept</c-> <c- nc>queryable</c-> <c- o>=</c-> <c- n>destructible</c-><c- o>&lt;</c-><c- n>T</c-><c- o>></c-><c- p>;</c->
</pre>
   <ol>
    <li data-md>
     <p>The <code class="highlight"><c- n>queryable</c-></code> concept specifies the constraints on the types of queryable
objects.</p>
    <li data-md>
     <p>Let <code class="highlight"><c- n>env</c-></code> be an object of type <code class="highlight"><c- n>Env</c-></code>. The type <code class="highlight"><c- n>Env</c-></code> models <code class="highlight"><c- n>queryable</c-></code> if for each
callable object <code class="highlight"><i><c- n>q</c-></i></code> and a pack of subexpressions <code class="highlight"><c- n>args</c-></code>,
if <code class="highlight"><c- k>requires</c-> <c- p>{</c-> <i><c- n>q</c-></i><c- p>(</c-><c- n>env</c-><c- p>,</c-> <c- n>args</c-><c- p>...)</c-> <c- p>}</c-></code> is <code class="highlight">true</code> then <code class="highlight"><i><c- n>q</c-></i><c- p>(</c-><c- n>env</c-><c- p>,</c-> <c- n>args</c-><c- p>...)</c-></code> meets any semantic requirements imposed by <code class="highlight"><i><c- n>q</c-></i></code>.</p>
   </ol>
   <h3 class="heading settled" data-level="11.3" id="spec-execution-async.ops"><span class="secno">11.3. </span><span class="content">Asynchronous operations <b>[async.ops]</b></span><a class="self-link" href="#spec-execution-async.ops"></a></h3>
   <ol>
    <li data-md>
     <p>An <dfn class="dfn-paneled" data-dfn-type="dfn" data-export id="execution-resource">execution resource</dfn> is a program entity that manages
a (possibly dynamic) set of execution agents
([thread.req.lockable.general]), which it uses to execute parallel work on
behalf of callers. [<em>Example 1</em>: The currently active thread, a
system-provided thread pool, and uses of an API associated with an external
hardware accelerator are all examples of execution resources. -- <em>end
example</em>] Execution resources execute asynchronous operations. An execution
resource is either valid or invalid.</p>
    <li data-md>
     <p>An <dfn data-dfn-type="dfn" data-export id="asynchronous-operation">asynchronous operation<a class="self-link" href="#asynchronous-operation"></a></dfn> is a distinct unit of
program execution that:</p>
     <ul>
      <li data-md>
       <p>is explicitly created;</p>
      <li data-md>
       <p>can be explicitly <dfn class="dfn-paneled" data-dfn-type="dfn" data-export data-lt="start" id="start">started</dfn>; an
  asynchronous operation can be started once at most;</p>
      <li data-md>
       <p>if started, eventually <dfn data-dfn-type="dfn" data-export data-lt="complete" id="complete">completes<a class="self-link" href="#complete"></a></dfn> with a (possibly empty) set of result datums, and in exactly one of
  three modes: success, failure, or cancellation, known as the
  operation’s <dfn data-dfn-type="dfn" data-export id="disposition">disposition<a class="self-link" href="#disposition"></a></dfn>; an asychronous
  operation can only complete once; a successful completion, also known
  as a <dfn data-dfn-type="dfn" data-export id="value-completion">value completion<a class="self-link" href="#value-completion"></a></dfn>, can have an arbitrary
  number of result datums; a failure completion, also known as an <dfn data-dfn-type="dfn" data-export id="error-completion">error completion<a class="self-link" href="#error-completion"></a></dfn>, has a single result datum; a
  cancellation completion, also known as a <dfn data-dfn-type="dfn" data-export data-lt="stopped completion" id="stopped-completion">stopped
  completion<a class="self-link" href="#stopped-completion"></a></dfn>, has no result datum; an asynchronous operation’s <dfn data-dfn-type="dfn" data-export id="async-result">async result<a class="self-link" href="#async-result"></a></dfn> is its disposition and its
  (possibly empty) set of result datums.</p>
      <li data-md>
       <p>can complete on a different execution resource than that on which it
  started; and</p>
      <li data-md>
       <p>can create and start other asychronous operations called <dfn data-dfn-type="dfn" data-export id="child-operations">child operations<a class="self-link" href="#child-operations"></a></dfn>. A child operation is an
  asynchronous operation that is created by the parent operation and, if
  started, completes before the parent operation completes. A <dfn data-dfn-type="dfn" data-export id="parent-operation">parent operation<a class="self-link" href="#parent-operation"></a></dfn> is the asynchronous operation that
  created a particular child operation.</p>
     </ul>
     <p><span class="wg21note">An asynchronous operation can in fact execute
synchronously; that is, it can complete during the execution of its start
operation on the thread of execution that started it.</span></p>
    <li data-md>
     <p>An asynchronous operation has associated state known as its <dfn class="dfn-paneled" data-dfn-type="dfn" data-export id="operation-state">operation state</dfn>.</p>
    <li data-md>
     <p>An asynchronous operation has an associated environment. An <dfn data-dfn-type="dfn" data-export id="environment">environment<a class="self-link" href="#environment"></a></dfn> is a queryable object ([exec.queryable])
representing the execution-time properties of the operation’s caller. The <dfn data-dfn-type="dfn" data-export data-lt="caller" id="caller">caller of an asynchronous operation<a class="self-link" href="#caller"></a></dfn> is
its parent operation or the function that created it. An asynchronous
operation’s operation state owns the operation’s environment.</p>
    <li data-md>
     <p>An asynchronous operation has an associated receiver. A <dfn class="dfn-paneled" data-dfn-type="dfn" data-export id="receiver">receiver</dfn> is an aggregation of three handlers for the three
asynchronous completion dispositions: a value completion handler for a value
completion, an error completion handler for an error completion, and a
stopped completion handler for a stopped completion. A receiver has an
associated environment. An asynchronous operation’s operation state owns the
operation’s receiver. The environment of an asynchronous operation is equal
to its receiver’s environment.</p>
    <li data-md>
     <p>For each completion disposition, there is a <dfn data-dfn-type="dfn" data-export data-lt="completion function" id="completion-function">completion
function<a class="self-link" href="#completion-function"></a></dfn>. A completion function is a customization point object
([customization.point.object]) that accepts an asynchronous operation’s
receiver as the first argument and the result datums of the asynchronous
operation as additional arguments. The value completion function invokes the
receiver’s value completion handler with the value result datums; likewise
for the error completion function and the stopped completion function. A
completion function has an associated type known as its <dfn data-dfn-type="dfn" data-export id="completion-tag">completion tag<a class="self-link" href="#completion-tag"></a></dfn> that names the unqualified type of the
completion function. A valid invocation of a completion function is called a <dfn data-dfn-type="dfn" data-export id="completion-operation">completion operation<a class="self-link" href="#completion-operation"></a></dfn>.</p>
    <li data-md>
     <p>The <dfn data-dfn-type="dfn" data-export data-lt="asychronous operation lifetime" id="asychronous-operation-lifetime">lifetime of an
asynchronous operation<a class="self-link" href="#asychronous-operation-lifetime"></a></dfn>, also known as the operation’s <dfn data-dfn-type="dfn" data-export id="async-lifetime">async lifetime<a class="self-link" href="#async-lifetime"></a></dfn>, begins when its start operation begins
executing and ends when its completion operation begins executing. If the
lifetime of an asynchronous operation’s associated operation state ends
before the lifetime of the asynchronous operation, the behavior is
undefined. After an asynchronous operation executes a completion operation,
its associated operation state is invalid. Accessing any part of an invalid
operation state is undefined behavior.</p>
    <li data-md>
     <p>An asynchronous operation shall not execute a completion operation before its
start operation has begun executing. After its start operation has begun
executing, exactly one completion operation shall execute. The lifetime of an
asynchronous operation’s operation state can end during the execution of the
completion operation.</p>
    <li data-md>
     <p>A <dfn class="dfn-paneled" data-dfn-type="dfn" data-export id="sender">sender</dfn> is a factory for one or more asynchronous
operations. <dfn class="dfn-paneled" data-dfn-type="dfn" data-export data-lt="connect" id="connect">Connecting</dfn> a sender and a
receiver creates an asynchronous operation. The asynchronous operation’s
associated receiver is equal to the receiver used to create it, and its
associated environment is equal to the environment associated with the
receiver used to create it. The lifetime of an asynchronous operation’s
associated operation state does not depend on the lifetimes of either the
sender or the receiver from which it was created. A sender <dfn class="dfn-paneled" data-dfn-type="dfn" data-export data-lt="send" id="send">sends</dfn> its results by way of the asynchronous operation(s)
it produces, and a receiver <dfn data-dfn-type="dfn" data-export data-lt="receive" id="receive">receives<a class="self-link" href="#receive"></a></dfn> those results. A sender is either valid or invalid; it becomes invalid
when its parent sender (see below) becomes invalid.</p>
    <li data-md>
     <p>A <dfn class="dfn-paneled" data-dfn-type="dfn" data-export id="scheduler">scheduler</dfn> is an abstraction of an execution
resource with a uniform, generic interface for scheduling work onto that
resource. It is a factory for senders whose asynchronous operations execute
value completion operations on an execution agent belonging to the
scheduler’s associated execution resource. A <dfn data-dfn-type="dfn" data-export id="schedule-expression">schedule-expression<a class="self-link" href="#schedule-expression"></a></dfn> obtains such a sender from a
scheduler. A <dfn data-dfn-type="dfn" data-export id="schedule-sender">schedule sender<a class="self-link" href="#schedule-sender"></a></dfn> is the result of a
schedule expression. On success, an asynchronous operation produced by a
schedule sender executes a value completion operation with an empty set of
result datums. Multiple schedulers can refer to the same execution resource.
A scheduler can be valid or invalid. A scheduler becomes invalid when the
execution resource to which it refers becomes invalid, as do any schedule
senders obtained from the scheduler, and any operation states obtained from
those senders.</p>
    <li data-md>
     <p>An asynchronous operation has one or more associated completion schedulers
for each of its possible dispositions. A <dfn class="dfn-paneled" data-dfn-type="dfn" data-export data-lt="completion scheduler" id="completion-scheduler">completion
scheduler</dfn> is a scheduler whose associated execution resource is used
to execute a completion operation for an asynchronous operation. A value
completion scheduler is a scheduler on which an asynchronous operation’s
value completion operation can execute. Likewise for error completion
schedulers and stopped completion schedulers.</p>
    <li data-md>
     <p>A sender has an associated queryable object ([exec.queryable]) known as its <dfn data-dfn-type="dfn" data-export id="attributes">attributes<a class="self-link" href="#attributes"></a></dfn> that describes various characteristics of
the sender and of the asynchronous operation(s) it produces. For each
disposition, there is a query object for reading the associated completion
scheduler from a sender’s attributes; <em>i.e.</em>, a value completion scheduler
query object for reading a sender’s value completion scheduler, <em>etc</em>. If a
completion scheduler query is well-formed, the returned completion scheduler
is unique for that disposition for any asynchronous operation the sender
creates. A schedule sender is required to have a value completion scheduler
attribute whose value is equal to the scheduler that produced the schedule
sender.</p>
    <li data-md>
     <p>A <dfn data-dfn-type="dfn" data-export id="completion-signature">completion signature<a class="self-link" href="#completion-signature"></a></dfn> is a function type that
describes a completion operation. An asychronous operation has a finite set
of possible completion signatures corresponding to the completion operations
that the asynchronous operation potentially evaluates ([basic.def.odr]). For
a completion function <code class="highlight"><i><c- n>set</c-></i></code>, receiver <code class="highlight"><i><c- n>rcvr</c-></i></code>, and pack of arguments <code class="highlight"><i><c- n>args</c-></i></code>,
let <code class="highlight"><c- n>c</c-></code> be the completion operation <code class="highlight"><i><c- n>set</c-></i><c- p>(</c-><i><c- n>rcvr</c-></i><c- p>,</c-> <i><c- n>args</c-></i><c- p>...)</c-></code>, and let <code class="highlight"><c- n>F</c-></code> be the function type <code class="highlight"><c- k>decltype</c-><c- p>(</c-><c- k>auto</c-><c- p>(</c-><i><c- n>set</c-></i><c- p>))(</c-><c- k>decltype</c-><c- p>((</c-><i><c- n>args</c-></i><c- p>))...)</c-></code>.
A completion signature <code class="highlight"><c- n>Sig</c-></code> is associated with <code class="highlight"><c- n>c</c-></code> if and only if <code class="highlight"><i><c- n>MATCHING</c-><c- o>-</c-><c- n>SIG</c-></i><c- p>(</c-><c- n>Sig</c-><c- p>,</c-> <c- n>F</c-><c- p>)</c-></code> is <code class="highlight">true</code> ([exec.general]). Together,
a sender type and an environment type <code class="highlight"><c- n>Env</c-></code> determine the set of completion
signatures of an asynchronous operation that results from connecting the
sender with a receiver that has an environment of type <code class="highlight"><c- n>Env</c-></code>. <span class="wg21note">The type of the receiver does not affect an asychronous
operation’s completion signatures, only the type of the receiver’s
environment.</span></p>
    <li data-md>
     <p>A <dfn class="dfn-paneled" data-dfn-type="dfn" data-export id="sender-algorithm">sender algorithm</dfn> is a function that takes and/or
returns a sender. There are three categories of sender algorithms:</p>
     <ul>
      <li data-md>
       <p>A <dfn class="dfn-paneled" data-dfn-type="dfn" data-export id="sender-factory">sender factory</dfn> is a function that takes
non-senders as arguments and that returns a sender.</p>
      <li data-md>
       <p>A <dfn class="dfn-paneled" data-dfn-type="dfn" data-export id="sender-adaptor">sender adaptor</dfn> is a function that constructs and
returns a parent sender from a set of one or more child senders and a
(possibly empty) set of additional arguments. An asynchronous operation
created by a <dfn data-dfn-type="dfn" data-export id="parent-sender">parent sender<a class="self-link" href="#parent-sender"></a></dfn> is a parent to the
child operations created by the <dfn data-dfn-type="dfn" data-export data-lt="child sender" id="child-sender">child
senders<a class="self-link" href="#child-sender"></a></dfn>.</p>
      <li data-md>
       <p>A <dfn class="dfn-paneled" data-dfn-type="dfn" data-export id="sender-consumer">sender consumer</dfn> is a function that takes one or
more senders and a (possibly empty) set of additional arguments, and
whose return type is not the type of a sender.</p>
     </ul>
   </ol>
   <h3 class="heading settled" data-level="11.4" id="spec-execution.syn"><span class="secno">11.4. </span><span class="content">Header <code class="highlight"><c- o>&lt;</c-><c- n>execution</c-><c- o>></c-></code> synopsis <b>[exec.syn]</b></span><a class="self-link" href="#spec-execution.syn"></a></h3>
<pre class="highlight"><c- k>namespace</c-> <c- nn>std</c-> <c- p>{</c->
  <c- c1>// [exec.general], helper concepts</c->
  <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>T</c-><c- o>></c->
    <c- k>concept</c-> <i><c- nc>movable</c-><c- o>-</c-><c- n>value</c-></i> <c- o>=</c-> <i><c- n>see</c-> <c- n>below</c-></i><c- p>;</c-> <i><c- c1>// exposition only</c-></i>

  <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>From</c-><c- p>,</c-> <c- k>class</c-> <c- nc>To</c-><c- o>></c->
    <c- k>concept</c-> <i><c- nc>decays</c-><c- o>-</c-><c- n>to</c-></i> <c- o>=</c-> <c- n>same_as</c-><c- o>&lt;</c-><c- n>decay_t</c-><c- o>&lt;</c-><c- n>From</c-><c- o>></c-><c- p>,</c-> <c- n>To</c-><c- o>></c-><c- p>;</c-> <i><c- c1>// exposition only</c-></i>

  <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>T</c-><c- o>></c->
    <c- k>concept</c-> <i><c- nc>class</c-><c- o>-</c-><c- n>type</c-></i> <c- o>=</c-> <i><c- n>decays</c-><c- o>-</c-><c- n>to</c-></i><c- o>&lt;</c-><c- n>T</c-><c- p>,</c-> <c- n>T</c-><c- o>></c-> <c- o>&amp;&amp;</c-> <c- n>is_class_v</c-><c- o>&lt;</c-><c- n>T</c-><c- o>></c-><c- p>;</c->  <i><c- c1>// exposition only</c-></i>

  <c- c1>// [exec.queryable], queryable objects</c->
  <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>T</c-><c- o>></c->
    <c- k>concept</c-> <c- nc>queryable</c-> <c- o>=</c-> <c- n>destructible</c-><t><c- p>;</c->

  <c- c1>// [exec.queries], queries</c->
  <c- k>namespace</c-> <i><c- nn>queries</c-></i> <c- p>{</c-> <i><c- c1>// exposition only</c-></i>
    <c- k>struct</c-> <c- nc>forwarding_query_t</c-><c- p>;</c->
    <c- k>struct</c-> <c- nc>get_allocator_t</c-><c- p>;</c->
    <c- k>struct</c-> <c- nc>get_stop_token_t</c-><c- p>;</c->
  <c- p>}</c->
  <c- k>using</c-> <i><c- n>queries</c-></i><c- o>::</c-><c- n>forwarding_query_t</c-><c- p>;</c->
  <c- k>using</c-> <i><c- n>queries</c-></i><c- o>::</c-><c- n>get_allocator_t</c-><c- p>;</c->
  <c- k>using</c-> <i><c- n>queries</c-></i><c- o>::</c-><c- n>get_stop_token_t</c-><c- p>;</c->
  <c- kr>inline</c-> <c- k>constexpr</c-> <c- n>forwarding_query_t</c-> <c- n>forwarding_query</c-><c- p>{};</c->
  <c- kr>inline</c-> <c- k>constexpr</c-> <c- n>get_allocator_t</c-> <c- n>get_allocator</c-><c- p>{};</c->
  <c- kr>inline</c-> <c- k>constexpr</c-> <c- n>get_stop_token_t</c-> <c- n>get_stop_token</c-><c- p>{};</c->

  <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>T</c-><c- o>></c->
    <c- k>using</c-> <c- n>stop_token_of_t</c-> <c- o>=</c->
      <c- n>remove_cvref_t</c-><c- o>&lt;</c-><c- k>decltype</c-><c- p>(</c-><c- n>get_stop_token</c-><c- p>(</c-><c- n>declval</c-><c- o>&lt;</c-><c- n>T</c-><c- o>></c-><c- p>()))</c-><c- o>></c-><c- p>;</c->

  <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>T</c-><c- o>></c->
    <c- k>concept</c-> <i><c- nc>forwarding</c-><c- o>-</c-><c- n>query</c-></i> <c- o>=</c-> <c- c1>// exposition only</c->
      <c- n>forwarding_query</c-><c- p>(</c-><c- n>T</c-><c- p>{});</c->
<c- p>}</c->

<c- k>namespace</c-> <c- nn>std</c-><c- o>::</c-><c- nn>execution</c-> <c- p>{</c->
  <c- c1>// [exec.queries], queries</c->
  <c- k>enum</c-> <c- k>class</c-> <c- nc>forward_progress_guarantee</c-><c- p>;</c->
  <c- k>namespace</c-> <i><c- nn>queries</c-></i> <c- p>{</c-> <c- c1>// exposition only</c->
    <c- k>struct</c-> <c- nc>get_domain_t</c-><c- p>;</c->
    <c- k>struct</c-> <c- nc>get_scheduler_t</c-><c- p>;</c->
    <c- k>struct</c-> <c- nc>get_delegatee_scheduler_t</c-><c- p>;</c->
    <c- k>struct</c-> <c- nc>get_forward_progress_guarantee_t</c-><c- p>;</c->
    <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>CPO</c-><c- o>></c->
      <c- k>struct</c-> <c- nc>get_completion_scheduler_t</c-><c- p>;</c->
  <c- p>}</c->
  <c- k>using</c-> <i><c- n>queries</c-></i><c- o>::</c-><c- n>get_domain_t</c-><c- p>;</c->
  <c- k>using</c-> <i><c- n>queries</c-></i><c- o>::</c-><c- n>get_scheduler_t</c-><c- p>;</c->
  <c- k>using</c-> <i><c- n>queries</c-></i><c- o>::</c-><c- n>get_delegatee_scheduler_t</c-><c- p>;</c->
  <c- k>using</c-> <i><c- n>queries</c-></i><c- o>::</c-><c- n>get_forward_progress_guarantee_t</c-><c- p>;</c->
  <c- k>using</c-> <i><c- n>queries</c-></i><c- o>::</c-><c- n>get_completion_scheduler_t</c-><c- p>;</c->
  <c- kr>inline</c-> <c- k>constexpr</c-> <c- n>get_domain_t</c-> <c- n>get_domain</c-><c- p>{};</c->
  <c- kr>inline</c-> <c- k>constexpr</c-> <c- n>get_scheduler_t</c-> <c- n>get_scheduler</c-><c- p>{};</c->
  <c- kr>inline</c-> <c- k>constexpr</c-> <c- n>get_delegatee_scheduler_t</c-> <c- n>get_delegatee_scheduler</c-><c- p>{};</c->
  <c- kr>inline</c-> <c- k>constexpr</c-> <c- n>get_forward_progress_guarantee_t</c-> <c- n>get_forward_progress_guarantee</c-><c- p>{};</c->
  <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>CPO</c-><c- o>></c->
    <c- kr>inline</c-> <c- k>constexpr</c-> <c- n>get_completion_scheduler_t</c-><c- o>&lt;</c-><c- n>CPO</c-><c- o>></c-> <c- n>get_completion_scheduler</c-><c- p>{};</c->

  <c- k>namespace</c-> <i><c- nn>exec</c-><c- o>-</c-><c- nn>envs</c-></i> <c- p>{</c-> <c- c1>// exposition only</c->
    <c- k>struct</c-> <c- nc>empty_env</c-> <c- p>{};</c->
    <c- k>struct</c-> <c- nc>get_env_t</c-><c- p>;</c->
  <c- p>}</c->
  <c- k>using</c-> <i><c- n>envs</c-><c- o>-</c-><c- n>envs</c-></i><c- o>::</c-><c- n>empty_env</c-><c- p>;</c->
  <c- k>using</c-> <i><c- n>envs</c-><c- o>-</c-><c- n>envs</c-></i><c- o>::</c-><c- n>get_env_t</c-><c- p>;</c->
  <c- kr>inline</c-> <c- k>constexpr</c-> <c- n>get_env_t</c-> <c- n>get_env</c-> <c- p>{};</c->

  <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>T</c-><c- o>></c->
    <c- k>using</c-> <c- n>env_of_t</c-> <c- o>=</c-> <c- k>decltype</c-><c- p>(</c-><c- n>get_env</c-><c- p>(</c-><c- n>declval</c-><c- o>&lt;</c-><c- n>T</c-><c- o>></c-><c- p>()));</c->

  <c- c1>// [exec.domain.default], execution domains</c->
  <c- k>struct</c-> <c- nc>default_domain</c-><c- p>;</c->

  <c- c1>// [exec.sched], schedulers</c->
  <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Sch</c-><c- o>></c->
    <c- k>concept</c-> <c- nc>scheduler</c-> <c- o>=</c-> <i><c- n>see</c-> <c- n>below</c-></i><c- p>;</c->

  <c- c1>// [exec.recv], receivers</c->
  <c- k>struct</c-> <c- nc>receiver_t</c-> <c- p>{};</c->

  <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Rcvr</c-><c- o>></c->
    <c- kr>inline</c-> <c- k>constexpr</c-> <c- b>bool</c-> <c- n>enable_receiver</c-> <c- o>=</c-> <i><c- n>see</c-> <c- n>below</c-></i><c- p>;</c->

  <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Rcvr</c-><c- o>></c->
    <c- k>concept</c-> <c- nc>receiver</c-> <c- o>=</c-> <i><c- n>see</c-> <c- n>below</c-></i><c- p>;</c->

  <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Rcvr</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Completions</c-><c- o>></c->
    <c- k>concept</c-> <c- nc>receiver_of</c-> <c- o>=</c-> <i><c- n>see</c-> <c- n>below</c-></i><c- p>;</c->

  <c- k>namespace</c-> <i><c- nn>receivers</c-></i> <c- p>{</c-> <c- c1>// exposition only</c->
    <c- k>struct</c-> <c- nc>set_value_t</c-><c- p>;</c->
    <c- k>struct</c-> <c- nc>set_error_t</c-><c- p>;</c->
    <c- k>struct</c-> <c- nc>set_stopped_t</c-><c- p>;</c->
  <c- p>}</c->
  <c- k>using</c-> <i><c- n>receivers</c-></i><c- o>::</c-><c- n>set_value_t</c-><c- p>;</c->
  <c- k>using</c-> <i><c- n>receivers</c-></i><c- o>::</c-><c- n>set_error_t</c-><c- p>;</c->
  <c- k>using</c-> <i><c- n>receivers</c-></i><c- o>::</c-><c- n>set_stopped_t</c-><c- p>;</c->
  <c- kr>inline</c-> <c- k>constexpr</c-> <c- n>set_value_t</c-> <c- n>set_value</c-><c- p>{};</c->
  <c- kr>inline</c-> <c- k>constexpr</c-> <c- n>set_error_t</c-> <c- n>set_error</c-><c- p>{};</c->
  <c- kr>inline</c-> <c- k>constexpr</c-> <c- n>set_stopped_t</c-> <c- n>set_stopped</c-><c- p>{};</c->

  <c- c1>// [exec.opstate], operation states</c->
  <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>O</c-><c- o>></c->
    <c- k>concept</c-> <c- nc>operation_state</c-> <c- o>=</c-> <i><c- n>see</c-> <c- n>below</c-></i><c- p>;</c->

  <c- k>namespace</c-> <i><c- nn>op</c-><c- o>-</c-><c- nn>state</c-></i> <c- p>{</c-> <c- c1>// exposition only</c->
    <c- k>struct</c-> <c- nc>start_t</c-><c- p>;</c->
  <c- p>}</c->
  <c- k>using</c-> <i><c- n>op</c-><c- o>-</c-><c- n>state</c-></i><c- o>::</c-><c- n>start_t</c-><c- p>;</c->
  <c- kr>inline</c-> <c- k>constexpr</c-> <c- n>start_t</c-> <c- n>start</c-><c- p>{};</c->

  <c- c1>// [exec.snd], senders</c->
  <c- k>struct</c-> <c- nc>sender_t</c-> <c- p>{};</c->

  <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Sndr</c-><c- o>></c->
    <c- kr>inline</c-> <c- k>constexpr</c-> <c- b>bool</c-> <c- n>enable_sender</c-> <c- o>=</c-> <i><c- n>see</c-> <c- n>below</c-></i><c- p>;</c->

  <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Sndr</c-><c- o>></c->
    <c- k>concept</c-> <c- nc>sender</c-> <c- o>=</c-> <i><c- n>see</c-> <c- n>below</c-></i><c- p>;</c->

  <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Sndr</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Env</c-> <c- o>=</c-> <c- n>empty_env</c-><c- o>></c->
    <c- k>concept</c-> <c- nc>sender_in</c-> <c- o>=</c-> <i><c- n>see</c-> <c- n>below</c-></i><c- p>;</c->

  <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Sndr</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Rcvr</c-><c- o>></c->
    <c- k>concept</c-> <c- nc>sender_to</c-> <c- o>=</c-> <i><c- n>see</c-> <c- n>below</c-></i><c- p>;</c->

  <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-><c- p>...</c-> <c- n>Ts</c-><c- o>></c->
    <c- k>struct</c-> <i><c- nc>type</c-><c- o>-</c-><c- n>list</c-></i><c- p>;</c-> <c- c1>// exposition only</c->

  <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Sndr</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Env</c-> <c- o>=</c-> <c- n>empty_env</c-><c- o>></c->
    <c- k>using</c-> <i><c- n>single</c-><c- o>-</c-><c- n>sender</c-><c- o>-</c-><c- n>value</c-><c- o>-</c-><c- n>type</c-></i> <c- o>=</c-> <i><c- n>see</c-> <c- n>below</c-></i><c- p>;</c-> <c- c1>// exposition only</c->

  <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Sndr</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Env</c-> <c- o>=</c-> <c- n>empty_env</c-><c- o>></c->
    <c- k>concept</c-> <i><c- nc>single</c-><c- o>-</c-><c- n>sender</c-></i> <c- o>=</c-> <i><c- n>see</c-> <c- n>below</c-></i><c- p>;</c-> <c- c1>// exposition only</c->

  <c- c1>// [exec.getcomplsigs], completion signatures</c->
  <c- k>namespace</c-> <i><c- nn>completion</c-><c- o>-</c-><c- nn>signatures</c-></i> <c- p>{</c-> <c- c1>// exposition only</c->
    <c- k>struct</c-> <c- nc>get_completion_signatures_t</c-><c- p>;</c->
  <c- p>}</c->
  <c- k>using</c-> <i><c- n>completion</c-><c- o>-</c-><c- n>signatures</c-></i><c- o>::</c-><c- n>get_completion_signatures_t</c-><c- p>;</c->
  <c- kr>inline</c-> <c- k>constexpr</c-> <c- n>get_completion_signatures_t</c-> <c- n>get_completion_signatures</c-> <c- p>{};</c->

  <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Sndr</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Env</c-> <c- o>=</c-> <c- n>empty_env</c-><c- o>></c->
      <c- k>requires</c-> <c- n>sender_in</c-><c- o>&lt;</c-><c- n>Sndr</c-><c- p>,</c-> <c- n>Env</c-><c- o>></c->
    <c- k>using</c-> <c- n>completion_signatures_of_t</c-> <c- o>=</c-> <i><c- n>call</c-><c- o>-</c-><c- n>result</c-><c- o>-</c-><c- n>t</c-></i><c- o>&lt;</c-><c- n>get_completion_signatures_t</c-><c- p>,</c-> <c- n>Sndr</c-><c- p>,</c-> <c- n>Env</c-><c- o>></c-><c- p>;</c->

  <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-><c- p>...</c-> <c- n>Ts</c-><c- o>></c->
    <c- k>using</c-> <i><c- n>decayed</c-><c- o>-</c-><c- n>tuple</c-></i> <c- o>=</c-> <c- n>tuple</c-><c- o>&lt;</c-><c- n>decay_t</c-><c- o>&lt;</c-><c- n>Ts</c-><c- o>></c-><c- p>...</c-><c- o>></c-><c- p>;</c-> <c- c1>// exposition only</c->

  <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-><c- p>...</c-> <c- n>Ts</c-><c- o>></c->
    <c- k>using</c-> <i><c- n>variant</c-><c- o>-</c-><c- n>or</c-><c- o>-</c-><c- n>empty</c-></i> <c- o>=</c-> <i><c- n>see</c-> <c- n>below</c-></i><c- p>;</c-> <c- c1>// exposition only</c->

  <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Sndr</c-><c- p>,</c->
           <c- k>class</c-> <c- nc>Env</c-> <c- o>=</c-> <c- n>empty_env</c-><c- p>,</c->
           <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-><c- p>...</c-><c- o>></c-> <c- k>class</c-> <c- nc>Tuple</c-> <c- o>=</c-> <i><c- n>decayed</c-><c- o>-</c-><c- n>tuple</c-></i><c- p>,</c->
           <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-><c- p>...</c-><c- o>></c-> <c- k>class</c-> <c- nc>Variant</c-> <c- o>=</c-> <i><c- n>variant</c-><c- o>-</c-><c- n>or</c-><c- o>-</c-><c- n>empty</c-></i><c- o>></c->
      <c- k>requires</c-> <c- n>sender_in</c-><c- o>&lt;</c-><c- n>Sndr</c-><c- p>,</c-> <c- n>Env</c-><c- o>></c->
    <c- k>using</c-> <c- n>value_types_of_t</c-> <c- o>=</c-> <i><c- n>see</c-> <c- n>below</c-></i><c- p>;</c->

  <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Sndr</c-><c- p>,</c->
           <c- k>class</c-> <c- nc>Env</c-> <c- o>=</c-> <c- n>empty_env</c-><c- p>,</c->
           <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-><c- p>...</c-><c- o>></c-> <c- k>class</c-> <c- nc>Variant</c-> <c- o>=</c-> <i><c- n>variant</c-><c- o>-</c-><c- n>or</c-><c- o>-</c-><c- n>empty</c-></i><c- o>></c->
      <c- k>requires</c-> <c- n>sender_in</c-><c- o>&lt;</c-><c- n>Sndr</c-><c- p>,</c-> <c- n>Env</c-><c- o>></c->
    <c- k>using</c-> <c- n>error_types_of_t</c-> <c- o>=</c-> <i><c- n>see</c-> <c- n>below</c-></i><c- p>;</c->

  <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Sndr</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Env</c-> <c- o>=</c-> <c- n>empty_env</c-><c- o>></c->
      <c- k>requires</c-> <c- n>sender_in</c-><c- o>&lt;</c-><c- n>Sndr</c-><c- p>,</c-> <c- n>Env</c-><c- o>></c->
    <c- kr>inline</c-> <c- k>constexpr</c-> <c- b>bool</c-> <c- n>sends_stopped</c-> <c- o>=</c-> <i><c- n>see</c-> <c- n>below</c-></i><c- p>;</c->

  <c- k>template</c-> <c- o>&lt;</c-><c- n>sender</c-> <c- n>Sndr</c-><c- o>></c->
    <c- k>using</c-> <c- n>tag_of_t</c-> <c- o>=</c-> <c- n>see</c-> <c- n>below</c-><c- p>;</c->

  <c- c1>// [exec.snd.transform], sender transformations</c->
  <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Domain</c-><c- p>,</c-> <c- n>sender</c-> <c- n>Sndr</c-><c- o>></c->
    <c- k>constexpr</c-> <c- n>sender</c-> <c- k>decltype</c-><c- p>(</c-><c- k>auto</c-><c- p>)</c-> <c- n>transform_sender</c-><c- p>(</c-><c- n>Domain</c-> <c- n>dom</c-><c- p>,</c-> <c- n>Sndr</c-><c- o>&amp;&amp;</c-> <c- n>sndrv</c-><c- p>);</c->

  <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Domain</c-><c- p>,</c-> <c- n>sender</c-> <c- n>Sndr</c-><c- p>,</c-> <c- n>queryable</c-> <c- n>Env</c-><c- o>></c->
    <c- k>constexpr</c-> <c- n>sender</c-> <c- k>decltype</c-><c- p>(</c-><c- k>auto</c-><c- p>)</c-> <c- n>transform_sender</c-><c- p>(</c-><c- n>Domain</c-> <c- n>dom</c-><c- p>,</c-> <c- n>Sndr</c-><c- o>&amp;&amp;</c-> <c- n>sndr</c-><c- p>,</c-> <c- k>const</c-> <c- n>Env</c-><c- o>&amp;</c-> <c- n>env</c-><c- p>);</c->

  <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Domain</c-><c- p>,</c-> <c- n>sender</c-> <c- n>Sndr</c-><c- p>,</c-> <c- n>queryable</c-> <c- n>Env</c-><c- o>></c->
    <c- k>constexpr</c-> <c- k>decltype</c-><c- p>(</c-><c- k>auto</c-><c- p>)</c-> <c- n>transform_env</c-><c- p>(</c-><c- n>Domain</c-> <c- n>dom</c-><c- p>,</c-> <c- n>Sndr</c-><c- o>&amp;&amp;</c-> <c- n>sndr</c-><c- p>,</c-> <c- n>Env</c-><c- o>&amp;&amp;</c-> <c- n>env</c-><c- p>)</c-> <c- k>noexcept</c-><c- p>;</c->

  <c- c1>// [exec.snd.apply], sender algorithm application</c->
  <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Domain</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Tag</c-><c- p>,</c-> <c- n>sender</c-> <c- n>Sndr</c-><c- p>,</c-> <c- k>class</c-><c- p>...</c-> <c- n>Args</c-><c- o>></c->
    <c- k>constexpr</c-> <c- k>decltype</c-><c- p>(</c-><c- k>auto</c-><c- p>)</c-> <c- n>apply_sender</c-><c- p>(</c-><c- n>Domain</c-> <c- n>dom</c-><c- p>,</c-> <c- n>Tag</c-><c- p>,</c-> <c- n>Sndr</c-><c- o>&amp;&amp;</c-> <c- n>sndr</c-><c- p>,</c-> <c- n>Args</c-><c- o>&amp;&amp;</c-><c- p>...</c-> <c- n>args</c-><c- p>)</c-> <c- k>noexcept</c-><c- p>(</c-><i><c- n>see</c-> <c- n>below</c-></i><c- p>);</c->

  <c- c1>// [exec.connect], the connect sender algorithm</c->
  <c- k>namespace</c-> <i><c- nn>senders</c-><c- o>-</c-><c- nn>connect</c-></i> <c- p>{</c-> <c- c1>// exposition only</c->
    <c- k>struct</c-> <c- nc>connect_t</c-><c- p>;</c->
  <c- p>}</c->
  <c- k>using</c-> <i><c- n>senders</c-><c- o>-</c-><c- n>connect</c-></i><c- o>::</c-><c- n>connect_t</c-><c- p>;</c->
  <c- kr>inline</c-> <c- k>constexpr</c-> <c- n>connect_t</c-> <c- n>connect</c-><c- p>{};</c->

  <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Sndr</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Rcvr</c-><c- o>></c->
    <c- k>using</c-> <c- n>connect_result_t</c-> <c- o>=</c-> <c- k>decltype</c-><c- p>(</c-><c- n>connect</c-><c- p>(</c-><c- n>declval</c-><c- o>&lt;</c-><c- n>Sndr</c-><c- o>></c-><c- p>(),</c-> <c- n>declval</c-><c- o>&lt;</c-><c- n>Rcvr</c-><c- o>></c-><c- p>()));</c->

  <c- c1>// [exec.factories], sender factories</c->
  <c- k>namespace</c-> <i><c- nn>sender</c-><c- o>-</c-><c- nn>factories</c-></i> <c- p>{</c-> <c- c1>// exposition only</c->
    <c- k>struct</c-> <c- nc>just_t</c-><c- p>;</c->
    <c- k>struct</c-> <c- nc>just_error_t</c-><c- p>;</c->
    <c- k>struct</c-> <c- nc>just_stopped_t</c-><c- p>;</c->
    <c- k>struct</c-> <c- nc>schedule_t</c-><c- p>;</c->
  <c- p>}</c->
  <c- kr>inline</c-> <c- k>constexpr</c-> <c- n>just</c-> <c- n>just</c-><c- p>{};</c->
  <c- kr>inline</c-> <c- k>constexpr</c-> <c- n>just_error_t</c-> <c- n>just_error</c-><c- p>{};</c->
  <c- kr>inline</c-> <c- k>constexpr</c-> <c- n>just_stopped_t</c-> <c- n>just_stopped</c-><c- p>{};</c->
  <c- k>using</c-> <i><c- n>sender</c-><c- o>-</c-><c- n>factories</c-></i><c- o>::</c-><c- n>schedule_t</c-><c- p>;</c->
  <c- kr>inline</c-> <c- k>constexpr</c-> <c- n>schedule_t</c-> <c- n>schedule</c-><c- p>{};</c->
  <c- kr>inline</c-> <c- k>constexpr</c-> <i><c- n>unspecified</c-></i> <c- n>read</c-><c- p>{};</c->

  <c- k>template</c-><c- o>&lt;</c-><c- n>scheduler</c-> <c- n>Sndr</c-><c- o>></c->
    <c- k>using</c-> <c- n>schedule_result_t</c-> <c- o>=</c-> <c- k>decltype</c-><c- p>(</c-><c- n>schedule</c-><c- p>(</c-><c- n>declval</c-><c- o>&lt;</c-><c- n>Sndr</c-><c- o>></c-><c- p>()));</c->

  <c- c1>// [exec.adapt], sender adaptors</c->
  <c- k>namespace</c-> <i><c- nn>sender</c-><c- o>-</c-><c- nn>adaptor</c-><c- o>-</c-><c- nn>closure</c-></i> <c- p>{</c-> <c- c1>// exposition only</c->
    <c- k>template</c-><c- o>&lt;</c-><i><c- k>class</c-><c- o>-</c-><c- n>type</c-></i> <c- n>D</c-><c- o>></c->
      <c- k>struct</c-> <c- nc>sender_adaptor_closure</c-> <c- p>{</c-> <c- p>};</c->
  <c- p>}</c->
  <c- k>using</c-> <i><c- n>sender</c-><c- o>-</c-><c- n>adaptor</c-><c- o>-</c-><c- n>closure</c-></i><c- o>::</c-><c- n>sender_adaptor_closure</c-><c- p>;</c->

  <c- k>namespace</c-> <i><c- nn>sender</c-><c- o>-</c-><c- nn>adaptors</c-></i> <c- p>{</c-> <c- c1>// exposition only</c->
    <c- k>struct</c-> <c- nc>on_t</c-><c- p>;</c->
    <c- k>struct</c-> <c- nc>transfer_t</c-><c- p>;</c->
    <c- k>struct</c-> <c- nc>schedule_from_t</c-><c- p>;</c->
    <c- k>struct</c-> <c- nc>then_t</c-><c- p>;</c->
    <c- k>struct</c-> <c- nc>upon_error_t</c-><c- p>;</c->
    <c- k>struct</c-> <c- nc>upon_stopped_t</c-><c- p>;</c->
    <c- k>struct</c-> <c- nc>let_value_t</c-><c- p>;</c->
    <c- k>struct</c-> <c- nc>let_error_t</c-><c- p>;</c->
    <c- k>struct</c-> <c- nc>let_stopped_t</c-><c- p>;</c->
    <c- k>struct</c-> <c- nc>bulk_t</c-><c- p>;</c->
    <c- k>struct</c-> <c- nc>split_t</c-><c- p>;</c->
    <c- k>struct</c-> <c- nc>when_all_t</c-><c- p>;</c->
    <c- k>struct</c-> <c- nc>when_all_with_variant_t</c-><c- p>;</c->
    <c- k>struct</c-> <c- nc>into_variant_t</c-><c- p>;</c->
    <c- k>struct</c-> <c- nc>stopped_as_optional_t</c-><c- p>;</c->
    <c- k>struct</c-> <c- nc>stopped_as_error_t</c-><c- p>;</c->
    <c- k>struct</c-> <c- nc>ensure_started_t</c-><c- p>;</c->
  <c- p>}</c->
  <c- k>using</c-> <i><c- n>sender</c-><c- o>-</c-><c- n>adaptors</c-></i><c- o>::</c-><c- n>on_t</c-><c- p>;</c->
  <c- k>using</c-> <i><c- n>sender</c-><c- o>-</c-><c- n>adaptors</c-></i><c- o>::</c-><c- n>transfer_t</c-><c- p>;</c->
  <c- k>using</c-> <i><c- n>sender</c-><c- o>-</c-><c- n>adaptors</c-></i><c- o>::</c-><c- n>schedule_from_t</c-><c- p>;</c->
  <c- k>using</c-> <i><c- n>sender</c-><c- o>-</c-><c- n>adaptors</c-></i><c- o>::</c-><c- n>then_t</c-><c- p>;</c->
  <c- k>using</c-> <i><c- n>sender</c-><c- o>-</c-><c- n>adaptors</c-></i><c- o>::</c-><c- n>upon_error_t</c-><c- p>;</c->
  <c- k>using</c-> <i><c- n>sender</c-><c- o>-</c-><c- n>adaptors</c-></i><c- o>::</c-><c- n>upon_stopped_t</c-><c- p>;</c->
  <c- k>using</c-> <i><c- n>sender</c-><c- o>-</c-><c- n>adaptors</c-></i><c- o>::</c-><c- n>let_value_t</c-><c- p>;</c->
  <c- k>using</c-> <i><c- n>sender</c-><c- o>-</c-><c- n>adaptors</c-></i><c- o>::</c-><c- n>let_error_t</c-><c- p>;</c->
  <c- k>using</c-> <i><c- n>sender</c-><c- o>-</c-><c- n>adaptors</c-></i><c- o>::</c-><c- n>let_stopped_t</c-><c- p>;</c->
  <c- k>using</c-> <i><c- n>sender</c-><c- o>-</c-><c- n>adaptors</c-></i><c- o>::</c-><c- n>bulk_t</c-><c- p>;</c->
  <c- k>using</c-> <i><c- n>sender</c-><c- o>-</c-><c- n>adaptors</c-></i><c- o>::</c-><c- n>split_t</c-><c- p>;</c->
  <c- k>using</c-> <i><c- n>sender</c-><c- o>-</c-><c- n>adaptors</c-></i><c- o>::</c-><c- n>when_all_t</c-><c- p>;</c->
  <c- k>using</c-> <i><c- n>sender</c-><c- o>-</c-><c- n>adaptors</c-></i><c- o>::</c-><c- n>when_all_with_variant_t</c-><c- p>;</c->
  <c- k>using</c-> <i><c- n>sender</c-><c- o>-</c-><c- n>adaptors</c-></i><c- o>::</c-><c- n>into_variant_t</c-><c- p>;</c->
  <c- k>using</c-> <i><c- n>sender</c-><c- o>-</c-><c- n>adaptors</c-></i><c- o>::</c-><c- n>stopped_as_optional_t</c-><c- p>;</c->
  <c- k>using</c-> <i><c- n>sender</c-><c- o>-</c-><c- n>adaptors</c-></i><c- o>::</c-><c- n>stopped_as_error_t</c-><c- p>;</c->
  <c- k>using</c-> <i><c- n>sender</c-><c- o>-</c-><c- n>adaptors</c-></i><c- o>::</c-><c- n>ensure_started_t</c-><c- p>;</c->

  <c- kr>inline</c-> <c- k>constexpr</c-> <c- n>on_t</c-> <c- n>on</c-><c- p>{};</c->
  <c- kr>inline</c-> <c- k>constexpr</c-> <c- n>transfer_t</c-> <c- n>transfer</c-><c- p>{};</c->
  <c- kr>inline</c-> <c- k>constexpr</c-> <c- n>schedule_from_t</c-> <c- n>schedule_from</c-><c- p>{};</c->

  <c- kr>inline</c-> <c- k>constexpr</c-> <c- n>then_t</c-> <c- n>then</c-><c- p>{};</c->
  <c- kr>inline</c-> <c- k>constexpr</c-> <c- n>upon_error_t</c-> <c- n>upon_error</c-><c- p>{};</c->
  <c- kr>inline</c-> <c- k>constexpr</c-> <c- n>upon_stopped_t</c-> <c- n>upon_stopped</c-><c- p>{};</c->

  <c- kr>inline</c-> <c- k>constexpr</c-> <c- n>let_value_t</c-> <c- n>let_value</c-><c- p>{};</c->
  <c- kr>inline</c-> <c- k>constexpr</c-> <c- n>let_error_t</c-> <c- n>let_error</c-><c- p>{};</c->
  <c- kr>inline</c-> <c- k>constexpr</c-> <c- n>let_stopped_t</c-> <c- n>let_stopped</c-><c- p>{};</c->

  <c- kr>inline</c-> <c- k>constexpr</c-> <c- n>bulk_t</c-> <c- n>bulk</c-><c- p>{};</c->

  <c- kr>inline</c-> <c- k>constexpr</c-> <c- n>split_t</c-> <c- n>split</c-><c- p>{};</c->
  <c- kr>inline</c-> <c- k>constexpr</c-> <c- n>when_all_t</c-> <c- n>when_all</c-><c- p>{};</c->
  <c- kr>inline</c-> <c- k>constexpr</c-> <c- n>when_all_with_variant_t</c-> <c- n>when_all_with_variant</c-><c- p>{};</c->

  <c- kr>inline</c-> <c- k>constexpr</c-> <c- n>into_variant_t</c-> <c- n>into_variant</c-><c- p>{};</c->

  <c- kr>inline</c-> <c- k>constexpr</c-> <c- n>stopped_as_optional_t</c-> <c- n>stopped_as_optional</c-><c- p>;</c->

  <c- kr>inline</c-> <c- k>constexpr</c-> <c- n>stopped_as_error_t</c-> <c- n>stopped_as_error</c-><c- p>;</c->

  <c- kr>inline</c-> <c- k>constexpr</c-> <c- n>ensure_started_t</c-> <c- n>ensure_started</c-><c- p>{};</c->

  <c- c1>// [exec.consumers], sender consumers</c->
  <c- k>namespace</c-> <i><c- nn>sender</c-><c- o>-</c-><c- nn>consumers</c-></i> <c- p>{</c-> <c- c1>// exposition only</c->
    <c- k>struct</c-> <c- nc>start_detached_t</c-><c- p>;</c->
  <c- p>}</c->
  <c- k>using</c-> <i><c- n>sender</c-><c- o>-</c-><c- n>consumers</c-></i><c- o>::</c-><c- n>start_detached_t</c-><c- p>;</c->
  <c- kr>inline</c-> <c- k>constexpr</c-> <c- n>start_detached_t</c-> <c- n>start_detached</c-><c- p>{};</c->

  <c- c1>// [exec.utils], sender and receiver utilities</c->
  <c- c1>// [exec.utils.rcvr.adptr]</c->
  <c- k>template</c-><c- o>&lt;</c->
      <i><c- k>class</c-><c- o>-</c-><c- n>type</c-></i> <c- n>Derived</c-><c- p>,</c->
      <c- n>receiver</c-> <c- n>Base</c-> <c- o>=</c-> <i><c- n>unspecified</c-></i><c- o>></c-> <c- c1>// arguments are not associated entities ([lib.tmpl-heads])</c->
    <c- k>class</c-> <c- nc>receiver_adaptor</c-><c- p>;</c->

  <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Fn</c-><c- o>></c->
    <c- k>concept</c-> <i><c- nc>completion</c-><c- o>-</c-><c- n>signature</c-></i> <c- o>=</c-> <i><c- c1>// exposition only</c-></i>
      <i><c- n>see</c-> <c- n>below</c-></i><c- p>;</c->

  <c- c1>// [exec.utils.cmplsigs]</c->
  <c- k>template</c-><c- o>&lt;</c-><i><c- n>completion</c-><c- o>-</c-><c- n>signature</c-></i><c- p>...</c-> <c- n>Fns</c-><c- o>></c->
    <c- k>struct</c-> <c- nc>completion_signatures</c-> <c- p>{};</c->

  <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-><c- p>...</c-> <c- n>Args</c-><c- o>></c-> <i><c- c1>// exposition only</c-></i>
    <c- k>using</c-> <i><c- k>default</c-><c- o>-</c-><c- n>set</c-><c- o>-</c-><c- n>value</c-></i> <c- o>=</c->
      <c- n>completion_signatures</c-><c- o>&lt;</c-><c- n>set_value_t</c-><c- p>(</c-><c- n>Args</c-><c- p>...)</c-><c- o>></c-><c- p>;</c->

  <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Err</c-><c- o>></c-> <i><c- c1>// exposition only</c-></i>
    <c- k>using</c-> <i><c- k>default</c-><c- o>-</c-><c- n>set</c-><c- o>-</c-><c- n>error</c-></i> <c- o>=</c->
      <c- n>completion_signatures</c-><c- o>&lt;</c-><c- n>set_error_t</c-><c- p>(</c-><c- n>Err</c-><c- p>)</c-><c- o>></c-><c- p>;</c->

  <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Sigs</c-><c- o>></c-> <c- c1>// exposition only</c->
    <c- k>concept</c-> <i><c- nc>valid</c-><c- o>-</c-><c- n>completion</c-><c- o>-</c-><c- n>signatures</c-></i> <c- o>=</c-> <i><c- n>see</c-> <c- n>below</c-></i><c- p>;</c->

  <c- c1>// [exec.utils.mkcmplsigs]</c->
  <c- k>template</c-><c- o>&lt;</c->
    <i><c- n>valid</c-><c- o>-</c-><c- n>completion</c-><c- o>-</c-><c- n>signatures</c-></i> <c- n>InputSignatures</c-><c- p>,</c->
    <i><c- n>valid</c-><c- o>-</c-><c- n>completion</c-><c- o>-</c-><c- n>signatures</c-></i> <c- n>AdditionalSignatures</c-> <c- o>=</c-> <c- n>completion_signatures</c-><c- o>&lt;></c-><c- p>,</c->
    <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-><c- p>...</c-><c- o>></c-> <c- k>class</c-> <c- nc>SetValue</c-> <c- o>=</c-> <i><c- n>see</c-> <c- n>below</c-></i><c- p>,</c->
    <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-><c- o>></c-> <c- k>class</c-> <c- nc>SetError</c-> <c- o>=</c-> <i><c- n>see</c-> <c- n>below</c-></i><c- p>,</c->
    <i><c- n>valid</c-><c- o>-</c-><c- n>completion</c-><c- o>-</c-><c- n>signatures</c-></i> <c- n>SetStopped</c-> <c- o>=</c-> <c- n>completion_signatures</c-><c- o>&lt;</c-><c- n>set_stopped_t</c-><c- p>()</c-><c- o>>></c->
  <c- k>using</c-> <c- n>transform_completion_signatures</c-> <c- o>=</c-> <c- n>completion_signatures</c-><c- o>&lt;</c-><i><c- n>see</c-> <c- n>below</c-></i><c- o>></c-><c- p>;</c->

  <c- k>template</c-><c- o>&lt;</c->
    <c- n>sender</c-> <c- n>Sndr</c-><c- p>,</c->
    <c- k>class</c-> <c- nc>Env</c-> <c- o>=</c-> <c- n>empty_env</c-><c- p>,</c->
    <i><c- n>valid</c-><c- o>-</c-><c- n>completion</c-><c- o>-</c-><c- n>signatures</c-></i> <c- n>AdditionalSignatures</c-> <c- o>=</c-> <c- n>completion_signatures</c-><c- o>&lt;></c-><c- p>,</c->
    <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-><c- p>...</c-><c- o>></c-> <c- k>class</c-> <c- nc>SetValue</c-> <c- o>=</c-> <i><c- n>see</c-> <c- n>below</c-></i><c- p>,</c->
    <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-><c- o>></c-> <c- k>class</c-> <c- nc>SetError</c-> <c- o>=</c-> <i><c- n>see</c-> <c- n>below</c-></i><c- p>,</c->
    <i><c- n>valid</c-><c- o>-</c-><c- n>completion</c-><c- o>-</c-><c- n>signatures</c-></i> <c- n>SetStopped</c-> <c- o>=</c-> <c- n>completion_signatures</c-><c- o>&lt;</c-><c- n>set_stopped_t</c-><c- p>()</c-><c- o>>></c->
      <c- k>requires</c-> <c- n>sender_in</c-><c- o>&lt;</c-><c- n>Sndr</c-><c- p>,</c-> <c- n>Env</c-><c- o>></c->
  <c- k>using</c-> <c- n>transform_completion_signatures_of</c-> <c- o>=</c->
    <c- n>transform_completion_signatures</c-><c- o>&lt;</c->
      <c- n>completion_signatures_of_t</c-><c- o>&lt;</c-><c- n>Sndr</c-><c- p>,</c-> <c- n>Env</c-><c- o>></c-><c- p>,</c-> <c- n>AdditionalSignatures</c-><c- p>,</c-> <c- n>SetValue</c-><c- p>,</c-> <c- n>SetError</c-><c- p>,</c-> <c- n>SetStopped</c-><c- o>></c-><c- p>;</c->

  <c- c1>// [exec.ctx], execution resources</c->
  <c- k>class</c-> <c- nc>run_loop</c-><c- p>;</c->
<c- p>}</c->

<c- k>namespace</c-> <c- nn>std</c-><c- o>::</c-><c- nn>this_thread</c-> <c- p>{</c->
  <c- c1>// [exec.queries], queries</c->
  <c- k>namespace</c-> <i><c- nn>queries</c-></i> <c- p>{</c-> <i><c- c1>// exposition only</c-></i>
    <c- k>struct</c-> <c- nc>execute_may_block_caller_t</c-><c- p>;</c->
  <c- p>}</c->
  <c- k>using</c-> <i><c- n>queries</c-></i><c- o>::</c-><c- n>execute_may_block_caller_t</c-><c- p>;</c->
  <c- kr>inline</c-> <c- k>constexpr</c-> <c- n>execute_may_block_caller_t</c-> <c- n>execute_may_block_caller</c-><c- p>{};</c->

  <c- k>namespace</c-> <i><c- nn>this</c-><c- o>-</c-><c- nn>thread</c-></i> <c- p>{</c-> <i><c- c1>// exposition only</c-></i>
    <c- k>struct</c-> <i><c- nc>sync</c-><c- o>-</c-><c- n>wait</c-><c- o>-</c-><c- n>env</c-></i><c- p>;</c-> <i><c- c1>// exposition only</c-></i>
    <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Sndr</c-><c- o>></c->
        <c- k>requires</c-> <c- n>sender_in</c-><c- o>&lt;</c-><c- n>Sndr</c-><c- p>,</c-> <i><c- n>sync</c-><c- o>-</c-><c- n>wait</c-><c- o>-</c-><c- n>env</c-></i><c- o>></c->
      <c- k>using</c-> <i><c- n>sync</c-><c- o>-</c-><c- n>wait</c-><c- o>-</c-><c- n>type</c-></i> <c- o>=</c-> <i><c- n>see</c-> <c- n>below</c-></i><c- p>;</c-> <i><c- c1>// exposition only</c-></i>
    <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Sndr</c-><c- o>></c->
      <c- k>using</c-> <i><c- n>sync</c-><c- o>-</c-><c- n>wait</c-><c- o>-</c-><c- n>with</c-><c- o>-</c-><c- n>variant</c-><c- o>-</c-><c- n>type</c-></i> <c- o>=</c-> <i><c- n>see</c-> <c- n>below</c-></i><c- p>;</c-> <i><c- c1>// exposition only</c-></i>

    <c- k>struct</c-> <c- nc>sync_wait_t</c-><c- p>;</c->
    <c- k>struct</c-> <c- nc>sync_wait_with_variant_t</c-><c- p>;</c->
  <c- p>}</c->
  <c- k>using</c-> <i><c- k>this</c-><c- o>-</c-><c- kr>thread</c-></i><c- o>::</c-><c- n>sync_wait_t</c-><c- p>;</c->
  <c- k>using</c-> <i><c- k>this</c-><c- o>-</c-><c- kr>thread</c-></i><c- o>::</c-><c- n>sync_wait_with_variant_t</c-><c- p>;</c->
  <c- kr>inline</c-> <c- k>constexpr</c-> <c- n>sync_wait_t</c-> <c- n>sync_wait</c-><c- p>{};</c->
  <c- kr>inline</c-> <c- k>constexpr</c-> <c- n>sync_wait_with_variant_t</c-> <c- n>sync_wait_with_variant</c-><c- p>{};</c->
<c- p>}</c->

<c- k>namespace</c-> <c- nn>std</c-><c- o>::</c-><c- nn>execution</c-> <c- p>{</c->
  <c- c1>// [exec.execute], one-way execution</c->
  <c- k>namespace</c-> <i><c- nn>execute</c-></i> <c- p>{</c-> <c- c1>// exposition only</c->
    <c- k>struct</c-> <c- nc>execute_t</c-><c- p>;</c->
  <c- p>}</c->
  <c- k>using</c-> <i><c- n>execute</c-></i><c- o>::</c-><c- n>execute_t</c-><c- p>;</c->
  <c- kr>inline</c-> <c- k>constexpr</c-> <c- n>execute_t</c-> <c- n>execute</c-><c- p>{};</c->

  <c- c1>// [exec.as.awaitable]</c->
  <c- k>namespace</c-> <i><c- nn>coro</c-><c- o>-</c-><c- nn>utils</c-></i> <c- p>{</c-> <c- c1>// exposition only</c->
    <c- k>struct</c-> <c- nc>as_awaitable_t</c-><c- p>;</c->
  <c- p>}</c->
  <c- k>using</c-> <i><c- n>coro</c-><c- o>-</c-><c- n>utils</c-></i><c- o>::</c-><c- n>as_awaitable_t</c-><c- p>;</c->
  <c- kr>inline</c-> <c- k>constexpr</c-> <c- n>as_awaitable_t</c-> <c- n>as_awaitable</c-><c- p>;</c->

  <c- c1>// [exec.with.awaitable.senders]</c->
  <c- k>template</c-><c- o>&lt;</c-><i><c- k>class</c-><c- o>-</c-><c- n>type</c-></i> <c- n>Promise</c-><c- o>></c->
    <c- k>struct</c-> <c- nc>with_awaitable_senders</c-><c- p>;</c->
<c- p>}</c->
</t></pre>
   <ol>
    <li data-md>
     <p>The exposition-only type <code class="highlight"><i><c- n>variant</c-><c- o>-</c-><c- n>or</c-><c- o>-</c-><c- n>empty</c-><c- o>&lt;</c-><c- n>Ts</c-><c- p>...</c-><c- o>></c-></i></code> is
 defined as follows:</p>
     <ol>
      <li data-md>
       <p>If <code class="highlight"><c- k>sizeof</c-><c- p>...(</c-><c- n>Ts</c-><c- p>)</c-></code> is greater than zero, <code class="highlight"><i><c- n>variant</c-><c- o>-</c-><c- n>or</c-><c- o>-</c-><c- n>empty</c-><c- o>&lt;</c-><c- n>Ts</c-><c- p>...</c-><c- o>></c-></i></code> names the type <code class="highlight"><c- n>variant</c-><c- o>&lt;</c-><c- n>Us</c-><c- p>...</c-><c- o>></c-></code> where <code class="highlight"><c- n>Us</c-><c- p>...</c-></code> is the pack <code class="highlight"><c- n>decay_t</c-><c- o>&lt;</c-><c- n>Ts</c-><c- o>></c-><c- p>...</c-></code> with
duplicate types removed.</p>
      <li data-md>
       <p>Otherwise, <code class="highlight"><i><c- n>variant</c-><c- o>-</c-><c- n>or</c-><c- o>-</c-><c- n>empty</c-><c- o>&lt;</c-><c- n>Ts</c-><c- p>...</c-><c- o>></c-></i></code> names the
exposition-only class type:</p>
<pre class="highlight"><c- k>struct</c-> <i><c- nc>empty</c-><c- o>-</c-><c- n>variant</c-></i> <c- p>{</c->
  <i><c- n>empty</c-><c- o>-</c-><c- n>variant</c-></i><c- p>()</c-> <c- o>=</c-> <c- k>delete</c-><c- p>;</c->
<c- p>};</c->
</pre>
     </ol>
   </ol>
   <h3 class="heading settled" data-level="11.5" id="spec-execution.queries"><span class="secno">11.5. </span><span class="content">Queries <b>[exec.queries]</b></span><a class="self-link" href="#spec-execution.queries"></a></h3>
   <h4 class="heading settled" data-level="11.5.1" id="spec-execution.forwarding_query"><span class="secno">11.5.1. </span><span class="content"><code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>forwarding_query</c-></code> <b>[exec.fwd.env]</b></span><a class="self-link" href="#spec-execution.forwarding_query"></a></h4>
   <ol>
    <li data-md>
     <p><code class="highlight"><c- n>forwarding_query</c-></code> asks a query object whether it should be forwarded
through queryable adaptors.</p>
    <li data-md>
     <p>The name <code class="highlight"><c- n>forwarding_query</c-></code> denotes a query object. For some query
object <code class="highlight"><c- n>q</c-></code> of type <code class="highlight"><c- n>Q</c-></code>, <code class="highlight"><c- n>forwarding_query</c-><c- p>(</c-><c- n>q</c-><c- p>)</c-></code> is expression-equivalent
to:</p>
     <ol>
      <li data-md>
       <p><code class="highlight"><i><c- n>mandate</c-><c- o>-</c-><c- n>nothrow</c-><c- o>-</c-><c- n>call</c-></i><c- p>(</c-><c- n>tag_invoke</c-><c- p>,</c-> <c- n>forwarding_query</c-><c- p>,</c-> <c- n>q</c-><c- p>)</c-></code> if that expression is well-formed.</p>
       <ul>
        <li data-md>
         <p><i>Mandates:</i> The expression above has type <code class="highlight"><c- b>bool</c-></code> and is a core
constant expressions if <code class="highlight"><c- n>q</c-></code> is a core constant expression.</p>
       </ul>
      <li data-md>
       <p>Otherwise, <code class="highlight">true</code> if <code class="highlight"><c- n>derived_from</c-><c- o>&lt;</c-><c- n>Q</c-><c- p>,</c-> <c- n>forwarding_query_t</c-><c- o>></c-></code> is <code class="highlight">true</code>.</p>
      <li data-md>
       <p>Otherwise, <code class="highlight">false</code>.</p>
     </ol>
   </ol>
   <h4 class="heading settled" data-level="11.5.2" id="spec-execution.get_allocator"><span class="secno">11.5.2. </span><span class="content"><code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>get_allocator</c-></code> <b>[exec.get.allocator]</b></span><a class="self-link" href="#spec-execution.get_allocator"></a></h4>
   <ol>
    <li data-md>
     <p><code class="highlight"><c- n>get_allocator</c-></code> asks an object for its associated allocator.</p>
    <li data-md>
     <p>The name <code class="highlight"><c- n>get_allocator</c-></code> denotes a query object. For some subexpression <code class="highlight"><c- n>env</c-></code>, <code class="highlight"><c- n>get_allocator</c-><c- p>(</c-><c- n>env</c-><c- p>)</c-></code> is expression-equivalent to <code class="highlight"><i><c- n>mandate</c-><c- o>-</c-><c- n>nothrow</c-><c- o>-</c-><c- n>call</c-></i><c- p>(</c-><c- n>tag_invoke</c-><c- p>,</c-> <c- n>get_allocator</c-><c- p>,</c-> <c- n>as_const</c-><c- p>(</c-><c- n>env</c-><c- p>))</c-></code>.</p>
     <ul>
      <li data-md>
       <p><i>Mandates:</i> The type of the expression above
satisfies <i>Allocator</i>.</p>
     </ul>
    <li data-md>
     <p><code class="highlight"><c- n>forwarding_query</c-><c- p>(</c-><c- n>get_allocator</c-><c- p>)</c-></code> is <code class="highlight">true</code>.</p>
    <li data-md>
     <p><code class="highlight"><c- n>get_allocator</c-><c- p>()</c-></code> (with no arguments) is expression-equivalent to <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>read</c-><c- p>(</c-><c- n>get_allocator</c-><c- p>)</c-></code> ([exec.read]).</p>
   </ol>
   <h4 class="heading settled" data-level="11.5.3" id="spec-execution.get_stop_token"><span class="secno">11.5.3. </span><span class="content"><code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>get_stop_token</c-></code> <b>[exec.get.stop.token]</b></span><a class="self-link" href="#spec-execution.get_stop_token"></a></h4>
   <ol>
    <li data-md>
     <p><code class="highlight"><c- n>get_stop_token</c-></code> asks an object for an associated stop token.</p>
    <li data-md>
     <p>The name <code class="highlight"><c- n>get_stop_token</c-></code> denotes a query object. For some subexpression <code class="highlight"><c- n>env</c-></code>, <code class="highlight"><c- n>get_stop_token</c-><c- p>(</c-><c- n>env</c-><c- p>)</c-></code> is expression-equivalent to:</p>
     <ol>
      <li data-md>
       <p><code class="highlight"><i><c- n>mandate</c-><c- o>-</c-><c- n>nothrow</c-><c- o>-</c-><c- n>call</c-></i><c- p>(</c-><c- n>tag_invoke</c-><c- p>,</c-> <c- n>get_stop_token</c-><c- p>,</c-> <c- n>as_const</c-><c- p>(</c-><c- n>env</c-><c- p>))</c-></code>, if this expression is well-formed.</p>
       <ul>
        <li data-md>
         <p><i>Mandates:</i> The type of the expression above satisfies <code class="highlight"><c- n>stoppable_token</c-></code>.</p>
       </ul>
      <li data-md>
       <p>Otherwise, <code class="highlight"><c- n>never_stop_token</c-><c- p>{}</c-></code>.</p>
     </ol>
    <li data-md>
     <p><code class="highlight"><c- n>forwarding_query</c-><c- p>(</c-><c- n>get_stop_token</c-><c- p>)</c-></code> is a core constant
expression and has value <code class="highlight">true</code>.</p>
    <li data-md>
     <p><code class="highlight"><c- n>get_stop_token</c-><c- p>()</c-></code> (with no arguments) is expression-equivalent to <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>read</c-><c- p>(</c-><c- n>get_stop_token</c-><c- p>)</c-></code> ([exec.read]).</p>
   </ol>
   <h4 class="heading settled" data-level="11.5.4" id="spec-execution.environment.get_env"><span class="secno">11.5.4. </span><span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>get_env</c-></code> <b>[exec.get.env]</b></span><a class="self-link" href="#spec-execution.environment.get_env"></a></h4>
   <ol>
    <li data-md>
     <p><code class="highlight"><c- n>get_env</c-></code> is a customization point object. For some subexpression <code class="highlight"><c- n>o</c-></code> of type <code class="highlight"><c- n>O</c-></code>, <code class="highlight"><c- n>get_env</c-><c- p>(</c-><c- n>o</c-><c- p>)</c-></code> is expression-equivalent to</p>
     <ol>
      <li data-md>
       <p><code class="highlight"><c- n>tag_invoke</c-><c- p>(</c-><c- n>get_env</c-><c- p>,</c-> <c- k>const_cast</c-><c- o>&lt;</c-><c- k>const</c-> <c- n>O</c-><c- o>&amp;></c-><c- p>(</c-><c- n>o</c-><c- p>))</c-></code> if that expression is
well-formed.</p>
       <ul>
        <li data-md>
         <p><i>Mandates:</i> The expression above is not potentially throwing, and
its type satisfies <code class="highlight"><c- n>queryable</c-></code> ([exec.queryable]).</p>
       </ul>
      <li data-md>
       <p>Otherwise, <code class="highlight"><c- n>empty_env</c-><c- p>{}</c-></code>.</p>
     </ol>
    <li data-md>
     <p>The value of <code class="highlight"><c- n>get_env</c-><c- p>(</c-><c- n>o</c-><c- p>)</c-></code> shall be valid while <code class="highlight"><c- n>o</c-></code> is valid.</p>
    <li data-md>
     <p>When passed a sender object, <code class="highlight"><c- n>get_env</c-></code> returns the sender’s attributes. When
passed a receiver, <code class="highlight"><c- n>get_env</c-></code> returns the receiver’s environment.</p>
   </ol>
   <h4 class="heading settled" data-level="11.5.5" id="spec-execution.get_domain"><span class="secno">11.5.5. </span><span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>get_domain</c-></code> <b>[exec.get.domain]</b></span><a class="self-link" href="#spec-execution.get_domain"></a></h4>
   <ol>
    <li data-md>
     <p><code class="highlight"><c- n>get_domain</c-></code> asks an object for an associated execution domain tag.</p>
    <li data-md>
     <p>The name <code class="highlight"><c- n>get_domain</c-></code> denotes a query object. For some subexpression <code class="highlight"><c- n>env</c-></code>, <code class="highlight"><c- n>get_domain</c-><c- p>(</c-><c- n>env</c-><c- p>)</c-></code> is expression-equivalent to <code class="highlight"><i><c- n>mandate</c-><c- o>-</c-><c- n>nothrow</c-><c- o>-</c-><c- n>call</c-></i><c- p>(</c-><c- n>tag_invoke</c-><c- p>,</c-> <c- n>get_domain</c-><c- p>,</c-> <c- n>as_const</c-><c- p>(</c-><c- n>env</c-><c- p>))</c-></code>,
if this expression is well-formed.</p>
    <li data-md>
     <p><code class="highlight"><c- n>forwarding_query</c-><c- p>(</c-><c- n>execution</c-><c- o>::</c-><c- n>get_domain</c-><c- p>)</c-></code> is a core constant
expression and has value <code class="highlight">true</code>.</p>
    <li data-md>
     <p><code class="highlight"><c- n>get_domain</c-><c- p>()</c-></code> (with no arguments) is expression-equivalent to <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>read</c-><c- p>(</c-><c- n>get_domain</c-><c- p>)</c-></code> ([exec.read]).</p>
   </ol>
   <h4 class="heading settled" data-level="11.5.6" id="spec-execution.get_scheduler"><span class="secno">11.5.6. </span><span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>get_scheduler</c-></code> <b>[exec.get.scheduler]</b></span><a class="self-link" href="#spec-execution.get_scheduler"></a></h4>
   <ol>
    <li data-md>
     <p><code class="highlight"><c- n>get_scheduler</c-></code> asks an object for its associated scheduler.</p>
    <li data-md>
     <p>The name <code class="highlight"><c- n>get_scheduler</c-></code> denotes a query object. For some
subexpression <code class="highlight"><c- n>env</c-></code>, <code class="highlight"><c- n>get_scheduler</c-><c- p>(</c-><c- n>env</c-><c- p>)</c-></code> is expression-equivalent to <code class="highlight"><i><c- n>mandate</c-><c- o>-</c-><c- n>nothrow</c-><c- o>-</c-><c- n>call</c-></i><c- p>(</c-><c- n>tag_invoke</c-><c- p>,</c-> <c- n>get_scheduler</c-><c- p>,</c-> <c- n>as_const</c-><c- p>(</c-><c- n>env</c-><c- p>))</c-></code>.</p>
     <ul>
      <li data-md>
       <p><i>Mandates:</i> The type of the expression above satisfies <code class="highlight"><c- n>scheduler</c-></code>.</p>
     </ul>
    <li data-md>
     <p><code class="highlight"><c- n>forwarding_query</c-><c- p>(</c-><c- n>execution</c-><c- o>::</c-><c- n>get_scheduler</c-><c- p>)</c-></code> is a core constant
expression and has value <code class="highlight">true</code>.</p>
    <li data-md>
     <p><code class="highlight"><c- n>get_scheduler</c-><c- p>()</c-></code> (with no arguments) is expression-equivalent to <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>read</c-><c- p>(</c-><c- n>get_scheduler</c-><c- p>)</c-></code> ([exec.read]).</p>
   </ol>
   <h4 class="heading settled" data-level="11.5.7" id="spec-execution.get_delegatee_scheduler"><span class="secno">11.5.7. </span><span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>get_delegatee_scheduler</c-></code> <b>[exec.get.delegatee.scheduler]</b></span><a class="self-link" href="#spec-execution.get_delegatee_scheduler"></a></h4>
   <ol>
    <li data-md>
     <p><code class="highlight"><c- n>get_delegatee_scheduler</c-></code> asks an object for a scheduler that can be used to delegate work to for the purpose of forward progress delegation.</p>
    <li data-md>
     <p>The name <code class="highlight"><c- n>get_delegatee_scheduler</c-></code> denotes a query object. For some
subexpression <code class="highlight"><c- n>env</c-></code>, <code class="highlight"><c- n>get_delegatee_scheduler</c-><c- p>(</c-><c- n>env</c-><c- p>)</c-></code> is expression-equivalent to <code class="highlight"><i><c- n>mandate</c-><c- o>-</c-><c- n>nothrow</c-><c- o>-</c-><c- n>call</c-></i><c- p>(</c-><c- n>tag_invoke</c-><c- p>,</c-> <c- n>get_delegatee_scheduler</c-><c- p>,</c-> <c- n>as_const</c-><c- p>(</c-><c- n>env</c-><c- p>))</c-></code>.</p>
     <ul>
      <li data-md>
       <p><i>Mandates:</i> The type of the expression above is satisfies <code class="highlight"><c- n>scheduler</c-></code>.</p>
     </ul>
    <li data-md>
     <p><code class="highlight"><c- n>forwarding_query</c-><c- p>(</c-><c- n>execution</c-><c- o>::</c-><c- n>get_delegatee_scheduler</c-><c- p>)</c-></code> is a core
constant expression and has value <code class="highlight">true</code>.</p>
    <li data-md>
     <p><code class="highlight"><c- n>get_delegatee_scheduler</c-><c- p>()</c-></code> (with no arguments) is expression-equivalent to <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>read</c-><c- p>(</c-><c- n>get_delegatee_scheduler</c-><c- p>)</c-></code> ([exec.read]).</p>
   </ol>
   <h4 class="heading settled" data-level="11.5.8" id="spec-execution.get_forward_progress_guarantee"><span class="secno">11.5.8. </span><span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>get_forward_progress_guarantee</c-></code> <b>[exec.get.forward.progress.guarantee]</b></span><a class="self-link" href="#spec-execution.get_forward_progress_guarantee"></a></h4>
<pre class="highlight"><c- k>enum</c-> <c- k>class</c-> <c- nc>forward_progress_guarantee</c-> <c- p>{</c->
  <c- n>concurrent</c-><c- p>,</c->
  <c- n>parallel</c-><c- p>,</c->
  <c- n>weakly_parallel</c->
<c- p>};</c->
</pre>
   <ol>
    <li data-md>
     <p><code class="highlight"><c- n>get_forward_progress_guarantee</c-></code> asks a scheduler about the forward progress guarantees of execution agents created by that scheduler.</p>
    <li data-md>
     <p>The name <code class="highlight"><c- n>get_forward_progress_guarantee</c-></code> denotes a query object. For some subexpression <code class="highlight"><c- n>sch</c-></code>, let <code class="highlight"><c- n>Sch</c-></code> be <code class="highlight"><c- k>decltype</c-><c- p>((</c-><c- n>sch</c-><c- p>))</c-></code>. If <code class="highlight"><c- n>Sch</c-></code> does not satisfy <code class="highlight"><c- n>scheduler</c-></code>, <code class="highlight"><c- n>get_forward_progress_guarantee</c-></code> is ill-formed.
Otherwise, <code class="highlight"><c- n>get_forward_progress_guarantee</c-><c- p>(</c-><c- n>sch</c-><c- p>)</c-></code> is expression-equivalent to:</p>
     <ol>
      <li data-md>
       <p><code class="highlight"><i><c- n>mandate</c-><c- o>-</c-><c- n>nothrow</c-><c- o>-</c-><c- n>call</c-></i><c- p>(</c-><c- n>tag_invoke</c-><c- p>,</c-> <c- n>get_forward_progress_guarantee</c-><c- p>,</c-> <c- n>as_const</c-><c- p>(</c-><c- n>sch</c-><c- p>))</c-></code>, if this expression is well-formed.</p>
       <ul>
        <li data-md>
         <p><i>Mandates:</i> The type of the expression above is <code class="highlight"><c- n>forward_progress_guarantee</c-></code>.</p>
       </ul>
      <li data-md>
       <p>Otherwise, <code class="highlight"><c- n>forward_progress_guarantee</c-><c- o>::</c-><c- n>weakly_parallel</c-></code>.</p>
     </ol>
    <li data-md>
     <p>If <code class="highlight"><c- n>get_forward_progress_guarantee</c-><c- p>(</c-><c- n>sch</c-><c- p>)</c-></code> for some scheduler <code class="highlight"><c- n>sch</c-></code> returns <code class="highlight"><c- n>forward_progress_guarantee</c-><c- o>::</c-><c- n>concurrent</c-></code>, all execution agents created by that scheduler shall provide the concurrent forward progress guarantee. If it returns <code class="highlight"><c- n>forward_progress_guarantee</c-><c- o>::</c-><c- n>parallel</c-></code>, all execution agents created by that scheduler shall provide at least the parallel forward progress guarantee.</p>
   </ol>
   <h4 class="heading settled" data-level="11.5.9" id="spec-execution.execute_may_block_caller"><span class="secno">11.5.9. </span><span class="content"><code class="highlight"><c- n>this_thread</c-><c- o>::</c-><c- n>execute_may_block_caller</c-></code> <b>[exec.execute.may.block.caller]</b></span><a class="self-link" href="#spec-execution.execute_may_block_caller"></a></h4>
   <ol>
    <li data-md>
     <p><code class="highlight"><c- n>this_thread</c-><c- o>::</c-><c- n>execute_may_block_caller</c-></code> asks a scheduler <code class="highlight"><c- n>sch</c-></code> whether a call <code class="highlight"><c- n>execute</c-><c- p>(</c-><c- n>sch</c-><c- p>,</c-> <c- n>f</c-><c- p>)</c-></code> with any invocable <code class="highlight"><c- n>f</c-></code> may block the thread where such a call occurs.</p>
    <li data-md>
     <p>The name <code class="highlight"><c- n>this_thread</c-><c- o>::</c-><c- n>execute_may_block_caller</c-></code> denotes a query object. For some subexpression <code class="highlight"><c- n>sch</c-></code>, let <code class="highlight"><c- n>Sch</c-></code> be <code class="highlight"><c- k>decltype</c-><c- p>((</c-><c- n>sch</c-><c- p>))</c-></code>. If <code class="highlight"><c- n>Sch</c-></code> does not satisfy <code class="highlight"><c- n>scheduler</c-></code>, <code class="highlight"><c- n>this_thread</c-><c- o>::</c-><c- n>execute_may_block_caller</c-></code> is ill-formed. Otherwise, <code class="highlight"><c- n>this_thread</c-><c- o>::</c-><c- n>execute_may_block_caller</c-><c- p>(</c-><c- n>sch</c-><c- p>)</c-></code> is expression-equivalent to:</p>
     <ol>
      <li data-md>
       <p><code class="highlight"><i><c- n>mandate</c-><c- o>-</c-><c- n>nothrow</c-><c- o>-</c-><c- n>call</c-></i><c- p>(</c-><c- n>tag_invoke</c-><c- p>,</c-> <c- n>this_thread</c-><c- o>::</c-><c- n>execute_may_block_caller</c-><c- p>,</c-> <c- n>as_const</c-><c- p>(</c-><c- n>sch</c-><c- p>))</c-></code>, if this expression is well-formed.</p>
       <ul>
        <li data-md>
         <p><i>Mandates:</i> The type of the expression above is <code class="highlight"><c- b>bool</c-></code>.</p>
       </ul>
      <li data-md>
       <p>Otherwise, <code class="highlight">true</code>.</p>
     </ol>
    <li data-md>
     <p>If <code class="highlight"><c- n>this_thread</c-><c- o>::</c-><c- n>execute_may_block_caller</c-><c- p>(</c-><c- n>sch</c-><c- p>)</c-></code> for some scheduler <code class="highlight"><c- n>sch</c-></code> returns <code class="highlight">false</code>, no <code class="highlight"><c- n>execute</c-><c- p>(</c-><c- n>sch</c-><c- p>,</c-> <c- n>f</c-><c- p>)</c-></code> call with some invocable <code class="highlight"><c- n>f</c-></code> shall block the calling thread.</p>
   </ol>
   <h4 class="heading settled" data-level="11.5.10" id="spec-execution.get_completion_scheduler"><span class="secno">11.5.10. </span><span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>get_completion_scheduler</c-></code> <b>[exec.completion.scheduler]</b></span><a class="self-link" href="#spec-execution.get_completion_scheduler"></a></h4>
   <ol>
    <li data-md>
     <p><code class="highlight"><c- n>get_completion_scheduler</c-><c- o>&lt;</c-><i><c- n>completion</c-><c- o>-</c-><c- n>tag</c-></i><c- o>></c-></code> obtains the
completion scheduler associated with a completion tag from a sender’s
attributes.</p>
    <li data-md>
     <p>The name <code class="highlight"><c- n>get_completion_scheduler</c-></code> denotes a query object template. For some
subexpression <code class="highlight"><c- n>q</c-></code>, let <code class="highlight"><c- n>Q</c-></code> be <code class="highlight"><c- k>decltype</c-><c- p>((</c-><c- n>q</c-><c- p>))</c-></code>. If the template argument <code class="highlight"><c- n>Tag</c-></code> in <code class="highlight"><c- n>get_completion_scheduler</c-><c- o>&lt;</c-><c- n>Tag</c-><c- o>></c-><c- p>(</c-><c- n>q</c-><c- p>)</c-></code> is not one of <code class="highlight"><c- n>set_value_t</c-></code>, <code class="highlight"><c- n>set_error_t</c-></code>, or <code class="highlight"><c- n>set_stopped_t</c-></code>, <code class="highlight"><c- n>get_completion_scheduler</c-><c- o>&lt;</c-><c- n>Tag</c-><c- o>></c-><c- p>(</c-><c- n>q</c-><c- p>)</c-></code> is
ill-formed. Otherwise, <code class="highlight"><c- n>get_completion_scheduler</c-><c- o>&lt;</c-><c- n>Tag</c-><c- o>></c-><c- p>(</c-><c- n>q</c-><c- p>)</c-></code> is
expression-equivalent to <code class="highlight"><i><c- n>mandate</c-><c- o>-</c-><c- n>nothrow</c-><c- o>-</c-><c- n>call</c-></i><c- p>(</c-><c- n>tag_invoke</c-><c- p>,</c-> <c- n>get_completion_scheduler</c-><c- o>&lt;</c-><c- n>Tag</c-><c- o>></c-><c- p>,</c-> <c- n>as_const</c-><c- p>(</c-><c- n>q</c-><c- p>))</c-></code> if this expression is
well-formed.</p>
     <ul>
      <li data-md>
       <p><i>Mandates:</i> The type of the expression above satisfies <code class="highlight"><c- n>scheduler</c-></code>.</p>
     </ul>
    <li data-md>
     <p>If, for some sender <code class="highlight"><c- n>sndr</c-></code> and completion function <code class="highlight"><c- n>C</c-></code> that has an associated
completion tag <code class="highlight"><c- n>Tag</c-></code>, <code class="highlight"><c- n>get_completion_scheduler</c-><c- o>&lt;</c-><c- n>Tag</c-><c- o>></c-><c- p>(</c-><c- n>get_env</c-><c- p>(</c-><c- n>sndr</c-><c- p>))</c-></code> is
well-formed and results in a scheduler <code class="highlight"><c- n>sch</c-></code>, and the sender <code class="highlight"><c- n>sndr</c-></code> invokes <code class="highlight"><c- n>C</c-><c- p>(</c-><c- n>rcvr</c-><c- p>,</c-> <c- n>args</c-><c- p>...)</c-></code>, for some receiver <code class="highlight"><c- n>rcvr</c-></code> that has been connected to <code class="highlight"><c- n>sndr</c-></code>, with
additional arguments <code class="highlight"><c- n>args</c-><c- p>...</c-></code>, on an execution agent that does not
belong to the associated execution resource of <code class="highlight"><c- n>sch</c-></code>, the behavior is
undefined.</p>
    <li data-md>
     <p>The expression <code class="highlight"><c- n>forwarding_query</c-><c- p>(</c-><c- n>get_completion_scheduler</c-><c- o>&lt;</c-><c- n>CPO</c-><c- o>></c-><c- p>)</c-></code> is a core constant expression and has value <code class="highlight">true</code>.</p>
   </ol>
   <h3 class="heading settled" data-level="11.6" id="spec-execution.schedulers"><span class="secno">11.6. </span><span class="content">Schedulers <b>[exec.sched] </b></span><a class="self-link" href="#spec-execution.schedulers"></a></h3>
   <ol>
    <li data-md>
     <p>The <code class="highlight"><c- n>scheduler</c-></code> concept defines the requirements of a scheduler type
([async.ops]). <code class="highlight"><c- n>schedule</c-></code> is a customization point object that accepts a
scheduler. A valid invocation of <code class="highlight"><c- n>schedule</c-></code> is a schedule-expression.</p>
<pre class="highlight"><c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Sch</c-><c- o>></c->
  <c- k>concept</c-> <c- nc>scheduler</c-> <c- o>=</c->
    <c- n>queryable</c-><c- o>&lt;</c-><c- n>Sch</c-><c- o>></c-> <c- o>&amp;&amp;</c->
    <c- k>requires</c-><c- p>(</c-><c- n>Sch</c-><c- o>&amp;&amp;</c-> <c- n>sch</c-><c- p>,</c-> <c- k>const</c-> <c- n>get_completion_scheduler_t</c-><c- o>&lt;</c-><c- n>set_value_t</c-><c- o>></c-> <c- n>tag</c-><c- p>)</c-> <c- p>{</c->
      <c- p>{</c-> <c- n>schedule</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>Sch</c-><c- o>></c-><c- p>(</c-><c- n>sch</c-><c- p>))</c-> <c- p>}</c-> <c- o>-></c-> <c- n>sender</c-><c- p>;</c->
      <c- p>{</c-> <c- n>tag_invoke</c-><c- p>(</c-><c- n>tag</c-><c- p>,</c-> <c- n>get_env</c-><c- p>(</c->
          <c- n>schedule</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>Sch</c-><c- o>></c-><c- p>(</c-><c- n>sch</c-><c- p>))))</c-> <c- p>}</c-> <c- o>-></c-> <c- n>same_as</c-><c- o>&lt;</c-><c- n>remove_cvref_t</c-><c- o>&lt;</c-><c- n>Sch</c-><c- o>>></c-><c- p>;</c->
    <c- p>}</c-> <c- o>&amp;&amp;</c->
    <c- n>equality_comparable</c-><c- o>&lt;</c-><c- n>remove_cvref_t</c-><c- o>&lt;</c-><c- n>Sch</c-><c- o>>></c-> <c- o>&amp;&amp;</c->
    <c- n>copy_constructible</c-><c- o>&lt;</c-><c- n>remove_cvref_t</c-><c- o>&lt;</c-><c- n>Sch</c-><c- o>>></c-><c- p>;</c->
</pre>
    <li data-md>
     <p>Let <code class="highlight"><c- n>Sch</c-></code> be the type of a scheduler and let <code class="highlight"><c- n>Env</c-></code> be the type of an execution
environment for which <code class="highlight"><c- n>sender_in</c-><c- o>&lt;</c-><c- n>schedule_result_t</c-><c- o>&lt;</c-><c- n>Sch</c-><c- o>></c-><c- p>,</c-> <c- n>Env</c-><c- o>></c-></code> is <code class="highlight">true</code>. Then <code class="highlight"><i><c- n>sender</c-><c- o>-</c-><c- n>of</c-><c- o>-</c-><c- n>in</c-></i><c- o>&lt;</c-><c- n>schedule_result_t</c-><c- o>&lt;</c-><c- n>Sch</c-><c- o>></c-><c- p>,</c-> <c- n>Env</c-><c- o>></c-></code> shall be <code class="highlight">true</code>.</p>
    <li data-md>
     <p>None of a scheduler’s copy constructor, destructor, equality comparison, or <code class="highlight"><c- n>swap</c-></code> member functions shall exit via an exception.</p>
    <li data-md>
     <p>None of these member functions, nor a scheduler type’s <code class="highlight"><c- n>schedule</c-></code> function,
shall introduce data races as a result of concurrent invocations of those
functions from different threads.</p>
    <li data-md>
     <p>For any two (possibly <code class="highlight"><c- k>const</c-></code>) values <code class="highlight"><c- n>sch1</c-></code> and <code class="highlight"><c- n>sch2</c-></code> of some scheduler type <code class="highlight"><c- n>Sch</c-></code>, <code class="highlight"><c- n>sch1</c-> <c- o>==</c-> <c- n>sch2</c-></code> shall return <code class="highlight">true</code> only if both <code class="highlight"><c- n>sch1</c-></code> and <code class="highlight"><c- n>sch2</c-></code> share the
same associated execution resource.</p>
    <li data-md>
     <p>For a given scheduler expression <code class="highlight"><c- n>sch</c-></code>, the expression <code class="highlight"><c- n>get_completion_scheduler</c-><c- o>&lt;</c-><c- n>set_value_t</c-><c- o>></c-><c- p>(</c-><c- n>get_env</c-><c- p>(</c-><c- n>schedule</c-><c- p>(</c-><c- n>sch</c-><c- p>)))</c-></code> shall
compare equal to <code class="highlight"><c- n>sch</c-></code>.</p>
    <li data-md>
     <p>For a given scheduler expression <code class="highlight"><c- n>sch</c-></code>, if the expression <code class="highlight"><c- n>get_domain</c-><c- p>(</c-><c- n>sch</c-><c- p>)</c-></code> is well-formed, then the expression <code class="highlight"><c- n>get_domain</c-><c- p>(</c-><c- n>get_env</c-><c- p>(</c-><c- n>schedule</c-><c- p>(</c-><c- n>sch</c-><c- p>)))</c-></code> is also well-formed and has the same type.</p>
    <li data-md>
     <p>A scheduler type’s destructor shall not block pending completion of any
receivers connected to the sender objects returned from <code class="highlight"><c- n>schedule</c-></code>. <span class="wg21note">The ability to wait for completion of submitted function
objects can be provided by the associated execution resource of the
scheduler.</span></p>
   </ol>
   <h3 class="heading settled" data-level="11.7" id="spec-execution.receivers"><span class="secno">11.7. </span><span class="content">Receivers <b>[exec.recv]</b></span><a class="self-link" href="#spec-execution.receivers"></a></h3>
   <h4 class="heading settled" data-level="11.7.1" id="spec-execution.receiver_concepts"><span class="secno">11.7.1. </span><span class="content">Receiver concepts <b>[exec.recv.concepts]</b></span><a class="self-link" href="#spec-execution.receiver_concepts"></a></h4>
   <ol>
    <li data-md>
     <p>A receiver represents the continuation of an asynchronous operation. The <code class="highlight"><c- n>receiver</c-></code> concept defines the requirements for a receiver type
([async.ops]). The <code class="highlight"><c- n>receiver_of</c-></code> concept defines the requirements for a
receiver type that is usable as the first argument of a set of completion
operations corresponding to a set of completion signatures. The <code class="highlight"><c- n>get_env</c-></code> customization point is used to access a receiver’s associated environment.</p>
<pre class="highlight"><c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Rcvr</c-><c- o>></c->
  <c- k>concept</c-> <i><c- nc>is</c-><c- o>-</c-><c- n>receiver</c-></i> <c- o>=</c-> <c- c1>// exposition only</c->
    <c- n>derived_from</c-><c- o>&lt;</c-><c- k>typename</c-> <c- nc>Rcvr</c-><c- o>::</c-><c- n>receiver_concept</c-><c- p>,</c-> <c- n>receiver_t</c-><c- o>></c-><c- p>;</c->

<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Rcvr</c-><c- o>></c->
  <c- kr>inline</c-> <c- k>constexpr</c-> <c- b>bool</c-> <c- n>enable_receiver</c-> <c- o>=</c-> <i><c- n>is</c-><c- o>-</c-><c- n>receiver</c-></i><c- o>&lt;</c-><c- n>Rcvr</c-><c- o>></c-><c- p>;</c->

<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Rcvr</c-><c- o>></c->
  <c- k>concept</c-> <c- nc>receiver</c-> <c- o>=</c->
    <c- n>enable_receiver</c-><c- o>&lt;</c-><c- n>remove_cvref_t</c-><c- o>&lt;</c-><c- n>Rcvr</c-><c- o>>></c-> <c- o>&amp;&amp;</c->
    <c- k>requires</c-><c- p>(</c-><c- k>const</c-> <c- n>remove_cvref_t</c-><c- o>&lt;</c-><c- n>Rcvr</c-><c- o>>&amp;</c-> <c- n>rcvr</c-><c- p>)</c-> <c- p>{</c->
      <c- p>{</c-> <c- n>get_env</c-><c- p>(</c-><c- n>rcvr</c-><c- p>)</c-> <c- p>}</c-> <c- o>-></c-> <c- n>queryable</c-><c- p>;</c->
    <c- p>}</c-> <c- o>&amp;&amp;</c->
    <c- n>move_constructible</c-><c- o>&lt;</c-><c- n>remove_cvref_t</c-><c- o>&lt;</c-><c- n>Rcvr</c-><c- o>>></c-> <c- o>&amp;&amp;</c->  <i><c- c1>// rvalues are movable, and</c-></i>
    <c- n>constructible_from</c-><c- o>&lt;</c-><c- n>remove_cvref_t</c-><c- o>&lt;</c-><c- n>Rcvr</c-><c- o>></c-><c- p>,</c-> <c- n>Rcvr</c-><c- o>></c-><c- p>;</c-> <i><c- c1>// lvalues are copyable</c-></i>

<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Signature</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Rcvr</c-><c- o>></c->
  <c- k>concept</c-> <i><c- nc>valid</c-><c- o>-</c-><c- n>completion</c-><c- o>-</c-><c- k>for</c-></i> <c- o>=</c-> <i><c- c1>// exposition only</c-></i>
    <c- k>requires</c-> <c- p>(</c-><c- n>Signature</c-><c- o>*</c-> <c- n>sig</c-><c- p>)</c-> <c- p>{</c->
      <c- p>[]</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Tag</c-><c- p>,</c-> <c- k>class</c-><c- p>...</c-> <c- n>Args</c-><c- o>></c-><c- p>(</c-><c- n>Tag</c-><c- p>(</c-><c- o>*</c-><c- p>)(</c-><c- n>Args</c-><c- p>...))</c->
          <c- k>requires</c-> <i><c- n>callable</c-></i><c- o>&lt;</c-><c- n>Tag</c-><c- p>,</c-> <c- n>remove_cvref_t</c-><c- o>&lt;</c-><c- n>Rcvr</c-><c- o>></c-><c- p>,</c-> <c- n>Args</c-><c- p>...</c-><c- o>></c->
      <c- p>{}(</c-><c- n>sig</c-><c- p>);</c->
    <c- p>};</c->

<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Rcvr</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Completions</c-><c- o>></c->
  <c- k>concept</c-> <c- nc>receiver_of</c-> <c- o>=</c->
    <c- n>receiver</c-><c- o>&lt;</c-><c- n>Rcvr</c-><c- o>></c-> <c- o>&amp;&amp;</c->
    <c- k>requires</c-> <c- p>(</c-><c- n>Completions</c-><c- o>*</c-> <c- n>completions</c-><c- p>)</c-> <c- p>{</c->
      <c- p>[]</c-><c- o>&lt;</c-><i><c- n>valid</c-><c- o>-</c-><c- n>completion</c-><c- o>-</c-><c- k>for</c-></i><c- o>&lt;</c-><c- n>Rcvr</c-><c- o>></c-><c- p>...</c-><c- n>Sigs</c-><c- o>></c-><c- p>(</c-><c- n>completion_signatures</c-><c- o>&lt;</c-><c- n>Sigs</c-><c- p>...</c-><c- o>>*</c-><c- p>)</c->
      <c- p>{}(</c-><c- n>completions</c-><c- p>);</c->
    <c- p>};</c->
</pre>
    <li data-md>
     <p><i>Remarks:</i> Pursuant to [namespace.std], users can specialize <code class="highlight"><c- n>enable_receiver</c-></code> to <code class="highlight">true</code> for cv-unqualified program-defined types that model <code class="highlight"><c- n>receiver</c-></code>, and <code class="highlight">false</code> for types that do not. Such specializations shall be usable in constant
expressions ([expr.const]) and have type <code class="highlight"><c- k>const</c-> <c- b>bool</c-></code>.</p>
    <li data-md>
     <p>Let <code class="highlight"><c- n>rcvr</c-></code> be a receiver and let <code class="highlight"><c- n>op_state</c-></code> be an operation state associated
with an asynchronous operation created by connecting <code class="highlight"><c- n>rcvr</c-></code> with a sender. Let <code class="highlight"><c- n>token</c-></code> be a stop token equal to <code class="highlight"><c- n>get_stop_token</c-><c- p>(</c-><c- n>get_env</c-><c- p>(</c-><c- n>rcvr</c-><c- p>))</c-></code>. <code class="highlight"><c- n>token</c-></code> shall
remain valid for the duration of the asynchronous operation’s lifetime
([async.ops]). <span class="wg21note">This means that, unless it knows about
further guarantees provided by the type of receiver <code class="highlight"><c- n>rcvr</c-></code>, the implementation
of <code class="highlight"><c- n>op_state</c-></code> can not use <code class="highlight"><c- n>token</c-></code> after it executes a completion operation.
This also implies that any stop callbacks registered on <code class="highlight"><c- n>token</c-></code> must be
destroyed before the invocation of the completion operation.</span></p>
   </ol>
   <h4 class="heading settled" data-level="11.7.2" id="spec-execution.receivers.set_value"><span class="secno">11.7.2. </span><span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_value</c-></code> <b>[exec.set.value]</b></span><a class="self-link" href="#spec-execution.receivers.set_value"></a></h4>
   <ol>
    <li data-md>
     <p><code class="highlight"><c- n>set_value</c-></code> is a value completion function ([async.ops]). Its associated
completion tag is <code class="highlight"><c- n>set_value_t</c-></code>. The expression <code class="highlight"><c- n>set_value</c-><c- p>(</c-><c- n>rcvr</c-><c- p>,</c-> <c- n>vs</c-><c- p>...)</c-></code> for
some subexpression <code class="highlight"><c- n>rcvr</c-></code> and pack of subexpressions <code class="highlight"><c- n>vs</c-></code> is ill-formed if <code class="highlight"><c- n>rcvr</c-></code> is an lvalue or a <code class="highlight"><c- k>const</c-></code> rvalue. Otherwise, it is expression-equivalent to <code class="highlight"><i><c- n>mandate</c-><c- o>-</c-><c- n>nothrow</c-><c- o>-</c-><c- n>call</c-></i><c- p>(</c-><c- n>tag_invoke</c-><c- p>,</c-> <c- n>set_value</c-><c- p>,</c-> <c- n>rcvr</c-><c- p>,</c-> <c- n>vs</c-><c- p>...)</c-></code>.</p>
   </ol>
   <h4 class="heading settled" data-level="11.7.3" id="spec-execution.receivers.set_error"><span class="secno">11.7.3. </span><span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_error</c-></code> <b>[exec.set.error]</b></span><a class="self-link" href="#spec-execution.receivers.set_error"></a></h4>
   <ol>
    <li data-md>
     <p><code class="highlight"><c- n>set_error</c-></code> is an error completion function. Its associated completion tag is <code class="highlight"><c- n>set_error_t</c-></code>. The expression <code class="highlight"><c- n>set_error</c-><c- p>(</c-><c- n>rcvr</c-><c- p>,</c-> <c- n>err</c-><c- p>)</c-></code> for some subexpressions <code class="highlight"><c- n>rcvr</c-></code> and <code class="highlight"><c- n>err</c-></code> is ill-formed if <code class="highlight"><c- n>rcvr</c-></code> is an lvalue or a <code class="highlight"><c- k>const</c-></code> rvalue. Otherwise, it is
expression-equivalent to <code class="highlight"><i><c- n>mandate</c-><c- o>-</c-><c- n>nothrow</c-><c- o>-</c-><c- n>call</c-></i><c- p>(</c-><c- n>tag_invoke</c-><c- p>,</c-> <c- n>set_error</c-><c- p>,</c-> <c- n>rcvr</c-><c- p>,</c-> <c- n>err</c-><c- p>)</c-></code>.</p>
   </ol>
   <h4 class="heading settled" data-level="11.7.4" id="spec-execution.receivers.set_stopped"><span class="secno">11.7.4. </span><span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>set_stopped</c-></code> <b>[exec.set.stopped]</b></span><a class="self-link" href="#spec-execution.receivers.set_stopped"></a></h4>
   <ol>
    <li data-md>
     <p><code class="highlight"><c- n>set_stopped</c-></code> is a stopped completion function. Its associated completion tag
is <code class="highlight"><c- n>set_stopped_t</c-></code>.  The expression <code class="highlight"><c- n>set_stopped</c-><c- p>(</c-><c- n>rcvr</c-><c- p>)</c-></code> for some subexpression <code class="highlight"><c- n>rcvr</c-></code> is ill-formed if <code class="highlight"><c- n>rcvr</c-></code> is an lvalue or a <code class="highlight"><c- k>const</c-></code> rvalue. Otherwise, it is
expression-equivalent to <code class="highlight"><i><c- n>mandate</c-><c- o>-</c-><c- n>nothrow</c-><c- o>-</c-><c- n>call</c-></i><c- p>(</c-><c- n>tag_invoke</c-><c- p>,</c-> <c- n>set_stopped</c-><c- p>,</c-> <c- n>rcvr</c-><c- p>)</c-></code>.</p>
   </ol>
   <h3 class="heading settled" data-level="11.8" id="spec-execution.opstate"><span class="secno">11.8. </span><span class="content">Operation states <b>[exec.opstate]</b></span><a class="self-link" href="#spec-execution.opstate"></a></h3>
   <ol>
    <li data-md>
     <p>The <code class="highlight"><c- n>operation_state</c-></code> concept defines the requirements of an operation state
type ([async.ops]).</p>
<pre class="highlight"><c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>O</c-><c- o>></c->
  <c- k>concept</c-> <c- nc>operation_state</c-> <c- o>=</c->
    <c- n>queryable</c-><c- o>&lt;</c-><c- n>O</c-><c- o>></c-> <c- o>&amp;&amp;</c->
    <c- n>is_object_v</c-><c- o>&lt;</c-><c- n>O</c-><c- o>></c-> <c- o>&amp;&amp;</c->
    <c- k>requires</c-> <c- p>(</c-><c- n>O</c-><c- o>&amp;</c-> <c- n>o</c-><c- p>)</c-> <c- p>{</c->
      <c- p>{</c-> <c- n>start</c-><c- p>(</c-><c- n>o</c-><c- p>)</c-> <c- p>}</c-> <c- k>noexcept</c-><c- p>;</c->
    <c- p>};</c->
</pre>
    <li data-md>
     <p>If an <code class="highlight"><c- n>operation_state</c-></code> object is moved during the lifetime of its
asynchronous operation ([async.ops]), the behavior is undefined.</p>
    <li data-md>
     <p>Library-provided operation state types are non-movable.</p>
   </ol>
   <h4 class="heading settled" data-level="11.8.1" id="spec-execution.opstate.start"><span class="secno">11.8.1. </span><span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>start</c-></code> <b>[exec.opstate.start]</b></span><a class="self-link" href="#spec-execution.opstate.start"></a></h4>
   <ol>
    <li data-md>
     <p>The name <code class="highlight"><c- n>start</c-></code> denotes a customization point object that starts
([async.ops]) the asynchronous operation associated with the operation state
object. The expression <code class="highlight"><c- n>start</c-><c- p>(</c-><c- n>O</c-><c- p>)</c-></code> for some subexpression <code class="highlight"><c- n>O</c-></code> is ill-formed
if <code class="highlight"><c- n>O</c-></code> is an rvalue. Otherwise, it is expression-equivalent to:</p>
<pre class="highlight"><i><c- n>mandate</c-><c- o>-</c-><c- n>nothrow</c-><c- o>-</c-><c- n>call</c-></i><c- p>(</c-><c- n>tag_invoke</c-><c- p>,</c-> <c- n>start</c-><c- p>,</c-> <c- n>O</c-><c- p>)</c->
</pre>
    <li data-md>
     <p>If the function selected by <code class="highlight"><c- n>tag_invoke</c-></code> does not start the asynchronous
operation associated with the operation state <code class="highlight"><c- n>O</c-></code>, the behavior of calling <code class="highlight"><c- n>start</c-><c- p>(</c-><c- n>O</c-><c- p>)</c-></code> is undefined.</p>
   </ol>
   <h3 class="heading settled" data-level="11.9" id="spec-execution.senders"><span class="secno">11.9. </span><span class="content">Senders <b>[exec.snd]</b></span><a class="self-link" href="#spec-execution.senders"></a></h3>
   <h4 class="heading settled" data-level="11.9.1" id="spec-execution.senders.general"><span class="secno">11.9.1. </span><span class="content">General <b>[exec.snd.general]</b></span><a class="self-link" href="#spec-execution.senders.general"></a></h4>
   <ol>
    <li data-md>
     <p>For the purposes of this subclause, a sender is an object that satisfies the <code class="highlight"><c- n>sender</c-></code> concept ([async.ops]).</p>
    <li data-md>
     <p>Subclauses [exec.factories] and [exec.adapt] define customizable algorithms
that return senders. Each algorithm has a default implementation. Let <code class="highlight"><c- n>sndr</c-></code> be the result of an invocation of such an algorithm or an object equal to
such ([concepts.equality]), and let <code class="highlight"><c- n>Sndr</c-></code> be <code class="highlight"><c- k>decltype</c-><c- p>((</c-><c- n>sndr</c-><c- p>))</c-></code>. Let <code class="highlight"><c- n>rcvr</c-></code> be a receiver with associated environment <code class="highlight"><c- n>env</c-></code> of type <code class="highlight"><c- n>Env</c-></code> such that <code class="highlight"><c- n>sender_in</c-><c- o>&lt;</c-><c- n>Sndr</c-><c- p>,</c-> <c- n>Env</c-><c- o>></c-></code> is <code class="highlight">true</code>. For the default implementation of the
algorithm that produced <code class="highlight"><c- n>sndr</c-></code>, connecting <code class="highlight"><c- n>sndr</c-></code> to <code class="highlight"><c- n>rcvr</c-></code> and starting the
resulting operation state ([async.ops]) necessarily results in the potential
evaluation ([basic.def.odr]) of a set of completion operations whose first
argument is a subexpression equal to <code class="highlight"><c- n>rcvr</c-></code>. Let <code class="highlight"><c- n>Sigs</c-></code> be a pack of
completion signatures corresponding to this set of completion operations.
Then the type of the expression <code class="highlight"><c- n>get_completion_signatures</c-><c- p>(</c-><c- n>sndr</c-><c- p>,</c-> <c- n>env</c-><c- p>)</c-></code> is a
specialization of the class template <code class="highlight"><c- n>completion_signatures</c-></code>,
([exec.utils.cmplsigs]) the set of whose template arguments is <code class="highlight"><c- n>Sigs</c-></code>. If a
user-provided implementation of the algorithm that produced <code class="highlight"><c- n>sndr</c-></code> is
selected instead of the default, any completion signature that is in the set
of types denoted by <code class="highlight"><c- n>completion_signatures_of_t</c-><c- o>&lt;</c-><c- n>Sndr</c-><c- p>,</c-> <c- n>Env</c-><c- o>></c-></code> and that is not
part of <code class="highlight"><c- n>Sigs</c-></code> shall correspond to error or stopped completion operations,
unless otherwise specified.</p>
    <li data-md>
     <p>This subclause makes use of the following exposition-only entities.</p>
     <ol>
      <li data-md>
       <p>For a queryable object <code class="highlight"><c- n>env</c-></code>, let <code class="highlight"><i><c- n>FWD</c-><c- o>-</c-><c- n>ENV</c-></i><c- p>(</c-><c- n>env</c-><c- p>)</c-></code> be a
queryable object such that for a query object <code class="highlight"><c- n>q</c-></code> and a pack of
subexpressions <code class="highlight"><c- n>as</c-></code>, the expression <code class="highlight"><c- n>tag_invoke</c-><c- p>(</c-><c- n>q</c-><c- p>,</c-> <i><c- n>FWD</c-><c- o>-</c-><c- n>ENV</c-></i><c- p>(</c-><c- n>env</c-><c- p>),</c-> <c- n>as</c-><c- p>...)</c-></code> is ill-formed if <code class="highlight"><c- n>forwarding_query</c-><c- p>(</c-><c- n>q</c-><c- p>)</c-></code> is <code class="highlight">false</code>;
otherwise, it is expression-equivalent to <code class="highlight"><c- n>tag_invoke</c-><c- p>(</c-><c- n>q</c-><c- p>,</c-> <c- n>env</c-><c- p>,</c-> <c- n>as</c-><c- p>...)</c-></code>.</p>
      <li data-md>
       <p>For a query object <code class="highlight"><c- n>q</c-></code> and a subexpression <code class="highlight"><c- n>v</c-></code>, let <code class="highlight"><i><c- n>MAKE</c-><c- o>-</c-><c- n>ENV</c-></i><c- p>(</c-><c- n>q</c-><c- p>,</c-> <c- n>v</c-><c- p>)</c-></code> be a queryable object <code class="highlight"><c- n>env</c-></code> such that
the result of <code class="highlight"><c- n>tag_invoke</c-><c- p>(</c-><c- n>q</c-><c- p>,</c-> <c- n>env</c-><c- p>)</c-></code> has a value equal to <code class="highlight"><c- n>v</c-></code> ([concepts.equality]). Unless otherwise stated, the object to which <code class="highlight"><c- n>tag_invoke</c-><c- p>(</c-><c- n>q</c-><c- p>,</c-> <c- n>env</c-><c- p>)</c-></code> refers remains valid while <code class="highlight"><c- n>env</c-></code> remains valid.</p>
      <li data-md>
       <p>For two queryable objects <code class="highlight"><c- n>env1</c-></code> and <code class="highlight"><c- n>env2</c-></code>, a query object <code class="highlight"><c- n>q</c-></code> and a
pack of subexpressions <code class="highlight"><c- n>as</c-></code>, let <code class="highlight"><i><c- n>JOIN</c-><c- o>-</c-><c- n>ENV</c-></i><c- p>(</c-><c- n>env1</c-><c- p>,</c-> <c- n>env2</c-><c- p>)</c-></code> be a queryable object <code class="highlight"><c- n>env3</c-></code> such that <code class="highlight"><c- n>tag_invoke</c-><c- p>(</c-><c- n>q</c-><c- p>,</c-> <c- n>env3</c-><c- p>,</c-> <c- n>as</c-><c- p>...)</c-></code> is expression-equivalent to:</p>
       <ul>
        <li data-md>
         <p><code class="highlight"><c- n>tag_invoke</c-><c- p>(</c-><c- n>q</c-><c- p>,</c-> <c- n>env1</c-><c- p>,</c-> <c- n>as</c-><c- p>...)</c-></code> if that expression is well-formed,</p>
        <li data-md>
         <p>otherwise, <code class="highlight"><c- n>tag_invoke</c-><c- p>(</c-><c- n>q</c-><c- p>,</c-> <c- n>env2</c-><c- p>,</c-> <c- n>as</c-><c- p>...)</c-></code> if that expression is
  well-formed,</p>
        <li data-md>
         <p>otherwise, <code class="highlight"><c- n>tag_invoke</c-><c- p>(</c-><c- n>q</c-><c- p>,</c-> <c- n>env3</c-><c- p>,</c-> <c- n>as</c-><c- p>...)</c-></code> is ill-formed.</p>
       </ul>
      <li data-md>
       <p>The expansions of <i><code class="highlight"><c- n>FWD</c-><c- o>-</c-><c- n>ENV</c-></code></i>, <i><code class="highlight"><c- n>MAKE</c-><c- o>-</c-><c- n>ENV</c-></code></i>, and <i><code class="highlight"><c- n>JOIN</c-><c- o>-</c-><c- n>ENV</c-></code></i> can be context-dependent; <em>i.e.</em>, they can expand to
expressions with different types and value categories in different
contexts for the same arguments.</p>
      <li data-md>
       <p>For a scheduler <code class="highlight"><c- n>sch</c-></code>, let <code class="highlight"><i><c- n>SCHED</c-><c- o>-</c-><c- n>ATTRS</c-></i><c- p>(</c-><c- n>sch</c-><c- p>)</c-></code> be a
queryable object <code class="highlight"><c- n>o1</c-></code> such that <code class="highlight"><c- n>tag_invoke</c-><c- p>(</c-><c- n>get_completion_scheduler</c-><c- o>&lt;</c-><i><c- n>Tag</c-></i><c- o>></c-><c- p>,</c-> <c- n>o1</c-><c- p>)</c-></code> is a
prvalue with the same type and value as <code class="highlight"><c- n>sch</c-></code> where <i><code class="highlight"><c- n>Tag</c-></code></i> is one
of <code class="highlight"><c- n>set_value_t</c-></code> or <code class="highlight"><c- n>set_stopped_t</c-></code>; and let <code class="highlight"><c- n>tag_invoke</c-><c- p>(</c-><c- n>get_domain</c-><c- p>,</c-> <c- n>o1</c-><c- p>)</c-></code> be expression-equivalent to <code class="highlight"><c- n>tag_invoke</c-><c- p>(</c-><c- n>get_domain</c-><c- p>,</c-> <c- n>sch</c-><c- p>)</c-></code>. Let <code class="highlight"><i><c- n>SCHED</c-><c- o>-</c-><c- n>ENV</c-></i><c- p>(</c-><c- n>sch</c-><c- p>)</c-></code> be a queryable object <code class="highlight"><c- n>o2</c-></code> such that <code class="highlight"><c- n>tag_invoke</c-><c- p>(</c-><c- n>get_scheduler</c-><c- p>,</c-> <c- n>o2</c-><c- p>)</c-></code> is a prvalue with the same
type and value as <code class="highlight"><c- n>sch</c-></code>, and let <code class="highlight"><c- n>tag_invoke</c-><c- p>(</c-><c- n>get_domain</c-><c- p>,</c-> <c- n>o2</c-><c- p>)</c-></code> be expression-equivalent to <code class="highlight"><c- n>tag_invoke</c-><c- p>(</c-><c- n>get_domain</c-><c- p>,</c-> <c- n>sch</c-><c- p>)</c-></code>.</p>
      <li data-md>
       <p>For two subexpressions <code class="highlight"><c- n>rcvr</c-></code> and <code class="highlight"><c- n>expr</c-></code>, let <code class="highlight"><i><c- n>SET</c-><c- o>-</c-><c- n>VALUE</c-></i><c- p>(</c-><c- n>rcvr</c-><c- p>,</c-> <c- n>expr</c-><c- p>)</c-></code> be <code class="highlight"><c- p>(</c-><c- n>expr</c-><c- p>,</c-> <c- n>set_value</c-><c- p>(</c-><c- n>rcvr</c-><c- p>))</c-></code> if the type of <code class="highlight"><c- n>expr</c-></code> is <code class="highlight"><c- b>void</c-></code>;
otherwise, it is <code class="highlight"><c- n>set_value</c-><c- p>(</c-><c- n>rcvr</c-><c- p>,</c-> <c- n>expr</c-><c- p>)</c-></code>. Let <code class="highlight"><i><c- n>TRY</c-><c- o>-</c-><c- n>EVAL</c-></i><c- p>(</c-><c- n>rcvr</c-><c- p>,</c-> <c- n>expr</c-><c- p>)</c-></code> be:</p>
<pre class="highlight"><c- k>try</c-> <c- p>{</c->
  <c- n>expr</c-><c- p>;</c->
<c- p>}</c-> <c- k>catch</c-><c- p>(...)</c-> <c- p>{</c->
  <c- n>set_error</c-><c- p>(</c-><c- n>rcvr</c-><c- p>,</c-> <c- n>current_exception</c-><c- p>());</c->
<c- p>}</c->
</pre>
       <p>if <code class="highlight"><c- n>expr</c-></code> is potentially-throwing; otherwise, <code class="highlight"><c- n>expr</c-></code>. Let <code class="highlight"><i><c- n>TRY</c-><c- o>-</c-><c- n>SET</c-><c- o>-</c-><c- n>VALUE</c-></i><c- p>(</c-><c- n>rcvr</c-><c- p>,</c-> <c- n>expr</c-><c- p>)</c-></code> be <code class="highlight"><i><c- n>TRY</c-><c- o>-</c-><c- n>EVAL</c-></i><c- p>(</c-><c- n>rcvr</c-><c- p>,</c-> <i><c- n>SET</c-><c- o>-</c-><c- n>VALUE</c-></i><c- p>(</c-><c- n>rcvr</c-><c- p>,</c-> <c- n>expr</c-><c- p>))</c-></code> except that <code class="highlight"><c- n>rcvr</c-></code> is evaluated only once.</p>
      <li data-md>
<pre class="highlight"><c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Default</c-> <c- o>=</c-> <c- n>default_domain</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Sndr</c-><c- o>></c->
<c- k>constexpr</c-> <c- k>auto</c-> <i><c- n>completion</c-><c- o>-</c-><c- n>domain</c-></i><c- p>(</c-><c- k>const</c-> <c- n>Sndr</c-><c- o>&amp;</c-> <c- n>sndr</c-><c- p>)</c-> <c- k>noexcept</c-><c- p>;</c->
</pre>
       <ol>
        <li data-md>
         <p><em>Effects:</em> Let <code class="highlight"><i><c- n>COMPL</c-><c- o>-</c-><c- n>DOMAIN</c-></i><c- p>(</c-><c- n>T</c-><c- p>)</c-></code> be the type of the expression <code class="highlight"><c- n>get_domain</c-><c- p>(</c-><c- n>get_completion_scheduler</c-><c- o>&lt;</c-><c- n>T</c-><c- o>></c-><c- p>(</c-><c- n>get_env</c-><c- p>(</c-><c- n>sndr</c-><c- p>)))</c-></code>. If <code class="highlight"><i><c- n>COMPL</c-><c- o>-</c-><c- n>DOMAIN</c-></i><c- p>(</c-><c- n>set_value_t</c-><c- p>)</c-></code>, <code class="highlight"><i><c- n>COMPL</c-><c- o>-</c-><c- n>DOMAIN</c-></i><c- p>(</c-><c- n>set_error_t</c-><c- p>)</c-></code>, and <code class="highlight"><i><c- n>COMPL</c-><c- o>-</c-><c- n>DOMAIN</c-></i><c- p>(</c-><c- n>set_stopped_t</c-><c- p>)</c-></code> all share a common type
[meta.trans.other] (ignoring those types that are ill-formed), then <code class="highlight"><i><c- n>completion</c-><c- o>-</c-><c- n>domain</c-></i><c- o>&lt;</c-><c- n>Default</c-><c- o>></c-><c- p>(</c-><c- n>sndr</c-><c- p>)</c-></code> is a default-constructed
prvalue of that type.
Otherwise, if all of those types are ill-formed, <code class="highlight"><i><c- n>completion</c-><c- o>-</c-><c- n>domain</c-></i><c- o>&lt;</c-><c- n>Default</c-><c- o>></c-><c- p>(</c-><c- n>sndr</c-><c- p>)</c-></code> is a default-constructed
prvalue of type <code class="highlight"><c- n>Default</c-></code>.
Otherwise, <code class="highlight"><i><c- n>completion</c-><c- o>-</c-><c- n>domain</c-></i><c- o>&lt;</c-><c- n>Default</c-><c- o>></c-><c- p>(</c-><c- n>sndr</c-><c- p>)</c-></code> is ill-formed.</p>
       </ol>
      <li data-md>
<pre class="highlight"><c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Tag</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Env</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Default</c-><c- o>></c->
<c- k>constexpr</c-> <c- k>decltype</c-><c- p>(</c-><c- k>auto</c-><c- p>)</c-> <i><c- n>query</c-><c- o>-</c-><c- n>with</c-><c- o>-</c-><c- k>default</c-></i><c- p>(</c-><c- n>Tag</c-><c- p>,</c-> <c- k>const</c-> <c- n>Env</c-><c- o>&amp;</c-> <c- n>env</c-><c- p>,</c-> <c- n>Default</c-><c- o>&amp;&amp;</c-> <c- n>value</c-><c- p>)</c-> <c- k>noexcept</c-><c- p>(</c-><i><c- n>see</c-> <c- n>below</c-></i><c- p>);</c->
</pre>
       <ol>
        <li data-md>
         <p><i>Effects:</i> Equivalent to:</p>
         <ul>
          <li data-md>
           <p><code class="highlight"><c- k>return</c-> <c- n>Tag</c-><c- p>()(</c-><c- n>env</c-><c- p>);</c-></code> if that expression is well-formed,</p>
          <li data-md>
           <p><code class="highlight"><c- k>return</c-> <c- k>static_cast</c-><c- o>&lt;</c-><c- n>Default</c-><c- o>></c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>Default</c-><c- o>></c-><c- p>(</c-><c- n>value</c-><c- p>));</c-></code> otherwise.</p>
         </ul>
        <li data-md>
         <p><i>Remarks:</i> The expression in the <code class="highlight"><c- k>noexcept</c-></code> clause is:</p>
<pre class="highlight"><c- n>is_invocable_v</c-><c- o>&lt;</c-><c- n>Tag</c-><c- p>,</c-> <c- k>const</c-> <c- n>Env</c-><c- o>&amp;></c-> <c- o>?</c-> <c- n>is_nothrow_invocable_v</c-><c- o>&lt;</c-><c- n>Tag</c-><c- p>,</c-> <c- k>const</c-> <c- n>Env</c-><c- o>&amp;></c->
                                <c- o>:</c-> <c- n>is_nothrow_constructible_v</c-><c- o>&lt;</c-><c- n>Default</c-><c- p>,</c-> <c- n>Default</c-><c- o>></c->
</pre>
       </ol>
      <li data-md>
<pre class="highlight"><c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Sndr</c-><c- o>></c->
<c- k>constexpr</c-> <c- k>auto</c-> <i><c- n>get</c-><c- o>-</c-><c- n>domain</c-><c- o>-</c-><c- n>early</c-></i><c- p>(</c-><c- k>const</c-> <c- n>Sndr</c-><c- o>&amp;</c-> <c- n>sndr</c-><c- p>)</c-> <c- k>noexcept</c-><c- p>;</c->
</pre>
       <ol>
        <li data-md>
         <p><i>Effects:</i> Equivalent to <code class="highlight"><c- k>return</c-> <i><c- n>Domain</c-></i><c- p>();</c-></code> where <i><code class="highlight"><c- n>Domain</c-></code></i> is the decayed type of the first of the following
expressions that is well-formed:</p>
         <ul>
          <li data-md>
           <p><code class="highlight"><c- n>get_domain</c-><c- p>(</c-><c- n>get_env</c-><c- p>(</c-><c- n>sndr</c-><c- p>))</c-></code></p>
          <li data-md>
           <p><code class="highlight"><i><c- n>completion</c-><c- o>-</c-><c- n>domain</c-></i><c- p>(</c-><c- n>sndr</c-><c- p>)</c-></code></p>
          <li data-md>
           <p><code class="highlight"><c- n>default_domain</c-><c- p>()</c-></code></p>
         </ul>
       </ol>
      <li data-md>
<pre class="highlight"><c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Sndr</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Env</c-><c- o>></c->
<c- k>constexpr</c-> <c- k>auto</c-> <i><c- n>get</c-><c- o>-</c-><c- n>domain</c-><c- o>-</c-><c- n>late</c-></i><c- p>(</c-><c- k>const</c-> <c- n>Sndr</c-><c- o>&amp;</c-> <c- n>sndr</c-><c- p>,</c-> <c- k>const</c-> <c- n>Env</c-><c- o>&amp;</c-> <c- n>env</c-><c- p>)</c-> <c- k>noexcept</c-><c- p>;</c->
</pre>
       <ol>
        <li data-md>
         <p><i>Effects:</i> Equivalent to:</p>
         <ul>
          <li data-md>
           <p>If <code class="highlight"><i><c- n>sender</c-><c- o>-</c-><c- k>for</c-></i><c- o>&lt;</c-><c- n>Sndr</c-><c- p>,</c-> <c- n>transfer_t</c-><c- o>></c-></code> is <code class="highlight">true</code>,
then <code class="highlight"><c- k>return</c-> <i><c- n>Domain</c-></i><c- p>();</c-></code> where <i><code class="highlight"><c- n>Domain</c-></code></i> is
the type of the following expression:</p>
<pre class="highlight"><c- p>[]</c-> <c- p>{</c->
  <c- k>auto</c-> <c- p>[</c-><i><c- n>ignore1</c-></i><c- p>,</c-> <c- n>sch</c-><c- p>,</c-> <i><c- n>ignore2</c-></i><c- p>]</c-> <c- o>=</c-> <c- n>sndr</c-><c- p>;</c->
  <c- k>return</c-> <i><c- n>query</c-><c- o>-</c-><c- n>or</c-><c- o>-</c-><c- k>default</c-></i><c- p>(</c-><c- n>get_domain</c-><c- p>,</c-> <c- n>sch</c-><c- p>,</c-> <c- n>default_domain</c-><c- p>());</c->
<c- p>}();</c->
</pre>
          <li data-md>
           <p>Otherwise, <code class="highlight"><c- k>return</c-> <i><c- n>Domain</c-></i><c- p>();</c-></code> where <i><code class="highlight"><c- n>Domain</c-></code></i> is
the first of the following expressions that is well-formed and has class
type:</p>
           <ul>
            <li data-md>
             <p><code class="highlight"><c- n>get_domain</c-><c- p>(</c-><c- n>get_env</c-><c- p>(</c-><c- n>sndr</c-><c- p>))</c-></code></p>
            <li data-md>
             <p><code class="highlight"><i><c- n>completion</c-><c- o>-</c-><c- n>domain</c-></i><c- o>&lt;</c-><c- b>void</c-><c- o>></c-><c- p>(</c-><c- n>sndr</c-><c- p>)</c-></code></p>
            <li data-md>
             <p><code class="highlight"><c- n>get_domain</c-><c- p>(</c-><c- n>env</c-><c- p>)</c-></code></p>
            <li data-md>
             <p><code class="highlight"><c- n>get_domain</c-><c- p>(</c-><c- n>get_scheduler</c-><c- p>(</c-><c- n>env</c-><c- p>))</c-></code></p>
            <li data-md>
             <p><code class="highlight"><c- n>default_domain</c-><c- p>()</c-></code>.</p>
           </ul>
         </ul>
         <p><span class="wg21note">The <code class="highlight"><c- n>transfer</c-></code> algorithm is unique in that it ignores the
execution domain of its predecessor, using only the domain of its
destination scheduler to select a customization.</span></p>
       </ol>
      <li data-md>
<pre class="highlight"><c- k>template</c-><c- o>&lt;</c-><i><c- n>callable</c-></i> <c- n>Fun</c-><c- o>></c->
  <c- k>requires</c-> <c- n>is_nothrow_move_constructible_v</c-><c- o>&lt;</c-><c- n>Fun</c-><c- o>></c->
<c- k>struct</c-> <i><c- nc>emplace</c-><c- o>-</c-><c- n>from</c-></i> <c- p>{</c-> <c- c1>// exposition only</c->
  <c- n>Fun</c-> <i><c- n>fun</c-></i><c- p>;</c-> <c- c1>// exposition only</c->
  <c- k>using</c-> <c- n>type</c-> <c- o>=</c-> <i><c- n>call</c-><c- o>-</c-><c- n>result</c-><c- o>-</c-><c- n>t</c-></i><c- o>&lt;</c-><c- n>Fun</c-><c- o>></c-><c- p>;</c->

  <c- k>constexpr</c-> <c- k>operator</c-> <c- n>type</c-><c- p>()</c-> <c- o>&amp;&amp;</c-> <c- k>noexcept</c-><c- p>(</c-><i><c- n>nothrow</c-><c- o>-</c-><c- n>callable</c-></i><c- o>&lt;</c-><c- n>Fun</c-><c- o>></c-><c- p>)</c-> <c- p>{</c->
    <c- k>return</c-> <c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><i><c- n>fun</c-></i><c- p>)();</c->
  <c- p>}</c->

  <c- k>constexpr</c-> <c- n>type</c-> <c- k>operator</c-><c- p>()()</c-> <c- o>&amp;&amp;</c-> <c- k>noexcept</c-><c- p>(</c-><i><c- n>nothrow</c-><c- o>-</c-><c- n>callable</c-></i><c- o>&lt;</c-><c- n>Fun</c-><c- o>></c-><c- p>)</c-> <c- p>{</c->
    <c- k>return</c-> <c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><i><c- n>fun</c-></i><c- p>)();</c->
  <c- p>}</c->
<c- p>};</c->
</pre>
       <ol>
        <li data-md>
         <p><span class="wg21note"><i><code class="highlight"><c- n>emplace</c-><c- o>-</c-><c- n>from</c-></code></i> is used to emplace
non-movable types into containers like <code class="highlight"><c- n>tuple</c-></code>, <code class="highlight"><c- n>optional</c-></code>, and <code class="highlight"><c- n>variant</c-></code>.</span></p>
       </ol>
      <li data-md>
<pre class="highlight"><c- k>struct</c-> <i><c- nc>on</c-><c- o>-</c-><c- n>stop</c-><c- o>-</c-><c- n>request</c-></i> <c- p>{</c->
  <c- n>in_place_stop_source</c-><c- o>&amp;</c-> <c- n>stop_src</c-><c- p>;</c->
  <c- b>void</c-> <c- nf>operator</c-><c- p>()()</c-> <c- k>noexcept</c-> <c- p>{</c-> <c- n>stop_src</c-><c- p>.</c-><c- n>request_stop</c-><c- p>();</c-> <c- p>}</c->
<c- p>};</c->
</pre>
      <li data-md>
<pre class="highlight"><c- k>template</c-><c- o>&lt;</c-><c- k>class</c-><c- p>...</c-> <c- n>T</c-><c- o>></c->
<c- k>struct</c-> <i><c- nc>product</c-><c- o>-</c-><c- n>type</c-></i> <c- p>{</c->
  <c- k>using</c-> <c- n>type</c-><sub><i><c- n>0</c-></i></sub> <c- o>=</c-> <c- n>T</c-><sub><i><c- n>0</c-></i></sub><c- p>;</c->      <c- c1>// exposition only</c->
  <c- k>using</c-> <c- n>type</c-><sub><i><c- n>1</c-></i></sub> <c- o>=</c-> <c- n>T</c-><sub><i><c- n>1</c-></i></sub><c- p>;</c->      <c- c1>// exposition only</c->
    <c- p>...</c->
  <c- k>using</c-> <c- n>type</c-><sub><i><c- n>n</c-><c- mi>-1</c-></i></sub> <c- o>=</c-> <c- n>T</c-><sub><i><c- n>n</c-><c- mi>-1</c-></i></sub><c- p>;</c->   <c- c1>// exposition only</c->

  <c- n>T</c-><sub><i><c- n>0</c-></i></sub> <i><c- n>t</c-><sub><c- n>0</c-></sub></i><c- p>;</c->      <c- c1>// exposition only</c->
  <c- n>T</c-><sub><i><c- n>1</c-></i></sub> <i><c- n>t</c-><sub><c- n>1</c-></sub></i><c- p>;</c->      <c- c1>// exposition only</c->
    <c- p>...</c->
  <c- n>T</c-><sub><i><c- n>n</c-><c- mi>-1</c-></i></sub> <i><c- n>t</c-><sub><c- n>n</c-><c- mi>-1</c-></sub></i><c- p>;</c->   <c- c1>// exposition only</c->
<c- p>};</c->
</pre>
       <ol>
        <li data-md>
         <p><span class="wg21note">An expression of type <code class="highlight"><i><c- n>product</c-><c- o>-</c-><c- n>type</c-></i></code> is usable as the initializer of a
structured binding declaration [dcl.struct.bind].</span></p>
       </ol>
      <li data-md>
<pre class="highlight"><c- k>template</c-> <c- o>&lt;</c-><c- n>semiregular</c-> <c- n>Tag</c-><c- p>,</c-> <i><c- n>movable</c-><c- o>-</c-><c- n>value</c-></i> <c- n>Data</c-> <c- o>=</c-> <i><c- n>see</c-> <c- n>below</c-></i><c- p>,</c-> <c- n>sender</c-><c- p>...</c-> <c- n>Child</c-><c- o>></c->
<c- k>constexpr</c-> <c- k>auto</c-> <i><c- n>make</c-><c- o>-</c-><c- n>sender</c-></i><c- p>(</c-><c- n>Tag</c-><c- p>,</c-> <c- n>Data</c-><c- o>&amp;&amp;</c-> <c- n>data</c-><c- p>,</c-> <c- n>Child</c-><c- o>&amp;&amp;</c-><c- p>...</c-> <c- n>child</c-><c- p>);</c->
</pre>
       <ol>
        <li data-md>
         <p><em>Remarks:</em> The default template argument for the <code class="highlight"><c- n>Data</c-></code> template parameter
denotes an unspecified empty trivial class type.</p>
        <li data-md>
         <p><em>Returns:</em> A prvalue of type <code class="highlight"><i><c- n>basic</c-><c- o>-</c-><c- n>sender</c-></i><c- o>&lt;</c-><c- n>Tag</c-><c- p>,</c-> <c- n>decay_t</c-><c- o>&lt;</c-><c- n>Data</c-><c- o>></c-><c- p>,</c-> <c- n>decay_t</c-><c- o>&lt;</c-><c- n>Child</c-><c- o>></c-><c- p>...</c-><c- o>></c-></code> where the <code class="highlight"><i><c- n>tag</c-></i></code> member has been default-initialized and the <code class="highlight"><i><c- n>data</c-></i></code> and <code class="highlight"><i><c- n>child</c-><sub><c- n>n</c-></sub></i><c- p>...</c-></code> members have
been direct initialized from their respective forwarded arguments, where <code class="highlight"><i><c- n>basic</c-><c- o>-</c-><c- n>sender</c-></i></code> is the following exposition-only class template
except as noted below:</p>
<pre class="highlight"><c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>T</c-><c- p>,</c-> <c- k>class</c-><c- p>...</c-> <c- n>Us</c-><c- o>></c->
<c- k>concept</c-> <i><c- nc>one</c-><c- o>-</c-><c- n>of</c-></i> <c- o>=</c-> <c- p>(</c-><c- n>same_as</c-><c- o>&lt;</c-><c- n>T</c-><c- p>,</c-> <c- n>Us</c-><c- o>></c-> <c- o>||</c-><c- p>...);</c-> <c- c1>// exposition only</c->

<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Tag</c-><c- o>></c->
<c- k>concept</c-> <i><c- nc>completion</c-><c- o>-</c-><c- n>tag</c-></i> <c- o>=</c-> <c- c1>// exposition only</c->
  <i><c- n>one</c-><c- o>-</c-><c- n>of</c-></i><c- o>&lt;</c-><c- n>Tag</c-><c- p>,</c-> <c- n>set_value_t</c-><c- p>,</c-> <c- n>set_error_t</c-><c- p>,</c-> <c- n>set_stopped_t</c-><c- o>></c-><c- p>;</c->

<c- k>template</c-><c- o>&lt;</c-><c- k>template</c-><c- o>&lt;</c-><c- k>class</c-><c- p>...</c-><c- o>></c-> <c- k>class</c-> <c- nc>T</c-><c- p>,</c-> <c- k>class</c-><c- p>...</c-> <c- n>Args</c-><c- o>></c->
<c- k>concept</c-> <i><c- nc>well</c-><c- o>-</c-><c- n>formed</c-></i> <c- o>=</c-> <c- k>requires</c-> <c- p>{</c-> <c- k>typename</c-> <c- nc>T</c-><c- o>&lt;</c-><c- n>Args</c-><c- p>...</c-><c- o>></c-><c- p>;</c-> <c- p>};</c-> <c- c1>// exposition only</c->

<c- k>template</c-><c- o>&lt;</c-><c- k>const</c-> <c- k>auto</c-><c- o>&amp;</c-> <c- n>Fun</c-><c- p>,</c-> <c- k>class</c-><c- p>...</c-> <c- n>Args</c-><c- o>></c->
<c- k>concept</c-> <i><c- nc>cpo</c-><c- o>-</c-><c- n>callable</c-></i> <c- o>=</c-> <i><c- n>callable</c-></i><c- o>&lt;</c-><c- k>decltype</c-><c- p>(</c-><c- n>Fun</c-><c- p>),</c-> <c- n>Args</c-><c- p>...</c-><c- o>></c-><c- p>;</c-> <c- c1>// exposition only</c->

<c- k>template</c-><c- o>&lt;</c-><c- k>const</c-> <c- k>auto</c-><c- o>&amp;</c-> <c- n>Fun</c-><c- p>,</c-> <c- k>class</c-><c- p>...</c-> <c- n>Args</c-><c- o>></c->
<c- k>using</c-> <i><c- n>cpo</c-><c- o>-</c-><c- n>result</c-><c- o>-</c-><c- n>t</c-></i> <c- o>=</c-> <i><c- n>call</c-><c- o>-</c-><c- n>result</c-><c- o>-</c-><c- n>t</c-></i><c- o>&lt;</c-><c- k>decltype</c-><c- p>(</c-><c- n>Fun</c-><c- p>),</c-> <c- n>Args</c-><c- p>...</c-><c- o>></c-><c- p>;</c-> <c- c1>// exposition only</c->

<c- k>struct</c-> <i><c- nc>default</c-><c- o>-</c-><c- n>impls</c-></i> <c- p>{</c->  <c- c1>// exposition only</c->
  <c- k>static</c-> <c- k>constexpr</c-> <c- k>auto</c-> <i><c- n>get</c-><c- o>-</c-><c- n>attrs</c-></i> <c- o>=</c-> <i><c- n>see</c-> <c- n>below</c-></i><c- p>;</c->
  <c- k>static</c-> <c- k>constexpr</c-> <c- k>auto</c-> <i><c- n>get</c-><c- o>-</c-><c- n>env</c-></i> <c- o>=</c-> <i><c- n>see</c-> <c- n>below</c-></i><c- p>;</c->
  <c- k>static</c-> <c- k>constexpr</c-> <c- k>auto</c-> <i><c- n>get</c-><c- o>-</c-><c- n>state</c-></i> <c- o>=</c-> <i><c- n>see</c-> <c- n>below</c-></i><c- p>;</c->
  <c- k>static</c-> <c- k>constexpr</c-> <c- k>auto</c-> <i><c- n>start</c-></i> <c- o>=</c-> <i><c- n>see</c-> <c- n>below</c-></i><c- p>;</c->
  <c- k>static</c-> <c- k>constexpr</c-> <c- k>auto</c-> <i><c- n>complete</c-></i> <c- o>=</c-> <i><c- n>see</c-> <c- n>below</c-></i><c- p>;</c->
<c- p>};</c->

<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Tag</c-><c- o>></c->
<c- k>struct</c-> <i><c- nc>impls</c-><c- o>-</c-><c- k>for</c-></i> <c- o>:</c-> <i><c- k>default</c-><c- o>-</c-><c- n>impls</c-></i> <c- p>{};</c-> <c- c1>// exposition only</c->

<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Sndr</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Rcvr</c-><c- o>></c-> <c- c1>// exposition only</c->
<c- k>using</c-> <i><c- n>state</c-><c- o>-</c-><c- n>type</c-></i> <c- o>=</c-> <c- n>decay_t</c-><c- o>&lt;</c-><i><c- n>cpo</c-><c- o>-</c-><c- n>result</c-><c- o>-</c-><c- n>t</c-></i><c- o>&lt;</c->
  <i><c- n>impls</c-><c- o>-</c-><c- k>for</c-></i><c- o>&lt;</c-><c- n>tag_of_t</c-><c- o>&lt;</c-><c- n>Sndr</c-><c- o>>>::</c-><i><c- n>get</c-><c- o>-</c-><c- n>state</c-></i><c- p>,</c-> <c- n>Sndr</c-><c- p>,</c-> <c- n>Rcvr</c-><c- o>&amp;>></c-><c- p>;</c->

<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Index</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Sndr</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Rcvr</c-><c- o>></c-> <c- c1>// exposition only</c->
<c- k>using</c-> <i><c- n>env</c-><c- o>-</c-><c- n>type</c-></i> <c- o>=</c-> <i><c- n>cpo</c-><c- o>-</c-><c- n>result</c-><c- o>-</c-><c- n>t</c-></i><c- o>&lt;</c->
  <i><c- n>impls</c-><c- o>-</c-><c- k>for</c-></i><c- o>&lt;</c-><c- n>tag_of_t</c-><c- o>&lt;</c-><c- n>Sndr</c-><c- o>>>::</c-><i><c- n>get</c-><c- o>-</c-><c- n>env</c-></i><c- p>,</c-> <c- n>Index</c-><c- p>,</c->
  <i><c- n>state</c-><c- o>-</c-><c- n>type</c-></i><c- o>&lt;</c-><c- n>Sndr</c-><c- p>,</c-> <c- n>Rcvr</c-><c- o>>&amp;</c-><c- p>,</c-> <c- k>const</c-> <c- n>Rcvr</c-><c- o>&amp;>></c-><c- p>;</c->

<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Sndr</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Rcvr</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Index</c-><c- o>></c->  <c- c1>// arguments are not associated entities ([lib.tmpl-heads])</c->
  <c- k>requires</c-> <i><c- n>well</c-><c- o>-</c-><c- n>formed</c-></i><c- o>&lt;</c-><i><c- n>env</c-><c- o>-</c-><c- n>type</c-></i><c- p>,</c-> <c- n>Index</c-><c- p>,</c-> <c- n>Sndr</c-><c- p>,</c-> <c- n>Rcvr</c-><c- o>></c->
<c- k>struct</c-> <i><c- nc>basic</c-><c- o>-</c-><c- n>receiver</c-></i> <c- p>{</c->  <c- c1>// exposition only</c->
  <c- k>using</c-> <c- n>tag_t</c-> <c- o>=</c-> <c- n>tag_of_t</c-><c- o>&lt;</c-><c- n>Sndr</c-><c- o>></c-><c- p>;</c-> <c- c1>// exposition only</c->
  <c- k>using</c-> <c- n>receiver_concept</c-> <c- o>=</c-> <c- n>receiver_t</c-><c- p>;</c->

  <c- k>template</c-><c- o>&lt;</c-><i><c- n>completion</c-><c- o>-</c-><c- n>tag</c-></i> <c- n>Tag</c-><c- p>,</c-> <c- k>class</c-><c- p>...</c-> <c- n>Args</c-><c- o>></c->
    <c- k>requires</c-> <i><c- n>cpo</c-><c- o>-</c-><c- n>callable</c-></i><c- o>&lt;</c-><i><c- n>impls</c-><c- o>-</c-><c- k>for</c-></i><c- o>&lt;</c-><c- n>tag_t</c-><c- o>>::</c-><i><c- n>complete</c-></i><c- p>,</c->
      <c- n>Index</c-><c- p>,</c-> <i><c- n>state</c-><c- o>-</c-><c- n>type</c-></i><c- o>&lt;</c-><c- n>Sndr</c-><c- p>,</c-> <c- n>Rcvr</c-><c- o>>&amp;</c-><c- p>,</c-> <c- n>Rcvr</c-><c- o>&amp;</c-><c- p>,</c-> <c- n>Tag</c-><c- p>,</c-> <c- n>Args</c-><c- p>...</c-><c- o>></c->
  <c- k>friend</c-> <c- b>void</c-> <c- n>tag_invoke</c-><c- p>(</c-><c- n>Tag</c-><c- p>,</c-> <i><c- n>basic</c-><c- o>-</c-><c- n>receiver</c-></i><c- o>&amp;&amp;</c-> <c- n>self</c-><c- p>,</c-> <c- n>Args</c-><c- o>&amp;&amp;</c-><c- p>...</c-> <c- n>args</c-><c- p>)</c-> <c- k>noexcept</c-> <c- p>{</c->
    <c- p>(</c-><c- b>void</c-><c- p>)</c-> <i><c- n>impls</c-><c- o>-</c-><c- k>for</c-></i><c- o>&lt;</c-><c- n>tag_t</c-><c- o>>::</c-><i><c- n>complete</c-></i><c- p>(</c->
      <c- n>Index</c-><c- p>(),</c-> <c- n>self</c-><c- p>.</c-><c- n>op_</c-><c- o>-></c-><c- n>state_</c-><c- p>,</c-> <c- n>self</c-><c- p>.</c-><c- n>op_</c-><c- o>-></c-><c- n>rcvr_</c-><c- p>,</c-> <c- n>Tag</c-><c- p>(),</c-> <c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>Args</c-><c- o>></c-><c- p>(</c-><c- n>args</c-><c- p>)...);</c->
  <c- p>}</c->

  <c- k>template</c-><c- o>&lt;</c-><c- n>same_as</c-><c- o>&lt;</c-><c- n>get_env_t</c-><c- o>></c-> <c- n>Tag</c-><c- o>></c->
  <c- k>friend</c-> <c- k>auto</c-> <c- n>tag_invoke</c-><c- p>(</c-><c- n>Tag</c-><c- p>,</c-> <c- k>const</c-> <i><c- n>basic</c-><c- o>-</c-><c- n>receiver</c-></i><c- o>&amp;</c-> <c- n>self</c-><c- p>)</c-> <c- k>noexcept</c->
    <c- o>-></c-> <i><c- n>env</c-><c- o>-</c-><c- n>type</c-></i><c- o>&lt;</c-><c- n>Index</c-><c- p>,</c-> <c- n>Sndr</c-><c- p>,</c-> <c- n>Rcvr</c-><c- o>></c-> <c- p>{</c->
    <c- k>const</c-> <c- k>auto</c-><c- o>&amp;</c-> <c- n>rcvr</c-> <c- o>=</c-> <c- n>self</c-><c- p>.</c-><c- n>op_</c-><c- o>-></c-><c- n>rcvr_</c-><c- p>;</c->
    <c- k>return</c-> <i><c- n>impls</c-><c- o>-</c-><c- k>for</c-></i><c- o>&lt;</c-><c- n>tag_t</c-><c- o>>::</c-><i><c- n>get</c-><c- o>-</c-><c- n>env</c-></i><c- p>(</c-><c- n>Index</c-><c- p>(),</c-> <c- n>self</c-><c- p>.</c-><c- n>op_</c-><c- o>-></c-><c- n>state_</c-><c- p>,</c-> <c- n>rcvr</c-><c- p>);</c->
  <c- p>}</c->

  <i><c- n>basic</c-><c- o>-</c-><c- n>operation</c-></i><c- o>&lt;</c-><c- n>Sndr</c-><c- p>,</c-> <c- n>Rcvr</c-><c- o>>*</c-> <c- n>op_</c-><c- p>;</c-> <c- c1>// exposition only</c->
<c- p>};</c->

<c- k>constexpr</c-> <c- k>auto</c-> <i><c- n>connect</c-><c- o>-</c-><c- n>all</c-></i> <c- o>=</c->   <c- c1>// exposition only</c->
  <c- p>[]</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Sndr</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Rcvr</c-><c- p>,</c-> <c- b>size_t</c-><c- p>...</c-> <c- n>Is</c-><c- o>></c-><c- p>(</c->
    <i><c- n>basic</c-><c- o>-</c-><c- n>operation</c-></i><c- o>&lt;</c-><c- n>Sndr</c-><c- p>,</c-> <c- n>Rcvr</c-><c- o>>*</c-> <c- n>op</c-><c- p>,</c-> <c- n>Sndr</c-><c- o>&amp;&amp;</c-> <c- n>sndr</c-><c- p>,</c-> <c- n>index_sequence</c-><c- o>&lt;</c-><c- n>Is</c-><c- p>...</c-><c- o>></c-><c- p>)</c->
      <c- k>noexcept</c-><c- p>(</c-> <i><b><c- n>TODO</c-></b></i> <c- p>)</c-> <c- k>requires</c-> <c- p>(</c-> <i><b><c- n>TODO</c-></b></i> <c- p>)</c-> <c- p>{</c->
      <c- k>auto</c-><c- o>&amp;&amp;</c-> <c- p>[</c-><c- n>ign1</c-><c- p>,</c-> <c- n>ign2</c-><c- p>,</c-> <c- p>...</c-><c- n>child</c-><c- p>]</c-> <c- o>=</c-> <c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>Sndr</c-><c- o>></c-><c- p>(</c-><c- n>sndr</c-><c- p>);</c->
      <c- k>return</c-> <i><c- n>product</c-><c- o>-</c-><c- n>type</c-></i><c- p>{</c-><c- n>connect</c-><c- p>(</c->
        <c- n>std</c-><c- o>::</c-><c- n>forward_like</c-><c- o>&lt;</c-><c- n>Sndr</c-><c- o>></c-><c- p>(</c-><c- n>child</c-><c- p>),</c->
        <i><c- n>basic</c-><c- o>-</c-><c- n>receiver</c-></i><c- o>&lt;</c-><c- n>Sndr</c-><c- p>,</c-> <c- n>Rcvr</c-><c- p>,</c-> <c- n>integral_constant</c-><c- o>&lt;</c-><c- b>size_t</c-><c- p>,</c-> <c- n>Is</c-><c- o>>></c-><c- p>{</c-><c- n>op</c-><c- p>})...};</c->
    <c- p>};</c->

<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Sndr</c-><c- o>></c->
<c- k>using</c-> <i><c- n>indices</c-><c- o>-</c-><c- k>for</c-></i> <c- o>=</c-> <c- n>make_index_sequence</c-><c- o>&lt;</c-><c- n>tuple_size_v</c-><c- o>&lt;</c-><c- n>Sndr</c-><c- o>></c-><c- mi>-2</c-><c- o>></c-><c- p>;</c-> <c- c1>// exposition only</c->

<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Sndr</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Rcvr</c-><c- o>></c->
<c- k>using</c-> <i><c- n>inner</c-><c- o>-</c-><c- n>ops</c-><c- o>-</c-><c- n>tuple</c-></i> <c- o>=</c->   <c- c1>// exposition only</c->
  <i><c- n>cpo</c-><c- o>-</c-><c- n>result</c-><c- o>-</c-><c- n>t</c-></i><c- o>&lt;</c-><i><c- n>connect</c-><c- o>-</c-><c- n>all</c-></i><c- p>,</c-> <i><c- n>basic</c-><c- o>-</c-><c- n>operation</c-></i><c- o>&lt;</c-><c- n>Sndr</c-><c- p>,</c-> <c- n>Rcvr</c-><c- o>>*</c-><c- p>,</c-> <c- n>Sndr</c-><c- p>,</c->
    <i><c- n>indices</c-><c- o>-</c-><c- k>for</c-></i><c- o>&lt;</c-><c- n>Sndr</c-><c- o>>></c-><c- p>;</c->

<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Sndr</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Rcvr</c-><c- o>></c-> <c- c1>// arguments are not associated entities ([lib.tmpl-heads])</c->
  <c- k>requires</c-> <i><c- n>well</c-><c- o>-</c-><c- n>formed</c-></i><c- o>&lt;</c-><i><c- n>state</c-><c- o>-</c-><c- n>type</c-></i><c- p>,</c-> <c- n>Sndr</c-><c- p>,</c-> <c- n>Rcvr</c-><c- o>></c-> <c- o>&amp;&amp;</c->
    <i><c- n>well</c-><c- o>-</c-><c- n>formed</c-></i><c- o>&lt;</c-><i><c- n>inner</c-><c- o>-</c-><c- n>ops</c-><c- o>-</c-><c- n>tuple</c-></i><c- p>,</c-> <c- n>Sndr</c-><c- p>,</c-> <c- n>Rcvr</c-><c- o>></c->
<c- k>struct</c-> <i><c- nc>basic</c-><c- o>-</c-><c- n>operation</c-></i> <c- p>{</c->  <c- c1>// exposition only</c->
  <c- k>using</c-> <c- n>tag_t</c-> <c- o>=</c-> <c- n>tag_of_t</c-><c- o>&lt;</c-><c- n>Sndr</c-><c- o>></c-><c- p>;</c-> <c- c1>// exposition only</c->

  <c- n>Rcvr</c-> <c- n>rcvr_</c-><c- p>;</c-> <c- c1>// exposition only</c->
  <i><c- n>state</c-><c- o>-</c-><c- n>type</c-></i><c- o>&lt;</c-><c- n>Sndr</c-><c- p>,</c-> <c- n>Rcvr</c-><c- o>></c-> <c- n>state_</c-><c- p>;</c-> <c- c1>// exposition only</c->
  <i><c- n>inner</c-><c- o>-</c-><c- n>ops</c-><c- o>-</c-><c- n>tuple</c-></i><c- o>&lt;</c-><c- n>Sndr</c-><c- p>,</c-> <c- n>Rcvr</c-><c- o>></c-> <c- n>inner_ops_</c-><c- p>;</c-> <c- c1>// exposition only</c->

  <i><c- n>basic</c-><c- o>-</c-><c- n>operation</c-></i><c- p>(</c-><c- n>Sndr</c-><c- o>&amp;&amp;</c-> <c- n>sndr</c-><c- p>,</c-> <c- n>Rcvr</c-> <c- n>rcvr</c-><c- p>)</c->  <c- c1>// exposition only</c->
    <c- o>:</c-> <c- n>rcvr_</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>rcvr</c-><c- p>))</c->
    <c- p>,</c-> <c- n>state_</c-><c- p>(</c-><i><c- n>impls</c-><c- o>-</c-><c- k>for</c-></i><c- o>&lt;</c-><c- n>tag_t</c-><c- o>>::</c-><i><c- n>get</c-><c- o>-</c-><c- n>state</c-></i><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>Sndr</c-><c- o>></c-><c- p>(</c-><c- n>sndr</c-><c- p>),</c-> <c- n>rcvr_</c-><c- p>))</c->
    <c- p>,</c-> <c- n>inner_ops_</c-><c- p>(</c-><i><c- n>connect</c-><c- o>-</c-><c- n>all</c-></i><c- p>(</c-><c- k>this</c-><c- p>,</c-> <c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>Sndr</c-><c- o>></c-><c- p>(</c-><c- n>sndr</c-><c- p>),</c-> <i><c- n>indices</c-><c- o>-</c-><c- k>for</c-></i><c- o>&lt;</c-><c- n>Sndr</c-><c- o>></c-><c- p>()))</c->
  <c- p>{}</c->

  <c- k>friend</c-> <c- b>void</c-> <c- n>tag_invoke</c-><c- p>(</c-><c- n>start_t</c-><c- p>,</c-> <i><c- n>basic</c-><c- o>-</c-><c- n>operation</c-></i><c- o>&amp;</c-> <c- n>self</c-><c- p>)</c-> <c- k>noexcept</c-> <c- p>{</c->
    <c- k>auto</c-><c- o>&amp;</c-> <c- p>[...</c-><c- n>ops</c-><c- p>]</c-> <c- o>=</c-> <c- n>self</c-><c- p>.</c-><c- n>inner_ops_</c-><c- p>;</c->
    <i><c- n>impls</c-><c- o>-</c-><c- k>for</c-></i><c- o>&lt;</c-><c- n>tag_t</c-><c- o>>::</c-><i><c- n>start</c-></i><c- p>(</c-><c- n>self</c-><c- p>.</c-><c- n>state_</c-><c- p>,</c-> <c- n>self</c-><c- p>.</c-><c- n>rcvr_</c-><c- p>,</c-> <c- n>ops</c-><c- p>...);</c->
  <c- p>}</c->
<c- p>};</c->

<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Sndr</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Env</c-><c- o>></c->
<c- k>using</c-> <i><c- n>completion</c-><c- o>-</c-><c- n>signatures</c-><c- o>-</c-><c- k>for</c-></i> <c- o>=</c->  <i><c- n>see</c-> <c- n>below</c-></i><c- p>;</c-> <c- c1>// exposition only</c->

<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Tag</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Data</c-><c- p>,</c-> <c- k>class</c-><c- p>...</c-> <c- n>Child</c-><c- o>></c-> <c- c1>// arguments are not associated entities ([lib.tmpl-heads])</c->
<c- k>struct</c-> <i><c- nc>basic</c-><c- o>-</c-><c- n>sender</c-></i> <c- p>{</c->  <c- c1>// exposition only</c->
  <c- k>using</c-> <c- n>sender_concept</c-> <c- o>=</c-> <c- n>sender_t</c-><c- p>;</c->

  <c- k>template</c-><c- o>&lt;</c-><c- n>same_as</c-><c- o>&lt;</c-><c- n>get_env_t</c-><c- o>></c-> <c- n>GetEnvTag</c-><c- o>></c->
  <c- k>friend</c-> <c- k>decltype</c-><c- p>(</c-><c- k>auto</c-><c- p>)</c-> <c- n>tag_invoke</c-><c- p>(</c-><c- n>GetEnvTag</c-><c- p>,</c-> <c- k>const</c-> <i><c- n>basic</c-><c- o>-</c-><c- n>sender</c-></i><c- o>&amp;</c-> <c- n>self</c-><c- p>)</c-> <c- k>noexcept</c-> <c- p>{</c->
    <c- k>return</c-> <i><c- n>impls</c-><c- o>-</c-><c- k>for</c-></i><c- o>&lt;</c-><c- n>Tag</c-><c- o>>::</c-><i><c- n>get</c-><c- o>-</c-><c- n>attrs</c-></i><c- p>(</c-><i><c- n>data</c-></i><c- p>,</c-> <i><c- n>child</c-><sub><c- n>0</c-></sub></i><c- p>,</c-> <c- p>...</c-> <i><c- n>child</c-><sub><c- n>n</c-><c- mi>-1</c-></sub></i><c- p>);</c->
  <c- p>}</c->

  <c- k>template</c-><c- o>&lt;</c-><c- n>same_as</c-><c- o>&lt;</c-><c- n>connect_t</c-><c- o>></c-> <c- n>ConnectTag</c-><c- p>,</c->
           <i><c- n>decays</c-><c- o>-</c-><c- n>to</c-></i><c- o>&lt;</c-><i><c- n>basic</c-><c- o>-</c-><c- n>sender</c-></i><c- o>></c-> <c- n>Self</c-><c- p>,</c-> <c- n>receiver</c-> <c- n>Rcvr</c-><c- o>></c->
  <c- k>friend</c-> <c- k>auto</c-> <c- n>tag_invoke</c-><c- p>(</c-><c- n>ConnectTag</c-><c- p>,</c-> <c- n>Self</c-><c- o>&amp;&amp;</c-> <c- n>self</c-><c- p>,</c-> <c- n>Rcvr</c-> <c- n>rcvr</c-><c- p>)</c->
    <c- o>-></c-> <i><c- n>basic</c-><c- o>-</c-><c- n>operation</c-></i><c- o>&lt;</c-><c- n>Self</c-><c- p>,</c-> <c- n>Rcvr</c-><c- o>></c-> <c- p>{</c->
    <c- k>return</c-> <c- p>{</c-><c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>Self</c-><c- o>></c-><c- p>(</c-><c- n>self</c-><c- p>),</c-> <c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>rcvr</c-><c- p>)};</c->
  <c- p>}</c->

  <c- k>template</c-><c- o>&lt;</c-><c- n>same_as</c-><c- o>&lt;</c-><c- n>get_completion_signatures_t</c-><c- o>></c-> <c- n>GetComplSigsTag</c-><c- p>,</c->
           <i><c- n>decays</c-><c- o>-</c-><c- n>to</c-></i><c- o>&lt;</c-><i><c- n>basic</c-><c- o>-</c-><c- n>sender</c-></i><c- o>></c-> <c- n>Self</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Env</c-><c- o>></c->
  <c- k>friend</c-> <c- k>auto</c-> <c- n>tag_invoke</c-><c- p>(</c-><c- n>GetComplSigsTag</c-><c- p>,</c-> <c- n>Self</c-><c- o>&amp;&amp;</c-> <c- n>self</c-><c- p>,</c-> <c- n>Env</c-><c- o>&amp;&amp;</c-> <c- n>env</c-><c- p>)</c-> <c- k>noexcept</c->
    <c- o>-></c-> <i><c- n>completion</c-><c- o>-</c-><c- n>signatures</c-><c- o>-</c-><c- k>for</c-></i><c- o>&lt;</c-><c- n>Self</c-><c- p>,</c-> <c- n>Env</c-><c- o>></c-> <c- p>{</c->
    <c- k>return</c-> <c- p>{};</c->
  <c- p>}</c->

  <c- n>Tag</c-> <i><c- n>tag</c-></i><c- p>;</c->            <c- c1>// exposition only</c->
  <c- n>Data</c-> <i><c- n>data</c-></i><c- p>;</c->          <c- c1>// exposition only</c->
  <c- n>Child</c-><sub><i><c- n>0</c-></i></sub> <i><c- n>child</c-><sub><c- n>0</c-></sub></i><c- p>;</c->      <c- c1>// exposition only</c->
  <c- n>Child</c-><sub><i><c- n>1</c-></i></sub> <i><c- n>child</c-><sub><c- n>1</c-></sub></i><c- p>;</c->      <c- c1>// exposition only</c->
    <c- p>...</c->
  <c- n>Child</c-><sub><i><c- n>n</c-><c- mi>-1</c-></i></sub> <i><c- n>child</c-><sub><c- n>n</c-><c- mi>-1</c-></sub></i><c- p>;</c->   <c- c1>// exposition only</c->
<c- p>};</c->

<c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-> <c- nc>Sndr</c-><c- o>></c->
<c- k>using</c-> <i><c- n>data</c-><c- o>-</c-><c- n>type</c-></i> <c- o>=</c-> <c- k>decltype</c-><c- p>((</c-><c- n>declval</c-><c- o>&lt;</c-><c- n>Sndr</c-><c- o>></c-><c- p>().</c-><i><c- n>data</c-></i><c- p>));</c-> <c- c1>// exposition only</c->

<c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-> <c- nc>Sndr</c-><c- p>,</c-> <c- b>size_t</c-> <c- n>N</c-> <c- o>=</c-> <c- mi>0</c-><c- o>></c->
<c- k>using</c-> <i><c- n>child</c-><c- o>-</c-><c- n>type</c-></i> <c- o>=</c-> <c- k>decltype</c-><c- p>((</c-><c- n>declval</c-><c- o>&lt;</c-><c- n>Sndr</c-><c- o>></c-><c- p>().</c-><i><c- n>child</c-><sub><c- n>N</c-></sub></i><c- p>));</c-> <c- c1>// exposition only</c->
</pre>
        <li data-md>
         <p>It is unspecified whether instances of <code class="highlight"><i><c- n>basic</c-><c- o>-</c-><c- n>sender</c-></i></code> can be
aggregate initialized.</p>
        <li data-md>
         <p><span class="wg21note">An expression of type <code class="highlight"><i><c- n>basic</c-><c- o>-</c-><c- n>sender</c-></i></code> is usable as the
initializer of a structured binding declaration
[dcl.struct.bind].</span></p>
        <li data-md>
         <p>The member <code class="highlight"><i><c- k>default</c-><c- o>-</c-><c- n>impls</c-></i><c- o>::</c-><i><c- n>get</c-><c- o>-</c-><c- n>attrs</c-></i></code> is initialized
with a callable object equivalent to the following lambda:</p>
<pre class="highlight"><c- p>[](</c-><c- k>const</c-> <c- k>auto</c-><c- o>&amp;</c-> <c- n>data</c-><c- p>,</c-> <c- k>const</c-> <c- k>auto</c-><c- o>&amp;</c-><c- p>...</c-> <c- n>child</c-><c- p>)</c-> <c- k>noexcept</c-> <c- o>-></c-> <c- k>decltype</c-><c- p>(</c-><c- k>auto</c-><c- p>)</c-> <c- p>{</c->
  <c- k>if</c-> <c- k>constexpr</c-> <c- p>(</c-><c- k>sizeof</c-><c- p>...(</c-><c- n>child</c-><c- p>)</c-> <c- o>==</c-> <c- mi>1</c-><c- p>)</c->
    <c- k>return</c-> <i><c- n>FWD</c-><c- o>-</c-><c- n>ENV</c-></i><c- p>(</c-><c- n>get_env</c-><c- p>(</c-><c- n>child</c-><c- p>...));</c-> <c- c1>//</c->
  <c- k>else</c->
    <c- k>return</c-> <c- n>empty_env</c-><c- p>();</c->
<c- p>}</c->
</pre>
        <li data-md>
         <p>The member <code class="highlight"><i><c- k>default</c-><c- o>-</c-><c- n>impls</c-></i><c- o>::</c-><i><c- n>get</c-><c- o>-</c-><c- n>env</c-></i></code> is initialized
with a callable object equivalent to the following lambda:</p>
<pre class="highlight"><c- p>[]</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Rcvr</c-><c- o>></c-><c- p>(</c-><c- k>auto</c-> <c- n>index</c-><c- p>,</c-> <c- k>auto</c-><c- o>&amp;</c-> <c- n>state</c-><c- p>,</c-> <c- k>const</c-> <c- n>Rcvr</c-><c- o>&amp;</c-> <c- n>rcvr</c-><c- p>)</c-> <c- k>noexcept</c->
  <c- o>-></c-> <c- k>decltype</c-><c- p>(</c-><i><c- n>FWD</c-><c- o>-</c-><c- n>ENV</c-></i><c- p>(</c-><c- n>get_env</c-><c- p>(</c-><c- n>rcvr</c-><c- p>)))</c-> <c- p>{</c->
  <c- k>return</c-> <i><c- n>FWD</c-><c- o>-</c-><c- n>ENV</c-></i><c- p>(</c-><c- n>get_env</c-><c- p>(</c-><c- n>rcvr</c-><c- p>));</c->
<c- p>}</c->
</pre>
        <li data-md>
         <p>The member <code class="highlight"><i><c- k>default</c-><c- o>-</c-><c- n>impls</c-></i><c- o>::</c-><i><c- n>get</c-><c- o>-</c-><c- n>state</c-></i></code> is initialized
with a callable object equivalent to the following lambda:</p>
<pre class="highlight"><c- p>[]</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Sndr</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Rcvr</c-><c- o>></c-><c- p>(</c-><c- n>Sndr</c-><c- o>&amp;&amp;</c-> <c- n>sndr</c-><c- p>,</c-> <c- n>Rcvr</c-><c- o>&amp;</c-> <c- n>rcvr</c-><c- p>)</c-> <c- k>noexcept</c-> <c- o>-></c-> <c- k>decltype</c-><c- p>(</c-><c- k>auto</c-><c- p>)</c-> <c- p>{</c->
  <c- k>return</c-> <c- n>get</c-><c- o>&lt;</c-><c- mi>1</c-><c- o>></c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>Sndr</c-><c- o>></c-><c- p>(</c-><c- n>sndr</c-><c- p>));</c->
<c- p>}</c->
</pre>
        <li data-md>
         <p>The member <code class="highlight"><i><c- k>default</c-><c- o>-</c-><c- n>impls</c-></i><c- o>::</c-><i><c- n>start</c-></i></code> is initialized
with a callable object equivalent to the following lambda:</p>
<pre class="highlight"><c- p>[](</c-><c- k>auto</c-><c- o>&amp;</c-> <c- n>state</c-><c- p>,</c-> <c- k>auto</c-><c- o>&amp;</c-> <c- n>rcvr</c-><c- p>,</c-> <c- k>auto</c-><c- o>&amp;</c-><c- p>...</c-> <c- n>ops</c-><c- p>)</c-> <c- k>noexcept</c-> <c- o>-></c-> <c- b>void</c-> <c- p>{</c->
  <c- p>(</c-><c- n>execution</c-><c- o>::</c-><c- n>start</c-><c- p>(</c-><c- n>ops</c-><c- p>),</c-> <c- p>...);</c->
<c- p>}</c->
</pre>
        <li data-md>
         <p>The member <code class="highlight"><i><c- k>default</c-><c- o>-</c-><c- n>impls</c-></i><c- o>::</c-><i><c- n>complete</c-></i></code> is initialized
with a callable object equivalent to the following lambda:</p>
<pre class="highlight"><c- p>[]</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Index</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Rcvr</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Tag</c-><c- p>,</c-> <c- k>class</c-><c- p>...</c-> <c- n>Args</c-><c- o>></c-><c- p>(</c->
  <c- n>Index</c-><c- p>,</c-> <c- k>auto</c-><c- o>&amp;</c-> <c- n>state</c-><c- p>,</c-> <c- n>Rcvr</c-><c- o>&amp;</c-> <c- n>rcvr</c-><c- p>,</c-> <c- n>Tag</c-><c- p>,</c-> <c- n>Args</c-><c- o>&amp;&amp;</c-><c- p>...</c-> <c- n>args</c-><c- p>)</c-> <c- k>noexcept</c->
    <c- o>-></c-> <c- b>void</c-> <c- k>requires</c-> <i><c- n>callable</c-></i><c- o>&lt;</c-><c- n>Tag</c-><c- p>,</c-> <c- n>Rcvr</c-><c- p>,</c-> <c- n>Args</c-><c- p>...</c-><c- o>></c-> <c- p>{</c->
  <i><c- c1>// Mandates: Index::value == 0</c-></i>
  <c- n>Tag</c-><c- p>()(</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>rcvr</c-><c- p>),</c-> <c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>Args</c-><c- o>></c-><c- p>(</c-><c- n>args</c-><c- p>)...);</c->
<c- p>}</c->
</pre>
        <li data-md>
         <p>For a subexpression <code class="highlight"><c- n>sndr</c-></code> let <code class="highlight"><c- n>Sndr</c-></code> be <code class="highlight"><c- k>decltype</c-><c- p>((</c-><c- n>sndr</c-><c- p>))</c-></code>. Let <code class="highlight"><c- n>rcvr</c-></code> be a receiver that has an associated environment of type <code class="highlight"><c- n>Env</c-></code> such that <code class="highlight"><c- n>sender_in</c-><c- o>&lt;</c-><c- n>Sndr</c-><c- p>,</c-> <c- n>Env</c-><c- o>></c-></code> is <code class="highlight">true</code>. <code class="highlight"><i><c- n>completion</c-><c- o>-</c-><c- n>signatures</c-><c- o>-</c-><c- k>for</c-></i><c- o>&lt;</c-><c- n>Sndr</c-><c- p>,</c-> <c- n>Env</c-><c- o>></c-></code> denotes
a specialization of <code class="highlight"><c- n>completion_signatures</c-></code>, the set of whose
template arguments correspond to the set of completion operations
that are potentially evaluated as a result of calling <code class="highlight"><c- n>start</c-></code> on the
operation state that results from connecting <code class="highlight"><c- n>sndr</c-></code> and <code class="highlight"><c- n>rcvr</c-></code>. When <code class="highlight"><c- n>sender_in</c-><c- o>&lt;</c-><c- n>Sndr</c-><c- p>,</c-> <c- n>Env</c-><c- o>></c-></code> is <code class="highlight">false</code>, the type denoted by <code class="highlight"><i><c- n>completion</c-><c- o>-</c-><c- n>signatures</c-><c- o>-</c-><c- k>for</c-></i><c- o>&lt;</c-><c- n>Sndr</c-><c- p>,</c-> <c- n>Env</c-><c- o>></c-></code>, if any,
is not a specialization of <code class="highlight"><c- n>completion_signatures</c-></code>.</p>
         <p><em>Recommended practice:</em> When <code class="highlight"><c- n>sender_in</c-><c- o>&lt;</c-><c- n>Sndr</c-><c- p>,</c-> <c- n>Env</c-><c- o>></c-></code> is <code class="highlight">false</code>,
implementations are encouraged to use the type denoted by <code class="highlight"><i><c- n>completion</c-><c- o>-</c-><c- n>signatures</c-><c- o>-</c-><c- k>for</c-></i><c- o>&lt;</c-><c- n>Sndr</c-><c- p>,</c-> <c- n>Env</c-><c- o>></c-></code> to
communicate to users why.</p>
       </ol>
     </ol>
   </ol>
   <h4 class="heading settled" data-level="11.9.2" id="spec-execution.snd.concepts"><span class="secno">11.9.2. </span><span class="content">Sender concepts <b>[exec.snd.concepts]</b></span><a class="self-link" href="#spec-execution.snd.concepts"></a></h4>
   <ol>
    <li data-md>
     <p>The <code class="highlight"><c- n>sender</c-></code> concept defines the requirements for a sender type
([async.ops]). The <code class="highlight"><c- n>sender_in</c-></code> concept defines the requirements for a sender
type that can create asynchronous operations given an associated environment
type. The <code class="highlight"><c- n>sender_to</c-></code> concept defines the requirements for a sender type
that can connect with a specific receiver type. The <code class="highlight"><c- n>get_env</c-></code> customization
point object is used to access a sender’s associated attributes. The <code class="highlight"><c- n>connect</c-></code> customization point object is used to connect ([async.ops]) a
sender and a receiver to produce an operation state.</p>
<pre class="highlight"><c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Sigs</c-><c- o>></c->
  <c- k>concept</c-> <i><c- nc>valid</c-><c- o>-</c-><c- n>completion</c-><c- o>-</c-><c- n>signatures</c-></i> <c- o>=</c-> <i><c- n>see</c-> <c- n>below</c-></i><c- p>;</c-> <c- c1>// exposition only</c->

<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Sndr</c-><c- o>></c->
  <c- k>concept</c-> <i><c- nc>is</c-><c- o>-</c-><c- n>sender</c-></i> <c- o>=</c-> <c- c1>// exposition only</c->
    <c- n>derived_from</c-><c- o>&lt;</c-><c- k>typename</c-> <c- nc>Sndr</c-><c- o>::</c-><c- n>sender_concept</c-><c- p>,</c-> <c- n>sender_t</c-><c- o>></c-><c- p>;</c->

<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Sndr</c-><c- o>></c->
  <c- kr>inline</c-> <c- k>constexpr</c-> <c- b>bool</c-> <c- n>enable_sender</c-> <c- o>=</c-> <i><c- n>is</c-><c- o>-</c-><c- n>sender</c-></i><c- o>&lt;</c-><c- n>Sndr</c-><c- o>></c-><c- p>;</c->

<c- k>template</c-><c- o>&lt;</c-><i><c- n>is</c-><c- o>-</c-><c- n>awaitable</c-></i><c- o>&lt;</c-><i><c- n>env</c-><c- o>-</c-><c- n>promise</c-></i><c- o>&lt;</c-><c- n>empty_env</c-><c- o>>></c-> <c- n>Sndr</c-><c- o>></c-> <i><c- c1>// [exec.awaitables]</c-></i>
  <c- kr>inline</c-> <c- k>constexpr</c-> <c- b>bool</c-> <c- n>enable_sender</c-><c- o>&lt;</c-><c- n>Sndr</c-><c- o>></c-> <c- o>=</c-> true<c- p>;</c->

<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Sndr</c-><c- o>></c->
  <c- k>concept</c-> <c- nc>sender</c-> <c- o>=</c->
    <c- n>enable_sender</c-><c- o>&lt;</c-><c- n>remove_cvref_t</c-><c- o>&lt;</c-><c- n>Sndr</c-><c- o>>></c-> <c- o>&amp;&amp;</c->
    <c- k>requires</c-> <c- p>(</c-><c- k>const</c-> <c- n>remove_cvref_t</c-><c- o>&lt;</c-><c- n>Sndr</c-><c- o>>&amp;</c-> <c- n>sndr</c-><c- p>)</c-> <c- p>{</c->
      <c- p>{</c-> <c- n>get_env</c-><c- p>(</c-><c- n>sndr</c-><c- p>)</c-> <c- p>}</c-> <c- o>-></c-> <c- n>queryable</c-><c- p>;</c->
    <c- p>}</c-> <c- o>&amp;&amp;</c->
    <c- n>move_constructible</c-><c- o>&lt;</c-><c- n>remove_cvref_t</c-><c- o>&lt;</c-><c- n>Sndr</c-><c- o>>></c-> <c- o>&amp;&amp;</c->  <i><c- c1>// rvalues are movable, and</c-></i>
    <c- n>constructible_from</c-><c- o>&lt;</c-><c- n>remove_cvref_t</c-><c- o>&lt;</c-><c- n>Sndr</c-><c- o>></c-><c- p>,</c-> <c- n>Sndr</c-><c- o>></c-><c- p>;</c-> <i><c- c1>// lvalues are copyable</c-></i>

<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Sndr</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Env</c-> <c- o>=</c-> <c- n>empty_env</c-><c- o>></c->
  <c- k>concept</c-> <c- nc>sender_in</c-> <c- o>=</c->
    <c- n>sender</c-><c- o>&lt;</c-><c- n>Sndr</c-><c- o>></c-> <c- o>&amp;&amp;</c->
    <c- n>queryable</c-><c- o>&lt;</c-><c- n>Env</c-><c- o>></c-> <c- o>&amp;&amp;</c->
    <c- k>requires</c-> <c- p>(</c-><c- n>Sndr</c-><c- o>&amp;&amp;</c-> <c- n>sndr</c-><c- p>,</c-> <c- n>Env</c-><c- o>&amp;&amp;</c-> <c- n>env</c-><c- p>)</c-> <c- p>{</c->
      <c- p>{</c-> <c- n>get_completion_signatures</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>Sndr</c-><c- o>></c-><c- p>(</c-><c- n>sndr</c-><c- p>),</c-> <c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>Env</c-><c- o>></c-><c- p>(</c-><c- n>env</c-><c- p>))</c-> <c- p>}</c-> <c- o>-></c->
        <i><c- n>valid</c-><c- o>-</c-><c- n>completion</c-><c- o>-</c-><c- n>signatures</c-></i><c- p>;</c->
    <c- p>};</c->

<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Sndr</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Rcvr</c-><c- o>></c->
  <c- k>concept</c-> <c- nc>sender_to</c-> <c- o>=</c->
    <c- n>sender_in</c-><c- o>&lt;</c-><c- n>Sndr</c-><c- p>,</c-> <c- n>env_of_t</c-><c- o>&lt;</c-><c- n>Rcvr</c-><c- o>>></c-> <c- o>&amp;&amp;</c->
    <c- n>receiver_of</c-><c- o>&lt;</c-><c- n>Rcvr</c-><c- p>,</c-> <c- n>completion_signatures_of_t</c-><c- o>&lt;</c-><c- n>Sndr</c-><c- p>,</c-> <c- n>env_of_t</c-><c- o>&lt;</c-><c- n>Rcvr</c-><c- o>>>></c-> <c- o>&amp;&amp;</c->
    <c- k>requires</c-> <c- p>(</c-><c- n>Sndr</c-><c- o>&amp;&amp;</c-> <c- n>sndr</c-><c- p>,</c-> <c- n>Rcvr</c-><c- o>&amp;&amp;</c-> <c- n>rcvr</c-><c- p>)</c-> <c- p>{</c->
      <c- n>connect</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>Sndr</c-><c- o>></c-><c- p>(</c-><c- n>sndr</c-><c- p>),</c-> <c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>Rcvr</c-><c- o>></c-><c- p>(</c-><c- n>rcvr</c-><c- p>));</c->
    <c- p>};</c->
</pre>
    <li data-md>
     <p>Given a subexpression <code class="highlight"><c- n>sndr</c-></code>, let <code class="highlight"><c- n>Sndr</c-></code> be <code class="highlight"><c- k>decltype</c-><c- p>((</c-><c- n>sndr</c-><c- p>))</c-></code>, let <code class="highlight"><c- n>Env</c-></code> be
the type of an environment, and let <code class="highlight"><c- n>rcvr</c-></code> be a receiver with an associated
environment <code class="highlight"><c- n>Env</c-></code>. A completion operation is a <dfn data-dfn-type="dfn" data-export id="permissible-completion">permissible completion<a class="self-link" href="#permissible-completion"></a></dfn> for <code class="highlight"><c- n>Sndr</c-></code> and <code class="highlight"><c- n>Env</c-></code> if its
completion signature appears in the argument list of the specialization of <code class="highlight"><c- n>completion_signatures</c-></code> denoted by <code class="highlight"><c- n>completion_signatures_of_t</c-><c- o>&lt;</c-><c- n>Sndr</c-><c- p>,</c-> <c- n>Env</c-><c- o>></c-></code>. <code class="highlight"><c- n>Sndr</c-></code> and <code class="highlight"><c- n>Env</c-></code> model <code class="highlight"><c- n>sender_in</c-><c- o>&lt;</c-><c- n>Sndr</c-><c- p>,</c-> <c- n>Env</c-><c- o>></c-></code> if all the completion
operations that are potentially evaluated by connecting <code class="highlight"><c- n>sndr</c-></code> to <code class="highlight"><c- n>rcvr</c-></code> and
starting the resulting operation state are permissible completions for <code class="highlight"><c- n>Sndr</c-></code> and <code class="highlight"><c- n>Env</c-></code>.</p>
    <li data-md>
     <p>A type <code class="highlight"><c- n>Sigs</c-></code> satisfies and models the exposition-only concept <code class="highlight"><i><c- n>valid</c-><c- o>-</c-><c- n>completion</c-><c- o>-</c-><c- n>signatures</c-></i></code> if it denotes a specialization
of the <code class="highlight"><c- n>completion_signatures</c-></code> class template.</p>
    <li data-md>
     <p><i>Remarks:</i> Pursuant to [namespace.std], users can specialize <code class="highlight"><c- n>enable_sender</c-></code> to <code class="highlight">true</code> for cv-unqualified program-defined types that model <code class="highlight"><c- n>sender</c-></code>, and <code class="highlight">false</code> for types that do not. Such specializations shall be usable in constant
expressions ([expr.const]) and have type <code class="highlight"><c- k>const</c-> <c- b>bool</c-></code>.</p>
    <li data-md>
     <p>The exposition-only concepts <code class="highlight"><i><c- n>sender</c-><c- o>-</c-><c- n>of</c-></i></code> and <code class="highlight"><i><c- n>sender</c-><c- o>-</c-><c- n>of</c-><c- o>-</c-><c- n>in</c-></i></code> define the requirements for a sender
type that completes with a given unique set of value result types.</p>
<pre class="highlight"><c- k>template</c-><c- o>&lt;</c-><c- k>class</c-><c- p>...</c-> <c- n>As</c-><c- o>></c->
  <c- k>using</c-> <i><c- n>value</c-><c- o>-</c-><c- n>signature</c-></i> <c- o>=</c-> <c- n>set_value_t</c-><c- p>(</c-><c- n>As</c-><c- p>...);</c-> <i><c- c1>// exposition only</c-></i>

<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Sndr</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Env</c-><c- p>,</c-> <c- k>class</c-><c- p>...</c-> <c- n>Values</c-><c- o>></c->
  <c- k>concept</c-> <i><c- nc>sender</c-><c- o>-</c-><c- n>of</c-><c- o>-</c-><c- n>in</c-></i> <c- o>=</c->
    <c- n>sender_in</c-><c- o>&lt;</c-><c- n>Sndr</c-><c- p>,</c-> <c- n>Env</c-><c- o>></c-> <c- o>&amp;&amp;</c->
    <i><c- n>MATCHING</c-><c- o>-</c-><c- n>SIG</c-></i><c- p>(</c-> <i><c- c1>// see [exec.general]</c-></i>
      <c- n>set_value_t</c-><c- p>(</c-><c- n>Values</c-><c- p>...),</c->
      <c- n>value_types_of_t</c-><c- o>&lt;</c-><c- n>Sndr</c-><c- p>,</c-> <c- n>Env</c-><c- p>,</c-> <i><c- n>value</c-><c- o>-</c-><c- n>signature</c-></i><c- p>,</c-> <c- n>type_identity_t</c-><c- o>></c-><c- p>);</c->

<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Sndr</c-><c- p>,</c-> <c- k>class</c-><c- p>...</c-> <c- n>Values</c-><c- o>></c->
  <c- k>concept</c-> <i><c- nc>sender</c-><c- o>-</c-><c- n>of</c-></i> <c- o>=</c-> <i><c- n>sender</c-><c- o>-</c-><c- n>of</c-><c- o>-</c-><c- n>in</c-></i><c- o>&lt;</c-><c- n>Sndr</c-><c- p>,</c-> <c- n>empty_env</c-><c- p>,</c-> <c- n>Values</c-><c- p>...</c-><c- o>></c-><c- p>;</c->
</pre>
    <li data-md>
     <p>Let <code class="highlight"><c- n>sndr</c-></code> be an expression such that <code class="highlight"><c- k>decltype</c-><c- p>((</c-><c- n>sndr</c-><c- p>))</c-></code> is <code class="highlight"><c- n>Sndr</c-></code>. The type <code class="highlight"><c- n>tag_of_t</c-><c- o>&lt;</c-><c- n>Sndr</c-><c- o>></c-></code> is as follows:</p>
     <ul>
      <li data-md>
       <p>If the declaration <code class="highlight"><c- k>auto</c-><c- o>&amp;&amp;</c-> <c- p>[</c-><c- n>tag</c-><c- p>,</c-> <c- n>data</c-><c- p>,</c-> <c- p>...</c-><c- n>children</c-><c- p>]</c-> <c- o>=</c-> <c- n>sndr</c-><c- p>;</c-></code> would be
well-formed, <code class="highlight"><c- n>tag_of_t</c-><c- o>&lt;</c-><c- n>Sndr</c-><c- o>></c-></code> is an alias for <code class="highlight"><c- k>decltype</c-><c- p>(</c-><c- k>auto</c-><c- p>(</c-><c- n>tag</c-><c- p>))</c-></code>.</p>
      <li data-md>
       <p>Otherwise, <code class="highlight"><c- n>tag_of_t</c-><c- o>&lt;</c-><c- n>Sndr</c-><c- o>></c-></code> is ill-formed.</p>
     </ul>
     <div class="ed-note"> There is no way in standard C++ to determine whether the above declaration
is well-formed without causing a hard error, so this presumes compiler
magic. However, the author anticipates the adoption of [@P2141R1], which
makes it possible to implement this purely in the library. P2141 has already
been approved by EWG for C++26.</div>
    <li data-md>
     <p>Let <code class="highlight"><i><c- n>sender</c-><c- o>-</c-><c- k>for</c-></i></code> be an exposition-only concept defined as follows:</p>
<pre class="highlight"><c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Sndr</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Tag</c-><c- o>></c->
<c- k>concept</c-> <i><c- nc>sender</c-><c- o>-</c-><c- k>for</c-></i> <c- o>=</c->
  <c- n>sender</c-><c- o>&lt;</c-><c- n>Sndr</c-><c- o>></c-> <c- o>&amp;&amp;</c->
  <c- n>same_as</c-><c- o>&lt;</c-><c- n>tag_of_t</c-><c- o>&lt;</c-><c- n>Sndr</c-><c- o>></c-><c- p>,</c-> <c- n>Tag</c-><c- o>></c-><c- p>;</c->
</pre>
    <li data-md>
     <p>For a type <code class="highlight"><c- n>T</c-></code>, <code class="highlight"><i><c- n>SET</c-><c- o>-</c-><c- n>VALUE</c-><c- o>-</c-><c- n>SIG</c-></i><c- p>(</c-><c- n>T</c-><c- p>)</c-></code> denotes the type <code class="highlight"><c- n>set_value_t</c-><c- p>()</c-></code> if <code class="highlight"><c- n>T</c-></code> is <em>cv</em> <code class="highlight"><c- b>void</c-></code>; otherwise, it denotes the type <code class="highlight"><c- n>set_value_t</c-><c- p>(</c-><c- n>T</c-><c- p>)</c-></code>.</p>
    <li data-md>
     <p>Library-provided sender types:</p>
     <ul>
      <li data-md>
       <p>Always expose an overload of a customization of <code class="highlight"><c- n>connect</c-></code> that accepts an rvalue sender.</p>
      <li data-md>
       <p>Only expose an overload of a customization of <code class="highlight"><c- n>connect</c-></code> that
  accepts an lvalue sender if they model <code class="highlight"><c- n>copy_constructible</c-></code>.</p>
      <li data-md>
       <p>Model <code class="highlight"><c- n>copy_constructible</c-></code> if they satisfy <code class="highlight"><c- n>copy_constructible</c-></code>.</p>
     </ul>
   </ol>
   <h4 class="heading settled" data-level="11.9.3" id="spec.exec-awaitables"><span class="secno">11.9.3. </span><span class="content">Awaitable helpers <b>[exec.awaitables]</b></span><a class="self-link" href="#spec.exec-awaitables"></a></h4>
   <ol>
    <li data-md>
     <p>The sender concepts recognize awaitables as senders. For this clause
([exec]), an <dfn data-dfn-type="dfn" data-export id="awaitable">awaitable<a class="self-link" href="#awaitable"></a></dfn> is an expression that would be
well-formed as the operand of a <code class="highlight"><c- k>co_await</c-></code> expression within a given
context.</p>
    <li data-md>
     <p>For a subexpression <code class="highlight"><c- n>c</c-></code>, let <code class="highlight"><i><c- n>GET</c-><c- o>-</c-><c- n>AWAITER</c-></i><c- p>(</c-><c- n>c</c-><c- p>,</c-> <c- n>p</c-><c- p>)</c-></code> be
expression-equivalent to the series of transformations and conversions
applied to <code class="highlight"><c- n>c</c-></code> as the operand of an <em>await-expression</em> in a coroutine,
resulting in lvalue <i><code class="highlight"><c- n>e</c-></code></i> as described by [expr.await]/3.2-4, where <code class="highlight"><c- n>p</c-></code> is an lvalue referring to the coroutine’s promise type, <code class="highlight"><c- n>Promise</c-></code>. <span class="wg21note">This includes the invocation of the promise type’s <code class="highlight"><c- n>await_transform</c-></code> member if any, the invocation of the <code class="highlight"><c- k>operator</c-> <c- k>co_await</c-></code> picked by overload resolution if any, and any necessary implicit
conversions and materializations.</span></p>
     <div class="ed-note">I have opened <a href="https://github.com/cplusplus/CWG/issues/250">cwg#250</a> to give these
transformations a term-of-art so we can more easily refer to it here.</div>
    <li data-md>
     <p>Let <code class="highlight"><i><c- n>is</c-><c- o>-</c-><c- n>awaitable</c-></i></code> be the following exposition-only
concept:</p>
<pre class="highlight"><c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>T</c-><c- o>></c->
<c- k>concept</c-> <i><c- nc>await</c-><c- o>-</c-><c- n>suspend</c-><c- o>-</c-><c- n>result</c-></i> <c- o>=</c-> <i><c- n>see</c-> <c- n>below</c-></i><c- p>;</c->

<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>A</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Promise</c-><c- o>></c->
<c- k>concept</c-> <i><c- nc>is</c-><c- o>-</c-><c- n>awaiter</c-></i> <c- o>=</c-> <i><c- c1>// exposition only</c-></i>
  <c- k>requires</c-> <c- p>(</c-><c- n>A</c-><c- o>&amp;</c-> <c- n>a</c-><c- p>,</c-> <c- n>coroutine_handle</c-><c- o>&lt;</c-><c- n>Promise</c-><c- o>></c-> <c- n>h</c-><c- p>)</c-> <c- p>{</c->
    <c- n>a</c-><c- p>.</c-><c- n>await_ready</c-><c- p>()</c-> <c- o>?</c-> <c- mi>1</c-> <c- o>:</c-> <c- mi>0</c-><c- p>;</c->
    <c- p>{</c-> <c- n>a</c-><c- p>.</c-><c- n>await_suspend</c-><c- p>(</c-><c- n>h</c-><c- p>)</c-> <c- p>}</c-> <c- o>-></c-> <i><c- n>await</c-><c- o>-</c-><c- n>suspend</c-><c- o>-</c-><c- n>result</c-></i><c- p>;</c->
    <c- n>a</c-><c- p>.</c-><c- n>await_resume</c-><c- p>();</c->
  <c- p>};</c->

<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>C</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Promise</c-><c- o>></c->
<c- k>concept</c-> <i><c- nc>is</c-><c- o>-</c-><c- n>awaitable</c-></i> <c- o>=</c->
  <c- k>requires</c-> <c- p>(</c-><c- n>C</c-> <c- p>(</c-><c- o>*</c-><c- n>fc</c-><c- p>)()</c-> <c- k>noexcept</c-><c- p>,</c-> <c- n>Promise</c-><c- o>&amp;</c-> <c- n>p</c-><c- p>)</c-> <c- p>{</c->
    <c- p>{</c-> <i><c- n>GET</c-><c- o>-</c-><c- n>AWAITER</c-></i><c- p>(</c-><c- n>fc</c-><c- p>(),</c-> <c- n>p</c-><c- p>)</c-> <c- p>}</c-> <c- o>-></c-> <i><c- n>is</c-><c- o>-</c-><c- n>awaiter</c-></i><c- o>&lt;</c-><c- n>Promise</c-><c- o>></c-><c- p>;</c->
  <c- p>};</c->
</pre>
     <p><code class="highlight"><i><c- n>await</c-><c- o>-</c-><c- n>suspend</c-><c- o>-</c-><c- n>result</c-></i><c- o>&lt;</c-><c- n>T</c-><c- o>></c-></code> is <code class="highlight">true</code> if and only if one
  of the following is <code class="highlight">true</code>:</p>
     <ul>
      <li data-md>
       <p><code class="highlight"><c- n>T</c-></code> is <code class="highlight"><c- b>void</c-></code>, or</p>
      <li data-md>
       <p><code class="highlight"><c- n>T</c-></code> is <code class="highlight"><c- b>bool</c-></code>, or</p>
      <li data-md>
       <p><code class="highlight"><c- n>T</c-></code> is a specialization of <code class="highlight"><c- n>coroutine_handle</c-></code>.</p>
     </ul>
    <li data-md>
     <p>For a subexpression <code class="highlight"><c- n>c</c-></code> such that <code class="highlight"><c- k>decltype</c-><c- p>((</c-><c- n>c</c-><c- p>))</c-></code> is type <code class="highlight"><c- n>C</c-></code>, and
an lvalue <code class="highlight"><c- n>p</c-></code> of type <code class="highlight"><c- n>Promise</c-></code>, <code class="highlight"><i><c- n>await</c-><c- o>-</c-><c- n>result</c-><c- o>-</c-><c- n>type</c-></i><c- o>&lt;</c-><c- n>C</c-><c- p>,</c-> <c- n>Promise</c-><c- o>></c-></code> denotes the type <code class="highlight"><c- k>decltype</c-><c- p>(</c-><i><c- n>GET</c-><c- o>-</c-><c- n>AWAITER</c-></i><c- p>(</c-><c- n>c</c-><c- p>,</c-> <c- n>p</c-><c- p>).</c-><c- n>await_resume</c-><c- p>())</c-></code>.</p>
    <li data-md>
     <p>Let <code class="highlight"><i><c- n>with</c-><c- o>-</c-><c- n>await</c-><c- o>-</c-><c- n>transform</c-></i></code> be the exposition-only class template:</p>
<pre class="highlight"><c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Derived</c-><c- o>></c->
<c- k>struct</c-> <i><c- nc>with</c-><c- o>-</c-><c- n>await</c-><c- o>-</c-><c- n>transform</c-></i> <c- p>{</c->
  <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>T</c-><c- o>></c->
  <c- n>T</c-><c- o>&amp;&amp;</c-> <c- n>await_transform</c-><c- p>(</c-><c- n>T</c-><c- o>&amp;&amp;</c-> <c- n>value</c-><c- p>)</c-> <c- k>noexcept</c-> <c- p>{</c->
    <c- k>return</c-> <c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>T</c-><c- o>></c-><c- p>(</c-><c- n>value</c-><c- p>);</c->
  <c- p>}</c->

  <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>T</c-><c- o>></c->
    <c- k>requires</c-> <c- n>tag_invocable</c-><c- o>&lt;</c-><c- n>as_awaitable_t</c-><c- p>,</c-> <c- n>T</c-><c- p>,</c-> <c- n>Derived</c-><c- o>&amp;></c->
  <c- k>auto</c-> <c- n>await_transform</c-><c- p>(</c-><c- n>T</c-><c- o>&amp;&amp;</c-> <c- n>value</c-><c- p>)</c->
    <c- k>noexcept</c-><c- p>(</c-><c- n>nothrow_tag_invocable</c-><c- o>&lt;</c-><c- n>as_awaitable_t</c-><c- p>,</c-> <c- n>T</c-><c- p>,</c-> <c- n>Derived</c-><c- o>&amp;></c-><c- p>)</c->
    <c- o>-></c-> <c- n>tag_invoke_result_t</c-><c- o>&lt;</c-><c- n>as_awaitable_t</c-><c- p>,</c-> <c- n>T</c-><c- p>,</c-> <c- n>Derived</c-><c- o>&amp;></c-> <c- p>{</c->
    <c- k>return</c-> <c- n>tag_invoke</c-><c- p>(</c-><c- n>as_awaitable</c-><c- p>,</c-> <c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>T</c-><c- o>></c-><c- p>(</c-><c- n>value</c-><c- p>),</c-> <c- k>static_cast</c-><c- o>&lt;</c-><c- n>Derived</c-><c- o>&amp;></c-><c- p>(</c-><c- o>*</c-><c- k>this</c-><c- p>));</c->
  <c- p>}</c->
<c- p>};</c->
</pre>
    <li data-md>
     <p>Let <code class="highlight"><i><c- n>env</c-><c- o>-</c-><c- n>promise</c-></i></code> be the exposition-only class template:</p>
<pre class="highlight"><c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Env</c-><c- o>></c->
<c- k>struct</c-> <i><c- nc>env</c-><c- o>-</c-><c- n>promise</c-></i> <c- o>:</c-> <i><c- n>with</c-><c- o>-</c-><c- n>await</c-><c- o>-</c-><c- n>transform</c-></i><c- o>&lt;</c-><i><c- n>env</c-><c- o>-</c-><c- n>promise</c-></i><c- o>&lt;</c-><c- n>Env</c-><c- o>>></c-> <c- p>{</c->
  <i><c- n>unspecified</c-></i> <c- nf>get_return_object</c-><c- p>()</c-> <c- k>noexcept</c-><c- p>;</c->
  <i><c- n>unspecified</c-></i> <c- nf>initial_suspend</c-><c- p>()</c-> <c- k>noexcept</c-><c- p>;</c->
  <i><c- n>unspecified</c-></i> <c- nf>final_suspend</c-><c- p>()</c-> <c- k>noexcept</c-><c- p>;</c->
  <c- b>void</c-> <c- nf>unhandled_exception</c-><c- p>()</c-> <c- k>noexcept</c-><c- p>;</c->
  <c- b>void</c-> <c- nf>return_void</c-><c- p>()</c-> <c- k>noexcept</c-><c- p>;</c->
  <c- n>coroutine_handle</c-><c- o>&lt;></c-> <c- n>unhandled_stopped</c-><c- p>()</c-> <c- k>noexcept</c-><c- p>;</c->

  <c- k>friend</c-> <c- k>const</c-> <c- n>Env</c-><c- o>&amp;</c-> <c- nf>tag_invoke</c-><c- p>(</c-><c- n>get_env_t</c-><c- p>,</c-> <c- k>const</c-> <i><c- n>env</c-><c- o>-</c-><c- n>promise</c-></i><c- o>&amp;</c-><c- p>)</c-> <c- k>noexcept</c-><c- p>;</c->
<c- p>};</c->
</pre>
     <p><span class="wg21note">Specializations of <code class="highlight"><i><c- n>env</c-><c- o>-</c-><c- n>promise</c-></i></code> are only used for the purpose of type computation; its members need not be
  defined.</span></p>
   </ol>
   <h4 class="heading settled" data-level="11.9.4" id="spec-execution.default_domain"><span class="secno">11.9.4. </span><span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>default_domain</c-></code> <b>[exec.domain.default]</b></span><a class="self-link" href="#spec-execution.default_domain"></a></h4>
<pre class="highlight"><c- k>struct</c-> <c- nc>default_domain</c-> <c- p>{</c->
  <c- k>template</c-> <c- o>&lt;</c-><c- n>sender</c-> <c- n>Sndr</c-><c- o>></c->
    <c- k>static</c-> <c- k>constexpr</c-> <c- n>sender</c-> <c- k>decltype</c-><c- p>(</c-><c- k>auto</c-><c- p>)</c-> <c- n>transform_sender</c-><c- p>(</c-><c- n>Sndr</c-><c- o>&amp;&amp;</c-> <c- n>sndr</c-><c- p>)</c-> <c- k>noexcept</c-><c- p>(</c-><i><c- n>see</c-> <c- n>below</c-></i><c- p>);</c->

  <c- k>template</c-> <c- o>&lt;</c-><c- n>sender</c-> <c- n>Sndr</c-><c- p>,</c-> <c- n>queryable</c-> <c- n>Env</c-><c- o>></c->
    <c- k>static</c-> <c- k>constexpr</c-> <c- n>sender</c-> <c- k>decltype</c-><c- p>(</c-><c- k>auto</c-><c- p>)</c-> <c- n>transform_sender</c-><c- p>(</c-><c- n>Sndr</c-><c- o>&amp;&amp;</c-> <c- n>sndr</c-><c- p>,</c-> <c- k>const</c-> <c- n>Env</c-><c- o>&amp;</c-> <c- n>env</c-><c- p>)</c-> <c- k>noexcept</c-><c- p>(</c-><i><c- n>see</c-> <c- n>below</c-></i><c- p>);</c->

  <c- k>template</c-> <c- o>&lt;</c-><c- n>sender</c-> <c- n>Sndr</c-><c- p>,</c-> <c- n>queryable</c-> <c- n>Env</c-><c- o>></c->
    <c- k>static</c-> <c- k>constexpr</c-> <c- k>decltype</c-><c- p>(</c-><c- k>auto</c-><c- p>)</c-> <c- n>transform_env</c-><c- p>(</c-><c- n>Sndr</c-><c- o>&amp;&amp;</c-> <c- n>sndr</c-><c- p>,</c-> <c- n>Env</c-><c- o>&amp;&amp;</c-> <c- n>env</c-><c- p>)</c-> <c- k>noexcept</c-><c- p>;</c->

  <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Tag</c-><c- p>,</c-> <c- n>sender</c-> <c- n>Sndr</c-><c- p>,</c-> <c- k>class</c-><c- p>...</c-> <c- n>Args</c-><c- o>></c->
    <c- k>static</c-> <c- k>constexpr</c-> <c- k>decltype</c-><c- p>(</c-><c- k>auto</c-><c- p>)</c-> <c- n>apply_sender</c-><c- p>(</c-><c- n>Tag</c-><c- p>,</c-> <c- n>Sndr</c-><c- o>&amp;&amp;</c-> <c- n>sndr</c-><c- p>,</c-> <c- n>Args</c-><c- o>&amp;&amp;</c-><c- p>...</c-> <c- n>args</c-><c- p>)</c-> <c- k>noexcept</c-><c- p>(</c-><i><c- n>see</c-> <c- n>below</c-></i><c- p>);</c->
<c- p>};</c->
</pre>
   <h5 class="heading settled" data-level="11.9.4.1" id="spec-execution.default_domain.statics"><span class="secno">11.9.4.1. </span><span class="content">Static members <b>[exec.domain.default.statics]</b></span><a class="self-link" href="#spec-execution.default_domain.statics"></a></h5>
<pre class="highlight"><c- k>template</c-> <c- o>&lt;</c-><c- n>sender</c-> <c- n>Sndr</c-><c- o>></c->
  <c- k>constexpr</c-> <c- n>sender</c-> <c- k>decltype</c-><c- p>(</c-><c- k>auto</c-><c- p>)</c-> <c- n>default_domain</c-><c- o>::</c-><c- n>transform_sender</c-><c- p>(</c-><c- n>Sndr</c-><c- o>&amp;&amp;</c-> <c- n>sndr</c-><c- p>)</c-> <c- k>noexcept</c-><c- p>(</c-><i><c- n>see</c-> <c- n>below</c-></i><c- p>);</c->
</pre>
   <ol>
    <li data-md>
     <p><i>Returns:</i> <code class="highlight"><c- n>tag_of_t</c-><c- o>&lt;</c-><c- n>Sndr</c-><c- o>></c-><c- p>().</c-><c- n>transform_sender</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>Sndr</c-><c- o>></c-><c- p>(</c-><c- n>sndr</c-><c- p>))</c-></code> if that expression is well-formed; otherwise, <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>Sndr</c-><c- o>></c-><c- p>(</c-><c- n>sndr</c-><c- p>)</c-></code>.</p>
    <li data-md>
     <p><i>Remarks:</i> The exception specification is equivalent to:</p>
<pre class="highlight"><c- k>noexcept</c-><c- p>(</c-><c- n>tag_of_t</c-><c- o>&lt;</c-><c- n>Sndr</c-><c- o>></c-><c- p>().</c-><c- n>transform_sender</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>Sndr</c-><c- o>></c-><c- p>(</c-><c- n>sndr</c-><c- p>)))</c->
</pre>
     <p>if that expression is well-formed; otherwise, <code class="highlight">true</code>;</p>
   </ol>
<pre class="highlight"><c- k>template</c-> <c- o>&lt;</c-><c- n>sender</c-> <c- n>Sndr</c-><c- p>,</c-> <c- n>queryable</c-> <c- n>Env</c-><c- o>></c->
  <c- k>constexpr</c-> <c- n>sender</c-> <c- k>decltype</c-><c- p>(</c-><c- k>auto</c-><c- p>)</c-> <c- n>default_domain</c-><c- o>::</c-><c- n>transform_sender</c-><c- p>(</c-><c- n>Sndr</c-><c- o>&amp;&amp;</c-> <c- n>sndr</c-><c- p>,</c-> <c- k>const</c-> <c- n>Env</c-><c- o>&amp;</c-> <c- n>env</c-><c- p>)</c-> <c- k>noexcept</c-><c- p>(</c-><i><c- n>see</c-> <c- n>below</c-></i><c- p>);</c->
</pre>
   <ol>
    <li data-md>
     <p><i>Returns:</i> <code class="highlight"><c- n>tag_of_t</c-><c- o>&lt;</c-><c- n>Sndr</c-><c- o>></c-><c- p>().</c-><c- n>transform_sender</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>Sndr</c-><c- o>></c-><c- p>(</c-><c- n>sndr</c-><c- p>),</c-> <c- n>env</c-><c- p>)</c-></code> if that expression is well-formed; otherwise, <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>Sndr</c-><c- o>></c-><c- p>(</c-><c- n>sndr</c-><c- p>)</c-></code>.</p>
    <li data-md>
     <p><i>Remarks:</i> The exception specification is equivalent to:</p>
<pre class="highlight"><c- k>noexcept</c-><c- p>(</c-><c- n>tag_of_t</c-><c- o>&lt;</c-><c- n>Sndr</c-><c- o>></c-><c- p>().</c-><c- n>transform_sender</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>Sndr</c-><c- o>></c-><c- p>(</c-><c- n>sndr</c-><c- p>),</c-> <c- n>env</c-><c- p>))</c->
</pre>
     <p>if that expression is well-formed; otherwise, <code class="highlight">true</code>;</p>
   </ol>
<pre class="highlight"><c- k>template</c-> <c- o>&lt;</c-><c- n>sender</c-> <c- n>Sndr</c-><c- p>,</c-> <c- n>queryable</c-> <c- n>Env</c-><c- o>></c->
  <c- k>constexpr</c-> <c- k>decltype</c-><c- p>(</c-><c- k>auto</c-><c- p>)</c-> <c- n>default_domain</c-><c- o>::</c-><c- n>transform_env</c-><c- p>(</c-><c- n>Sndr</c-><c- o>&amp;&amp;</c-> <c- n>sndr</c-><c- p>,</c-> <c- n>Env</c-><c- o>&amp;&amp;</c-> <c- n>env</c-><c- p>)</c-> <c- k>noexcept</c-><c- p>;</c->
</pre>
   <ol start="3">
    <li data-md>
     <p><i>Returns:</i> <code class="highlight"><c- n>tag_of_t</c-><c- o>&lt;</c-><c- n>Sndr</c-><c- o>></c-><c- p>().</c-><c- n>transform_env</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>Sndr</c-><c- o>></c-><c- p>(</c-><c- n>sndr</c-><c- p>),</c-> <c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>Env</c-><c- o>></c-><c- p>(</c-><c- n>env</c-><c- p>))</c-></code> if that expression is well-formed; otherwise, <code class="highlight"><c- k>static_cast</c-><c- o>&lt;</c-><c- n>Env</c-><c- o>></c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>Env</c-><c- o>></c-><c- p>(</c-><c- n>env</c-><c- p>))</c-></code>.</p>
    <li data-md>
     <p><i>Mandates:</i> The selected expression in <i>Returns:</i> is not potentially throwing.</p>
   </ol>
<pre class="highlight"><c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Tag</c-><c- p>,</c-> <c- n>sender</c-> <c- n>Sndr</c-><c- p>,</c-> <c- k>class</c-><c- p>...</c-> <c- n>Args</c-><c- o>></c->
  <c- k>static</c-> <c- k>constexpr</c-> <c- k>decltype</c-><c- p>(</c-><c- k>auto</c-><c- p>)</c-> <c- n>default_domain</c-><c- o>::</c-><c- n>apply_sender</c-><c- p>(</c-><c- n>Tag</c-><c- p>,</c-> <c- n>Sndr</c-><c- o>&amp;&amp;</c-> <c- n>sndr</c-><c- p>,</c-> <c- n>Args</c-><c- o>&amp;&amp;</c-><c- p>...</c-> <c- n>args</c-><c- p>)</c-> <c- k>noexcept</c-><c- p>(</c-><i><c- n>see</c-> <c- n>below</c-></i><c- p>);</c->
</pre>
   <ol start="5">
    <li data-md>
     <p><i>Returns:</i> <code class="highlight"><c- n>Tag</c-><c- p>().</c-><c- n>apply_sender</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>Sndr</c-><c- o>></c-><c- p>(</c-><c- n>sndr</c-><c- p>),</c-> <c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>Args</c-><c- o>></c-><c- p>(</c-><c- n>args</c-><c- p>)...)</c-></code> if that expression is well-formed; otherwise, this function shall not participate
in overload resolution.</p>
    <li data-md>
     <p><i>Remarks:</i> The exception specification is equivalent to:</p>
<pre class="highlight"><c- k>noexcept</c-><c- p>(</c-><c- n>Tag</c-><c- p>().</c-><c- n>apply_sender</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>Sndr</c-><c- o>></c-><c- p>(</c-><c- n>sndr</c-><c- p>),</c-> <c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>Args</c-><c- o>></c-><c- p>(</c-><c- n>args</c-><c- p>)...))</c->
</pre>
   </ol>
   <h4 class="heading settled" data-level="11.9.5" id="spec-execution.sender_transform"><span class="secno">11.9.5. </span><span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>transform_sender</c-></code> <b>[exec.snd.transform]</b></span><a class="self-link" href="#spec-execution.sender_transform"></a></h4>
<pre class="highlight"><c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Domain</c-><c- p>,</c-> <c- n>sender</c-> <c- n>Sndr</c-><c- o>></c->
  <c- k>constexpr</c-> <c- n>sender</c-> <c- k>decltype</c-><c- p>(</c-><c- k>auto</c-><c- p>)</c-> <c- n>transform_sender</c-><c- p>(</c-><c- n>Domain</c-> <c- n>dom</c-><c- p>,</c-> <c- n>Sndr</c-><c- o>&amp;&amp;</c-> <c- n>sndr</c-><c- p>);</c->

<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Domain</c-><c- p>,</c-> <c- n>sender</c-> <c- n>Sndr</c-><c- p>,</c-> <c- n>queryable</c-> <c- n>Env</c-><c- o>></c->
  <c- k>constexpr</c-> <c- n>sender</c-> <c- k>decltype</c-><c- p>(</c-><c- k>auto</c-><c- p>)</c-> <c- n>transform_sender</c-><c- p>(</c-><c- n>Domain</c-> <c- n>dom</c-><c- p>,</c-> <c- n>Sndr</c-><c- o>&amp;&amp;</c-> <c- n>sndr</c-><c- p>,</c-> <c- k>const</c-> <c- n>Env</c-><c- o>&amp;</c-> <c- n>env</c-><c- p>);</c->
</pre>
   <ol>
    <li data-md>
     <p><i>Returns:</i> Let <code class="highlight"><i><c- n>ENV</c-></i></code> be a parameter pack consisting of
  the single expression <code class="highlight"><c- n>env</c-></code> for the second overload and an empty pack for
  the first. Let <code class="highlight"><c- n>sndr2</c-></code> be the expression <code class="highlight"><c- n>dom</c-><c- p>.</c-><c- n>transform_sender</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>Sndr</c-><c- o>></c-><c- p>(</c-><c- n>sndr</c-><c- p>),</c-> <i><c- n>ENV</c-></i><c- p>...)</c-></code> if that expression is well-formed; otherwise, <code class="highlight"><c- n>default_domain</c-><c- p>().</c-><c- n>transform_sender</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>Sndr</c-><c- o>></c-><c- p>(</c-><c- n>sndr</c-><c- p>),</c-> <i><c- n>ENV</c-></i><c- p>...)</c-></code>. If <code class="highlight"><c- n>sndr2</c-></code> and <code class="highlight"><c- n>sndr</c-></code> have the same type ignoring <em>cv</em> qualifiers, returns <code class="highlight"><c- n>sndr2</c-></code>; otherwise, <code class="highlight"><c- n>transform_sender</c-><c- p>(</c-><c- n>dom</c-><c- p>,</c-> <c- n>sndr2</c-><c- p>,</c-> <i><c- n>ENV</c-></i><c- p>...)</c-></code>.</p>
   </ol>
<pre class="highlight"><c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Domain</c-><c- p>,</c-> <c- n>sender</c-> <c- n>Sndr</c-><c- p>,</c-> <c- n>queryable</c-> <c- n>Env</c-><c- o>></c->
  <c- k>constexpr</c-> <c- k>decltype</c-><c- p>(</c-><c- k>auto</c-><c- p>)</c-> <c- n>transform_env</c-><c- p>(</c-><c- n>Domain</c-> <c- n>dom</c-><c- p>,</c-> <c- n>Sndr</c-><c- o>&amp;&amp;</c-> <c- n>sndr</c-><c- p>,</c-> <c- n>Env</c-><c- o>&amp;&amp;</c-> <c- n>env</c-><c- p>)</c-> <c- k>noexcept</c-><c- p>;</c->
</pre>
   <ol start="3">
    <li data-md>
     <p><i>Returns:</i> <code class="highlight"><c- n>dom</c-><c- p>.</c-><c- n>transform_sender</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>Sndr</c-><c- o>></c-><c- p>(</c-><c- n>sndr</c-><c- p>),</c-> <c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>Env</c-><c- o>></c-><c- p>(</c-><c- n>env</c-><c- p>))</c-></code> if that
  expression is well-formed; otherwise, <code class="highlight"><c- n>default_domain</c-><c- p>().</c-><c- n>transform_sender</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>Sndr</c-><c- o>></c-><c- p>(</c-><c- n>sndr</c-><c- p>),</c-> <c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>Env</c-><c- o>></c-><c- p>(</c-><c- n>env</c-><c- p>))</c-></code>.</p>
   </ol>
   <h4 class="heading settled" data-level="11.9.6" id="spec-execution.apply_sender"><span class="secno">11.9.6. </span><span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>apply_sender</c-></code> <b>[exec.snd.apply]</b></span><a class="self-link" href="#spec-execution.apply_sender"></a></h4>
<pre class="highlight"><c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Domain</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Tag</c-><c- p>,</c-> <c- n>sender</c-> <c- n>Sndr</c-><c- p>,</c-> <c- k>class</c-><c- p>...</c-> <c- n>Args</c-><c- o>></c->
  <c- k>constexpr</c-> <c- k>decltype</c-><c- p>(</c-><c- k>auto</c-><c- p>)</c-> <c- n>apply_sender</c-><c- p>(</c-><c- n>Domain</c-> <c- n>dom</c-><c- p>,</c-> <c- n>Tag</c-><c- p>,</c-> <c- n>Sndr</c-><c- o>&amp;&amp;</c-> <c- n>sndr</c-><c- p>,</c-> <c- n>Args</c-><c- o>&amp;&amp;</c-><c- p>...</c-> <c- n>args</c-><c- p>)</c-> <c- k>noexcept</c-><c- p>(</c-><i><c- n>see</c-> <c- n>below</c-></i><c- p>);</c->
</pre>
   <ol>
    <li data-md>
     <p><i>Returns:</i> <code class="highlight"><c- n>dom</c-><c- p>.</c-><c- n>apply_sender</c-><c- p>(</c-><c- n>Tag</c-><c- p>(),</c-> <c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>Sndr</c-><c- o>></c-><c- p>(</c-><c- n>sndr</c-><c- p>),</c-> <c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>Args</c-><c- o>></c-><c- p>(</c-><c- n>args</c-><c- p>)...)</c-></code> if that
  expression is well-formed; otherwise, <code class="highlight"><c- n>default_domain</c-><c- p>().</c-><c- n>apply_sender</c-><c- p>(</c-><c- n>Tag</c-><c- p>(),</c-> <c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>Sndr</c-><c- o>></c-><c- p>(</c-><c- n>sndr</c-><c- p>),</c-> <c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>Args</c-><c- o>></c-><c- p>(</c-><c- n>args</c-><c- p>)...)</c-></code> if that expression is well-formed; otherwise, this function shall not participate in
  overload resolution.</p>
    <li data-md>
     <p><i>Remarks:</i> The exception specification is equivalent to:</p>
<pre class="highlight"><c- k>noexcept</c-><c- p>(</c-><c- n>dom</c-><c- p>.</c-><c- n>apply_sender</c-><c- p>(</c-><c- n>Tag</c-><c- p>(),</c-> <c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>Sndr</c-><c- o>></c-><c- p>(</c-><c- n>sndr</c-><c- p>),</c-> <c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>Args</c-><c- o>></c-><c- p>(</c-><c- n>args</c-><c- p>)...))</c->
</pre>
     <p>if that expression is well-formed; otherwise,</p>
<pre class="highlight"><c- k>noexcept</c-><c- p>(</c-><c- n>default_domain</c-><c- p>().</c-><c- n>apply_sender</c-><c- p>(</c-><c- n>Tag</c-><c- p>(),</c-> <c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>Sndr</c-><c- o>></c-><c- p>(</c-><c- n>sndr</c-><c- p>),</c-> <c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>Args</c-><c- o>></c-><c- p>(</c-><c- n>args</c-><c- p>)...))</c->
</pre>
   </ol>
   <h4 class="heading settled" data-level="11.9.7" id="spec-execution.getcomplsigs"><span class="secno">11.9.7. </span><span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>get_completion_signatures</c-></code> <b>[exec.getcomplsigs]</b></span><a class="self-link" href="#spec-execution.getcomplsigs"></a></h4>
   <ol>
    <li data-md>
     <p><code class="highlight"><c- n>get_completion_signatures</c-></code> is a customization point object. Let <code class="highlight"><c- n>sndr</c-></code> be an
expression such that <code class="highlight"><c- k>decltype</c-><c- p>((</c-><c- n>sndr</c-><c- p>))</c-></code> is <code class="highlight"><c- n>Sndr</c-></code>, and let <code class="highlight"><c- n>env</c-></code> be an expression
such that <code class="highlight"><c- k>decltype</c-><c- p>((</c-><c- n>env</c-><c- p>))</c-></code> is <code class="highlight"><c- n>Env</c-></code>. Then <code class="highlight"><c- n>get_completion_signatures</c-><c- p>(</c-><c- n>sndr</c-><c- p>,</c-> <c- n>env</c-><c- p>)</c-></code> is
expression-equivalent to:</p>
     <ol>
      <li data-md>
       <p><code class="highlight"><c- n>tag_invoke_result_t</c-><c- o>&lt;</c-><c- n>get_completion_signatures_t</c-><c- p>,</c-> <c- n>Sndr</c-><c- p>,</c-> <c- n>Env</c-><c- o>></c-><c- p>{}</c-></code> if that
expression is well-formed,</p>
      <li data-md>
       <p>Otherwise, <code class="highlight"><c- n>remove_cvref_t</c-><c- o>&lt;</c-><c- n>Sndr</c-><c- o>>::</c-><c- n>completion_signatures</c-><c- p>{}</c-></code> if that expression is well-formed,</p>
      <li data-md>
       <p>Otherwise, if <code class="highlight"><i><c- n>is</c-><c- o>-</c-><c- n>awaitable</c-></i><c- o>&lt;</c-><c- n>Sndr</c-><c- p>,</c-> <i><c- n>env</c-><c- o>-</c-><c- n>promise</c-></i><c- o>&lt;</c-><c- n>Env</c-><c- o>>></c-></code> is <code class="highlight">true</code>, then:</p>
<pre class="highlight"><c- n>completion_signatures</c-><c- o>&lt;</c->
  <i><c- n>SET</c-><c- o>-</c-><c- n>VALUE</c-><c- o>-</c-><c- n>SIG</c-></i><c- p>(</c-><i><c- n>await</c-><c- o>-</c-><c- n>result</c-><c- o>-</c-><c- n>type</c-></i><c- o>&lt;</c-><c- n>Sndr</c-><c- p>,</c-> <i><c- n>env</c-><c- o>-</c-><c- n>promise</c-></i><c- o>&lt;</c-><c- n>Env</c-><c- o>>></c-><c- p>),</c-> <i><c- c1>// see [exec.snd.concepts]</c-></i>
  <c- n>set_error_t</c-><c- p>(</c-><c- n>exception_ptr</c-><c- p>),</c->
  <c- n>set_stopped_t</c-><c- p>()</c-><c- o>></c-><c- p>{}</c->
</pre>
      <li data-md>
       <p>Otherwise, <code class="highlight"><c- n>get_completion_signatures</c-><c- p>(</c-><c- n>sndr</c-><c- p>,</c-> <c- n>env</c-><c- p>)</c-></code> is ill-formed.</p>
     </ol>
    <li data-md>
     <p>Let <code class="highlight"><c- n>rcvr</c-></code> be an rvalue receiver of type <code class="highlight"><c- n>Rcvr</c-></code>, and let <code class="highlight"><c- n>Sndr</c-></code> be the type of a
sender such that <code class="highlight"><c- n>sender_in</c-><c- o>&lt;</c-><c- n>Sndr</c-><c- p>,</c-> <c- n>env_of_t</c-><c- o>&lt;</c-><c- n>Rcvr</c-><c- o>>></c-></code> is <code class="highlight">true</code>. Let <code class="highlight"><c- n>Sigs</c-><c- p>...</c-></code> be the
template arguments of the <code class="highlight"><c- n>completion_signatures</c-></code> specialization named by <code class="highlight"><c- n>completion_signatures_of_t</c-><c- o>&lt;</c-><c- n>Sndr</c-><c- p>,</c-> <c- n>env_of_t</c-><c- o>&lt;</c-><c- n>Rcvr</c-><c- o>>></c-></code>. Let <code class="highlight"><i><c- n>CSO</c-></i></code> be
a completion function. If sender <code class="highlight"><c- n>Sndr</c-></code> or its operation state cause the
expression <code class="highlight"><i><c- n>CSO</c-></i><c- p>(</c-><c- n>rcvr</c-><c- p>,</c-> <c- n>args</c-><c- p>...)</c-></code> to be potentially evaluated
([basic.def.odr]) then there shall be a signature <code class="highlight"><c- n>Sig</c-></code> in <code class="highlight"><c- n>Sigs</c-><c- p>...</c-></code> such
that <code class="highlight"><i><c- n>MATCHING</c-><c- o>-</c-><c- n>SIG</c-></i><c- p>(</c-><c- n>tag_t</c-><c- o>&lt;</c-><i><c- n>CSO</c-></i><c- o>></c-><c- p>(</c-><c- k>decltype</c-><c- p>(</c-><c- n>args</c-><c- p>)...),</c-> <c- n>Sig</c-><c- p>)</c-></code> is <code class="highlight">true</code> ([exec.general]).</p>
   </ol>
   <h4 class="heading settled" data-level="11.9.8" id="spec-execution.senders.connect"><span class="secno">11.9.8. </span><span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>connect</c-></code> <b>[exec.connect]</b></span><a class="self-link" href="#spec-execution.senders.connect"></a></h4>
   <ol>
    <li data-md>
     <p><code class="highlight"><c- n>connect</c-></code> connects ([async.ops]) a sender with a receiver.</p>
    <li data-md>
     <p>The name <code class="highlight"><c- n>connect</c-></code> denotes a customization point object. For subexpressions <code class="highlight"><c- n>sndr</c-></code> and <code class="highlight"><c- n>rcvr</c-></code>, let <code class="highlight"><c- n>Sndr</c-></code> be <code class="highlight"><c- k>decltype</c-><c- p>((</c-><c- n>sndr</c-><c- p>))</c-></code> and <code class="highlight"><c- n>Rcvr</c-></code> be <code class="highlight"><c- k>decltype</c-><c- p>((</c-><c- n>rcvr</c-><c- p>))</c-></code>, and let <code class="highlight"><c- n>DS</c-></code> and <code class="highlight"><c- n>DR</c-></code> be the decayed types of <code class="highlight"><c- n>Sndr</c-></code> and <code class="highlight"><c- n>Rcvr</c-></code>, respectively.</p>
    <li data-md>
     <p>Let <code class="highlight"><i><c- n>connect</c-><c- o>-</c-><c- n>awaitable</c-><c- o>-</c-><c- n>promise</c-></i></code> be the following class:</p>
<pre class="highlight"><c- k>struct</c-> <i><c- nc>connect</c-><c- o>-</c-><c- n>awaitable</c-><c- o>-</c-><c- n>promise</c-></i> <c- o>:</c-> <i><c- n>with</c-><c- o>-</c-><c- n>await</c-><c- o>-</c-><c- n>transform</c-></i><c- o>&lt;</c-><i><c- n>connect</c-><c- o>-</c-><c- n>awaitable</c-><c- o>-</c-><c- n>promise</c-></i><c- o>></c-> <c- p>{</c->
  <c- n>DR</c-><c- o>&amp;</c-> <i><c- n>rcvr</c-></i><c- p>;</c-> <i><c- c1>// exposition only</c-></i>

  <i><c- n>connect</c-><c- o>-</c-><c- n>awaitable</c-><c- o>-</c-><c- n>promise</c-></i><c- p>(</c-><c- n>DS</c-><c- o>&amp;</c-><c- p>,</c-> <c- n>DR</c-><c- o>&amp;</c-> <c- n>rcvr</c-><c- p>)</c-> <c- k>noexcept</c-> <c- o>:</c-> <i><c- n>rcvr</c-></i><c- p>(</c-><c- n>rcvr</c-><c- p>)</c-> <c- p>{}</c->

  <c- n>suspend_always</c-> <c- n>initial_suspend</c-><c- p>()</c-> <c- k>noexcept</c-> <c- p>{</c-> <c- k>return</c-> <c- p>{};</c-> <c- p>}</c->
  <c- p>[[</c-><c- n>noreturn</c-><c- p>]]</c-> <c- n>suspend_always</c-> <c- n>final_suspend</c-><c- p>()</c-> <c- k>noexcept</c-> <c- p>{</c-> <c- n>terminate</c-><c- p>();</c-> <c- p>}</c->
  <c- p>[[</c-><c- n>noreturn</c-><c- p>]]</c-> <c- b>void</c-> <c- n>unhandled_exception</c-><c- p>()</c-> <c- k>noexcept</c-> <c- p>{</c-> <c- n>terminate</c-><c- p>();</c-> <c- p>}</c->
  <c- p>[[</c-><c- n>noreturn</c-><c- p>]]</c-> <c- b>void</c-> <c- n>return_void</c-><c- p>()</c-> <c- k>noexcept</c-> <c- p>{</c-> <c- n>terminate</c-><c- p>();</c-> <c- p>}</c->

  <c- n>coroutine_handle</c-><c- o>&lt;></c-> <c- n>unhandled_stopped</c-><c- p>()</c-> <c- k>noexcept</c-> <c- p>{</c->
    <c- n>set_stopped</c-><c- p>((</c-><c- n>DR</c-><c- o>&amp;&amp;</c-><c- p>)</c-> <i><c- n>rcvr</c-></i><c- p>);</c->
    <c- k>return</c-> <c- n>noop_coroutine</c-><c- p>();</c->
  <c- p>}</c->

  <i><c- n>operation</c-><c- o>-</c-><c- n>state</c-><c- o>-</c-><c- n>task</c-></i> <c- n>get_return_object</c-><c- p>()</c-> <c- k>noexcept</c-> <c- p>{</c->
    <c- k>return</c-> <i><c- n>operation</c-><c- o>-</c-><c- n>state</c-><c- o>-</c-><c- n>task</c-></i><c- p>{</c->
      <c- n>coroutine_handle</c-><c- o>&lt;</c-><i><c- n>connect</c-><c- o>-</c-><c- n>awaitable</c-><c- o>-</c-><c- n>promise</c-></i><c- o>>::</c-><c- n>from_promise</c-><c- p>(</c-><c- o>*</c-><c- k>this</c-><c- p>)};</c->
  <c- p>}</c->

  <c- k>friend</c-> <c- n>env_of_t</c-><c- o>&lt;</c-><c- k>const</c-> <c- n>DR</c-><c- o>&amp;></c-> <c- n>tag_invoke</c-><c- p>(</c-><c- n>get_env_t</c-><c- p>,</c-> <c- k>const</c-> <i><c- n>connect</c-><c- o>-</c-><c- n>awaitable</c-><c- o>-</c-><c- n>promise</c-></i><c- o>&amp;</c-> <c- n>self</c-><c- p>)</c-> <c- k>noexcept</c-> <c- p>{</c->
    <c- k>return</c-> <c- n>get_env</c-><c- p>(</c-><c- n>self</c-><c- p>.</c-><i><c- n>rcvr</c-></i><c- p>);</c->
  <c- p>}</c->
<c- p>};</c->
</pre>
    <li data-md>
     <p>Let <code class="highlight"><i><c- n>operation</c-><c- o>-</c-><c- n>state</c-><c- o>-</c-><c- n>task</c-></i></code> be the following class:</p>
<pre class="highlight"><c- k>struct</c-> <i><c- nc>operation</c-><c- o>-</c-><c- n>state</c-><c- o>-</c-><c- n>task</c-></i> <c- p>{</c->
  <c- k>using</c-> <c- n>promise_type</c-> <c- o>=</c-> <i><c- n>connect</c-><c- o>-</c-><c- n>awaitable</c-><c- o>-</c-><c- n>promise</c-></i><c- p>;</c->
  <c- n>coroutine_handle</c-><c- o>&lt;></c-> <i><c- n>coro</c-></i><c- p>;</c-> <i><c- c1>// exposition only</c-></i>

  <c- k>explicit</c-> <i><c- n>operation</c-><c- o>-</c-><c- n>state</c-><c- o>-</c-><c- n>task</c-></i><c- p>(</c-><c- n>coroutine_handle</c-><c- o>&lt;></c-> <c- n>h</c-><c- p>)</c-> <c- k>noexcept</c-> <c- o>:</c-> <i><c- n>coro</c-></i><c- p>(</c-><c- n>h</c-><c- p>)</c-> <c- p>{}</c->
  <i><c- n>operation</c-><c- o>-</c-><c- n>state</c-><c- o>-</c-><c- n>task</c-></i><c- p>(</c-><i><c- n>operation</c-><c- o>-</c-><c- n>state</c-><c- o>-</c-><c- n>task</c-></i><c- o>&amp;&amp;</c-> <c- n>o</c-><c- p>)</c-> <c- k>noexcept</c->
    <c- o>:</c-> <i><c- n>coro</c-></i><c- p>(</c-><c- n>exchange</c-><c- p>(</c-><c- n>o</c-><c- p>.</c-><i><c- n>coro</c-></i><c- p>,</c-> <c- p>{}))</c-> <c- p>{}</c->
  <c- o>~</c-><i><c- n>operation</c-><c- o>-</c-><c- n>state</c-><c- o>-</c-><c- n>task</c-></i><c- p>()</c-> <c- p>{</c-> <c- k>if</c-> <c- p>(</c-><i><c- n>coro</c-></i><c- p>)</c-> <i><c- n>coro</c-></i><c- p>.</c-><c- n>destroy</c-><c- p>();</c-> <c- p>}</c->

  <c- k>friend</c-> <c- b>void</c-> <c- n>tag_invoke</c-><c- p>(</c-><c- n>start_t</c-><c- p>,</c-> <i><c- n>operation</c-><c- o>-</c-><c- n>state</c-><c- o>-</c-><c- n>task</c-></i><c- o>&amp;</c-> <c- n>self</c-><c- p>)</c-> <c- k>noexcept</c-> <c- p>{</c->
    <c- n>self</c-><c- p>.</c-><i><c- n>coro</c-></i><c- p>.</c-><c- n>resume</c-><c- p>();</c->
  <c- p>}</c->
<c- p>};</c->
</pre>
    <li data-md>
     <p>Let <code class="highlight"><c- n>V</c-></code> name the type <code class="highlight"><i><c- n>await</c-><c- o>-</c-><c- n>result</c-><c- o>-</c-><c- n>type</c-></i><c- o>&lt;</c-><c- n>DS</c-><c- p>,</c-> <i><c- n>connect</c-><c- o>-</c-><c- n>awaitable</c-><c- o>-</c-><c- n>promise</c-></i><c- o>></c-></code>, let <code class="highlight"><c- n>Sigs</c-></code> name the type:</p>
<pre class="highlight"><c- n>completion_signatures</c-><c- o>&lt;</c->
  <i><c- n>SET</c-><c- o>-</c-><c- n>VALUE</c-><c- o>-</c-><c- n>SIG</c-></i><c- p>(</c-><c- n>V</c-><c- p>),</c-> <i><c- c1>// see [exec.snd.concepts]</c-></i>
  <c- n>set_error_t</c-><c- p>(</c-><c- n>exception_ptr</c-><c- p>),</c->
  <c- n>set_stopped_t</c-><c- p>()</c-><c- o>></c->
</pre>
     <p>and let <code class="highlight"><i><c- n>connect</c-><c- o>-</c-><c- n>awaitable</c-></i></code> be an exposition-only
coroutine defined as follows:</p>
<pre class="highlight"><c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Fun</c-><c- p>,</c-> <c- k>class</c-><c- p>...</c-> <c- n>Ts</c-><c- o>></c->
<c- k>auto</c-> <i><c- n>suspend</c-><c- o>-</c-><c- n>complete</c-></i><c- p>(</c-><c- n>Fun</c-> <c- n>fun</c-><c- p>,</c-> <c- n>Ts</c-><c- o>&amp;&amp;</c-><c- p>...</c-> <c- n>as</c-><c- p>)</c-> <c- k>noexcept</c-> <c- p>{</c-> <i><c- c1>// exposition only</c-></i>
  <c- k>auto</c-> <c- n>fn</c-> <c- o>=</c-> <c- p>[</c-><c- o>&amp;</c-><c- p>,</c-> <c- n>fun</c-><c- p>]()</c-> <c- k>noexcept</c-> <c- p>{</c-> <c- n>fun</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>Ts</c-><c- o>></c-><c- p>(</c-><c- n>as</c-><c- p>)...);</c-> <c- p>};</c->

  <c- k>struct</c-> <c- nc>awaiter</c-> <c- p>{</c->
    <c- k>decltype</c-><c- p>(</c-><c- n>fn</c-><c- p>)</c-> <i><c- n>fn_</c-></i><c- p>;</c->

    <c- k>static</c-> <c- b>bool</c-> <c- nf>await_ready</c-><c- p>()</c-> <c- k>noexcept</c-> <c- p>{</c-> <c- k>return</c-> false<c- p>;</c-> <c- p>}</c->
    <c- b>void</c-> <c- nf>await_suspend</c-><c- p>(</c-><c- n>coroutine_handle</c-><c- o>&lt;></c-><c- p>)</c-> <c- k>noexcept</c-> <c- p>{</c-> <i><c- n>fn_</c-></i><c- p>();</c-> <c- p>}</c->
    <c- p>[[</c-><c- n>noreturn</c-><c- p>]]</c-> <c- b>void</c-> <c- n>await_resume</c-><c- p>()</c-> <c- k>noexcept</c-> <c- p>{</c-> <c- n>unreachable</c-><c- p>();</c-> <c- p>}</c->
  <c- p>};</c->
  <c- k>return</c-> <c- n>awaiter</c-><c- p>{</c-><c- n>fn</c-><c- p>};</c->
<c- p>};</c->

<i><c- n>operation</c-><c- o>-</c-><c- n>state</c-><c- o>-</c-><c- n>task</c-></i> <i><c- n>connect</c-><c- o>-</c-><c- n>awaitable</c-></i><c- p>(</c-><c- n>DS</c-> <c- n>sndr</c-><c- p>,</c-> <c- n>DR</c-> <c- n>rcvr</c-><c- p>)</c-> <c- k>requires</c-> <c- n>receiver_of</c-><c- o>&lt;</c-><c- n>DR</c-><c- p>,</c-> <c- n>Sigs</c-><c- o>></c-> <c- p>{</c->
  <c- n>exception_ptr</c-> <c- n>ep</c-><c- p>;</c->
  <c- k>try</c-> <c- p>{</c->
    <c- k>if</c-> <c- k>constexpr</c-> <c- p>(</c-><c- n>same_as</c-><c- o>&lt;</c-><c- n>V</c-><c- p>,</c-> <c- b>void</c-><c- o>></c-><c- p>)</c-> <c- p>{</c->
      <c- k>co_await</c-> <c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>sndr</c-><c- p>);</c->
      <c- k>co_await</c-> <i><c- n>suspend</c-><c- o>-</c-><c- n>complete</c-></i><c- p>(</c-><c- n>set_value</c-><c- p>,</c-> <c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>rcvr</c-><c- p>));</c->
    <c- p>}</c-> <c- k>else</c-> <c- p>{</c->
      <c- k>co_await</c-> <i><c- n>suspend</c-><c- o>-</c-><c- n>complete</c-></i><c- p>(</c-><c- n>set_value</c-><c- p>,</c-> <c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>rcvr</c-><c- p>),</c-> <c- k>co_await</c-> <c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>sndr</c-><c- p>));</c->
    <c- p>}</c->
  <c- p>}</c-> <c- k>catch</c-><c- p>(...)</c-> <c- p>{</c->
    <c- n>ep</c-> <c- o>=</c-> <c- n>current_exception</c-><c- p>();</c->
  <c- p>}</c->
  <c- k>co_await</c-> <i><c- n>suspend</c-><c- o>-</c-><c- n>complete</c-></i><c- p>(</c-><c- n>set_error</c-><c- p>,</c-> <c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>rcvr</c-><c- p>),</c-> <c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>ep</c-><c- p>));</c->
<c- p>}</c->
</pre>
    <li data-md>
     <p>If <code class="highlight"><c- n>Sndr</c-></code> does not satisfy <code class="highlight"><c- n>sender</c-></code> or if <code class="highlight"><c- n>Rcvr</c-></code> does not satisfy <code class="highlight"><c- n>receiver</c-></code>, <code class="highlight"><c- n>connect</c-><c- p>(</c-><c- n>sndr</c-><c- p>,</c-> <c- n>rcvr</c-><c- p>)</c-></code> is ill-formed. Otherwise, the expression <code class="highlight"><c- n>connect</c-><c- p>(</c-><c- n>sndr</c-><c- p>,</c-> <c- n>rcvr</c-><c- p>)</c-></code> is
expression-equivalent to:</p>
     <ol>
      <li data-md>
       <p><code class="highlight"><c- n>tag_invoke</c-><c- p>(</c-><c- n>connect</c-><c- p>,</c-> <c- n>sndr</c-><c- p>,</c-> <c- n>rcvr</c-><c- p>)</c-></code> if <code class="highlight"><i><c- n>connectable</c-><c- o>-</c-><c- n>with</c-><c- o>-</c-><c- n>tag</c-><c- o>-</c-><c- n>invoke</c-></i><c- o>&lt;</c-><c- n>Sndr</c-><c- p>,</c-> <c- n>Rcvr</c-><c- o>></c-></code> is modeled.</p>
       <ul>
        <li data-md>
         <p><i>Mandates:</i> The type of the <code class="highlight"><c- n>tag_invoke</c-></code> expression above
satisfies <code class="highlight"><c- n>operation_state</c-></code>.</p>
       </ul>
      <li data-md>
       <p>Otherwise, <code class="highlight"><i><c- n>connect</c-><c- o>-</c-><c- n>awaitable</c-></i><c- p>(</c-><c- n>sndr</c-><c- p>,</c-> <c- n>rcvr</c-><c- p>)</c-></code> if that expression is
well-formed.</p>
      <li data-md>
       <p>Otherwise, <code class="highlight"><c- n>connect</c-><c- p>(</c-><c- n>sndr</c-><c- p>,</c-> <c- n>rcvr</c-><c- p>)</c-></code> is ill-formed.</p>
     </ol>
   </ol>
   <h4 class="heading settled" data-level="11.9.9" id="spec-execution.senders.factories"><span class="secno">11.9.9. </span><span class="content">Sender factories <b>[exec.factories]</b></span><a class="self-link" href="#spec-execution.senders.factories"></a></h4>
   <h5 class="heading settled" data-level="11.9.9.1" id="spec-execution.senders.schedule"><span class="secno">11.9.9.1. </span><span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>schedule</c-></code> <b>[exec.schedule]</b></span><a class="self-link" href="#spec-execution.senders.schedule"></a></h5>
   <ol>
    <li data-md>
     <p><code class="highlight"><c- n>schedule</c-></code> obtains a schedule-sender ([async.ops]) from a scheduler.</p>
    <li data-md>
     <p>The name <code class="highlight"><c- n>schedule</c-></code> denotes a customization point object. For some
subexpression <code class="highlight"><c- n>sch</c-></code>, the expression <code class="highlight"><c- n>schedule</c-><c- p>(</c-><c- n>sch</c-><c- p>)</c-></code> is expression-equivalent to:</p>
     <ol>
      <li data-md>
       <p><code class="highlight"><c- n>tag_invoke</c-><c- p>(</c-><c- n>schedule</c-><c- p>,</c-> <c- n>sch</c-><c- p>)</c-></code>, if that expression is valid. If the function
selected by <code class="highlight"><c- n>tag_invoke</c-></code> does not return a sender whose <code class="highlight"><c- n>set_value</c-></code> completion scheduler is equivalent to <code class="highlight"><c- n>sch</c-></code>, the behavior of calling <code class="highlight"><c- n>schedule</c-><c- p>(</c-><c- n>sch</c-><c- p>)</c-></code> is undefined.</p>
       <ul>
        <li data-md>
         <p><i>Mandates:</i> The type of the <code class="highlight"><c- n>tag_invoke</c-></code> expression above
satisfies <code class="highlight"><c- n>sender</c-></code>.</p>
       </ul>
      <li data-md>
       <p>Otherwise, <code class="highlight"><c- n>schedule</c-><c- p>(</c-><c- n>sch</c-><c- p>)</c-></code> is ill-formed.</p>
     </ol>
   </ol>
   <h5 class="heading settled" data-level="11.9.9.2" id="spec-execution.senders.just"><span class="secno">11.9.9.2. </span><span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>just</c-></code>, <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>just_error</c-></code>, <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>just_stopped</c-></code> <b>[exec.just]</b></span><a class="self-link" href="#spec-execution.senders.just"></a></h5>
   <ol>
    <li data-md>
     <p><code class="highlight"><c- n>just</c-></code>, <code class="highlight"><c- n>just_error</c-></code>, and <code class="highlight"><c- n>just_stopped</c-></code> are sender factories whose
asynchronous operations complete synchronously in their start operation
with a value completion operation, an error completion operation, or a
stopped completion operation respectively.</p>
    <li data-md>
     <p>The names <code class="highlight"><c- n>just</c-></code>, <code class="highlight"><c- n>just_error</c-></code>, and <code class="highlight"><c- n>just_stopped</c-></code> denote customization
point objects. Let <code class="highlight"><i><c- n>just</c-><c- o>-</c-><c- n>cpo</c-></i></code> be one of <code class="highlight"><c- n>just</c-></code>, <code class="highlight"><c- n>just_error</c-></code>, or <code class="highlight"><c- n>just_stopped</c-></code>. For a pack of subexpressions <code class="highlight"><c- n>ts</c-></code>, let <code class="highlight"><c- n>Ts</c-></code> be the template parameter pack <code class="highlight"><c- k>decltype</c-><c- p>((</c-><c- n>ts</c-><c- p>))</c-></code>. The expression <code class="highlight"><i><c- n>just</c-><c- o>-</c-><c- n>cpo</c-></i><c- p>(</c-><c- n>ts</c-><c- p>...)</c-></code> is ill-formed if:</p>
     <ul>
      <li data-md>
       <p><code class="highlight"><c- p>(</c-><i><c- n>movable</c-><c- o>-</c-><c- n>value</c-></i><c- o>&lt;</c-><c- n>Ts</c-><c- o>></c-> <c- o>&amp;&amp;</c-><c- p>...)</c-></code> is <code class="highlight">false</code>, or</p>
      <li data-md>
       <p><code class="highlight"><i><c- n>just</c-><c- o>-</c-><c- n>cpo</c-></i></code> is <code class="highlight"><c- n>just_error</c-></code> and <code class="highlight"><c- k>sizeof</c-><c- p>...(</c-><c- n>ts</c-><c- p>)</c-> <c- o>==</c-> <c- mi>1</c-></code> is <code class="highlight">false</code>, or</p>
      <li data-md>
       <p><code class="highlight"><i><c- n>just</c-><c- o>-</c-><c- n>cpo</c-></i></code> is <code class="highlight"><c- n>just_stopped</c-></code> and <code class="highlight"><c- k>sizeof</c-><c- p>...(</c-><c- n>ts</c-><c- p>)</c-> <c- o>==</c-> <c- mi>0</c-></code> is <code class="highlight">false</code>;</p>
     </ul>
     <p>Otherwise, it is expression-equivalent to <code class="highlight"><i><c- n>make</c-><c- o>-</c-><c- n>sender</c-></i><c- p>(</c-><i><c- n>just</c-><c- o>-</c-><c- n>cpo</c-></i><c- p>,</c-> <i><c- n>product</c-><c- o>-</c-><c- n>type</c-></i><c- p>{</c-><c- n>vs</c-><c- p>...})</c-></code>.</p>
    <li data-md>
     <p>For <code class="highlight"><c- n>just</c-></code>, <code class="highlight"><c- n>just_error</c-></code>, and <code class="highlight"><c- n>just_stopped</c-></code>, let <code class="highlight"><i><c- n>set</c-><c- o>-</c-><c- n>cpo</c-></i></code> be <code class="highlight"><c- n>set_value</c-></code>, <code class="highlight"><c- n>set_error</c-></code>, and <code class="highlight"><c- n>set_stopped</c-></code> respectively. The
exposition-only class template <code class="highlight"><i><c- n>impls</c-><c- o>-</c-><c- k>for</c-></i></code> ([exec.snd.general]) is specialized for <code class="highlight"><i><c- n>just</c-><c- o>-</c-><c- n>cpo</c-></i></code> as
follows:</p>
<pre class="highlight"><c- k>template</c-><c- o>&lt;></c->
<c- k>struct</c-> <i><c- nc>impls</c-><c- o>-</c-><c- k>for</c-></i><c- o>&lt;</c-><c- n>tag_t</c-><c- o>&lt;</c-><i><c- n>just</c-><c- o>-</c-><c- n>cpo</c-></i><c- o>>></c-> <c- o>:</c-> <i><c- k>default</c-><c- o>-</c-><c- n>impls</c-></i> <c- p>{</c->
  <c- k>static</c-> <c- k>constexpr</c-> <c- k>auto</c-> <c- n>start</c-> <c- o>=</c->
    <c- p>[](</c-><c- k>auto</c-><c- o>&amp;</c-> <c- n>state</c-><c- p>,</c-> <c- k>auto</c-><c- o>&amp;</c-> <c- n>rcvr</c-><c- p>)</c-> <c- k>noexcept</c-> <c- o>-></c-> <c- b>void</c-> <c- p>{</c->
      <c- k>auto</c-><c- o>&amp;</c-> <c- p>[...</c-><c- n>ts</c-><c- p>]</c-> <c- o>=</c-> <c- n>state</c-><c- p>;</c->
      <i><c- n>set</c-><c- o>-</c-><c- n>cpo</c-></i><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>rcvr</c-><c- p>),</c-> <c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>ts</c-><c- p>)...);</c->
    <c- p>};</c->
<c- p>};</c->
</pre>
   </ol>
   <h5 class="heading settled" data-level="11.9.9.3" id="spec-execution.senders.read"><span class="secno">11.9.9.3. </span><span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>read</c-></code> <b>[exec.read]</b></span><a class="self-link" href="#spec-execution.senders.read"></a></h5>
   <ol>
    <li data-md>
     <p><code class="highlight"><c- n>read</c-></code> is a sender factory for a sender whose asynchronous operation
completes synchronously in its start operation with a value completion
result equal to a value read from the receiver’s associated environment.</p>
    <li data-md>
     <p><code class="highlight"><c- n>read</c-></code> is a customization point object. For some query object <code class="highlight"><c- n>q</c-></code>,
the expression <code class="highlight"><c- n>read</c-><c- p>(</c-><c- n>q</c-><c- p>)</c-></code> is expression-equivalent to <code class="highlight"><i><c- n>make</c-><c- o>-</c-><c- n>sender</c-></i><c- p>(</c-><c- n>read</c-><c- p>,</c-> <c- n>q</c-><c- p>)</c-></code>.</p>
    <li data-md>
     <p>The exposition-only class template <code class="highlight"><i><c- n>impls</c-><c- o>-</c-><c- k>for</c-></i></code> ([exec.snd.general])
is specialized for <code class="highlight"><c- n>read</c-></code> as follows:</p>
<pre class="highlight"><c- k>template</c-><c- o>&lt;></c->
<c- k>struct</c-> <i><c- nc>impls</c-><c- o>-</c-><c- k>for</c-></i><c- o>&lt;</c-><c- n>tag_t</c-><c- o>&lt;</c-><c- n>read</c-><c- o>>></c-> <c- o>:</c-> <i><c- k>default</c-><c- o>-</c-><c- n>impls</c-></i> <c- p>{</c->
  <c- k>static</c-> <c- k>constexpr</c-> <c- k>auto</c-> <c- n>start</c-> <c- o>=</c-> <c- p>[](</c-><c- k>auto</c-> <c- n>query</c-><c- p>,</c-> <c- k>auto</c-><c- o>&amp;</c-> <c- n>rcvr</c-><c- p>)</c-> <c- k>noexcept</c-> <c- o>-></c-> <c- b>void</c-> <c- p>{</c->
    <i><c- n>TRY</c-><c- o>-</c-><c- n>SET</c-><c- o>-</c-><c- n>VALUE</c-></i><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>rcvr</c-><c- p>),</c-> <c- n>query</c-><c- p>(</c-><c- n>get_env</c-><c- p>(</c-><c- n>rcvr</c-><c- p>)));</c->
  <c- p>};</c->
<c- p>};</c->
</pre>
   </ol>
   <h4 class="heading settled" data-level="11.9.10" id="spec-execution.senders.adapt"><span class="secno">11.9.10. </span><span class="content">Sender adaptors <b>[exec.adapt]</b></span><a class="self-link" href="#spec-execution.senders.adapt"></a></h4>
   <h5 class="heading settled" data-level="11.9.10.1" id="spec-execution.senders.adapt.general"><span class="secno">11.9.10.1. </span><span class="content">General <b>[exec.adapt.general]</b></span><a class="self-link" href="#spec-execution.senders.adapt.general"></a></h5>
   <ol>
    <li data-md>
     <p>Subclause [exec.adapt] specifies a set of sender adaptors.</p>
    <li data-md>
     <p>The bitwise OR operator is overloaded for the purpose of creating sender
chains. The adaptors also support function call syntax with equivalent
semantics.</p>
    <li data-md>
     <p>Unless otherwise specified, a sender adaptor is required to not begin
executing any functions that would observe or modify any of the arguments
of the adaptor before the returned sender is connected with a receiver using <code class="highlight"><c- n>connect</c-></code>, and <code class="highlight"><c- n>start</c-></code> is called on the resulting operation state. This
requirement applies to any function that is selected by the implementation
of the sender adaptor.</p>
    <li data-md>
     <p>Unless otherwise specified, a parent sender ([async.ops]) with a single child
sender <code class="highlight"><c- n>sndr</c-></code> has an associated attribute object equal to <code class="highlight"><i><c- n>FWD</c-><c- o>-</c-><c- n>ENV</c-></i><c- p>(</c-><c- n>get_env</c-><c- p>(</c-><c- n>sndr</c-><c- p>))</c-></code> ([exec.fwd.env]). Unless
otherwise specified, a parent sender with more than one child senders has an
associated attributes object equal to <code class="highlight"><c- n>empty_env</c-><c- p>{}</c-></code>. These
requirements apply to any function that is selected by the implementation of
the sender adaptor.</p>
    <li data-md>
     <p>Unless otherwise specified, when a parent sender is connected to a receiver <code class="highlight"><c- n>rcvr</c-></code>, any receiver used to connect a child sender has an associated
environment equal to <code class="highlight"><i><c- n>FWD</c-><c- o>-</c-><c- n>ENV</c-></i><c- p>(</c-><c- n>get_env</c-><c- p>(</c-><c- n>rcvr</c-><c- p>))</c-></code>. This
requirements applies to any sender returned from a function that is selected
by the implementation of such sender adaptor.</p>
    <li data-md>
     <p>For any sender type, receiver type, operation state type, queryable type, or
coroutine promise type that is part of the implementation of any sender
adaptor in this subclause and that is a class template, the template
arguments do not contribute to the associated entities
([basic.lookup.argdep]) of a function call where a specialization of the
class template is an associated entity.</p>
     <p>[<em>Example:</em></p>
<pre class="highlight"><c- k>namespace</c-> <i><c- nn>sender</c-><c- o>-</c-><c- nn>adaptors</c-></i> <c- p>{</c-> <c- c1>// exposition only</c->
  <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Sch</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Sndr</c-><c- o>></c-> <c- c1>// arguments are not associated entities ([lib.tmpl-heads])</c->
  <c- k>class</c-> <i><c- nc>on</c-><c- o>-</c-><c- n>sender</c-></i> <c- p>{</c->
    <c- c1>// ...</c->
  <c- p>};</c->

  <c- k>struct</c-> <c- nc>on_t</c-> <c- p>{</c->
    <c- k>template</c-><c- o>&lt;</c-><c- n>scheduler</c-> <c- n>Sch</c-><c- p>,</c-> <c- n>sender</c-> <c- n>Sndr</c-><c- o>></c->
    <i><c- n>on</c-><c- o>-</c-><c- n>sender</c-></i><c- o>&lt;</c-><c- n>Sch</c-><c- p>,</c-> <c- n>Sndr</c-><c- o>></c-> <c- k>operator</c-><c- p>()(</c-><c- n>Sch</c-><c- o>&amp;&amp;</c-> <c- n>sch</c-><c- p>,</c-> <c- n>Sndr</c-><c- o>&amp;&amp;</c-> <c- n>sndr</c-><c- p>)</c-> <c- k>const</c-> <c- p>{</c->
      <c- c1>// ...</c->
    <c- p>}</c->
  <c- p>};</c->
<c- p>}</c->
<c- kr>inline</c-> <c- k>constexpr</c-> <i><c- n>sender</c-><c- o>-</c-><c- n>adaptors</c-></i><c- o>::</c-><c- n>on_t</c-> <c- n>on</c-><c- p>{};</c->
</pre>
     <p>-- <i>end example</i>]</p>
    <li data-md>
     <p>If a sender returned from a sender adaptor specified in this subclause is
specified to include <code class="highlight"><c- n>set_error_t</c-><c- p>(</c-><c- n>Err</c-><c- p>)</c-></code> among its set of completion signatures
where <code class="highlight"><c- n>decay_t</c-><c- o>&lt;</c-><c- n>Err</c-><c- o>></c-></code> denotes the type <code class="highlight"><c- n>exception_ptr</c-></code>, but the implementation
does not potentially evaluate an error completion operation with an <code class="highlight"><c- n>exception_ptr</c-></code> argument, the implementation is allowed to omit the <code class="highlight"><c- n>exception_ptr</c-></code> error completion signature from the set.</p>
   </ol>
   <h5 class="heading settled" data-level="11.9.10.2" id="spec-execution.senders.adaptor.objects"><span class="secno">11.9.10.2. </span><span class="content">Sender adaptor closure objects <b>[exec.adapt.objects]</b></span><a class="self-link" href="#spec-execution.senders.adaptor.objects"></a></h5>
   <ol>
    <li data-md>
     <p>A <i>pipeable sender adaptor closure object</i> is a function object that
accepts one or more <code class="highlight"><c- n>sender</c-></code> arguments and returns a <code class="highlight"><c- n>sender</c-></code>. For a sender
adaptor closure object <code class="highlight"><c- n>c</c-></code> and an expression <code class="highlight"><c- n>sndr</c-></code> such that <code class="highlight"><c- k>decltype</c-><c- p>((</c-><c- n>sndr</c-><c- p>))</c-></code> models <code class="highlight"><c- n>sender</c-></code>, the following expressions are equivalent
and yield a <code class="highlight"><c- n>sender</c-></code>:</p>
<pre class="highlight"><c- n>c</c-><c- p>(</c-><c- n>sndr</c-><c- p>)</c->
<c- n>sndr</c-> <c- o>|</c-> <c- n>c</c->
</pre>
     <p>Given an additional pipeable sender adaptor closure object <code class="highlight"><c- n>d</c-></code>, the expression <code class="highlight"><c- n>c</c-> <c- o>|</c-> <c- n>d</c-></code> produces another pipeable sender adaptor closure object <code class="highlight"><c- n>e</c-></code>:</p>
     <p><code class="highlight"><c- n>e</c-></code> is a perfect forwarding call wrapper ([func.require]) with the following properties:</p>
     <ul>
      <li data-md>
       <p>Its target object is an object <code class="highlight"><c- n>d2</c-></code> of type <code class="highlight"><c- n>decay_t</c-><c- o>&lt;</c-><c- k>decltype</c-><c- p>((</c-><c- n>d</c-><c- p>))</c-><c- o>></c-></code> direct-non-list-initialized with <code class="highlight"><c- n>d</c-></code>.</p>
      <li data-md>
       <p>It has one bound argument entity, an object <code class="highlight"><c- n>c2</c-></code> of type <code class="highlight"><c- n>decay_t</c-><c- o>&lt;</c-><c- k>decltype</c-><c- p>((</c-><c- n>c</c-><c- p>))</c-><c- o>></c-></code> direct-non-list-initialized with <code class="highlight"><c- n>C</c-></code>.</p>
      <li data-md>
       <p>Its call pattern is <code class="highlight"><c- n>d2</c-><c- p>(</c-><c- n>c2</c-><c- p>(</c-><c- n>arg</c-><c- p>))</c-></code>, where <code class="highlight"><c- n>arg</c-></code> is the argument used in a function call expression of <code class="highlight"><c- n>e</c-></code>.</p>
     </ul>
     <p>The expression <code class="highlight"><c- n>c</c-> <c- o>|</c-> <c- n>d</c-></code> is well-formed if and only if the initializations of the state entities of <code class="highlight"><c- n>e</c-></code> are all well-formed.</p>
    <li data-md>
     <p>An object <code class="highlight"><c- n>t</c-></code> of type <code class="highlight"><c- n>T</c-></code> is a pipeable sender adaptor closure object if <code class="highlight"><c- n>T</c-></code> models <code class="highlight"><c- n>derived_from</c-><c- o>&lt;</c-><c- n>sender_adaptor_closure</c-><c- o>&lt;</c-><c- n>T</c-><c- o>>></c-></code>, <code class="highlight"><c- n>T</c-></code> has no other base
classes of type <code class="highlight"><c- n>sender_adaptor_closure</c-><c- o>&lt;</c-><c- n>U</c-><c- o>></c-></code> for any other type <code class="highlight"><c- n>U</c-></code>, and <code class="highlight"><c- n>T</c-></code> does not model <code class="highlight"><c- n>sender</c-></code>.</p>
    <li data-md>
     <p>The template parameter <code class="highlight"><c- n>D</c-></code> for <code class="highlight"><c- n>sender_adaptor_closure</c-></code> can be an incomplete type. Before any expression of type <code class="highlight"><i><c- n>cv</c-></i> <c- n>D</c-></code> appears as
an operand to the <code class="highlight"><c- o>|</c-></code> operator, <code class="highlight"><c- n>D</c-></code> shall be complete and model <code class="highlight"><c- n>derived_from</c-><c- o>&lt;</c-><c- n>sender_adaptor_closure</c-><c- o>&lt;</c-><c- n>D</c-><c- o>>></c-></code>. The behavior of an expression involving an
object of type <code class="highlight"><i><c- n>cv</c-></i> <c- n>D</c-></code> as an operand to the <code class="highlight"><c- o>|</c-></code> operator is undefined if overload resolution selects a program-defined <code class="highlight"><c- k>operator</c-><c- o>|</c-></code> function.</p>
    <li data-md>
     <p>A <i>pipeable sender adaptor object</i> is a customization point object that accepts a <code class="highlight"><c- n>sender</c-></code> as its first argument and returns a <code class="highlight"><c- n>sender</c-></code>.</p>
    <li data-md>
     <p>If a pipeable sender adaptor object accepts only one argument, then it is a pipeable sender adaptor closure object.</p>
    <li data-md>
     <p>If a pipeable sender adaptor object <code class="highlight"><c- n>adaptor</c-></code> accepts more than one argument, then let <code class="highlight"><c- n>sndr</c-></code> be an expression such that <code class="highlight"><c- k>decltype</c-><c- p>((</c-><c- n>sndr</c-><c- p>))</c-></code> models <code class="highlight"><c- n>sender</c-></code>,
let <code class="highlight"><c- n>args</c-><c- p>...</c-></code> be arguments such that <code class="highlight"><c- n>adaptor</c-><c- p>(</c-><c- n>sndr</c-><c- p>,</c-> <c- n>args</c-><c- p>...)</c-></code> is a well-formed expression as specified in the rest of this subclause
([exec.adapt.objects]), and let <code class="highlight"><c- n>BoundArgs</c-></code> be a pack that denotes <code class="highlight"><c- n>decay_t</c-><c- o>&lt;</c-><c- k>decltype</c-><c- p>((</c-><c- n>args</c-><c- p>))</c-><c- o>></c-><c- p>...</c-></code>. The expression <code class="highlight"><c- n>adaptor</c-><c- p>(</c-><c- n>args</c-><c- p>...)</c-></code> produces a pipeable sender adaptor closure object <code class="highlight"><c- n>f</c-></code> that is a perfect forwarding call wrapper with the following properties:</p>
     <ul>
      <li data-md>
       <p>Its target object is a copy of <code class="highlight"><c- n>adaptor</c-></code>.</p>
      <li data-md>
       <p>Its bound argument entities <code class="highlight"><c- n>bound_args</c-></code> consist of objects of types <code class="highlight"><c- n>BoundArgs</c-><c- p>...</c-></code> direct-non-list-initialized with <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- k>decltype</c-><c- p>((</c-><c- n>args</c-><c- p>))</c-><c- o>></c-><c- p>(</c-><c- n>args</c-><c- p>)...</c-></code>, respectively.</p>
      <li data-md>
       <p>Its call pattern is <code class="highlight"><c- n>adaptor</c-><c- p>(</c-><c- n>rcvr</c-><c- p>,</c-> <c- n>bound_args</c-><c- p>...)</c-></code>, where <code class="highlight"><c- n>rcvr</c-></code> is the argument used in a function call expression of <code class="highlight"><c- n>f</c-></code>.</p>
     </ul>
     <p>The expression <code class="highlight"><c- n>adaptor</c-><c- p>(</c-><c- n>args</c-><c- p>...)</c-></code> is well-formed if and only if the initializations of the bound argument entities of the result, as specified above,
 are all well-formed.</p>
   </ol>
   <h5 class="heading settled" data-level="11.9.10.3" id="spec-execution.senders.adapt.on"><span class="secno">11.9.10.3. </span><span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>on</c-></code> <b>[exec.on]</b></span><a class="self-link" href="#spec-execution.senders.adapt.on"></a></h5>
   <ol>
    <li data-md>
     <p><code class="highlight"><c- n>on</c-></code> adapts an input sender into a sender that will start on an execution
agent belonging to a particular scheduler’s associated execution resource.</p>
    <li data-md>
     <p>The name <code class="highlight"><c- n>on</c-></code> denotes a customization point object. For some subexpressions <code class="highlight"><c- n>sch</c-></code> and <code class="highlight"><c- n>sndr</c-></code>, if <code class="highlight"><c- k>decltype</c-><c- p>((</c-><c- n>sch</c-><c- p>))</c-></code> does not satisfy <code class="highlight"><c- n>scheduler</c-></code>, or <code class="highlight"><c- k>decltype</c-><c- p>((</c-><c- n>sndr</c-><c- p>))</c-></code> does not satisfy <code class="highlight"><c- n>sender</c-></code>, <code class="highlight"><c- n>on</c-><c- p>(</c-><c- n>sch</c-><c- p>,</c-> <c- n>sndr</c-><c- p>)</c-></code> is ill-formed.</p>
    <li data-md>
     <p>Otherwise, the expression <code class="highlight"><c- n>on</c-><c- p>(</c-><c- n>sch</c-><c- p>,</c-> <c- n>sndr</c-><c- p>)</c-></code> is expression-equivalent to:</p>
<pre class="highlight"><c- n>transform_sender</c-><c- p>(</c->
  <i><c- n>query</c-><c- o>-</c-><c- n>or</c-><c- o>-</c-><c- k>default</c-></i><c- p>(</c-><c- n>get_domain</c-><c- p>,</c-> <c- n>sch</c-><c- p>,</c-> <c- n>default_domain</c-><c- p>()),</c->
  <i><c- n>make</c-><c- o>-</c-><c- n>sender</c-></i><c- p>(</c-><c- n>on</c-><c- p>,</c-> <c- n>sch</c-><c- p>,</c-> <c- n>sndr</c-><c- p>));</c->
</pre>
    <li data-md>
     <p>Let <code class="highlight"><c- n>out_sndr</c-></code> and <code class="highlight"><c- n>env</c-></code> be subexpressions such that <code class="highlight"><c- n>OutSndr</c-></code> is <code class="highlight"><c- k>decltype</c-><c- p>((</c-><c- n>out_sndr</c-><c- p>))</c-></code>. If <code class="highlight"><i><c- n>sender</c-><c- o>-</c-><c- k>for</c-></i><c- o>&lt;</c-><c- n>OutSndr</c-><c- p>,</c-> <c- n>on_t</c-><c- o>></c-></code> is <code class="highlight">false</code>, then the expressions <code class="highlight"><c- n>on</c-><c- p>.</c-><c- n>transform_env</c-><c- p>(</c-><c- n>out_sndr</c-><c- p>,</c-> <c- n>env</c-><c- p>)</c-></code> and <code class="highlight"><c- n>on</c-><c- p>.</c-><c- n>transform_sender</c-><c- p>(</c-><c- n>out_sndr</c-><c- p>,</c-> <c- n>env</c-><c- p>)</c-></code> are ill-formed;
otherwise:</p>
     <ul>
      <li data-md>
       <p><code class="highlight"><c- n>on</c-><c- p>.</c-><c- n>transform_env</c-><c- p>(</c-><c- n>out_sndr</c-><c- p>,</c-> <c- n>env</c-><c- p>)</c-></code> is equivalent to:</p>
<pre class="highlight"><c- k>auto</c-><c- o>&amp;&amp;</c-> <c- p>[</c-><c- n>ign1</c-><c- p>,</c-> <c- n>sch</c-><c- p>,</c-> <c- n>ign2</c-><c- p>]</c-> <c- o>=</c-> <c- n>out_sndr</c-><c- p>;</c->
<c- k>return</c-> <i><c- n>JOIN</c-><c- o>-</c-><c- n>ENV</c-></i><c- p>(</c-><i><c- n>SCHED</c-><c- o>-</c-><c- n>ENV</c-></i><c- p>(</c-><c- n>sch</c-><c- p>),</c-> <i><c- n>FWD</c-><c- o>-</c-><c- n>ENV</c-></i><c- p>(</c-><c- n>env</c-><c- p>));</c->
</pre>
      <li data-md>
       <p><code class="highlight"><c- n>on</c-><c- p>.</c-><c- n>transform_sender</c-><c- p>(</c-><c- n>out_sndr</c-><c- p>,</c-> <c- n>env</c-><c- p>)</c-></code> is equivalent to:</p>
<pre class="highlight"><c- k>auto</c-><c- o>&amp;&amp;</c-> <c- p>[</c-><c- n>ign</c-><c- p>,</c-> <c- n>sch</c-><c- p>,</c-> <c- n>sndr</c-><c- p>]</c-> <c- o>=</c-> <c- n>out_sndr</c-><c- p>;</c->
<c- k>return</c-> <c- n>let_value</c-><c- p>(</c->
  <c- n>schedule</c-><c- p>(</c-><c- n>sch</c-><c- p>),</c->
  <c- p>[</c-><c- n>sndr</c-> <c- o>=</c-> <c- n>std</c-><c- o>::</c-><c- n>forward_like</c-><c- o>&lt;</c-><c- n>OutSndr</c-><c- o>></c-><c- p>(</c-><c- n>sndr</c-><c- p>)]()</c-> <c- k>mutable</c-> <c- p>{</c->
    <c- k>return</c-> <c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>sndr</c-><c- p>);</c->
  <c- p>});</c->
</pre>
     </ul>
    <li data-md>
     <p>Let <code class="highlight"><c- n>out_sndr</c-></code> be a subexpression denoting a sender returned from <code class="highlight"><c- n>on</c-><c- p>(</c-><c- n>sch</c-><c- p>,</c-> <c- n>sndr</c-><c- p>)</c-></code> or one equal to such, and let <code class="highlight"><c- n>OutSndr</c-></code> be the type <code class="highlight"><c- k>decltype</c-><c- p>((</c-><c- n>out_sndr</c-><c- p>))</c-></code>. Let <code class="highlight"><c- n>out_rcvr</c-></code> be a subexpression denoting a receiver that has an environment of
type <code class="highlight"><c- n>Env</c-></code> such that <code class="highlight"><c- n>sender_in</c-><c- o>&lt;</c-><c- n>OutSndr</c-><c- p>,</c-> <c- n>Env</c-><c- o>></c-></code> is <code class="highlight">true</code>. Let <code class="highlight"><c- n>op</c-></code> be an lvalue
referring to the operation state that results from connecting <code class="highlight"><c- n>out_sndr</c-></code> with <code class="highlight"><c- n>out_rcvr</c-></code>. Calling <code class="highlight"><c- n>start</c-><c- p>(</c-><c- n>op</c-><c- p>)</c-></code> shall start <code class="highlight"><c- n>sndr</c-></code> on an execution agent of the
associated execution resource of <code class="highlight"><c- n>sch</c-></code>, or failing that, shall execute an
error completion on <code class="highlight"><c- n>out_rcvr</c-></code>.</p>
   </ol>
   <h5 class="heading settled" data-level="11.9.10.4" id="spec-execution.senders.adapt.transfer"><span class="secno">11.9.10.4. </span><span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>transfer</c-></code> <b>[exec.transfer]</b></span><a class="self-link" href="#spec-execution.senders.adapt.transfer"></a></h5>
   <ol>
    <li data-md>
     <p><code class="highlight"><c- n>transfer</c-></code> adapts a sender into one with a different associated <code class="highlight"><c- n>set_value</c-></code> completion scheduler. <span class="wg21note">It results in a transition
between different execution resources when executed.</span></p>
    <li data-md>
     <p>The name <code class="highlight"><c- n>transfer</c-></code> denotes a customization point object. For some
subexpressions <code class="highlight"><c- n>sch</c-></code> and <code class="highlight"><c- n>sndr</c-></code>, if <code class="highlight"><c- k>decltype</c-><c- p>((</c-><c- n>sch</c-><c- p>))</c-></code> does not satisfy <code class="highlight"><c- n>scheduler</c-></code>, or <code class="highlight"><c- k>decltype</c-><c- p>((</c-><c- n>sndr</c-><c- p>))</c-></code> does not satisfy <code class="highlight"><c- n>sender</c-></code>, <code class="highlight"><c- n>transfer</c-><c- p>(</c-><c- n>sndr</c-><c- p>,</c-> <c- n>sch</c-><c- p>)</c-></code> is ill-formed.</p>
    <li data-md>
     <p>Otherwise, the expression <code class="highlight"><c- n>transfer</c-><c- p>(</c-><c- n>sndr</c-><c- p>,</c-> <c- n>sch</c-><c- p>)</c-></code> is expression-equivalent to:</p>
<pre class="highlight"><c- n>transform_sender</c-><c- p>(</c->
  <i><c- n>get</c-><c- o>-</c-><c- n>domain</c-><c- o>-</c-><c- n>early</c-></i><c- p>(</c-><c- n>sndr</c-><c- p>),</c->
  <i><c- n>make</c-><c- o>-</c-><c- n>sender</c-></i><c- p>(</c-><c- n>transfer</c-><c- p>,</c-> <c- n>sch</c-><c- p>,</c-> <c- n>sndr</c-><c- p>));</c->
</pre>
    <li data-md>
     <p>The exposition-only class template <code class="highlight"><i><c- n>impls</c-><c- o>-</c-><c- k>for</c-></i></code> is specialized
for <code class="highlight"><c- n>transfer_t</c-></code> as follows:</p>
<pre class="highlight"><c- k>template</c-><c- o>&lt;></c->
<c- k>struct</c-> <i><c- nc>impls</c-><c- o>-</c-><c- k>for</c-></i><c- o>&lt;</c-><c- n>transfer_t</c-><c- o>></c-> <c- o>:</c-> <i><c- k>default</c-><c- o>-</c-><c- n>impls</c-></i> <c- p>{</c->
  <c- k>static</c-> <c- k>constexpr</c-> <c- k>auto</c-> <c- n>get_attrs</c-> <c- o>=</c->
    <c- p>[](</c-><c- k>const</c-> <c- k>auto</c-><c- o>&amp;</c-> <c- n>data</c-><c- p>,</c-> <c- k>const</c-> <c- k>auto</c-><c- o>&amp;</c-> <c- n>child</c-><c- p>)</c-> <c- k>noexcept</c-> <c- o>-></c-> <c- k>decltype</c-><c- p>(</c-><c- k>auto</c-><c- p>)</c-> <c- p>{</c->
      <c- k>return</c-> <i><c- n>JOIN</c-><c- o>-</c-><c- n>ENV</c-></i><c- p>(</c-><i><c- n>SCHED</c-><c- o>-</c-><c- n>ATTRS</c-></i><c- p>(</c-><c- n>data</c-><c- p>),</c-> <i><c- n>FWD</c-><c- o>-</c-><c- n>ENV</c-></i><c- p>(</c-><c- n>get_env</c-><c- p>(</c-><c- n>child</c-><c- p>)));</c->
    <c- p>};</c->
<c- p>};</c->
</pre>
    <li data-md>
     <p>Let <code class="highlight"><c- n>sndr</c-></code> and <code class="highlight"><c- n>env</c-></code> be subexpressions such that <code class="highlight"><c- n>Sndr</c-></code> is <code class="highlight"><c- k>decltype</c-><c- p>((</c-><c- n>sndr</c-><c- p>))</c-></code>. If <code class="highlight"><i><c- n>sender</c-><c- o>-</c-><c- k>for</c-></i><c- o>&lt;</c-><c- n>Sndr</c-><c- p>,</c-> <c- n>transfer_t</c-><c- o>></c-></code> is <code class="highlight">false</code>, then the expression <code class="highlight"><c- n>transfer</c-><c- p>.</c-><c- n>transform_sender</c-><c- p>(</c-><c- n>sndr</c-><c- p>,</c-> <c- n>env</c-><c- p>)</c-></code> is ill-formed; otherwise, it
is equal to:</p>
<pre class="highlight"><c- k>auto</c-> <c- p>[</c-><c- n>tag</c-><c- p>,</c-> <c- n>data</c-><c- p>,</c-> <c- n>child</c-><c- p>]</c-> <c- o>=</c-> <c- n>sndr</c-><c- p>;</c->
<c- k>return</c-> <c- n>schedule_from</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>data</c-><c- p>),</c-> <c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>child</c-><c- p>));</c->
</pre>
     <p><span class="wg21note">This causes the <code class="highlight"><c- n>transfer</c-><c- p>(</c-><c- n>sndr</c-><c- p>,</c-> <c- n>sch</c-><c- p>)</c-></code> sender to become <code class="highlight"><c- n>schedule_from</c-><c- p>(</c-><c- n>sch</c-><c- p>,</c-> <c- n>sndr</c-><c- p>)</c-></code> when it is connected with a receiver with an
execution domain that does not customize <code class="highlight"><c- n>transfer</c-></code>.</span></p>
    <li data-md>
     <p>Let <code class="highlight"><c- n>out_sndr</c-></code> be a subexpression denoting a sender returned from <code class="highlight"><c- n>transfer</c-><c- p>(</c-><c- n>sndr</c-><c- p>,</c-> <c- n>sch</c-><c- p>)</c-></code> or one equal to such, and let <code class="highlight"><c- n>OutSndr</c-></code> be the type <code class="highlight"><c- k>decltype</c-><c- p>((</c-><c- n>out_sndr</c-><c- p>))</c-></code>. Let <code class="highlight"><c- n>out_rcvr</c-></code> be a subexpression denoting a
receiver that has an environment of type <code class="highlight"><c- n>Env</c-></code> such that <code class="highlight"><c- n>sender_in</c-><c- o>&lt;</c-><c- n>OutSndr</c-><c- p>,</c-> <c- n>Env</c-><c- o>></c-></code> is <code class="highlight">true</code>. Let <code class="highlight"><c- n>op</c-></code> be an lvalue referring to the operation state that
results from connecting <code class="highlight"><c- n>out_sndr</c-></code> with <code class="highlight"><c- n>out_rcvr</c-></code>. Calling <code class="highlight"><c- n>start</c-><c- p>(</c-><c- n>op</c-><c- p>)</c-></code> shall start <code class="highlight"><c- n>sndr</c-></code> on the current execution agent and execute completion
operations on <code class="highlight"><c- n>out_rcvr</c-></code> on an execution agent of the execution resource
associated with <code class="highlight"><c- n>sch</c-></code>. If scheduling onto <code class="highlight"><c- n>sch</c-></code> fails, execute an error
completion on <code class="highlight"><c- n>out_rcvr</c-></code> on an unspecified execution agent.</p>
   </ol>
   <h5 class="heading settled" data-level="11.9.10.5" id="spec-execution.senders.adaptors.schedule_from"><span class="secno">11.9.10.5. </span><span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>schedule_from</c-></code> <b>[exec.schedule.from]</b></span><a class="self-link" href="#spec-execution.senders.adaptors.schedule_from"></a></h5>
   <ol>
    <li data-md>
     <p><code class="highlight"><c- n>schedule_from</c-></code> schedules work dependent on the completion of a sender onto a
scheduler’s associated execution resource. <span class="wg21note"><code class="highlight"><c- n>schedule_from</c-></code> is not meant to be used in user code; it is
used in the implementation of <code class="highlight"><c- n>transfer</c-></code>.</span></p>
    <li data-md>
     <p>The name <code class="highlight"><c- n>schedule_from</c-></code> denotes a customization point object. For some
subexpressions <code class="highlight"><c- n>sch</c-></code> and <code class="highlight"><c- n>sndr</c-></code>, let <code class="highlight"><c- n>Sch</c-></code> be <code class="highlight"><c- k>decltype</c-><c- p>((</c-><c- n>sch</c-><c- p>))</c-></code> and <code class="highlight"><c- n>Sndr</c-></code> be <code class="highlight"><c- k>decltype</c-><c- p>((</c-><c- n>sndr</c-><c- p>))</c-></code>. If <code class="highlight"><c- n>Sch</c-></code> does not satisfy <code class="highlight"><c- n>scheduler</c-></code>, or <code class="highlight"><c- n>Sndr</c-></code> does not
satisfy <code class="highlight"><c- n>sender</c-></code>, <code class="highlight"><c- n>schedule_from</c-></code> is ill-formed.</p>
    <li data-md>
     <p>Otherwise, the expression <code class="highlight"><c- n>schedule_from</c-><c- p>(</c-><c- n>sch</c-><c- p>,</c-> <c- n>sndr</c-><c- p>)</c-></code> is expression-equivalent
to:</p>
<pre class="highlight"><c- n>transform_sender</c-><c- p>(</c->
  <i><c- n>query</c-><c- o>-</c-><c- n>or</c-><c- o>-</c-><c- k>default</c-></i><c- p>(</c-><c- n>get_domain</c-><c- p>,</c-> <c- n>sch</c-><c- p>,</c-> <c- n>default_domain</c-><c- p>()),</c->
  <i><c- n>make</c-><c- o>-</c-><c- n>sender</c-></i><c- p>(</c-><c- n>schedule_from</c-><c- p>,</c-> <c- n>sch</c-><c- p>,</c-> <c- n>sndr</c-><c- p>));</c->
</pre>
    <li data-md>
     <p>The exposition-only class template <code class="highlight"><i><c- n>impls</c-><c- o>-</c-><c- k>for</c-></i></code> ([exec.snd.general]) is specialized for <code class="highlight"><c- n>schedule_from_t</c-></code> as
follows:</p>
<pre class="highlight"><c- k>template</c-><c- o>&lt;></c->
<c- k>struct</c-> <i><c- nc>impls</c-><c- o>-</c-><c- k>for</c-></i><c- o>&lt;</c-><c- n>schedule_from_t</c-><c- o>></c-> <c- o>:</c-> <i><c- k>default</c-><c- o>-</c-><c- n>impls</c-></i> <c- p>{</c->
  <c- k>static</c-> <c- k>constexpr</c-> <c- k>auto</c-> <i><c- n>get</c-><c- o>-</c-><c- n>attrs</c-></i> <c- o>=</c-> <i><c- n>see</c-> <c- n>below</c-></i><c- p>;</c->
  <c- k>static</c-> <c- k>constexpr</c-> <c- k>auto</c-> <i><c- n>get</c-><c- o>-</c-><c- n>state</c-></i> <c- o>=</c-> <i><c- n>see</c-> <c- n>below</c-></i><c- p>;</c->
  <c- k>static</c-> <c- k>constexpr</c-> <c- k>auto</c-> <i><c- n>complete</c-></i> <c- o>=</c-> <i><c- n>see</c-> <c- n>below</c-></i><c- p>;</c->
<c- p>};</c->
</pre>
     <ol>
      <li data-md>
       <p>The member <code class="highlight"><i><c- n>impls</c-><c- o>-</c-><c- k>for</c-></i><c- o>&lt;</c-><c- n>schedule_from_t</c-><c- o>>::</c-><i><c- n>get</c-><c- o>-</c-><c- n>attrs</c-></i></code> is initialized
with a callable object equivalent to the following lambda:</p>
<pre class="highlight"><c- p>[](</c-><c- k>const</c-> <c- k>auto</c-><c- o>&amp;</c-> <c- n>data</c-><c- p>,</c-> <c- k>const</c-> <c- k>auto</c-><c- o>&amp;</c-> <c- n>child</c-><c- p>)</c-> <c- k>noexcept</c-> <c- o>-></c-> <c- k>decltype</c-><c- p>(</c-><c- k>auto</c-><c- p>)</c-> <c- p>{</c->
  <c- k>return</c-> <i><c- n>JOIN</c-><c- o>-</c-><c- n>ENV</c-></i><c- p>(</c-><i><c- n>SCHED</c-><c- o>-</c-><c- n>ATTRS</c-></i><c- p>(</c-><c- n>data</c-><c- p>),</c-> <i><c- n>FWD</c-><c- o>-</c-><c- n>ENV</c-></i><c- p>(</c-><c- n>get_env</c-><c- p>(</c-><c- n>child</c-><c- p>)));</c->
<c- p>}</c->
</pre>
      <li data-md>
       <p>The member <code class="highlight"><i><c- n>impls</c-><c- o>-</c-><c- k>for</c-></i><c- o>&lt;</c-><c- n>schedule_from_t</c-><c- o>>::</c-><i><c- n>get</c-><c- o>-</c-><c- n>state</c-></i></code> is initialized
with a callable object equivalent to the following lambda:</p>
<pre class="highlight"><c- p>[]</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Sndr</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Rcvr</c-><c- o>></c-><c- p>(</c-><c- n>Sndr</c-><c- o>&amp;&amp;</c-> <c- n>sndr</c-><c- p>,</c-> <c- n>Rcvr</c-><c- o>&amp;</c-> <c- n>rcvr</c-><c- p>)</c->
    <c- k>requires</c-> <c- n>sender_in</c-><c- o>&lt;</c-><i><c- n>child</c-><c- o>-</c-><c- n>type</c-></i><c- o>&lt;</c-><c- n>Sndr</c-><c- o>></c-><c- p>,</c-> <c- n>env_of_t</c-><c- o>&lt;</c-><c- n>Rcvr</c-><c- o>>></c-> <c- p>{</c->
  <c- k>return</c-> <c- n>apply</c-><c- p>(</c->
    <c- p>[</c-><c- o>&amp;</c-><c- p>]</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Sch</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Child</c-><c- o>></c-><c- p>(</c-><c- k>auto</c-><c- p>,</c-> <c- n>Sch</c-> <c- n>sch</c-><c- p>,</c-> <c- n>Child</c-><c- o>&amp;&amp;</c-> <c- n>child</c-><c- p>)</c-> <c- p>{</c->
      <c- k>using</c-> <i><c- n>variant</c-><c- o>-</c-><c- n>type</c-></i> <c- o>=</c-> <i><c- n>see</c-> <c- n>below</c-></i><c- p>;</c->
      <c- k>using</c-> <i><c- n>receiver</c-><c- o>-</c-><c- n>type</c-></i> <c- o>=</c-> <i><c- n>see</c-> <c- n>below</c-></i><c- p>;</c->
      <c- k>using</c-> <i><c- n>operation</c-><c- o>-</c-><c- n>type</c-></i> <c- o>=</c-> <c- n>connect_result_t</c-><c- o>&lt;</c-><c- n>schedule_result_t</c-><c- o>&lt;</c-><c- n>Sch</c-><c- o>></c-><c- p>,</c-> <i><c- n>receiver</c-><c- o>-</c-><c- n>type</c-></i><c- o>></c-><c- p>;</c->

      <c- k>struct</c-> <i><c- nc>state</c-><c- o>-</c-><c- n>type</c-></i> <c- p>{</c->
        <c- n>Rcvr</c-><c- o>&amp;</c-> <i><c- n>rcvr</c-></i><c- p>;</c->
        <i><c- n>variant</c-><c- o>-</c-><c- n>type</c-></i> <i><c- n>async</c-><c- o>-</c-><c- n>result</c-></i><c- p>;</c->
        <i><c- n>operation</c-><c- o>-</c-><c- n>type</c-></i> <i><c- n>op</c-><c- o>-</c-><c- n>state</c-></i><c- p>;</c->

        <c- k>explicit</c-> <i><c- n>state</c-><c- o>-</c-><c- n>type</c-></i><c- p>(</c-><c- n>Sch</c-> <c- n>sch</c-><c- p>,</c-> <c- n>Rcvr</c-><c- o>&amp;</c-> <c- n>rcvr</c-><c- p>)</c->
          <c- o>:</c-> <i><c- n>rcvr</c-></i><c- p>(</c-><c- n>rcvr</c-><c- p>),</c-> <i><c- n>op</c-><c- o>-</c-><c- n>state</c-></i><c- p>(</c-><c- n>connect</c-><c- p>(</c-><c- n>schedule</c-><c- p>(</c-><c- n>sch</c-><c- p>),</c-> <i><c- n>receiver</c-><c- o>-</c-><c- n>type</c-></i><c- p>{</c-><i></i><c- p>{},</c-> <c- k>this</c-><c- p>}))</c-> <c- p>{}</c->
      <c- p>};</c->

      <c- k>return</c-> <i><c- n>state</c-><c- o>-</c-><c- n>type</c-></i><c- p>{</c-><c- n>sch</c-><c- p>,</c-> <c- n>rcvr</c-><c- p>};</c->
    <c- p>},</c->
    <c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>Sndr</c-><c- o>></c-><c- p>(</c-><c- n>sndr</c-><c- p>));</c->
<c- p>}</c->
</pre>
       <ol>
        <li data-md>
         <p>The local class <i><code class="highlight"><c- n>state</c-><c- o>-</c-><c- n>type</c-></code></i> is a structural type.</p>
        <li data-md>
         <p>Let <code class="highlight"><c- n>Sigs</c-></code> be a pack of the arguments to the <code class="highlight"><c- n>completion_signatures</c-></code> specialization named by <code class="highlight"><c- n>completion_signatures_of_t</c-><c- o>&lt;</c-><c- n>Child</c-><c- p>,</c-> <c- n>env_of_t</c-><c- o>&lt;</c-><c- n>Rcvr</c-><c- o>>></c-></code>. Let <i><code class="highlight"><c- n>as</c-><c- o>-</c-><c- n>tuple</c-></code></i> be an alias template that transforms a
  completion signature <code class="highlight"><c- n>Tag</c-><c- p>(</c-><c- n>Args</c-><c- p>...)</c-></code> into the <code class="highlight"><c- n>tuple</c-></code> specialization <code class="highlight"><i><c- n>decayed</c-><c- o>-</c-><c- n>tuple</c-></i><c- o>&lt;</c-><c- n>Tag</c-><c- p>,</c-> <c- n>Args</c-><c- p>...</c-><c- o>></c-></code>.
  Then <i><code class="highlight"><c- n>variant</c-><c- o>-</c-><c- n>type</c-></code></i> denotes the type <code class="highlight"><c- n>variant</c-><c- o>&lt;</c-><c- n>monostate</c-><c- p>,</c-> <i><c- n>as</c-><c- o>-</c-><c- n>tuple</c-></i><c- o>&lt;</c-><c- n>Sigs</c-><c- o>></c-><c- p>...</c-><c- o>></c-></code>,
  except with duplicate types removed.</p>
        <li data-md>
         <p>Let <i><code class="highlight"><c- n>receiver</c-><c- o>-</c-><c- n>type</c-></code></i> denote the following class:</p>
<pre class="highlight"><c- k>struct</c-> <i><c- nc>receiver</c-><c- o>-</c-><c- n>type</c-></i> <c- o>:</c-> <c- n>receiver_adaptor</c-><c- o>&lt;</c-><i><c- n>receiver</c-><c- o>-</c-><c- n>type</c-></i><c- o>></c-> <c- p>{</c->
  <i><c- n>state</c-><c- o>-</c-><c- n>type</c-></i><c- o>*</c-> <i><c- n>state</c-></i><c- p>;</c-> <c- c1>// exposition only</c->

  <c- n>Rcvr</c-><c- o>&amp;&amp;</c-> <c- nf>base</c-><c- p>()</c-> <c- o>&amp;&amp;</c-> <c- k>noexcept</c-> <c- p>{</c-> <c- k>return</c-> <c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><i><c- n>state</c-></i><c- o>-></c-><i><c- n>rcvr</c-></i><c- p>);</c-> <c- p>}</c->
  <c- k>const</c-> <c- n>Rcvr</c-><c- o>&amp;</c-> <c- nf>base</c-><c- p>()</c-> <c- k>const</c-> <c- o>&amp;</c-> <c- k>noexcept</c-> <c- p>{</c-> <c- k>return</c-> <i><c- n>state</c-></i><c- o>-></c-><i><c- n>rcvr</c-></i><c- p>;</c-> <c- p>}</c->

  <c- b>void</c-> <c- nf>set_value</c-><c- p>()</c-> <c- o>&amp;&amp;</c-> <c- k>noexcept</c-> <c- p>{</c->
    <c- n>visit</c-><c- p>(</c->
      <c- p>[</c-><c- k>this</c-><c- p>]</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Tuple</c-><c- o>></c-><c- p>(</c-><c- n>Tuple</c-><c- o>&amp;</c-> <c- n>result</c-><c- p>)</c-> <c- k>noexcept</c-> <c- o>-></c-> <c- b>void</c-> <c- p>{</c->
        <c- k>if</c-> <c- k>constexpr</c-> <c- p>(</c-><c- o>!</c-><c- n>same_as</c-><c- o>&lt;</c-><c- n>monostate</c-><c- p>,</c-> <c- n>Tuple</c-><c- o>></c-><c- p>)</c-> <c- p>{</c->
          <c- k>auto</c-><c- o>&amp;</c-> <c- p>[</c-><c- n>tag</c-><c- p>,</c-> <c- p>...</c-><c- n>args</c-><c- p>]</c-> <c- o>=</c-> <c- n>result</c-><c- p>;</c->
          <c- n>tag</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><i><c- n>state</c-></i><c- o>-></c-><i><c- n>rcvr</c-></i><c- p>),</c-> <c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>args</c-><c- p>)...);</c->
        <c- p>}</c->
      <c- p>},</c->
      <i><c- n>state</c-></i><c- o>-></c-><i><c- n>async</c-><c- o>-</c-><c- n>result</c-></i><c- p>);</c->
  <c- p>}</c->
<c- p>};</c->
</pre>
       </ol>
      <li data-md>
       <p>The member <code class="highlight"><i><c- n>impls</c-><c- o>-</c-><c- k>for</c-></i><c- o>&lt;</c-><c- n>schedule_from_t</c-><c- o>>::</c-><i><c- n>complete</c-></i></code> is initialized with a callable object equivalent to the following lambda:</p>
<pre class="highlight"><c- p>[]</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Tag</c-><c- p>,</c-> <c- k>class</c-><c- p>...</c-> <c- n>Args</c-><c- o>></c-><c- p>(</c-><c- k>auto</c-><c- p>,</c-> <c- k>auto</c-><c- o>&amp;</c-> <c- n>state</c-><c- p>,</c-> <c- k>auto</c-><c- o>&amp;</c-> <c- n>rcvr</c-><c- p>,</c-> <c- n>Tag</c-><c- p>,</c-> <c- n>Args</c-><c- o>&amp;&amp;</c-><c- p>...</c-> <c- n>args</c-><c- p>)</c-> <c- k>noexcept</c-> <c- o>-></c-> <c- b>void</c-> <c- p>{</c->
  <c- k>using</c-> <c- n>result_t</c-> <c- o>=</c-> <i><c- n>decayed</c-><c- o>-</c-><c- n>tuple</c-></i><c- o>&lt;</c-><c- n>Tag</c-><c- p>,</c-> <c- n>Args</c-><c- p>...</c-><c- o>></c-><c- p>;</c->
  <c- k>constexpr</c-> <c- b>bool</c-> <c- n>nothrow</c-> <c- o>=</c-> <c- n>is_nothrow_constructible_v</c-><c- o>&lt;</c-><c- n>result_t</c-><c- p>,</c-> <c- n>Tag</c-><c- p>,</c-> <c- n>Args</c-><c- p>...</c-><c- o>></c-><c- p>;</c->

  <i><c- n>TRY</c-><c- o>-</c-><c- n>EVAL</c-></i><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>rcvr</c-><c- p>),</c-> <c- p>[</c-><c- o>&amp;</c-><c- p>]()</c-> <c- k>noexcept</c-><c- p>(</c-><c- n>nothrow</c-><c- p>)</c-> <c- p>{</c->
    <c- n>state</c-><c- p>.</c-><i><c- n>async</c-><c- o>-</c-><c- n>result</c-></i><c- p>.</c-><c- k>template</c-> <c- n>emplace</c-><c- o>&lt;</c-><c- n>result_t</c-><c- o>></c-><c- p>(</c-><c- n>Tag</c-><c- p>(),</c-> <c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>Args</c-><c- o>></c-><c- p>(</c-><c- n>args</c-><c- p>)...);</c->
  <c- p>}());</c->

  <c- k>if</c-> <c- p>(</c-><c- n>state</c-><c- p>.</c-><i><c- n>async</c-><c- o>-</c-><c- n>result</c-></i><c- p>.</c-><c- n>valueless_by_exception</c-><c- p>())</c->
    <c- k>return</c-><c- p>;</c->
  <c- k>if</c-> <c- p>(</c-><c- n>state</c-><c- p>.</c-><i><c- n>async</c-><c- o>-</c-><c- n>result</c-></i><c- p>.</c-><c- n>index</c-><c- p>()</c-> <c- o>==</c-> <c- mi>0</c-><c- p>)</c->
    <c- k>return</c-><c- p>;</c->

  <c- n>start</c-><c- p>(</c-><c- n>state</c-><c- p>.</c-><i><c- n>op</c-><c- o>-</c-><c- n>state</c-></i><c- p>);</c->
<c- p>};</c->
</pre>
     </ol>
    <li data-md>
     <p>Let the subexpression <code class="highlight"><c- n>out_sndr</c-></code> denote the result of the invocation <code class="highlight"><c- n>schedule_from</c-><c- p>(</c-><c- n>sch</c-><c- p>,</c-> <c- n>sndr</c-><c- p>)</c-></code> or an object copied or moved from such, and let
the subexpression <code class="highlight"><c- n>rcvr</c-></code> denote a receiver such that the expression <code class="highlight"><c- n>connect</c-><c- p>(</c-><c- n>out_sndr</c-><c- p>,</c-> <c- n>rcvr</c-><c- p>)</c-></code> is well-formed. The expression <code class="highlight"><c- n>connect</c-><c- p>(</c-><c- n>out_sndr</c-><c- p>,</c-> <c- n>rcvr</c-><c- p>)</c-></code> has undefined behavior unless it creates an
asynchronous operation ([async.ops]) that, when started:</p>
     <ul>
      <li data-md>
       <p>eventually completes on an execution agent belonging to the associated
execution resource of <code class="highlight"><c- n>sch</c-></code>, and</p>
      <li data-md>
       <p>completes with the same async result as <code class="highlight"><c- n>sndr</c-></code>.</p>
     </ul>
   </ol>
   <h5 class="heading settled" data-level="11.9.10.6" id="spec-execution.senders.adaptor.then"><span class="secno">11.9.10.6. </span><span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>then</c-></code>, <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>upon_error</c-></code>, <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>upon_stopped</c-></code> <b>[exec.then]</b></span><a class="self-link" href="#spec-execution.senders.adaptor.then"></a></h5>
   <ol>
    <li data-md>
     <p><code class="highlight"><c- n>then</c-></code> attaches an invocable as a continuation for an input sender’s value
completion operation. <code class="highlight"><c- n>upon_error</c-></code> and <code class="highlight"><c- n>upon_stopped</c-></code> do the same for the
error and stopped completion operations respectively, sending the result
of the invocable as a value completion.</p>
    <li data-md>
     <p>The names <code class="highlight"><c- n>then</c-></code>, <code class="highlight"><c- n>upon_error</c-></code>, and <code class="highlight"><c- n>upon_stopped</c-></code> denote customization point
objects. Let the expression <code class="highlight"><i><c- n>then</c-><c- o>-</c-><c- n>cpo</c-></i></code> be one of <code class="highlight"><c- n>then</c-></code>, <code class="highlight"><c- n>upon_error</c-></code>, or <code class="highlight"><c- n>upon_stopped</c-></code>. For subexpressions <code class="highlight"><c- n>sndr</c-></code> and <code class="highlight"><c- n>f</c-></code>, let <code class="highlight"><c- n>Sndr</c-></code> be <code class="highlight"><c- k>decltype</c-><c- p>((</c-><c- n>sndr</c-><c- p>))</c-></code> and let <code class="highlight"><c- n>F</c-></code> be the decayed type of <code class="highlight"><c- n>f</c-></code>. If <code class="highlight"><c- n>Sndr</c-></code> does not
satisfy <code class="highlight"><c- n>sender</c-></code>, or <code class="highlight"><c- n>F</c-></code> does not satisfy <code class="highlight"><i><c- n>movable</c-><c- o>-</c-><c- n>value</c-></i></code>, <code class="highlight"><i><c- n>then</c-><c- o>-</c-><c- n>cpo</c-></i><c- p>(</c-><c- n>sndr</c-><c- p>,</c-> <c- n>f</c-><c- p>)</c-></code> is ill-formed.</p>
    <li data-md>
     <p>Otherwise, the expression <code class="highlight"><i><c- n>then</c-><c- o>-</c-><c- n>cpo</c-></i><c- p>(</c-><c- n>sndr</c-><c- p>,</c-> <c- n>f</c-><c- p>)</c-></code> is
expression-equivalent to:</p>
<pre class="highlight"><c- n>transform_sender</c-><c- p>(</c->
  <i><c- n>get</c-><c- o>-</c-><c- n>domain</c-><c- o>-</c-><c- n>early</c-></i><c- p>(</c-><c- n>sndr</c-><c- p>),</c->
  <i><c- n>make</c-><c- o>-</c-><c- n>sender</c-></i><c- p>(</c-><i><c- n>then</c-><c- o>-</c-><c- n>cpo</c-></i><c- p>,</c-> <c- n>f</c-><c- p>,</c-> <c- n>sndr</c-><c- p>));</c->
</pre>
    <li data-md>
     <p>For <code class="highlight"><c- n>then</c-></code>, <code class="highlight"><c- n>upon_error</c-></code>, and <code class="highlight"><c- n>upon_stopped</c-></code>, let <code class="highlight"><i><c- n>set</c-><c- o>-</c-><c- n>cpo</c-></i></code> be <code class="highlight"><c- n>set_value</c-></code>, <code class="highlight"><c- n>set_error</c-></code>, and <code class="highlight"><c- n>set_stopped</c-></code> respectively. The
exposition-only class template <code class="highlight"><i><c- n>impls</c-><c- o>-</c-><c- k>for</c-></i></code> ([exec.snd.general]) is specialized for <i><code class="highlight"><c- n>then</c-><c- o>-</c-><c- n>cpo</c-></code></i> as follows:</p>
<pre class="highlight"><c- k>template</c-><c- o>&lt;></c->
<c- k>struct</c-> <i><c- nc>impls</c-><c- o>-</c-><c- k>for</c-></i><c- o>&lt;</c-><c- n>tag_t</c-><c- o>&lt;</c-><i><c- n>then</c-><c- o>-</c-><c- n>cpo</c-></i><c- o>>></c-> <c- o>:</c-> <i><c- k>default</c-><c- o>-</c-><c- n>impls</c-></i> <c- p>{</c->
  <c- k>static</c-> <c- k>constexpr</c-> <c- k>auto</c-> <c- n>complete</c-> <c- o>=</c->
    <c- p>[]</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Tag</c-><c- p>,</c-> <c- k>class</c-><c- p>...</c-> <c- n>Args</c-><c- o>></c->
      <c- p>(</c-><c- k>auto</c-> <c- d>/*index*/</c-><c- p>,</c-> <c- k>auto</c-><c- o>&amp;</c-> <c- n>fn</c-><c- p>,</c-> <c- k>auto</c-><c- o>&amp;</c-> <c- n>rcvr</c-><c- p>,</c-> <c- n>Tag</c-><c- p>,</c-> <c- n>Args</c-><c- o>&amp;&amp;</c-><c- p>...</c-> <c- n>args</c-><c- p>)</c-> <c- k>noexcept</c-> <c- o>-></c-> <c- b>void</c-> <c- p>{</c->
        <c- k>if</c-> <c- k>constexpr</c-> <c- p>(</c-><c- n>same_as</c-><c- o>&lt;</c-><c- n>Tag</c-><c- p>,</c-> <c- n>tag_t</c-><c- o>&lt;</c-><i><c- n>set</c-><c- o>-</c-><c- n>cpo</c-></i><c- o>>></c-><c- p>)</c-> <c- p>{</c->
          <i><c- n>TRY</c-><c- o>-</c-><c- n>SET</c-><c- o>-</c-><c- n>VALUE</c-></i><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>rcvr</c-><c- p>),</c->
                        <c- n>invoke</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>fn</c-><c- p>),</c-> <c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>Args</c-><c- o>></c-><c- p>(</c-><c- n>args</c-><c- p>)...));</c->
        <c- p>}</c-> <c- k>else</c-> <c- p>{</c->
          <c- n>Tag</c-><c- p>()(</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>rcvr</c-><c- p>),</c-> <c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>Args</c-><c- o>></c-><c- p>(</c-><c- n>args</c-><c- p>)...);</c->
        <c- p>}</c->
      <c- p>};</c->
<c- p>};</c->
</pre>
    <li data-md>
     <p>The expression <code class="highlight"><i><c- n>then</c-><c- o>-</c-><c- n>cpo</c-></i><c- p>(</c-><c- n>sndr</c-><c- p>,</c-> <c- n>f</c-><c- p>)</c-></code> has undefined behavior
unless it returns a sender <code class="highlight"><c- n>out_sndr</c-></code> that:</p>
     <ol>
      <li data-md>
       <p>Invokes <code class="highlight"><c- n>f</c-></code> or a copy of such with the value, error, or stopped result
datums of <code class="highlight"><c- n>sndr</c-></code> (for <code class="highlight"><c- n>then</c-></code>, <code class="highlight"><c- n>upon_error</c-></code>, and <code class="highlight"><c- n>upon_stopped</c-></code> respectively), using the result value of <code class="highlight"><c- n>f</c-></code> as <code class="highlight"><c- n>out_sndr</c-></code>'s value
completion, and</p>
      <li data-md>
       <p>Forwards all other completion operations unchanged.</p>
     </ol>
   </ol>
   <h5 class="heading settled" data-level="11.9.10.7" id="spec-execution.senders.adapt.let"><span class="secno">11.9.10.7. </span><span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>let_value</c-></code>, <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>let_error</c-></code>, <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>let_stopped</c-></code>, <b>[exec.let]</b></span><a class="self-link" href="#spec-execution.senders.adapt.let"></a></h5>
   <ol>
    <li data-md>
     <p><code class="highlight"><c- n>let_value</c-></code>, <code class="highlight"><c- n>let_error</c-></code>, and <code class="highlight"><c- n>let_stopped</c-></code> transform a sender’s value,
error, and stopped completions respectively into a new child asynchronous
operation by passing the sender’s result datums to a user-specified
callable, which returns a new sender that is connected and started.</p>
    <li data-md>
     <p>Let the expression <code class="highlight"><i><c- n>let</c-><c- o>-</c-><c- n>cpo</c-></i></code> be one of <code class="highlight"><c- n>let_value</c-></code>, <code class="highlight"><c- n>let_error</c-></code>, or <code class="highlight"><c- n>let_stopped</c-></code> and let <code class="highlight"><i><c- n>set</c-><c- o>-</c-><c- n>cpo</c-></i></code> be the
completion function that corresponds to <code class="highlight"><i><c- n>let</c-><c- o>-</c-><c- n>cpo</c-></i></code> (<code class="highlight"><c- n>set_value</c-></code> for <code class="highlight"><c- n>let_value</c-></code>, etc.). For a subexpression <code class="highlight"><c- n>sndr</c-></code>, let <code class="highlight"><i><c- n>let</c-><c- o>-</c-><c- n>env</c-></i><c- p>(</c-><c- n>sndr</c-><c- p>)</c-></code> be expression-equivalent to the first
well-formed expression below:</p>
     <ul>
      <li data-md>
       <p><code class="highlight"><i><c- n>SCHED</c-><c- o>-</c-><c- n>ENV</c-></i><c- p>(</c-><c- n>get_completion_scheduler</c-><c- o>&lt;</c-><c- n>tag_t</c-><c- o>&lt;</c-><i><c- n>set</c-><c- o>-</c-><c- n>cpo</c-></i><c- o>>></c-><c- p>(</c-><c- n>get_env</c-><c- p>(</c-><c- n>sndr</c-><c- p>)))</c-></code></p>
      <li data-md>
       <p><code class="highlight"><i><c- n>MAKE</c-><c- o>-</c-><c- n>ENV</c-></i><c- p>(</c-><c- n>get_domain</c-><c- p>,</c-> <c- n>get_domain</c-><c- p>(</c-><c- n>get_env</c-><c- p>(</c-><c- n>sndr</c-><c- p>)))</c-></code></p>
      <li data-md>
       <p><code class="highlight"><c- n>empty_env</c-><c- p>{}</c-></code></p>
     </ul>
    <li data-md>
     <p>The names <code class="highlight"><c- n>let_value</c-></code>, <code class="highlight"><c- n>let_error</c-></code>, and <code class="highlight"><c- n>let_stopped</c-></code> denote customization
point objects. For subexpressions <code class="highlight"><c- n>sndr</c-></code> and <code class="highlight"><c- n>f</c-></code>, let <code class="highlight"><c- n>Sndr</c-></code> be <code class="highlight"><c- k>decltype</c-><c- p>((</c-><c- n>sndr</c-><c- p>))</c-></code>,
let <code class="highlight"><c- n>F</c-></code> be the decayed type of <code class="highlight"><c- n>f</c-></code>. If <code class="highlight"><c- n>Sndr</c-></code> does not satisfy <code class="highlight"><c- n>sender</c-></code> or if <code class="highlight"><c- n>F</c-></code> does not satisfy <code class="highlight"><i><c- n>movable</c-><c- o>-</c-><c- n>value</c-></i></code>, the expression <code class="highlight"><i><c- n>let</c-><c- o>-</c-><c- n>cpo</c-></i><c- p>(</c-><c- n>sndr</c-><c- p>,</c-> <c- n>f</c-><c- p>)</c-></code> is ill-formed. If <code class="highlight"><c- n>F</c-></code> does not satisfy <code class="highlight"><c- n>invocable</c-></code>, the expression <code class="highlight"><c- n>let_stopped</c-><c- p>(</c-><c- n>sndr</c-><c- p>,</c-> <c- n>f</c-><c- p>)</c-></code> is ill-formed.</p>
    <li data-md>
     <p>Otherwise, the expression <code class="highlight"><i><c- n>let</c-><c- o>-</c-><c- n>cpo</c-></i><c- p>(</c-><c- n>sndr</c-><c- p>,</c-> <c- n>f</c-><c- p>)</c-></code> is
expression-equivalent to:</p>
<pre class="highlight"><c- n>transform_sender</c-><c- p>(</c->
  <i><c- n>get</c-><c- o>-</c-><c- n>domain</c-><c- o>-</c-><c- n>early</c-></i><c- p>(</c-><c- n>sndr</c-><c- p>),</c->
  <i><c- n>make</c-><c- o>-</c-><c- n>sender</c-></i><c- p>(</c-><i><c- n>let</c-><c- o>-</c-><c- n>cpo</c-></i><c- p>,</c-> <c- n>f</c-><c- p>,</c-> <c- n>sndr</c-><c- p>));</c->
</pre>
    <li data-md>
     <p>The exposition-only class template <code class="highlight"><i><c- n>impls</c-><c- o>-</c-><c- k>for</c-></i></code> ([exec.snd.general]) is specialized for <code class="highlight"><i><c- n>let</c-><c- o>-</c-><c- n>cpo</c-></i></code> as
follows:</p>
<pre class="highlight"><c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>State</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Rcvr</c-><c- p>,</c-> <c- k>class</c-><c- p>...</c-> <c- n>Args</c-><c- o>></c->
<c- b>void</c-> <i><c- n>let</c-><c- o>-</c-><c- n>bind</c-></i><c- p>(</c-><c- n>State</c-><c- o>&amp;</c-> <c- n>state</c-><c- p>,</c-> <c- n>Rcvr</c-><c- o>&amp;</c-> <c- n>rcvr</c-><c- p>,</c-> <c- n>Args</c-><c- o>&amp;&amp;</c-><c- p>...</c-> <c- n>args</c-><c- p>);</c-> <c- c1>// exposition only</c->

<c- k>template</c-><c- o>&lt;></c->
<c- k>struct</c-> <i><c- nc>impls</c-><c- o>-</c-><c- k>for</c-></i><c- o>&lt;</c-><c- n>tag_t</c-><c- o>&lt;</c-><i><c- n>let</c-><c- o>-</c-><c- n>cpo</c-></i><c- o>>></c-> <c- o>:</c-> <i><c- k>default</c-><c- o>-</c-><c- n>impls</c-></i> <c- p>{</c->
  <c- k>static</c-> <c- k>constexpr</c-> <c- k>auto</c-> <i><c- n>get</c-><c- o>-</c-><c- n>state</c-></i> <c- o>=</c-> <i><c- n>see</c-> <c- n>below</c-></i><c- p>;</c->
  <c- k>static</c-> <c- k>constexpr</c-> <c- k>auto</c-> <i><c- n>complete</c-></i> <c- o>=</c-> <i><c- n>see</c-> <c- n>below</c-></i><c- p>;</c->
<c- p>};</c->
</pre>
     <ol>
      <li data-md>
       <p>Let <i><code class="highlight"><c- n>receiver2</c-></code></i> denote the following exposition-only class template:</p>
<pre class="highlight"><c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Rcvr</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Env</c-><c- o>></c->
<c- k>struct</c-> <i><c- nc>receiver2</c-></i> <c- o>:</c-> <c- n>receiver_adaptor</c-><c- o>&lt;</c-><i><c- n>receiver2</c-></i><c- o>&lt;</c-><c- n>Rcvr</c-><c- p>,</c-> <c- n>Env</c-><c- o>></c-><c- p>,</c-> <c- n>Rcvr</c-><c- o>></c-> <c- p>{</c->
  <c- k>explicit</c-> <i><c- n>receiver2</c-></i><c- p>(</c-><c- n>Rcvr</c-> <c- n>rcvr</c-><c- p>,</c-> <c- n>Env</c-> <c- n>env</c-><c- p>)</c->
    <c- o>:</c-> <i><c- n>receiver2</c-></i><c- o>::</c-><c- n>receiver_adaptor</c-><c- p>{</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>rcvr</c-><c- p>)},</c-> <c- n>env</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>env</c-><c- p>))</c-> <c- p>{}</c->

  <c- k>auto</c-> <c- n>get_env</c-><c- p>()</c-> <c- k>const</c-> <c- k>noexcept</c-> <c- p>{</c->
    <c- k>return</c-> <i><c- n>JOIN</c-><c- o>-</c-><c- n>ENV</c-></i><c- p>(</c-><c- n>env</c-><c- p>,</c-> <i><c- n>FWD</c-><c- o>-</c-><c- n>ENV</c-></i><c- p>(</c-><c- n>execution</c-><c- o>::</c-><c- n>get_env</c-><c- p>(</c-><c- k>this</c-><c- o>-></c-><c- n>base</c-><c- p>())));</c->
  <c- p>}</c->

  <c- n>Env</c-> <c- n>env</c-><c- p>;</c-> <c- c1>// exposition only</c->
<c- p>};</c->
</pre>
      <li data-md>
       <p><code class="highlight"><i><c- n>impls</c-><c- o>-</c-><c- k>for</c-></i><c- o>&lt;</c-><c- n>tag_t</c-><c- o>&lt;</c-><i><c- n>let</c-><c- o>-</c-><c- n>cpo</c-></i><c- o>>>::</c-><i><c- n>get</c-><c- o>-</c-><c- n>state</c-></i></code> is
is initialized with a callable object equivalent to the following:</p>
<pre class="highlight"><c- p>[]</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Sndr</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Rcvr</c-><c- o>></c-><c- p>(</c-><c- n>Sndr</c-><c- o>&amp;&amp;</c-> <c- n>sndr</c-><c- p>,</c-> <c- n>Rcvr</c-><c- o>&amp;</c-> <c- n>rcvr</c-><c- p>)</c-> <c- k>requires</c-> <i><c- n>see</c-> <c- n>below</c-></i> <c- p>{</c->
  <c- k>auto</c-><c- o>&amp;&amp;</c-> <c- p>[</c-><c- n>tag</c-><c- p>,</c-> <c- n>data</c-><c- p>,</c-> <c- n>child</c-><c- p>]</c-> <c- o>=</c-> <c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>Sndr</c-><c- o>></c-><c- p>(</c-><c- n>sndr</c-><c- p>);</c->
  <c- k>return</c-> <c- p>[</c-><c- o>&amp;</c-><c- p>]</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Fn</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Env</c-><c- o>></c-><c- p>(</c-><c- n>Fn</c-> <c- n>fn</c-><c- p>,</c-> <c- n>Env</c-> <c- n>env</c-><c- p>)</c-> <c- p>{</c->
    <c- k>using</c-> <i><c- n>args</c-><c- o>-</c-><c- n>variant</c-><c- o>-</c-><c- n>type</c-></i> <c- o>=</c-> <i><c- n>see</c-> <c- n>below</c-></i><c- p>;</c->
    <c- k>using</c-> <i><c- n>ops2</c-><c- o>-</c-><c- n>variant</c-><c- o>-</c-><c- n>type</c-></i> <c- o>=</c-> <i><c- n>see</c-> <c- n>below</c-></i><c- p>;</c->

    <c- k>struct</c-> <i><c- nc>state</c-><c- o>-</c-><c- n>type</c-></i> <c- p>{</c->
      <c- n>Fn</c-> <c- n>fn</c-><c- p>;</c->
      <c- n>Env</c-> <c- n>env</c-><c- p>;</c->
      <i><c- n>args</c-><c- o>-</c-><c- n>variant</c-><c- o>-</c-><c- n>type</c-></i> <c- n>args</c-><c- p>;</c->
      <i><c- n>ops2</c-><c- o>-</c-><c- n>variant</c-><c- o>-</c-><c- n>type</c-></i> <c- n>ops2</c-><c- p>;</c->
    <c- p>};</c->
    <c- k>return</c-> <i><c- n>state</c-><c- o>-</c-><c- n>type</c-></i><c- p>{</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>fn</c-><c- p>),</c-> <c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>env</c-><c- p>),</c-> <c- p>{},</c-> <c- p>{}};</c->
  <c- p>}(</c-><c- n>std</c-><c- o>::</c-><c- n>forward_like</c-><c- o>&lt;</c-><c- n>Sndr</c-><c- o>></c-><c- p>(</c-><c- n>data</c-><c- p>),</c-> <i><c- n>let</c-><c- o>-</c-><c- n>env</c-></i><c- p>(</c-><c- n>child</c-><c- p>));</c->
<c- p>}</c->
</pre>
       <ol>
        <li data-md>
         <p>Let <code class="highlight"><c- n>Sigs</c-></code> be a pack of the arguments to the <code class="highlight"><c- n>completion_signatures</c-></code> specialization named by <code class="highlight"><c- n>completion_signatures_of_t</c-><c- o>&lt;</c-><i><c- n>child</c-><c- o>-</c-><c- n>type</c-></i><c- o>&lt;</c-><c- n>Sndr</c-><c- o>></c-><c- p>,</c-> <c- n>env_of_t</c-><c- o>&lt;</c-><c- n>Rcvr</c-><c- o>>></c-></code>. Let <code class="highlight"><c- n>LetSigs</c-></code> be a pack of those types in <code class="highlight"><c- n>Sigs</c-></code> with a return type of <code class="highlight"><c- n>tag_t</c-><c- o>&lt;</c-><i><c- n>set</c-><c- o>-</c-><c- n>cpo</c-></i><c- o>></c-></code>. Let <i><code class="highlight"><c- n>as</c-><c- o>-</c-><c- n>tuple</c-></code></i> be an alias template such that <code class="highlight"><i><c- n>as</c-><c- o>-</c-><c- n>tuple</c-></i><c- o>&lt;</c-><c- n>Tag</c-><c- p>(</c-><c- n>Args</c-><c- p>...)</c-><c- o>></c-></code> denotes the type <code class="highlight"><i><c- n>decayed</c-><c- o>-</c-><c- n>tuple</c-></i><c- o>&lt;</c-><c- n>Args</c-><c- p>...</c-><c- o>></c-></code>. Then <i><code class="highlight"><c- n>args</c-><c- o>-</c-><c- n>variant</c-><c- o>-</c-><c- n>type</c-></code></i> denotes the type <code class="highlight"><c- n>variant</c-><c- o>&lt;</c-><c- n>monostate</c-><c- p>,</c-> <i><c- n>as</c-><c- o>-</c-><c- n>tuple</c-></i><c- o>&lt;</c-><c- n>LetSigs</c-><c- o>></c-><c- p>...</c-><c- o>></c-></code>.</p>
        <li data-md>
         <p>Let <i><code class="highlight"><c- n>as</c-><c- o>-</c-><c- n>sndr2</c-></code></i> be an alias template such that <code class="highlight"><i><c- n>as</c-><c- o>-</c-><c- n>sndr2</c-></i><c- o>&lt;</c-><c- n>Tag</c-><c- p>(</c-><c- n>Args</c-><c- p>...)</c-><c- o>></c-></code> denotes the type <code class="highlight"><i><c- n>call</c-><c- o>-</c-><c- n>result</c-><c- o>-</c-><c- n>t</c-></i><c- o>&lt;</c-><c- n>Fn</c-><c- p>,</c-> <c- n>decay_t</c-><c- o>&lt;</c-><c- n>Args</c-><c- o>>&amp;</c-><c- p>...</c-><c- o>></c-></code>.
Then <i><code class="highlight"><c- n>ops2</c-><c- o>-</c-><c- n>variant</c-><c- o>-</c-><c- n>type</c-></code></i> denotes the type <code class="highlight"><c- n>variant</c-><c- o>&lt;</c-><c- n>monostate</c-><c- p>,</c-> <c- n>connect_result_t</c-><c- o>&lt;</c-><i><c- n>as</c-><c- o>-</c-><c- n>sndr2</c-></i><c- o>&lt;</c-><c- n>LetSigs</c-><c- o>></c-><c- p>,</c-> <i><c- n>receiver2</c-></i><c- o>&lt;</c-><c- n>Rcvr</c-><c- p>,</c-> <c- n>Env</c-><c- o>>></c-><c- p>...</c-><c- o>></c-></code>.</p>
        <li data-md>
         <p>The <i>requires-clause</i> constraining the above lambda is
satisfied if and only if the types <i><code class="highlight"><c- n>args</c-><c- o>-</c-><c- n>variant</c-><c- o>-</c-><c- n>type</c-></code></i> and <i><code class="highlight"><c- n>ops2</c-><c- o>-</c-><c- n>variant</c-><c- o>-</c-><c- n>type</c-></code></i> are well-formed.</p>
       </ol>
      <li data-md>
       <p>The exposition-only function template <i><code class="highlight"><c- n>let</c-><c- o>-</c-><c- n>bind</c-></code></i> is equal to:</p>
<pre class="highlight"><c- k>auto</c-><c- o>&amp;</c-> <c- n>args</c-> <c- o>=</c-> <c- n>state</c-><c- p>.</c-><c- n>args</c-><c- p>.</c-><c- n>emplace</c-><c- o>&lt;</c-><i><c- n>decayed</c-><c- o>-</c-><c- n>tuple</c-></i><c- o>&lt;</c-><c- n>Args</c-><c- p>...</c-><c- o>>></c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>Args</c-><c- o>></c-><c- p>(</c-><c- n>args</c-><c- p>)...);</c->
<c- k>auto</c-> <c- n>sndr2</c-> <c- o>=</c-> <c- n>apply</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>state</c-><c- p>.</c-><c- n>fn</c-><c- p>),</c-> <c- n>args</c-><c- p>);</c->
<c- k>auto</c-> <c- n>rcvr2</c-> <c- o>=</c-> <i><c- n>receiver2</c-></i><c- p>{</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>rcvr</c-><c- p>),</c-> <c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>state</c-><c- p>.</c-><c- n>env</c-><c- p>)};</c->
<c- k>auto</c-> <c- n>mkop2</c-> <c- o>=</c-> <c- p>[</c-><c- o>&amp;</c-><c- p>]</c-> <c- p>{</c-> <c- k>return</c-> <c- n>connect</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>sndr2</c-><c- p>),</c-> <c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>rcvr2</c-><c- p>));</c-> <c- p>};</c->
<c- k>auto</c-><c- o>&amp;</c-> <c- n>op2</c-> <c- o>=</c-> <c- n>state</c-><c- p>.</c-><c- n>ops2</c-><c- p>.</c-><c- n>emplace</c-><c- o>&lt;</c-><c- k>decltype</c-><c- p>(</c-><c- n>mkop2</c-><c- p>())</c-><c- o>></c-><c- p>(</c-><i><c- n>emplace</c-><c- o>-</c-><c- n>from</c-></i><c- p>{</c-><c- n>mkop2</c-><c- p>});</c->
<c- n>start</c-><c- p>(</c-><c- n>op2</c-><c- p>);</c->
</pre>
      <li data-md>
       <p><code class="highlight"><i><c- n>impls</c-><c- o>-</c-><c- k>for</c-></i><c- o>&lt;</c-><c- n>tag_t</c-><c- o>&lt;</c-><i><c- n>let</c-><c- o>-</c-><c- n>cpo</c-></i><c- o>>>::</c-><i><c- n>complete</c-></i></code> is
is initialized with a callable object equivalent to the following:</p>
<pre class="highlight"><c- p>[]</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Tag</c-><c- p>,</c-> <c- k>class</c-><c- p>...</c-> <c- n>Args</c-><c- o>></c->
  <c- p>(</c-><c- k>auto</c-><c- p>,</c-> <c- k>auto</c-><c- o>&amp;</c-> <c- n>state</c-><c- p>,</c-> <c- k>auto</c-><c- o>&amp;</c-> <c- n>rcvr</c-><c- p>,</c-> <c- n>Tag</c-><c- p>,</c-> <c- n>Args</c-><c- o>&amp;&amp;</c-><c- p>...</c-> <c- n>args</c-><c- p>)</c-> <c- k>noexcept</c-> <c- o>-></c-> <c- b>void</c-> <c- p>{</c->
    <c- k>if</c-> <c- k>constexpr</c-> <c- p>(</c-><c- n>same_as</c-><c- o>&lt;</c-><c- n>Tag</c-><c- p>,</c-> <c- n>tag_t</c-><c- o>&lt;</c-><i><c- n>set</c-><c- o>-</c-><c- n>cpo</c-></i><c- o>>></c-><c- p>)</c-> <c- p>{</c->
      <i><c- n>TRY</c-><c- o>-</c-><c- n>EVAL</c-></i><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>rcvr</c-><c- p>),</c-> <i><c- n>let</c-><c- o>-</c-><c- n>bind</c-></i><c- p>(</c-><c- n>state</c-><c- p>,</c-> <c- n>rcvr</c-><c- p>,</c-> <c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>Args</c-><c- o>></c-><c- p>(</c-><c- n>args</c-><c- p>)...));</c->
    <c- p>}</c-> <c- k>else</c-> <c- p>{</c->
      <c- n>Tag</c-><c- p>()(</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>rcvr</c-><c- p>),</c-> <c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>Args</c-><c- o>></c-><c- p>(</c-><c- n>args</c-><c- p>)...);</c->
    <c- p>}</c->
  <c- p>}</c->
</pre>
     </ol>
    <li data-md>
     <p>Let <code class="highlight"><c- n>sndr</c-></code> and <code class="highlight"><c- n>env</c-></code> be subexpressions, and let <code class="highlight"><c- n>Sndr</c-></code> be <code class="highlight"><c- k>decltype</c-><c- p>((</c-><c- n>sndr</c-><c- p>))</c-></code>.
If <code class="highlight"><i><c- n>sender</c-><c- o>-</c-><c- k>for</c-></i><c- o>&lt;</c-><c- n>Sndr</c-><c- p>,</c-> <c- n>tag_t</c-><c- o>&lt;</c-><i><c- n>let</c-><c- o>-</c-><c- n>cpo</c-></i><c- o>>></c-></code> is <code class="highlight">false</code>, then the expression <code class="highlight"><i><c- n>let</c-><c- o>-</c-><c- n>cpo</c-></i><c- p>.</c-><c- n>transform_env</c-><c- p>(</c-><c- n>sndr</c-><c- p>,</c-> <c- n>env</c-><c- p>)</c-></code> is ill-formed. Otherwise, it is equal to <code class="highlight"><i><c- n>JOIN</c-><c- o>-</c-><c- n>ENV</c-></i><c- p>(</c-><i><c- n>let</c-><c- o>-</c-><c- n>env</c-></i><c- p>(</c-><c- n>sndr</c-><c- p>),</c-> <i><c- n>FWD</c-><c- o>-</c-><c- n>ENV</c-></i><c- p>(</c-><c- n>env</c-><c- p>))</c-></code>.</p>
    <li data-md>
     <p>Let the subexpression <code class="highlight"><c- n>out_sndr</c-></code> denote the result of the invocation <code class="highlight"><i><c- n>let</c-><c- o>-</c-><c- n>cpo</c-></i><c- p>(</c-><c- n>sndr</c-><c- p>,</c-> <c- n>f</c-><c- p>)</c-></code> or an object copied or moved from such,
and let the subexpression <code class="highlight"><c- n>rcvr</c-></code> denote a receiver such that the expression <code class="highlight"><c- n>connect</c-><c- p>(</c-><c- n>out_sndr</c-><c- p>,</c-> <c- n>rcvr</c-><c- p>)</c-></code> is well-formed. The expression <code class="highlight"><c- n>connect</c-><c- p>(</c-><c- n>out_sndr</c-><c- p>,</c-> <c- n>rcvr</c-><c- p>)</c-></code> has undefined behavior unless it creates an asynchronous operation
([async.ops]) that, when started:</p>
     <ul>
      <li data-md>
       <p>invokes <code class="highlight"><c- n>f</c-></code> when <code class="highlight"><i><c- n>set</c-><c- o>-</c-><c- n>cpo</c-></i></code> is called with <code class="highlight"><c- n>sndr</c-></code>'s
  result datums,</p>
      <li data-md>
       <p>makes its completion dependent on the completion of a sender returned
  by <code class="highlight"><c- n>f</c-></code>, and</p>
      <li data-md>
       <p>propagates the other completion operations sent by <code class="highlight"><c- n>sndr</c-></code>.</p>
     </ul>
   </ol>
   <h5 class="heading settled" data-level="11.9.10.8" id="spec-execution.senders.adapt.bulk"><span class="secno">11.9.10.8. </span><span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>bulk</c-></code> <b>[exec.bulk]</b></span><a class="self-link" href="#spec-execution.senders.adapt.bulk"></a></h5>
   <ol>
    <li data-md>
     <p><code class="highlight"><c- n>bulk</c-></code> runs a task repeatedly for every index in an index space.</p>
    <li data-md>
     <p>The name <code class="highlight"><c- n>bulk</c-></code> denotes a customization point object. For subexpressions <code class="highlight"><c- n>sndr</c-></code>, <code class="highlight"><c- n>shape</c-></code>, and <code class="highlight"><c- n>f</c-></code>, let <code class="highlight"><c- n>Sndr</c-></code> be <code class="highlight"><c- k>decltype</c-><c- p>((</c-><c- n>sndr</c-><c- p>))</c-></code>, let <code class="highlight"><c- n>Shape</c-></code> be
the decayed type of <code class="highlight"><c- n>shape</c-></code>, and let <code class="highlight"><c- n>F</c-></code> be the decayed type of <code class="highlight"><c- n>f</c-></code>. If <code class="highlight"><c- n>Sndr</c-></code> does not satisfy <code class="highlight"><c- n>sender</c-></code>, or if <code class="highlight"><c- n>Shape</c-></code> does not satisfy <code class="highlight"><c- n>integral</c-></code>,
or if <code class="highlight"><c- n>F</c-></code> does not satisfy <code class="highlight"><i><c- n>movable</c-><c- o>-</c-><c- n>value</c-></i></code>, <code class="highlight"><c- n>bulk</c-><c- p>(</c-><c- n>sndr</c-><c- p>,</c-> <c- n>shape</c-><c- p>,</c-> <c- n>f</c-><c- p>)</c-></code> is ill-formed.</p>
    <li data-md>
     <p>Otherwise, the expression <code class="highlight"><c- n>bulk</c-><c- p>(</c-><c- n>sndr</c-><c- p>,</c-> <c- n>shape</c-><c- p>,</c-> <c- n>f</c-><c- p>)</c-></code> is
expression-equivalent to:</p>
<pre class="highlight"><c- n>transform_sender</c-><c- p>(</c->
  <i><c- n>get</c-><c- o>-</c-><c- n>domain</c-><c- o>-</c-><c- n>early</c-></i><c- p>(</c-><c- n>sndr</c-><c- p>),</c->
  <i><c- n>make</c-><c- o>-</c-><c- n>sender</c-></i><c- p>(</c-><c- n>bulk</c-><c- p>,</c-> <i><c- n>product</c-><c- o>-</c-><c- n>type</c-></i><c- p>{</c-><c- n>shape</c-><c- p>,</c-> <c- n>f</c-><c- p>},</c-> <c- n>sndr</c-><c- p>));</c->
</pre>
    <li data-md>
     <p>The exposition-only class template <code class="highlight"><i><c- n>impls</c-><c- o>-</c-><c- k>for</c-></i></code> ([exec.snd.general]) is specialized for <code class="highlight"><c- n>bulk_t</c-></code> as follows:</p>
<pre class="highlight"><c- k>template</c-><c- o>&lt;></c->
<c- k>struct</c-> <i><c- nc>impls</c-><c- o>-</c-><c- k>for</c-></i><c- o>&lt;</c-><c- n>bulk_t</c-><c- o>></c-> <c- o>:</c-> <i><c- k>default</c-><c- o>-</c-><c- n>impls</c-></i> <c- p>{</c->
  <c- k>static</c-> <c- k>constexpr</c-> <c- k>auto</c-> <c- n>complete</c-> <c- o>=</c-> <i><c- n>see</c-> <c- n>below</c-></i><c- p>;</c->
<c- p>};</c->
</pre>
     <ol>
      <li data-md>
       <p>The member <code class="highlight"><i><c- n>impls</c-><c- o>-</c-><c- k>for</c-></i><c- o>&lt;</c-><c- n>bulk_t</c-><c- o>>::</c-><c- n>complete</c-></code> is
initialized with a callable object equivalent to the following lambda:</p>
<pre class="highlight"><c- p>[]</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Index</c-><c- p>,</c-> <c- k>class</c-> <c- nc>State</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Rcvr</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Tag</c-><c- p>,</c-> <c- k>class</c-><c- p>...</c-> <c- n>Args</c-><c- o>></c->
  <c- p>(</c-><c- n>Index</c-><c- p>,</c-> <c- n>State</c-><c- o>&amp;</c-> <c- n>state</c-><c- p>,</c-> <c- n>Rcvr</c-><c- o>&amp;</c-> <c- n>rcvr</c-><c- p>,</c-> <c- n>Tag</c-><c- p>,</c-> <c- n>Args</c-><c- o>&amp;&amp;</c-><c- p>...</c-> <c- n>args</c-><c- p>)</c-> <c- k>noexcept</c-> <c- o>-></c-> <c- b>void</c-> <c- k>requires</c-> <i><c- n>see</c-> <c- n>below</c-></i> <c- p>{</c->
    <c- k>if</c-> <c- k>constexpr</c-> <c- p>(</c-><c- n>same_as</c-><c- o>&lt;</c-><c- n>Tag</c-><c- p>,</c-> <c- n>set_value_t</c-><c- o>></c-><c- p>)</c-> <c- p>{</c->
      <c- k>auto</c-><c- o>&amp;</c-> <c- p>[</c-><c- n>shape</c-><c- p>,</c-> <c- n>f</c-><c- p>]</c-> <c- o>=</c-> <c- n>state</c-><c- p>;</c->
      <c- k>constexpr</c-> <c- b>bool</c-> <c- n>nothrow</c-> <c- o>=</c-> <c- k>noexcept</c-><c- p>(</c-><c- n>f</c-><c- p>(</c-><c- k>auto</c-><c- p>(</c-><c- n>shape</c-><c- p>),</c-> <c- n>args</c-><c- p>...));</c->
      <i><c- n>TRY</c-><c- o>-</c-><c- n>EVAL</c-></i><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>rcvr</c-><c- p>),</c-> <c- p>[</c-><c- o>&amp;</c-><c- p>]()</c-> <c- k>noexcept</c-><c- p>(</c-><c- n>nothrow</c-><c- p>)</c-> <c- p>{</c->
        <c- k>for</c-> <c- p>(</c-><c- k>auto</c-> <c- n>max</c-> <c- o>=</c-> <c- n>shape</c-><c- p>,</c-> <c- n>i</c-> <c- o>=</c-> <c- mi>0</c-><c- p>;</c-> <c- n>i</c-> <c- o>&lt;</c-> <c- n>max</c-><c- p>;</c-> <c- o>++</c-><c- n>i</c-><c- p>)</c-> <c- p>{</c->
          <c- n>f</c-><c- p>(</c-><c- k>auto</c-><c- p>(</c-><c- n>i</c-><c- p>),</c-> <c- n>args</c-><c- p>...);</c->
        <c- p>}</c->
        <c- n>Tag</c-><c- p>()(</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>rcvr</c-><c- p>),</c-> <c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>Args</c-><c- o>></c-><c- p>(</c-><c- n>args</c-><c- p>)...);</c->
      <c- p>}());</c->
    <c- p>}</c-> <c- k>else</c-> <c- p>{</c->
      <c- n>Tag</c-><c- p>()(</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>rcvr</c-><c- p>),</c-> <c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>Args</c-><c- o>></c-><c- p>(</c-><c- n>args</c-><c- p>)...);</c->
    <c- p>}</c->
  <c- p>}</c->
</pre>
       <ol>
        <li data-md>
         <p>The expression in the <em>requires-clause</em> of the lambda above is <code class="highlight">true</code> if and only if <code class="highlight"><c- n>Tag</c-></code> denotes a type other than <code class="highlight"><c- n>set_value_t</c-></code> or if the expression <code class="highlight"><c- n>f</c-><c- p>(</c-><c- k>auto</c-><c- p>(</c-><c- n>shape</c-><c- p>),</c-> <c- n>args</c-><c- p>...)</c-></code> is well-formed.</p>
       </ol>
     </ol>
    <li data-md>
     <p>Let the subexpression <code class="highlight"><c- n>out_sndr</c-></code> denote the result of the invocation <code class="highlight"><c- n>bulk</c-><c- p>(</c-><c- n>sndr</c-><c- p>,</c-> <c- n>shape</c-><c- p>,</c-> <c- n>f</c-><c- p>)</c-></code> or an object copied or moved from such,
and let the subexpression <code class="highlight"><c- n>rcvr</c-></code> denote a receiver such that the expression <code class="highlight"><c- n>connect</c-><c- p>(</c-><c- n>out_sndr</c-><c- p>,</c-> <c- n>rcvr</c-><c- p>)</c-></code> is well-formed. The expression <code class="highlight"><c- n>connect</c-><c- p>(</c-><c- n>out_sndr</c-><c- p>,</c-> <c- n>rcvr</c-><c- p>)</c-></code> has undefined behavior unless it creates an asynchronous operation
([async.ops]) that, when started:</p>
     <ul>
      <li data-md>
       <p>on a value completion operation, invokes <code class="highlight"><c- n>f</c-><c- p>(</c-><c- n>i</c-><c- p>,</c-> <c- n>args</c-><c- p>...)</c-></code> for every <code class="highlight"><c- n>i</c-></code> of type <code class="highlight"><c- n>Shape</c-></code> from <code class="highlight"><c- mi>0</c-></code> to <code class="highlight"><c- n>shape</c-></code>, where <code class="highlight"><c- n>args</c-></code> is a pack of lvalue
  subexpressions referring to the value completion result datums of the
  input sender, and</p>
      <li data-md>
       <p>propagates all completion operations sent by <code class="highlight"><c- n>sndr</c-></code>.</p>
     </ul>
   </ol>
   <h5 class="heading settled" data-level="11.9.10.9" id="spec-execution.senders.adapt.split"><span class="secno">11.9.10.9. </span><span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>split</c-></code> and <code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>ensure_started</c-></code> <b>[exec.split]</b></span><a class="self-link" href="#spec-execution.senders.adapt.split"></a></h5>
   <ol>
    <li data-md>
     <p><code class="highlight"><c- n>split</c-></code> adapts an arbitrary sender into a sender that can be connected
multiple times. <code class="highlight"><c- n>ensure_started</c-></code> eagerly starts the execution of a sender,
returning a sender that is usable as input to additional sender algorithms.</p>
    <li data-md>
     <p>Let <code class="highlight"><i><c- n>shared</c-><c- o>-</c-><c- n>env</c-></i></code> be the type of an environment such that,
given an instance <code class="highlight"><c- n>env</c-></code>, the expression <code class="highlight"><c- n>get_stop_token</c-><c- p>(</c-><c- n>env</c-><c- p>)</c-></code> is well-formed
and has type <code class="highlight"><c- n>in_place_stop_token</c-></code>.</p>
    <li data-md>
     <p>
      The names <code class="highlight"><c- n>split</c-></code> and <code class="highlight"><c- n>ensure_started</c-></code> denote customization point objects.
Let the expression <i><code class="highlight"><c- n>shared</c-><c- o>-</c-><c- n>cpo</c-></code></i> be one of <code class="highlight"><c- n>split</c-></code> or <code class="highlight"><c- n>ensure_started</c-></code>. For a subexpression <code class="highlight"><c- n>sndr</c-></code>, let <code class="highlight"><c- n>Sndr</c-></code> be <code class="highlight"><c- k>decltype</c-><c- p>((</c-><c- n>sndr</c-><c- p>))</c-></code>. If <code class="highlight"><c- n>sender_in</c-><c- o>&lt;</c-><c- n>Sndr</c-><c- p>,</c-> <i><c- n>shared</c-><c- o>-</c-><c- n>env</c-></i><c- o>></c-></code> 
      <del>or <code class="highlight"><c- n>constructible_from</c-><c- o>&lt;</c-><c- n>decay_t</c-><c- o>&lt;</c-><c- n>env_of_t</c-><c- o>&lt;</c-><c- n>Sndr</c-><c- o>>></c-><c- p>,</c-> <c- n>env_of_t</c-><c- o>&lt;</c-><c- n>Sndr</c-><c- o>>></c-></code></del>
       is <code class="highlight">false</code>, <code class="highlight"><i><c- n>shared</c-><c- o>-</c-><c- n>cpo</c-></i><c- p>(</c-><c- n>sndr</c-><c- p>)</c-></code> is ill-formed.
     </p>
     <div class="ed-note"> Although it has not yet been approved by LEWG, there
is a bug in the current wording that makes it impossible to safely copy the
attributes of a sender; it may have reference semantics, leading to a
dangling reference. I am striking this part for now and will bring a fix to
LEWG.</div>
    <li data-md>
     <p>Otherwise, the expression <code class="highlight"><i><c- n>shared</c-><c- o>-</c-><c- n>cpo</c-></i><c- p>(</c-><c- n>sndr</c-><c- p>)</c-></code> is
expression-equivalent to:</p>
<pre class="highlight"><c- n>transform_sender</c-><c- p>(</c->
  <i><c- n>get</c-><c- o>-</c-><c- n>domain</c-><c- o>-</c-><c- n>early</c-></i><c- p>(</c-><c- n>sndr</c-><c- p>),</c->
  <i><c- n>make</c-><c- o>-</c-><c- n>sender</c-></i><c- p>(</c-><i><c- n>shared</c-><c- o>-</c-><c- n>cpo</c-></i><c- p>,</c-> <c- p>{},</c-> <c- n>sndr</c-><c- p>));</c->
</pre>
     <ul>
      <li data-md>
       <p><span class="wg21note">The default implementation of <code class="highlight"><c- n>transform_sender</c-></code> will have the effect of connecting the sender to a receiver and, in the
case of <code class="highlight"><c- n>ensure_started</c-></code>, calling <code class="highlight"><c- n>start</c-></code> on the resulting operation
state. It will return a sender with a different tag type.</span></p>
     </ul>
    <li data-md>
     <p>Let <i><code class="highlight"><c- n>local</c-><c- o>-</c-><c- n>state</c-></code></i> denote the following exposition-only class:</p>
<pre class="highlight"><c- k>struct</c-> <i><c- nc>local</c-><c- o>-</c-><c- n>state</c-><c- o>-</c-><c- n>base</c-></i> <c- p>{</c->
  <c- k>virtual</c-> <c- o>~</c-><i><c- n>local</c-><c- o>-</c-><c- n>state</c-><c- o>-</c-><c- n>base</c-></i><c- p>()</c-> <c- o>=</c-> <c- k>default</c-><c- p>;</c->
  <c- k>virtual</c-> <c- b>void</c-> <i><c- nf>notify</c-></i><c- p>()</c-> <c- k>noexcept</c-> <c- o>=</c-> <c- mi>0</c-><c- p>;</c->
  <c- k>virtual</c-> <c- b>void</c-> <i><c- nf>detach</c-></i><c- p>()</c-> <c- k>noexcept</c-> <c- o>=</c-> <c- mi>0</c-><c- p>;</c->
<c- p>};</c->

<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Sndr</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Rcvr</c-><c- o>></c->
<c- k>struct</c-> <i><c- nc>local</c-><c- o>-</c-><c- n>state</c-></i> <c- o>:</c-> <i><c- n>local</c-><c- o>-</c-><c- n>state</c-><c- o>-</c-><c- n>base</c-></i> <c- p>{</c->
  <c- k>using</c-> <i><c- n>on</c-><c- o>-</c-><c- n>stop</c-><c- o>-</c-><c- n>request</c-></i> <c- o>=</c-> <i><c- n>see</c-> <c- n>below</c-></i><c- p>;</c->
  <c- k>using</c-> <i><c- n>on</c-><c- o>-</c-><c- n>stop</c-><c- o>-</c-><c- n>callback</c-></i> <c- o>=</c-> <c- n>stop_token_of_t</c-><c- o>&lt;</c-><c- n>env_of_t</c-><c- o>&lt;</c-><c- n>Rcvr</c-><c- o>>>::</c->
                              <c- k>template</c-> <c- n>callback_type</c-><c- o>&lt;</c-><i><c- n>on</c-><c- o>-</c-><c- n>stop</c-><c- o>-</c-><c- n>request</c-></i><c- o>></c-><c- p>;</c->

  <i><c- n>local</c-><c- o>-</c-><c- n>state</c-></i><c- p>(</c-><c- n>Sndr</c-><c- o>&amp;&amp;</c-> <c- n>sndr</c-><c- p>,</c-> <c- n>Rcvr</c-><c- o>&amp;</c-> <c- n>rcvr</c-><c- p>)</c-> <c- k>noexcept</c-><c- p>;</c->
  <c- o>~</c-><i><c- n>local</c-><c- o>-</c-><c- n>state</c-></i><c- p>();</c->

  <c- b>void</c-> <i><c- nf>notify</c-></i><c- p>()</c-> <c- k>noexcept</c-> <c- k>override</c-><c- p>;</c->
  <c- b>void</c-> <i><c- nf>detach</c-></i><c- p>()</c-> <c- k>noexcept</c-> <c- k>override</c-><c- p>;</c->

  <c- n>optional</c-><c- o>&lt;</c-><i><c- n>on</c-><c- o>-</c-><c- n>stop</c-><c- o>-</c-><c- n>callback</c-></i><c- o>></c-> <c- n>on_stop</c-><c- p>;</c->
  <i><c- n>shared</c-><c- o>-</c-><c- n>state</c-></i><c- o>&lt;</c-><c- n>Sndr</c-><c- o>>*</c-> <c- n>sh_state</c-><c- p>;</c->
  <c- n>Rcvr</c-><c- o>*</c-> <c- n>rcvr</c-><c- p>;</c->
<c- p>};</c->
</pre>
     <ol>
      <li data-md>
<pre class="highlight"><i><c- n>local</c-><c- o>-</c-><c- n>state</c-></i><c- p>(</c-><c- n>Sndr</c-><c- o>&amp;&amp;</c-> <c- n>sndr</c-><c- p>,</c-> <c- n>Rcvr</c-><c- o>&amp;</c-> <c- n>rcvr</c-><c- p>)</c-> <c- k>noexcept</c-><c- p>;</c-></pre>
       <ol>
        <li data-md>
         <p><em>Effects:</em> Equivalent to:</p>
<pre class="highlight"><c- k>auto</c-><c- o>&amp;&amp;</c-> <c- p>[</c-><c- n>tag</c-><c- p>,</c-> <c- n>data</c-><c- p>,</c-> <c- n>child</c-><c- p>]</c-> <c- o>=</c-> <c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>Sndr</c-><c- o>></c-><c- p>(</c-><c- n>sndr</c-><c- p>);</c->
<c- k>this</c-><c- o>-></c-><c- n>sh_state</c-> <c- o>=</c-> <c- n>data</c-><c- p>.</c-><c- n>sh_state</c-><c- p>.</c-><c- n>get</c-><c- p>();</c->
<c- k>this</c-><c- o>-></c-><c- n>sh_state</c-><c- o>-></c-><i><c- n>inc</c-><c- o>-</c-><c- n>ref</c-></i><c- p>();</c->
<c- k>this</c-><c- o>-></c-><c- n>rcvr</c-> <c- o>=</c-> <c- o>&amp;</c-><c- n>rcvr</c-><c- p>;</c->
</pre>
       </ol>
      <li data-md>
<pre class="highlight"><c- o>~</c-><i><c- n>local</c-><c- o>-</c-><c- n>state</c-></i><c- p>();</c-></pre>
       <ol>
        <li data-md>
         <p><em>Effects:</em> Equivalent to:</p>
<pre class="highlight"><i><c- n>detach</c-></i><c- p>();</c->
<c- n>sh_state</c-><c- o>-></c-><i><c- n>dec</c-><c- o>-</c-><c- n>ref</c-></i><c- p>();</c->
</pre>
       </ol>
      <li data-md>
<pre class="highlight"><c- b>void</c-> <i><c- nf>notify</c-></i><c- p>()</c-> <c- k>noexcept</c-> <c- k>override</c-><c- p>;</c-></pre>
       <ol>
        <li data-md>
         <p><em>Effects:</em> Equivalent to:</p>
<pre class="highlight"><c- n>on_stop</c-><c- p>.</c-><c- n>reset</c-><c- p>();</c->
<c- n>visit</c-><c- p>(</c->
  <c- p>[</c-><c- k>this</c-><c- p>]</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Tuple</c-><c- o>></c-><c- p>(</c-><c- n>Tuple</c-><c- o>&amp;&amp;</c-> <c- n>tupl</c-><c- p>)</c-> <c- k>noexcept</c-> <c- o>-></c-> <c- b>void</c-> <c- p>{</c->
    <c- n>apply</c-><c- p>(</c->
      <c- p>[</c-><c- k>this</c-><c- p>](</c-><c- k>auto</c-> <c- n>tag</c-><c- p>,</c-> <c- k>auto</c-><c- o>&amp;</c-><c- p>...</c-> <c- n>args</c-><c- p>)</c-> <c- k>noexcept</c-> <c- o>-></c-> <c- b>void</c-> <c- p>{</c->
        <c- n>tag</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- o>*</c-><c- n>rcvr</c-><c- p>),</c-> <c- n>std</c-><c- o>::</c-><c- n>forward_like</c-><c- o>&lt;</c-><c- n>Tuple</c-><c- o>></c-><c- p>(</c-><c- n>args</c-><c- p>)...);</c->
      <c- p>},</c->
      <c- n>tupl</c-><c- p>);</c->
  <c- p>},</c->
  <i><c- n>QUAL</c-></i><c- p>(</c-><c- n>sh_state</c-><c- o>-></c-><c- n>result</c-><c- p>));</c->
<c- p>);</c->
</pre>
         <p>where <i><code class="highlight"><c- n>QUAL</c-></code></i> is <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>move</c-></code> if <code class="highlight"><c- n>same_as</c-><c- o>&lt;</c-><c- n>tag_of_t</c-><c- o>&lt;</c-><c- n>Sndr</c-><c- o>></c-><c- p>,</c-> <i><c- n>ensure</c-><c- o>-</c-><c- n>started</c-><c- o>-</c-><c- n>impl</c-><c- o>-</c-><c- n>tag</c-></i><c- o>></c-></code> is <code class="highlight">true</code>, and <code class="highlight"><c- n>as_const</c-></code> otherwise.</p>
       </ol>
      <li data-md>
<pre class="highlight"><c- b>void</c-> <i><c- nf>detach</c-></i><c- p>()</c-> <c- k>noexcept</c-> <c- k>override</c-><c- p>;</c-></pre>
       <ol>
        <li data-md>
         <p><em>Effects:</em> Equivalent to <code class="highlight"><c- n>sh_state</c-><c- o>-></c-><i><c- n>detach</c-></i><c- p>()</c-></code> if <code class="highlight"><c- n>same_as</c-><c- o>&lt;</c-><c- n>tag_of_t</c-><c- o>&lt;</c-><c- n>Sndr</c-><c- o>></c-><c- p>,</c-> <i><c- n>ensure</c-><c- o>-</c-><c- n>started</c-><c- o>-</c-><c- n>impl</c-><c- o>-</c-><c- n>tag</c-></i><c- o>></c-></code> is <code class="highlight">true</code>; otherwise,
nothing.</p>
       </ol>
     </ol>
    <li data-md>
     <p>Let <i><code class="highlight"><c- n>shared</c-><c- o>-</c-><c- n>receiver</c-></code></i> denote the following exposition-only class
template:</p>
<pre class="highlight"><c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Sndr</c-><c- o>></c->
<c- k>struct</c-> <i><c- nc>shared</c-><c- o>-</c-><c- n>receiver</c-></i> <c- p>{</c->
  <c- k>using</c-> <c- n>receiver_concept</c-> <c- o>=</c-> <c- n>receiver_t</c-><c- p>;</c->

  <c- k>template</c-><c- o>&lt;</c-><i><c- n>completion</c-><c- o>-</c-><c- n>tag</c-></i> <c- n>Tag</c-><c- p>,</c-> <c- k>class</c-><c- p>...</c-> <c- n>Args</c-><c- o>></c->
  <c- k>friend</c-> <c- b>void</c-> <c- n>tag_invoke</c-><c- p>(</c-><c- n>Tag</c-><c- p>,</c-> <i><c- n>shared</c-><c- o>-</c-><c- n>receiver</c-></i><c- o>&amp;&amp;</c-> <c- n>self</c-><c- p>,</c-> <c- n>Args</c-><c- o>&amp;&amp;</c-><c- p>...</c-> <c- n>args</c-><c- p>)</c-> <c- k>noexcept</c-> <c- p>{</c->
    <c- k>try</c-> <c- p>{</c->
      <c- k>using</c-> <c- n>tuple_t</c-> <c- o>=</c-> <i><c- n>decayed</c-><c- o>-</c-><c- n>tuple</c-></i><c- o>&lt;</c-><c- n>Tag</c-><c- p>,</c-> <c- n>Args</c-><c- p>...</c-><c- o>></c-><c- p>;</c->
      <c- n>self</c-><c- p>.</c-><c- n>sh_state</c-><c- o>-></c-><c- n>result</c-><c- p>.</c-><c- k>template</c-> <c- n>emplace</c-><c- o>&lt;</c-><c- n>tuple_t</c-><c- o>></c-><c- p>(</c-><c- n>Tag</c-><c- p>(),</c-> <c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>Args</c-><c- o>></c-><c- p>(</c-><c- n>args</c-><c- p>)...);</c->
    <c- p>}</c-> <c- k>catch</c-> <c- p>(...)</c-> <c- p>{</c->
      <c- k>using</c-> <c- n>tuple_t</c-> <c- o>=</c-> <c- n>tuple</c-><c- o>&lt;</c-><c- n>set_error_t</c-><c- p>,</c-> <c- n>exception_ptr</c-><c- o>></c-><c- p>;</c->
      <c- n>self</c-><c- p>.</c-><c- n>sh_state</c-><c- o>-></c-><c- n>result</c-><c- p>.</c-><c- k>template</c-> <c- n>emplace</c-><c- o>&lt;</c-><c- n>tuple_t</c-><c- o>></c-><c- p>(</c-><c- n>set_error</c-><c- p>,</c-> <c- n>current_exception</c-><c- p>());</c->
    <c- p>}</c->
    <c- n>self</c-><c- p>.</c-><c- n>sh_state</c-><c- o>-></c-><i><c- n>notify</c-></i><c- p>();</c->
  <c- p>}</c->

  <c- k>friend</c-> <c- k>decltype</c-><c- p>(</c-><c- k>auto</c-><c- p>)</c-> <c- n>tag_invoke</c-><c- p>(</c-><c- n>get_env_t</c-><c- p>,</c-> <c- k>const</c-> <i><c- n>shared</c-><c- o>-</c-><c- n>receiver</c-></i><c- o>&amp;</c-> <c- n>self</c-><c- p>)</c-> <c- k>noexcept</c-> <c- p>{</c->
    <c- k>return</c-> <i><c- n>MAKE</c-><c- o>-</c-><c- n>ENV</c-></i><c- p>(</c-><c- n>get_stop_token</c-><c- p>,</c-> <c- n>self</c-><c- p>.</c-><c- n>sh_state</c-><c- o>-></c-><c- n>stop_src</c-><c- p>.</c-><c- n>get_token</c-><c- p>());</c->
  <c- p>}</c->

  <i><c- n>shared</c-><c- o>-</c-><c- n>state</c-></i><c- o>&lt;</c-><c- n>Sndr</c-><c- o>>*</c-> <c- n>sh_state</c-><c- p>;</c->
<c- p>};</c->
</pre>
    <li data-md>
     <p>Let <i><code class="highlight"><c- n>shared</c-><c- o>-</c-><c- n>state</c-></code></i> denote the following exposition-only class
template:</p>
<pre class="highlight"><c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Sndr</c-><c- o>></c->
<c- k>struct</c-> <i><c- nc>shared</c-><c- o>-</c-><c- n>state</c-></i> <c- p>{</c->
  <c- k>using</c-> <i><c- n>variant</c-><c- o>-</c-><c- n>type</c-></i> <c- o>=</c-> <i><c- n>see</c-> <c- n>below</c-></i><c- p>;</c->
  <c- k>using</c-> <i><c- n>state</c-><c- o>-</c-><c- n>list</c-><c- o>-</c-><c- n>type</c-></i> <c- o>=</c-> <i><c- n>see</c-> <c- n>below</c-></i><c- p>;</c->
  <c- k>using</c-> <i><c- n>state</c-><c- o>-</c-><c- n>flag</c-><c- o>-</c-><c- n>type</c-></i> <c- o>=</c-> <i><c- n>see</c-> <c- n>below</c-></i><c- p>;</c->

  <c- k>explicit</c-> <i><c- n>shared</c-><c- o>-</c-><c- n>state</c-></i><c- p>(</c-><c- n>Sndr</c-><c- o>&amp;&amp;</c-> <c- n>sndr</c-><c- p>);</c->

  <c- b>void</c-> <i><c- n>start</c-><c- o>-</c-><c- n>op</c-></i><c- p>()</c-> <c- k>noexcept</c-><c- p>;</c->
  <c- b>void</c-> <i><c- nf>notify</c-></i><c- p>()</c-> <c- k>noexcept</c-><c- p>;</c->
  <c- b>void</c-> <i><c- nf>detach</c-></i><c- p>()</c-> <c- k>noexcept</c-><c- p>;</c->
  <c- b>void</c-> <i><c- n>inc</c-><c- o>-</c-><c- n>ref</c-></i><c- p>()</c-> <c- k>noexcept</c-><c- p>;</c->
  <c- b>void</c-> <i><c- n>dec</c-><c- o>-</c-><c- n>ref</c-></i><c- p>()</c-> <c- k>noexcept</c-><c- p>;</c->

  <c- n>in_place_stop_source</c-> <c- n>stop_src</c-><c- p>{};</c->
  <i><c- n>variant</c-><c- o>-</c-><c- n>type</c-></i> <c- n>result</c-><c- p>{};</c->
  <i><c- n>state</c-><c- o>-</c-><c- n>list</c-><c- o>-</c-><c- n>type</c-></i> <c- n>waiting_states</c-><c- p>;</c->
  <i><c- n>state</c-><c- o>-</c-><c- n>flag</c-><c- o>-</c-><c- n>type</c-></i> <c- n>completed</c-><c- p>;</c->
  <c- n>atomic</c-><c- o>&lt;</c-><c- b>size_t</c-><c- o>></c-> <c- n>ref_count</c-><c- p>{</c-><c- mi>1</c-><c- p>};</c->
  <c- n>connect_result_t</c-><c- o>&lt;</c-><c- n>Sndr</c-><c- p>,</c-> <i><c- n>shared</c-><c- o>-</c-><c- n>receiver</c-></i><c- o>&lt;</c-><c- n>Sndr</c-><c- o>>></c-> <c- n>op_state</c-><c- p>;</c->
<c- p>};</c->
</pre>
     <ol>
      <li data-md>
       <p>Let <code class="highlight"><c- n>Sigs</c-></code> be a pack of the arguments to the <code class="highlight"><c- n>completion_signatures</c-></code> specialization named by <code class="highlight"><c- n>completion_signatures_of_t</c-><c- o>&lt;</c-><c- n>Sndr</c-><c- o>></c-></code>. Let <i><code class="highlight"><c- n>as</c-><c- o>-</c-><c- n>tuple</c-></code></i> be an
  alias template such that <code class="highlight"><i><c- n>as</c-><c- o>-</c-><c- n>tuple</c-></i><c- o>&lt;</c-><c- n>Tag</c-><c- p>(</c-><c- n>Args</c-><c- p>...)</c-><c- o>></c-></code> denotes the type <code class="highlight"><i><c- n>decayed</c-><c- o>-</c-><c- n>tuple</c-></i><c- o>&lt;</c-><c- n>Tag</c-><c- p>,</c-> <c- n>Args</c-><c- p>...</c-><c- o>></c-></code>. Then <i><code class="highlight"><c- n>variant</c-><c- o>-</c-><c- n>type</c-></code></i> denotes the type <code class="highlight"><c- n>variant</c-><c- o>&lt;</c-><c- n>tuple</c-><c- o>&lt;</c-><c- n>set_stopped_t</c-><c- o>></c-><c- p>,</c-> <c- n>tuple</c-><c- o>&lt;</c-><c- n>set_error_t</c-><c- p>,</c-> <c- n>exception_ptr</c-><c- o>></c-><c- p>,</c-> <i><c- n>as</c-><c- o>-</c-><c- n>tuple</c-></i><c- o>&lt;</c-><c- n>Sigs</c-><c- o>></c-><c- p>...</c-><c- o>></c-></code>, but with
  duplicate types removed.</p>
      <li data-md>
       <p>Let <i><code class="highlight"><c- n>state</c-><c- o>-</c-><c- n>list</c-><c- o>-</c-><c- n>type</c-></code></i> be a type that stores a list of pointers
  to <i><code class="highlight"><c- n>local</c-><c- o>-</c-><c- n>state</c-><c- o>-</c-><c- n>base</c-></code></i> objects and that permits atomic insertion.
  Let <i><code class="highlight"><c- n>state</c-><c- o>-</c-><c- n>flag</c-><c- o>-</c-><c- n>type</c-></code></i> be a type that can be atomically toggled
  between <code class="highlight">true</code> and <code class="highlight">false</code>.</p>
      <li data-md>
<pre class="highlight">  <c- k>explicit</c-> <i><c- n>shared</c-><c- o>-</c-><c- n>state</c-></i><c- p>(</c-><c- n>Sndr</c-><c- o>&amp;&amp;</c-> <c- n>sndr</c-><c- p>);</c-></pre>
       <ol>
        <li data-md>
         <p><em>Effects:</em> Initializes <code class="highlight"><c- n>op_state</c-></code> with the result of <code class="highlight"><c- n>connect</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>Sndr</c-><c- o>></c-><c- p>(</c-><c- n>sndr</c-><c- p>),</c-> <i><c- n>shared</c-><c- o>-</c-><c- n>receiver</c-></i><c- p>{</c-><c- k>this</c-><c- p>})</c-></code>.</p>
        <li data-md>
         <p><em>Postcondition:</em> <code class="highlight"><c- n>waiting_states</c-></code> is empty, and <code class="highlight"><c- n>completed</c-></code> is <code class="highlight">false</code>.</p>
       </ol>
      <li data-md>
<pre class="highlight">  <c- b>void</c-> <i><c- n>start</c-><c- o>-</c-><c- n>op</c-></i><c- p>()</c-> <c- k>noexcept</c-><c- p>;</c-></pre>
       <ol>
        <li data-md>
         <p><em>Effects:</em> <code class="highlight"><i><c- n>inc</c-><c- o>-</c-><c- n>ref</c-></i><c- p>()</c-></code>. If <code class="highlight"><c- n>stop_src</c-><c- p>.</c-><c- n>stop_requested</c-><c- p>()</c-></code> is <code class="highlight">true</code>, calls <code class="highlight"><i><c- n>notify</c-></i><c- p>()</c-></code>; otherwise, calls <code class="highlight"><c- n>start</c-><c- p>(</c-><c- n>op_state</c-><c- p>)</c-></code>.</p>
       </ol>
      <li data-md>
<pre class="highlight">  <c- b>void</c-> <i><c- nf>notify</c-></i><c- p>()</c-> <c- k>noexcept</c-><c- p>;</c-></pre>
       <ol>
        <li data-md>
         <p><em>Effects:</em> Atomically does the following:</p>
         <ul>
          <li data-md>
           <p>Sets <code class="highlight"><c- n>completed</c-></code> to <code class="highlight">true</code>, and</p>
          <li data-md>
           <p>Exchanges <code class="highlight"><c- n>waiting_states</c-></code> with an empty list, storing the old
value in a local <code class="highlight"><c- n>prior_states</c-></code>. For each pointer <code class="highlight"><c- n>p</c-></code> in <code class="highlight"><c- n>prior_states</c-></code>, calls <code class="highlight"><c- n>p</c-><c- o>-></c-><i><c- n>notify</c-></i><c- p>()</c-></code>.
Finally, calls <code class="highlight"><i><c- n>dec</c-><c- o>-</c-><c- n>ref</c-></i><c- p>()</c-></code>.</p>
         </ul>
       </ol>
      <li data-md>
<pre class="highlight">  <c- b>void</c-> <i><c- nf>detach</c-></i><c- p>()</c-> <c- k>noexcept</c-><c- p>;</c-></pre>
       <ol>
        <li data-md>
         <p><em>Effects:</em> If <code class="highlight"><c- n>completed</c-></code> is <code class="highlight">false</code> and <code class="highlight"><c- n>waiting_states</c-></code> is empty,
  calls <code class="highlight"><c- n>stop_src</c-><c- p>.</c-><c- n>request_stop</c-><c- p>()</c-></code>. <span class="wg21note">This has
  the effect of requesting early termination of any asynchronous
  operation that was started as a result of a call to <code class="highlight"><c- n>ensure_started</c-></code>,
  but only if the resulting sender was never connected and started. </span></p>
       </ol>
      <li data-md>
<pre class="highlight">  <c- b>void</c-> <i><c- n>inc</c-><c- o>-</c-><c- n>ref</c-></i><c- p>()</c-> <c- k>noexcept</c-><c- p>;</c-></pre>
       <ol>
        <li data-md>
         <p><em>Effects:</em> Increments <code class="highlight"><c- n>ref_count</c-></code>.</p>
       </ol>
      <li data-md>
<pre class="highlight">  <c- b>void</c-> <i><c- n>dec</c-><c- o>-</c-><c- n>ref</c-></i><c- p>()</c-> <c- k>noexcept</c-><c- p>;</c-></pre>
       <ol>
        <li data-md>
         <p><em>Effects:</em> Decrements <code class="highlight"><c- n>ref_count</c-></code>. If the new value of <code class="highlight"><c- n>ref_count</c-></code> is <code class="highlight"><c- mi>0</c-></code>, calls <code class="highlight"><c- k>delete</c-> <c- k>this</c-></code>.</p>
        <li data-md>
         <p><em>Synchronization:</em> If <code class="highlight"><c- n>dec_ref</c-><c- p>()</c-></code> does not decrement the <code class="highlight"><c- n>ref_count</c-></code> to <code class="highlight"><c- mi>0</c-></code> then synchronizes with
  the call to <code class="highlight"><c- n>dec_ref</c-><c- p>()</c-></code> that decrements <code class="highlight"><c- n>ref_count</c-></code> to <code class="highlight"><c- mi>0</c-></code>.</p>
       </ol>
     </ol>
    <li data-md>
     <p>For each type <code class="highlight"><c- n>split_t</c-></code> and <code class="highlight"><c- n>ensure_started_t</c-></code>, there is a different,
associated exposition-only implementation tag type, <i><code class="highlight"><c- n>split</c-><c- o>-</c-><c- n>impl</c-><c- o>-</c-><c- n>tag</c-></code></i> and <i><code class="highlight"><c- n>ensure</c-><c- o>-</c-><c- n>started</c-><c- o>-</c-><c- n>impl</c-><c- o>-</c-><c- n>tag</c-></code></i>, respectively. Let <i><code class="highlight"><c- n>shared</c-><c- o>-</c-><c- n>impl</c-><c- o>-</c-><c- n>tag</c-></code></i> be the associated implementation tag type of <i><code class="highlight"><c- n>shared</c-><c- o>-</c-><c- n>cpo</c-></code></i>. Given an expression <code class="highlight"><c- n>sndr</c-></code>, the expression <code class="highlight"><i><c- n>shared</c-><c- o>-</c-><c- n>cpo</c-></i><c- p>.</c-><c- n>transform_sender</c-><c- p>(</c-><c- n>sndr</c-><c- p>)</c-></code> is equivalent to:</p>
<pre class="highlight"><c- k>auto</c-><c- o>&amp;&amp;</c-> <c- p>[</c-><c- n>tag</c-><c- p>,</c-> <c- n>data</c-><c- p>,</c-> <c- n>child</c-><c- p>]</c-> <c- o>=</c-> <c- n>sndr</c-><c- p>;</c->
<c- k>auto</c-><c- o>*</c-> <c- n>sh_state</c-> <c- o>=</c-> <c- k>new</c-> <i><c- n>shared</c-><c- o>-</c-><c- n>state</c-></i><c- p>{</c-><c- n>std</c-><c- o>::</c-><c- n>forward_like</c-><c- o>&lt;</c-><c- k>decltype</c-><c- p>((</c-><c- n>sndr</c-><c- p>))</c-><c- o>></c-><c- p>(</c-><c- n>child</c-><c- p>)};</c->
<c- k>return</c-> <i><c- n>make</c-><c- o>-</c-><c- n>sender</c-></i><c- p>(</c-><i><c- n>shared</c-><c- o>-</c-><c- n>impl</c-><c- o>-</c-><c- n>tag</c-></i><c- p>(),</c-> <i><c- n>shared</c-><c- o>-</c-><c- n>wrapper</c-></i><c- p>{</c-><c- n>sh_state</c-><c- p>,</c-> <c- n>tag</c-><c- p>});</c->
</pre>
     <p>where <i><code class="highlight"><c- n>shared</c-><c- o>-</c-><c- n>wrapper</c-></code></i> is an exposition-only class that manages the
reference count of the <code class="highlight"><c- n>shared</c-><c- o>-</c-><c- n>state</c-></code> object pointed to by <code class="highlight"><c- n>sh_state</c-></code>. <i><code class="highlight"><c- n>shared</c-><c- o>-</c-><c- n>wrapper</c-></code></i> models <code class="highlight"><c- n>movable</c-></code> with move operations nulling out the
moved-from object. If <code class="highlight"><c- n>tag</c-></code> is <code class="highlight"><c- n>split_t</c-></code>, <i><code class="highlight"><c- n>shared</c-><c- o>-</c-><c- n>wrapper</c-></code></i> models <code class="highlight"><c- n>copyable</c-></code> with copy operations incrementing the reference count by calling <code class="highlight"><c- n>sh_state</c-><c- o>-></c-><i><c- n>inc</c-><c- o>-</c-><c- n>ref</c-></i><c- p>()</c-></code>. The constructor calls <code class="highlight"><c- n>sh_state</c-><c- o>-></c-><i><c- n>start</c-><c- o>-</c-><c- n>op</c-></i><c- p>()</c-></code> if <code class="highlight"><c- n>tag</c-></code> is <code class="highlight"><c- n>ensure_started_t</c-></code>. The
destructor has no effect if <code class="highlight"><c- n>sh_state</c-></code> is null; otherwise, it calls <code class="highlight"><c- n>sh_state</c-><c- o>-></c-><i><c- n>detach</c-></i><c- p>()</c-></code> if <code class="highlight"><c- n>tag</c-></code> is <code class="highlight"><c- n>ensure_started_t</c-></code>;
and finally, it decrements the reference count by calling <code class="highlight"><c- n>sh_state</c-><c- o>-></c-><i><c- n>dec</c-><c- o>-</c-><c- n>ref</c-></i><c- p>()</c-></code>.</p>
    <li data-md>
     <p>The exposition-only class template <code class="highlight"><i><c- n>impls</c-><c- o>-</c-><c- k>for</c-></i></code> ([exec.snd.general]) is specialized for <code class="highlight"><i><c- n>shared</c-><c- o>-</c-><c- n>impl</c-><c- o>-</c-><c- n>tag</c-></i></code> as follows:</p>
<pre class="highlight"><c- k>template</c-><c- o>&lt;></c->
<c- k>struct</c-> <i><c- nc>impls</c-><c- o>-</c-><c- k>for</c-></i><c- o>&lt;</c-><i><c- n>shared</c-><c- o>-</c-><c- n>impl</c-><c- o>-</c-><c- n>tag</c-></i><c- o>></c-> <c- o>:</c-> <i><c- k>default</c-><c- o>-</c-><c- n>impls</c-></i> <c- p>{</c->
  <c- k>static</c-> <c- k>constexpr</c-> <c- k>auto</c-> <i><c- n>get</c-><c- o>-</c-><c- n>state</c-></i> <c- o>=</c-> <i><c- n>see</c-> <c- n>below</c-></i><c- p>;</c->
  <c- k>static</c-> <c- k>constexpr</c-> <c- k>auto</c-> <i><c- n>start</c-></i> <c- o>=</c-> <i><c- n>see</c-> <c- n>below</c-></i><c- p>;</c->
<c- p>};</c->
</pre>
     <ol>
      <li data-md>
       <p>The member <code class="highlight"><i><c- n>impls</c-><c- o>-</c-><c- k>for</c-></i><c- o>&lt;</c-><i><c- n>shared</c-><c- o>-</c-><c- n>impl</c-><c- o>-</c-><c- n>tag</c-></i><c- o>>::</c-><i><c- n>get</c-><c- o>-</c-><c- n>state</c-></i></code> is initialized with a callable object equivalent to the following lambda
expression:</p>
<pre class="highlight"><c- p>[]</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Sndr</c-><c- o>></c-><c- p>(</c-><c- n>Sndr</c-><c- o>&amp;&amp;</c-> <c- n>sndr</c-><c- p>,</c-> <c- k>auto</c-><c- o>&amp;</c-> <c- n>rcvr</c-><c- p>)</c-> <c- k>noexcept</c-> <c- p>{</c->
  <c- k>return</c-> <i><c- n>local</c-><c- o>-</c-><c- n>state</c-></i><c- p>{</c-><c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>Sndr</c-><c- o>></c-><c- p>(</c-><c- n>sndr</c-><c- p>),</c-> <c- n>rcvr</c-><c- p>};</c->
<c- p>}</c->
</pre>
      <li data-md>
       <p>The member <code class="highlight"><i><c- n>impls</c-><c- o>-</c-><c- k>for</c-></i><c- o>&lt;</c-><i><c- n>shared</c-><c- o>-</c-><c- n>impl</c-><c- o>-</c-><c- n>tag</c-></i><c- o>>::</c-><i><c- n>start</c-></i></code> is initialized with a callable object that has a call operator
equivalent to the following:</p>
<pre class="highlight"><c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-> <c- nc>Sndr</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Rcvr</c-><c- o>></c->
<c- b>void</c-> <c- k>operator</c-><c- p>()(</c-><i><c- n>local</c-><c- o>-</c-><c- n>state</c-></i><c- o>&lt;</c-><c- n>Sndr</c-><c- p>,</c-> <c- n>Rcvr</c-><c- o>>&amp;</c-> <c- n>state</c-><c- p>,</c-> <c- n>Rcvr</c-><c- o>&amp;</c-> <c- n>rcvr</c-><c- p>)</c-> <c- k>const</c-> <c- k>noexcept</c-><c- p>;</c-></pre>
       <ol>
        <li data-md>
         <p><em>Effects:</em></p>
         <ol>
          <li data-md>
           <p>If <code class="highlight"><c- n>state</c-><c- p>.</c-><c- n>sh_state</c-><c- o>-></c-><c- n>completed</c-></code> is <code class="highlight">true</code>, calls <code class="highlight"><c- n>state</c-><c- p>.</c-><i><c- n>notify</c-></i><c- p>()</c-></code> and returns.</p>
          <li data-md>
           <p>Otherwise, calls:</p>
<pre class="highlight"><c- n>state</c-><c- p>.</c-><c- n>on_stop</c-><c- p>.</c-><c- n>emplace</c-><c- p>(</c->
  <c- n>get_stop_token</c-><c- p>(</c-><c- n>get_env</c-><c- p>(</c-><c- n>rcvr</c-><c- p>)),</c->
  <i><c- n>on</c-><c- o>-</c-><c- n>stop</c-><c- o>-</c-><c- n>request</c-></i><c- p>{</c-><c- n>state</c-><c- p>.</c-><c- n>sh_state</c-><c- o>-></c-><c- n>stop_src</c-><c- p>})</c->
</pre>
           <p>If <i><code class="highlight"><c- n>shared</c-><c- o>-</c-><c- n>impl</c-><c- o>-</c-><c- n>tag</c-></code></i> is <i><code class="highlight"><c- n>ensure</c-><c- o>-</c-><c- n>started</c-><c- o>-</c-><c- n>impl</c-><c- o>-</c-><c- n>tag</c-></code></i>, and if <code class="highlight"><c- n>state</c-><c- p>.</c-><c- n>sh_state</c-><c- o>-></c-><c- n>stop_src</c-><c- p>.</c-><c- n>stop_requested</c-><c- p>()</c-></code> is <code class="highlight">true</code>, calls <code class="highlight"><c- n>set_stopped</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>rcvr</c-><c- p>))</c-></code> and returns.</p>
          <li data-md>
           <p>Then atomically does the following:</p>
           <ul>
            <li data-md>
             <p>Inserts <code class="highlight"><c- o>&amp;</c-><c- n>state</c-></code> into <code class="highlight"><c- n>state</c-><c- p>.</c-><c- n>sh_state</c-><c- o>-></c-><c- n>waiting_states</c-></code>, and</p>
            <li data-md>
             <p>Reads the value of <code class="highlight"><c- n>state</c-><c- p>.</c-><c- n>sh_state</c-><c- o>-></c-><c- n>completed</c-></code>.</p>
           </ul>
           <p>If the value is <code class="highlight">true</code>, calls <code class="highlight"><c- n>state</c-><c- p>.</c-><i><c- n>notify</c-></i><c- p>()</c-></code> and returns.</p>
          <li data-md>
           <p>If <i><code class="highlight"><c- n>shared</c-><c- o>-</c-><c- n>impl</c-><c- o>-</c-><c- n>tag</c-></code></i> is <i><code class="highlight"><c- n>split</c-><c- o>-</c-><c- n>impl</c-><c- o>-</c-><c- n>tag</c-></code></i>, and if <code class="highlight"><c- o>&amp;</c-><c- n>state</c-></code> is the first item added to <code class="highlight"><c- n>state</c-><c- p>.</c-><c- n>sh_state</c-><c- o>-></c-><c- n>waiting_states</c-></code>, calls <code class="highlight"><c- n>state</c-><c- p>.</c-><c- n>sh_state</c-><c- o>-></c-><i><c- n>start</c-><c- o>-</c-><c- n>op</c-></i><c- p>()</c-></code>.</p>
         </ol>
       </ol>
     </ol>
    <li data-md>
     <div class="wg21note">
      Under the following conditions, the results of the
child operation are discarded: 
      <ul>
       <li data-md>
        <p>When a sender returned from <code class="highlight"><c- n>ensure_started</c-></code> is destroyed without being
connected to a receiver, or</p>
       <li data-md>
        <p>If the sender is connected to a receiver but the operation state
is destroyed without having been started, or</p>
       <li data-md>
        <p>If polling the receiver’s stop token indicates that stop has been
requested when <code class="highlight"><c- n>start</c-></code> is called, and the operation has not yet
completed.</p>
      </ul>
     </div>
     <p></p>
   </ol>
   <h5 class="heading settled" data-level="11.9.10.10" id="spec-execution.senders.adaptor.when_all"><span class="secno">11.9.10.10. </span><span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>when_all</c-></code> <b>[exec.when.all]</b></span><a class="self-link" href="#spec-execution.senders.adaptor.when_all"></a></h5>
   <ol>
    <li data-md>
     <p><code class="highlight"><c- n>when_all</c-></code> and <code class="highlight"><c- n>when_all_with_variant</c-></code> both adapt multiple input senders into
a sender that completes when all input senders have completed. <code class="highlight"><c- n>when_all</c-></code> only accepts senders with a single value completion signature and on success
concatenates all the input senders' value result datums into its own value
completion operation. <code class="highlight"><c- n>when_all_with_variant</c-><c- p>(</c-><c- n>sndrs</c-><c- p>...)</c-></code> is semantically
equivalent to <code class="highlight"><c- n>when_all</c-><c- p>(</c-><c- n>into_variant</c-><c- p>(</c-><c- n>sndrs</c-><c- p>)...)</c-></code>, where <code class="highlight"><c- n>sndrs</c-></code> is a pack of
subexpressions of sender types.</p>
    <li data-md>
     <p>The names <code class="highlight"><c- n>when_all</c-></code> and <code class="highlight"><c- n>when_all_with_variant</c-></code> denote customization point
objects. For some subexpressions <code class="highlight"><c- n>sndr</c-><i><sub><c- n>i</c-></sub></i><c- p>...</c-></code>, let <code class="highlight"><c- n>Sndr</c-><i><sub><c- n>i</c-></sub></i><c- p>...</c-></code> be <code class="highlight"><c- k>decltype</c-><c- p>((</c-><c- n>sndr</c-><i><sub><c- n>i</c-></sub></i><c- p>))...</c-></code>. The expressions <code class="highlight"><c- n>when_all</c-><c- p>(</c-><c- n>sndr</c-><i><sub><c- n>i</c-></sub></i><c- p>...)</c-></code> and <code class="highlight"><c- n>when_all_with_variant</c-><c- p>(</c-><c- n>sndr</c-><i><sub><c- n>i</c-></sub></i><c- p>...)</c-></code> are ill-formed if
any of the following is true:</p>
     <ul>
      <li data-md>
       <p>If the number of subexpressions in <code class="highlight"><c- n>sndr</c-><i><sub><c- n>i</c-></sub></i><c- p>...</c-></code> is 0, or</p>
      <li data-md>
       <p>If any type <code class="highlight"><c- n>Sndr</c-><i><sub><c- n>i</c-></sub></i></code> does not satisfy <code class="highlight"><c- n>sender</c-></code>.</p>
      <li data-md>
       <p>If the types of the expressions <code class="highlight"><i><c- n>get</c-><c- o>-</c-><c- n>domain</c-><c- o>-</c-><c- n>early</c-></i><c- p>(</c-><c- n>sndr</c-><sub><i><c- n>i</c-></i></sub><c- p>)</c-></code> do not share
a common type ([meta.trans.other]) for all values of <code class="highlight"><i><c- n>i</c-></i></code>.</p>
     </ul>
     <p>Otherwise, let <i><code class="highlight"><c- n>CD</c-></code></i> be the common type of the input senders' domains.</p>
    <li data-md>
     <p>The expression <code class="highlight"><c- n>when_all</c-><c- p>(</c-><c- n>sndr</c-><i><sub><c- n>i</c-></sub></i><c- p>...)</c-></code> is
expression-equivalent to:</p>
<pre class="highlight"><c- n>transform_sender</c-><c- p>(</c->
  <i><c- n>CD</c-></i><c- p>(),</c->
  <i><c- n>make</c-><c- o>-</c-><c- n>sender</c-></i><c- p>(</c-><c- n>when_all</c-><c- p>,</c-> <c- p>{},</c-> <c- n>sndr</c-><sub><i><c- n>0</c-></i></sub><c- p>,</c-> <c- p>...</c-> <c- n>sndr</c-><sub><i><c- n>n</c-><c- mi>-1</c-></i></sub><c- p>));</c->
</pre>
    <li data-md>
     <p>The exposition-only class template <code class="highlight"><i><c- n>impls</c-><c- o>-</c-><c- k>for</c-></i></code> ([exec.snd.general]) is specialized for <code class="highlight"><c- n>when_all_t</c-></code> as follows:</p>
<pre class="highlight"><c- k>template</c-><c- o>&lt;></c->
<c- k>struct</c-> <i><c- nc>impls</c-><c- o>-</c-><c- k>for</c-></i><c- o>&lt;</c-><c- n>when_all_t</c-><c- o>></c-> <c- o>:</c-> <i><c- k>default</c-><c- o>-</c-><c- n>impls</c-></i> <c- p>{</c->
  <c- k>static</c-> <c- k>constexpr</c-> <c- k>auto</c-> <i><c- n>get</c-><c- o>-</c-><c- n>attrs</c-></i> <c- o>=</c-> <i><c- n>see</c-> <c- n>below</c-></i><c- p>;</c->
  <c- k>static</c-> <c- k>constexpr</c-> <c- k>auto</c-> <i><c- n>get</c-><c- o>-</c-><c- n>env</c-></i> <c- o>=</c-> <i><c- n>see</c-> <c- n>below</c-></i><c- p>;</c->
  <c- k>static</c-> <c- k>constexpr</c-> <c- k>auto</c-> <i><c- n>get</c-><c- o>-</c-><c- n>state</c-></i> <c- o>=</c-> <i><c- n>see</c-> <c- n>below</c-></i><c- p>;</c->
  <c- k>static</c-> <c- k>constexpr</c-> <c- k>auto</c-> <i><c- n>start</c-></i> <c- o>=</c-> <i><c- n>see</c-> <c- n>below</c-></i><c- p>;</c->
  <c- k>static</c-> <c- k>constexpr</c-> <c- k>auto</c-> <i><c- n>complete</c-></i> <c- o>=</c-> <i><c- n>see</c-> <c- n>below</c-></i><c- p>;</c->
<c- p>};</c->
</pre>
     <ol>
      <li data-md>
       <p>The member <code class="highlight"><i><c- n>impls</c-><c- o>-</c-><c- k>for</c-></i><c- o>&lt;</c-><c- n>when_all_t</c-><c- o>>::</c-><i><c- n>get</c-><c- o>-</c-><c- n>attrs</c-></i></code> is initialized with a callable object equivalent to the following lambda
expression:</p>
<pre class="highlight"><c- p>[](</c-><c- k>auto</c-><c- o>&amp;&amp;</c-><c- p>,</c-> <c- k>auto</c-><c- o>&amp;&amp;</c-><c- p>...</c-> <c- n>child</c-><c- p>)</c-> <c- k>noexcept</c-> <c- p>{</c->
  <c- k>auto</c-> <c- n>domain_fn</c-> <c- o>=</c-> <c- p>[]</c-><c- o>&lt;</c-><c- k>class</c-><c- p>...</c-> <c- n>Ds</c-><c- o>></c-><c- p>(</c-><c- n>Ds</c-><c- p>...)</c-> <c- k>noexcept</c-> <c- p>{</c-> <c- k>return</c-> <c- n>common_type_t</c-><c- o>&lt;</c-><c- n>Ds</c-><c- p>...</c-><c- o>></c-><c- p>();</c-> <c- p>};</c->
  <c- k>using</c-> <c- n>domain_type</c-> <c- o>=</c-> <c- k>decltype</c-><c- p>(</c-><c- n>domain_fn</c-><c- p>(</c-><i><c- n>get</c-><c- o>-</c-><c- n>domain</c-><c- o>-</c-><c- n>early</c-></i><c- p>(</c-><c- n>child</c-><c- p>)...));</c->
  <c- k>if</c-> <c- k>constexpr</c-> <c- p>(</c-><c- n>same_as</c-><c- o>&lt;</c-><c- n>domain_type</c-><c- p>,</c-> <c- n>default_domain</c-><c- o>></c-><c- p>)</c-> <c- p>{</c->
    <c- k>return</c-> <c- n>empty_env</c-><c- p>();</c->
  <c- p>}</c-> <c- k>else</c-> <c- p>{</c->
    <c- k>return</c-> <i><c- n>MAKE</c-><c- o>-</c-><c- n>ENV</c-></i><c- p>(</c-><c- n>get_domain</c-><c- p>,</c-> <c- n>domain_type</c-><c- p>());</c->
  <c- p>}</c->
<c- p>}</c->
</pre>
      <li data-md>
       <p>The member <code class="highlight"><i><c- n>impls</c-><c- o>-</c-><c- k>for</c-></i><c- o>&lt;</c-><c- n>when_all_t</c-><c- o>>::</c-><i><c- n>get</c-><c- o>-</c-><c- n>env</c-></i></code> is initialized with a callable object equivalent to the following lambda
expression:</p>
<pre class="highlight"><c- p>[]</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>State</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Rcvr</c-><c- o>></c-><c- p>(</c-><c- k>auto</c-><c- o>&amp;&amp;</c-><c- p>,</c-> <c- n>State</c-><c- o>&amp;</c-> <c- n>state</c-><c- p>,</c-> <c- k>const</c-> <c- n>Receiver</c-><c- o>&amp;</c-> <c- n>rcvr</c-><c- p>)</c-> <c- k>noexcept</c-> <c- p>{</c->
  <c- k>return</c-> <i><c- n>JOIN</c-><c- o>-</c-><c- n>ENV</c-></i><c- p>(</c->
    <i><c- n>MAKE</c-><c- o>-</c-><c- n>ENV</c-></i><c- p>(</c-><c- n>get_stop_token</c-><c- p>,</c-> <c- n>state</c-><c- p>.</c-><c- n>stop_src</c-><c- p>.</c-><c- n>get_token</c-><c- p>()),</c-> <c- n>get_env</c-><c- p>(</c-><c- n>rcvr</c-><c- p>));</c->
<c- p>}</c->
</pre>
      <li data-md>
       <p>The member <code class="highlight"><i><c- n>impls</c-><c- o>-</c-><c- k>for</c-></i><c- o>&lt;</c-><c- n>when_all_t</c-><c- o>>::</c-><i><c- n>get</c-><c- o>-</c-><c- n>state</c-></i></code> is initialized with a callable object equivalent to the following lambda
expression:</p>
<pre class="highlight"><div class="ed-note"><c- nl>BUG</c-><c- p>:</c-> <code class="highlight"><c- n><c- n>apply</c-></c-></code> <c- n>isn</c->’<c- n>t</c-> <c- n>constrained</c-></div>
<c- p>[]</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Sndr</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Rcvr</c-><c- o>></c-><c- p>(</c-><c- n>Sndr</c-><c- o>&amp;&amp;</c-> <c- n>sndr</c-><c- p>,</c-> <c- n>Rcvr</c-><c- o>&amp;</c-> <c- n>rcvr</c-><c- p>)</c->
  <c- o>-></c-> <c- k>decltype</c-><c- p>(</c-><c- n>apply</c-><c- p>(</c-><i><c- n>make</c-><c- o>-</c-><c- n>state</c-></i><c- o>&lt;</c-><c- n>Rcvr</c-><c- o>></c-><c- p>{</c-><c- n>get_env</c-><c- p>(</c-><c- n>rcvr</c-><c- p>)},</c-> <c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>Sndr</c-><c- o>></c-><c- p>(</c-><c- n>sndr</c-><c- p>)))</c-> <c- p>{</c->
  <c- k>return</c-> <c- n>apply</c-><c- p>(</c-><i><c- n>make</c-><c- o>-</c-><c- n>state</c-></i><c- o>&lt;</c-><c- n>Rcvr</c-><c- o>></c-><c- p>{</c-><c- n>get_env</c-><c- p>(</c-><c- n>rcvr</c-><c- p>)},</c-> <c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>Sndr</c-><c- o>></c-><c- p>(</c-><c- n>sndr</c-><c- p>));</c->
<c- p>}</c->
</pre>
       <p>where <i><code class="highlight"><c- n>make</c-><c- o>-</c-><c- n>state</c-></code></i> is the following exposition-only class type:</p>
<pre class="highlight"><c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Sndr</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Env</c-><c- o>></c->
<c- k>concept</c-> <i><c- nc>max</c-><c- mi>-1</c-><c- o>-</c-><c- n>sender</c-><c- o>-</c-><c- n>in</c-></i> <c- o>=</c-> <c- n>sender_in</c-><c- o>&lt;</c-><c- n>Sndr</c-><c- p>,</c-> <c- n>Env</c-><c- o>></c-> <c- o>&amp;&amp;</c->
  <c- p>(</c-><c- n>tuple_size_v</c-><c- o>&lt;</c-><c- n>value_types_of_t</c-><c- o>&lt;</c-><c- n>Sndr</c-><c- p>,</c-> <c- n>Env</c-><c- p>,</c-> <c- n>tuple</c-><c- p>,</c-> <c- n>tuple</c-><c- o>>></c-> <c- o>&lt;=</c-> <c- mi>1</c-><c- p>);</c->

<c- k>enum</c-> <c- k>class</c-> <i><c- nc>disposition</c-></i> <c- p>{</c-> <i><c- n>started</c-></i><c- p>,</c-> <i><c- n>error</c-></i><c- p>,</c-> <i><c- n>stopped</c-></i> <c- p>};</c->

<c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-> <c- nc>Rcvr</c-><c- o>></c->
<c- k>struct</c-> <i><c- nc>make</c-><c- o>-</c-><c- n>state</c-></i> <c- p>{</c->
  <c- k>const</c-> <c- n>env_of_t</c-><c- o>&lt;</c-><c- n>Rcvr</c-><c- o>>&amp;</c-> <c- n>env</c-><c- p>;</c->

  <c- k>template</c-> <c- o>&lt;</c-><i><c- n>max</c-><c- mi>-1</c-><c- o>-</c-><c- n>sender</c-><c- o>-</c-><c- n>in</c-></i><c- o>&lt;</c-><c- n>env_of_t</c-><c- o>&lt;</c-><c- n>Rcvr</c-><c- o>>></c-><c- p>...</c-> <c- n>Sndrs</c-><c- o>></c->
  <c- k>auto</c-> <c- k>operator</c-><c- p>()(</c-><c- k>auto</c-><c- p>,</c-> <c- k>auto</c-><c- p>,</c-> <c- n>Sndrs</c-><c- o>&amp;&amp;</c-><c- p>...</c-> <c- n>sndrs</c-><c- p>)</c-> <c- k>const</c-> <c- p>{</c->
    <c- k>using</c-> <c- n>values_tuple</c-> <c- o>=</c-> <i><c- n>see</c-> <c- n>below</c-></i><c- p>;</c->
    <c- k>using</c-> <c- n>errors_variant</c-> <c- o>=</c-> <i><c- n>see</c-> <c- n>below</c-></i><c- p>;</c->
    <c- k>using</c-> <c- n>stop_token</c-> <c- o>=</c-> <c- n>stop_token_of_t</c-><c- o>&lt;</c-><c- n>env_of_t</c-><c- o>&lt;</c-><c- n>Rcvr</c-><c- o>>></c-><c- p>;</c->
    <c- k>using</c-> <c- n>stop_callback</c-> <c- o>=</c-> <c- n>stop_token</c-><c- o>::</c-><c- k>template</c-> <c- n>callback_type</c-><c- o>&lt;</c-><i><c- n>on</c-><c- o>-</c-><c- n>stop</c-><c- o>-</c-><c- n>request</c-></i><c- o>></c-><c- p>;</c->

    <c- k>struct</c-> <i><c- nc>state</c-></i> <c- p>{</c->
      <c- b>void</c-> <i><c- nf>arrive</c-></i><c- p>(</c-><c- n>Rcvr</c-><c- o>&amp;</c-> <c- n>rcvr</c-><c- p>)</c-> <c- k>noexcept</c-> <c- p>{</c->
        <c- k>if</c-> <c- p>(</c-><c- mi>0</c-> <c- o>==</c-> <c- o>--</c-><c- n>count</c-><c- p>)</c-> <c- p>{</c->
          <i><c- n>complete</c-></i><c- p>(</c-><c- n>rcvr</c-><c- p>);</c->
        <c- p>}</c->
      <c- p>}</c->

      <c- b>void</c-> <i><c- nf>complete</c-></i><c- p>(</c-><c- n>Rcvr</c-><c- o>&amp;</c-> <c- n>rcvr</c-><c- p>)</c-> <c- k>noexcept</c-><c- p>;</c-> <c- c1>// see below</c->

      <c- n>atomic</c-><c- o>&lt;</c-><c- b>size_t</c-><c- o>></c-> <c- n>count</c-><c- p>{</c-><c- k>sizeof</c-><c- p>...(</c-><c- n>sndrs</c-><c- p>)};</c->
      <c- n>in_place_stop_source</c-> <c- n>stop_src</c-><c- p>{};</c->
      <c- n>atomic</c-><c- o>&lt;</c-><i><c- n>disposition</c-></i><c- o>></c-> <c- n>disp</c-><c- p>{</c-><i><c- n>disposition</c-></i><c- o>::</c-><i><c- n>started</c-></i><c- p>};</c->
      <c- n>errors_variant</c-> <c- n>errors</c-><c- p>{};</c->
      <c- n>values_tuple</c-> <c- n>values</c-><c- p>{};</c->
      <c- n>optional</c-><c- o>&lt;</c-><c- n>stop_callback</c-><c- o>></c-> <c- n>on_stop</c-><c- p>{</c-><c- n>nullopt</c-><c- p>};</c->
    <c- p>};</c->

    <c- k>return</c-> <i><c- n>state</c-></i><c- p>{};</c->
  <c- p>}</c->
<c- p>};</c->
</pre>
       <ol>
        <li data-md>
         <p>Let <i>copy-fail</i> be <code class="highlight"><c- n>exception_ptr</c-></code> if decay-copying any of the
  input senders' result datums can potentially throw; otherwise, <i><code class="highlight"><c- n>none</c-><c- o>-</c-><c- n>such</c-></code></i>, where <i><code class="highlight"><c- n>none</c-><c- o>-</c-><c- n>such</c-></code></i> is an unspecified
  empty class type.</p>
        <li data-md>
         <p>The alias <code class="highlight"><c- n>values_tuple</c-></code> denotes the type <code class="highlight"><c- n>tuple</c-><c- o>&lt;</c-><c- n>value_types_of_t</c-><c- o>&lt;</c-><c- n>Sndrs</c-><c- p>,</c-> <c- n>env_of_t</c-><c- o>&lt;</c-><c- n>Rcvr</c-><c- o>></c-><c- p>,</c-> <i><c- n>decayed</c-><c- o>-</c-><c- n>tuple</c-></i><c- p>,</c-> <c- n>optional</c-><c- o>></c-><c- p>...</c-><c- o>></c-></code> if that type is well-formed;
  otherwise, <code class="highlight"><c- n>tuple</c-><c- o>&lt;></c-></code>.</p>
        <li data-md>
         <p>The alias <code class="highlight"><c- n>errors_variant</c-></code> denotes the type <code class="highlight"><c- n>variant</c-><c- o>&lt;</c-><i><c- n>none</c-><c- o>-</c-><c- n>such</c-></i><c- p>,</c-> <i><c- n>copy</c-><c- o>-</c-><c- n>fail</c-></i><c- p>,</c-> <i><c- n>Es</c-></i><c- p>...</c-><c- o>></c-></code> with duplicate types removed, where <code class="highlight"><i><c- n>Es</c-></i></code> is the pack of the decayed types of all the
  input senders' possible error result datums.</p>
        <li data-md>
         <p>The member <code class="highlight"><c- b>void</c-> <i><c- n>state</c-></i><c- o>::</c-><i><c- n>complete</c-></i><c- p>(</c-><c- n>Rcvr</c-><c- o>&amp;</c-> <c- n>rcvr</c-><c- p>)</c-> <c- k>noexcept</c-></code> behaves as follows:</p>
         <ol>
          <li data-md>
           <p>If <code class="highlight"><c- n>disp</c-></code> is equal to <code class="highlight"><i><c- n>disposition</c-></i><c- o>::</c-><i><c- n>started</c-></i></code>,
  evaluates:</p>
<pre class="highlight"><c- k>auto</c-> <c- n>tie</c-> <c- o>=</c-> <c- p>[]</c-><c- o>&lt;</c-><c- k>class</c-><c- p>...</c-> <c- n>T</c-><c- o>></c-><c- p>(</c-><c- n>tuple</c-><c- o>&lt;</c-><c- n>T</c-><c- p>...</c-><c- o>>&amp;</c-> <c- n>t</c-><c- p>)</c-> <c- k>noexcept</c-> <c- p>{</c-> <c- k>return</c-> <c- n>tuple</c-><c- o>&lt;</c-><c- n>T</c-><c- o>&amp;</c-><c- p>...</c-><c- o>></c-><c- p>(</c-><c- n>t</c-><c- p>);</c-> <c- p>};</c->
<c- k>auto</c-> <c- n>set</c-> <c- o>=</c-> <c- p>[</c-><c- o>&amp;</c-><c- p>](</c-><c- k>auto</c-><c- o>&amp;</c-><c- p>...</c-> <c- n>t</c-><c- p>)</c-> <c- k>noexcept</c-> <c- p>{</c-> <c- n>set_value</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>rcvr</c-><c- p>),</c-> <c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>t</c-><c- p>)...);</c-> <c- p>};</c->

<c- n>on_stop</c-><c- p>.</c-><c- n>reset</c-><c- p>();</c->
<c- n>apply</c-><c- p>(</c->
  <c- p>[</c-><c- o>&amp;</c-><c- p>](</c-><c- k>auto</c-><c- o>&amp;</c-><c- p>...</c-> <c- n>opts</c-><c- p>)</c-> <c- k>noexcept</c-> <c- p>{</c->
    <c- n>apply</c-><c- p>(</c-><c- n>set</c-><c- p>,</c-> <c- n>tuple_cat</c-><c- p>(</c-><c- n>tie</c-><c- p>(</c-><c- o>*</c-><c- n>opts</c-><c- p>)...));</c->
  <c- p>},</c->
  <c- n>values</c-><c- p>);</c->
</pre>
          <li data-md>
           <p>Otherwise, if <code class="highlight"><c- n>disp</c-></code> is equal to <code class="highlight"><i><c- n>disposition</c-></i><c- o>::</c-><i><c- n>error</c-></i></code>, evaluates:</p>
<pre class="highlight"><c- n>on_stop</c-><c- p>.</c-><c- n>reset</c-><c- p>();</c->
<c- n>visit</c-><c- p>(</c->
  <c- p>[</c-><c- o>&amp;</c-><c- p>]</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Error</c-><c- o>></c-><c- p>(</c-><c- n>Error</c-><c- o>&amp;</c-> <c- n>error</c-><c- p>)</c-> <c- k>noexcept</c-> <c- p>{</c->
    <c- k>if</c-> <c- k>constexpr</c-> <c- p>(</c-><c- o>!</c-><c- n>same_as</c-><c- o>&lt;</c-><c- n>Error</c-><c- p>,</c-> <i><c- n>none</c-><c- o>-</c-><c- n>such</c-></i><c- o>></c-><c- p>)</c-> <c- p>{</c->
      <c- n>set_error</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>rcvr</c-><c- p>),</c-> <c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>error</c-><c- p>));</c->
    <c- p>}</c->
  <c- p>},</c->
  <c- n>errors</c-><c- p>);</c->
</pre>
          <li data-md>
           <p>Otherwise, evaluates:</p>
<pre class="highlight"><c- n>on_stop</c-><c- p>.</c-><c- n>reset</c-><c- p>();</c->
<c- n>set_stopped</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>rcvr</c-><c- p>));</c->
</pre>
         </ol>
       </ol>
      <li data-md>
       <p>The member <code class="highlight"><i><c- n>impls</c-><c- o>-</c-><c- k>for</c-></i><c- o>&lt;</c-><c- n>when_all_t</c-><c- o>>::</c-><i><c- n>start</c-></i></code> is initialized with a callable object equivalent to the following lambda
expression:</p>
<pre class="highlight"><c- p>[]</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>State</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Rcvr</c-><c- p>,</c-> <c- k>class</c-><c- p>...</c-> <c- n>Ops</c-><c- o>></c-><c- p>(</c->
    <c- n>State</c-><c- o>&amp;</c-> <c- n>state</c-><c- p>,</c-> <c- n>Rcvr</c-><c- o>&amp;</c-> <c- n>rcvr</c-><c- p>,</c-> <c- n>Ops</c-><c- o>&amp;</c-><c- p>...</c-> <c- n>ops</c-><c- p>)</c-> <c- k>noexcept</c-> <c- o>-></c-> <c- b>void</c-> <c- p>{</c->
  <c- n>state</c-><c- p>.</c-><c- n>on_stop</c-><c- p>.</c-><c- n>emplace</c-><c- p>(</c->
    <c- n>get_stop_token</c-><c- p>(</c-><c- n>get_env</c-><c- p>(</c-><c- n>rcvr</c-><c- p>)),</c->
    <i><c- n>on</c-><c- o>-</c-><c- n>stop</c-><c- o>-</c-><c- n>request</c-></i><c- p>{</c-><c- n>state</c-><c- p>.</c-><c- n>stop_src</c-><c- p>});</c->
  <c- k>if</c-> <c- p>(</c-><c- n>state</c-><c- p>.</c-><c- n>stop_src</c-><c- p>.</c-><c- n>stop_requested</c-><c- p>())</c-> <c- p>{</c->
    <c- n>state</c-><c- p>.</c-><c- n>on_stop</c-><c- p>.</c-><c- n>reset</c-><c- p>();</c->
    <c- n>set_stopped</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>rcvr</c-><c- p>));</c->
  <c- p>}</c-> <c- k>else</c-> <c- p>{</c->
    <c- p>(</c-><c- n>start</c-><c- p>(</c-><c- n>ops</c-><c- p>),</c-> <c- p>...);</c->
  <c- p>}</c->
<c- p>}</c->
</pre>
      <li data-md>
       <p>The member <code class="highlight"><i><c- n>impls</c-><c- o>-</c-><c- k>for</c-></i><c- o>&lt;</c-><c- n>when_all_t</c-><c- o>>::</c-><i><c- n>complete</c-></i></code> is initialized with a callable object equivalent to the following lambda
expression:</p>
<pre class="highlight"><c- p>[]</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Index</c-><c- p>,</c-> <c- k>class</c-> <c- nc>State</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Rcvr</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Set</c-><c- p>,</c-> <c- k>class</c-><c- p>...</c-> <c- n>Args</c-><c- o>></c-><c- p>(</c->
    <c- k>this</c-> <c- k>auto</c-><c- o>&amp;</c-> <c- n>complete</c-><c- p>,</c-> <c- n>Index</c-><c- p>,</c-> <c- n>State</c-><c- o>&amp;</c-> <c- n>state</c-><c- p>,</c-> <c- n>Rcvr</c-><c- o>&amp;</c-> <c- n>rcvr</c-><c- p>,</c-> <c- n>Set</c-><c- p>,</c-> <c- n>Args</c-><c- o>&amp;&amp;</c-><c- p>...</c-> <c- n>args</c-><c- p>)</c-> <c- k>noexcept</c-> <c- o>-></c-> <c- b>void</c-> <c- p>{</c->
  <c- k>if</c-> <c- k>constexpr</c-> <c- p>(</c-><c- n>same_as</c-><c- o>&lt;</c-><c- n>Set</c-><c- p>,</c-> <c- n>set_error_t</c-><c- o>></c-><c- p>)</c-> <c- p>{</c->
    <c- k>if</c-> <c- p>(</c-><i><c- n>disposition</c-></i><c- o>::</c-><i><c- n>error</c-></i> <c- o>!=</c-> <c- n>state</c-><c- p>.</c-><c- n>disp</c-><c- p>.</c-><c- n>exchange</c-><c- p>(</c-><i><c- n>disposition</c-></i><c- o>::</c-><i><c- n>error</c-></i><c- p>))</c-> <c- p>{</c->
      <c- n>state</c-><c- p>.</c-><c- n>stop_src</c-><c- p>.</c-><c- n>request_stop</c-><c- p>();</c->
      <i><c- n>TRY</c-><c- o>-</c-><c- n>EMPLACE</c-><c- o>-</c-><c- n>ERROR</c-></i><c- p>(</c-><c- n>state</c-><c- p>.</c-><c- n>errors</c-><c- p>,</c-> <c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>Args</c-><c- o>></c-><c- p>(</c-><c- n>args</c-><c- p>)...);</c->
    <c- p>}</c->
  <c- p>}</c-> <c- k>else</c-> <c- k>if</c-> <c- k>constexpr</c-> <c- p>(</c-><c- n>same_as</c-><c- o>&lt;</c-><c- n>Set</c-><c- p>,</c-> <c- n>set_stopped_t</c-><c- o>></c-><c- p>)</c-> <c- p>{</c->
    <c- k>auto</c-> <c- n>expected</c-> <c- o>=</c-> <i><c- n>disposition</c-></i><c- o>::</c-><i><c- n>started</c-></i><c- p>;</c->
    <c- k>if</c-> <c- p>(</c-><c- n>state</c-><c- p>.</c-><c- n>disp</c-><c- p>.</c-><c- n>compare_exchange_strong</c-><c- p>(</c-><c- n>expected</c-><c- p>,</c-> <i><c- n>disposition</c-></i><c- o>::</c-><i><c- n>stopped</c-></i><c- p>))</c-> <c- p>{</c->
      <c- n>state</c-><c- p>.</c-><c- n>stop_src</c-><c- p>.</c-><c- n>request_stop</c-><c- p>();</c->
    <c- p>}</c->
  <c- p>}</c-> <c- k>else</c-> <c- k>if</c-> <c- k>constexpr</c-> <c- p>(</c-><c- o>!</c-><c- n>same_as</c-><c- o>&lt;</c-><c- k>decltype</c-><c- p>(</c-><c- n>State</c-><c- o>::</c-><c- n>values</c-><c- p>),</c-> <c- n>tuple</c-><c- o>&lt;>></c-><c- p>)</c-> <c- p>{</c->
    <c- k>if</c-> <c- p>(</c-><c- n>state</c-><c- p>.</c-><c- n>disp</c-> <c- o>==</c-> <i><c- n>disposition</c-></i><c- o>::</c-><i><c- n>started</c-></i><c- p>)</c-> <c- p>{</c->
      <c- k>auto</c-><c- o>&amp;</c-> <c- n>opt</c-> <c- o>=</c-> <c- n>get</c-><c- o>&lt;</c-><c- n>Index</c-><c- o>::</c-><c- n>value</c-><c- o>></c-><c- p>(</c-><c- n>state</c-><c- p>.</c-><c- n>values</c-><c- p>);</c->
      <i><c- n>TRY</c-><c- o>-</c-><c- n>EMPLACE</c-><c- o>-</c-><c- n>VALUE</c-></i><c- p>(</c-><c- n>complete</c-><c- p>,</c-> <c- n>opt</c-><c- p>,</c-> <c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>Args</c-><c- o>></c-><c- p>(</c-><c- n>args</c-><c- p>)...);</c->
    <c- p>}</c->
  <c- p>}</c->

  <c- n>state</c-><c- p>.</c-><i><c- n>arrive</c-></i><c- p>(</c-><c- n>rcvr</c-><c- p>);</c->
<c- p>}</c->
</pre>
       <p>where <code class="highlight"><i><c- n>TRY</c-><c- o>-</c-><c- n>EMPLACE</c-><c- o>-</c-><c- n>ERROR</c-></i><c- p>(</c-><c- n>v</c-><c- p>,</c-> <c- n>e</c-><c- p>)</c-></code>, for subexpressions <code class="highlight"><c- n>v</c-></code> and <code class="highlight"><c- n>e</c-></code>, is equivalent to:</p>
<pre class="highlight"><c- k>try</c-> <c- p>{</c->
  <c- n>v</c-><c- p>.</c-><c- k>template</c-> <c- n>emplace</c-><c- o>&lt;</c-><c- k>decltype</c-><c- p>(</c-><c- k>auto</c-><c- p>(</c-><c- n>e</c-><c- p>))</c-><c- o>></c-><c- p>(</c-><c- n>e</c-><c- p>);</c->
<c- p>}</c-> <c- k>catch</c-> <c- p>(...)</c-> <c- p>{</c->
  <c- n>v</c-><c- p>.</c-><c- k>template</c-> <c- n>emplace</c-><c- o>&lt;</c-><c- n>exception_ptr</c-><c- o>></c-><c- p>(</c-><c- n>current_exception</c-><c- p>());</c->
<c- p>}</c->
</pre>
       <p>if the expression <code class="highlight"><c- k>decltype</c-><c- p>(</c-><c- k>auto</c-><c- p>(</c-><c- n>e</c-><c- p>))(</c-><c- n>e</c-><c- p>)</c-></code> is potentially throwing; otherwise, <code class="highlight"><c- n>v</c-><c- p>.</c-><c- k>template</c-> <c- n>emplace</c-><c- o>&lt;</c-><c- k>decltype</c-><c- p>(</c-><c- k>auto</c-><c- p>(</c-><c- n>e</c-><c- p>))</c-><c- o>></c-><c- p>(</c-><c- n>e</c-><c- p>)</c-></code>; and where <code class="highlight"><i><c- n>TRY</c-><c- o>-</c-><c- n>EMPLACE</c-><c- o>-</c-><c- n>VALUE</c-></i><c- p>(</c-><c- n>c</c-><c- p>,</c-> <c- n>o</c-><c- p>,</c-> <c- n>as</c-><c- p>...)</c-></code>, for subexpressions <code class="highlight"><c- n>c</c-></code>, <code class="highlight"><c- n>o</c-></code>, and pack of subexpressions <code class="highlight"><c- n>as</c-></code>, is equivalent to:</p>
<pre class="highlight"><c- k>try</c-> <c- p>{</c->
  <c- n>o</c-><c- p>.</c-><c- n>emplace</c-><c- p>(</c-><c- n>as</c-><c- p>...);</c->
<c- p>}</c-> <c- k>catch</c-> <c- p>(...)</c-> <c- p>{</c->
  <c- n>c</c-><c- p>(</c-><c- n>Index</c-><c- p>(),</c-> <c- n>state</c-><c- p>,</c-> <c- n>rcvr</c-><c- p>,</c-> <c- n>set_error</c-><c- p>,</c-> <c- n>current_exception</c-><c- p>());</c->
  <c- k>return</c-><c- p>;</c->
<c- p>}</c->
</pre>
       <p>if the expression <code class="highlight"><i><c- n>decayed</c-><c- o>-</c-><c- n>tuple</c-></i><c- o>&lt;</c-><c- k>decltype</c-><c- p>(</c-><c- n>as</c-><c- p>)...</c-><c- o>></c-><c- p>{</c-><c- n>as</c-><c- p>...}</c-></code> is potentially throwing; otherwise, <code class="highlight"><c- n>o</c-><c- p>.</c-><c- n>emplace</c-><c- p>(</c-><c- n>as</c-><c- p>...)</c-></code>.</p>
     </ol>
    <li data-md>
     <p>The expression <code class="highlight"><c- n>when_all_with_variant</c-><c- p>(</c-><c- n>sndr</c-><sub><i><c- n>i</c-></i></sub><c- p>...)</c-></code> is
expression-equivalent to:</p>
<pre class="highlight"><c- n>transform_sender</c-><c- p>(</c->
  <i><c- n>CD</c-></i><c- p>(),</c->
  <i><c- n>make</c-><c- o>-</c-><c- n>sender</c-></i><c- p>(</c-><c- n>when_all_with_variant</c-><c- p>,</c-> <c- p>{},</c-> <c- n>sndr</c-><sub><i><c- n>0</c-></i></sub><c- p>,</c-> <c- p>...</c-> <c- n>sndr</c-><sub><i><c- n>n</c-><c- mi>-1</c-></i></sub><c- p>));</c->
</pre>
    <li data-md>
     <p>Given subexpressions <code class="highlight"><c- n>sndr</c-></code> and <code class="highlight"><c- n>env</c-></code>, if <code class="highlight"><i><c- n>sender</c-><c- o>-</c-><c- k>for</c-></i><c- o>&lt;</c-><c- k>decltype</c-><c- p>((</c-><c- n>sndr</c-><c- p>)),</c-> <c- n>when_all_with_variant_t</c-><c- o>></c-></code> is <code class="highlight">false</code>,
then the expression <code class="highlight"><c- n>when_all_with_variant</c-><c- p>.</c-><c- n>transform_sender</c-><c- p>(</c-><c- n>sndr</c-><c- p>,</c-> <c- n>env</c-><c- p>)</c-></code> is
ill-formed; otherwise, the body of the <code class="highlight"><c- n>transform_sender</c-></code> member-function is equivalent to:</p>
<pre class="highlight"><c- k>auto</c-> <c- p>[</c-><c- n>tag</c-><c- p>,</c-> <c- n>data</c-><c- p>,</c-> <c- p>...</c-><c- n>child</c-><c- p>]</c-> <c- o>=</c-> <c- n>sndr</c-><c- p>;</c->
<c- k>return</c-> <c- n>when_all</c-><c- p>(</c-><c- n>into_variant</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>child</c-><c- p>))...);</c->
</pre>
     <p><span class="wg21note">This causes the <code class="highlight"><c- n>when_all_with_variant</c-><c- p>(</c-><c- n>sndr</c-><c- p>...)</c-></code> sender
to become <code class="highlight"><c- n>when_all</c-><c- p>(</c-><c- n>into_variant</c-><c- p>(</c-><c- n>sndr</c-><c- p>)...)</c-></code> when it is connected with a
receiver with an execution domain that does not customize <code class="highlight"><c- n>when_all_with_variant</c-></code>.</span></p>
   </ol>
   <h5 class="heading settled" data-level="11.9.10.11" id="spec-execution.senders.adapt.into_variant"><span class="secno">11.9.10.11. </span><span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>into_variant</c-></code> <b>[exec.into.variant]</b></span><a class="self-link" href="#spec-execution.senders.adapt.into_variant"></a></h5>
   <ol>
    <li data-md>
     <p><code class="highlight"><c- n>into_variant</c-></code> adapts a sender with multiple value completion signatures into
a sender with just one consisting of a <code class="highlight"><c- n>variant</c-></code> of <code class="highlight"><c- n>tuple</c-></code>s.</p>
    <li data-md>
     <p>The template <code class="highlight"><i><c- n>into</c-><c- o>-</c-><c- n>variant</c-><c- o>-</c-><c- n>type</c-></i></code> computes the type sent by
a sender returned from <code class="highlight"><c- n>into_variant</c-></code>.</p>
<pre class="highlight"><c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Sndr</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Env</c-><c- o>></c->
    <c- k>requires</c-> <c- n>sender_in</c-><c- o>&lt;</c-><c- n>Sndr</c-><c- p>,</c-> <c- n>Env</c-><c- o>></c->
  <c- k>using</c-> <i><c- n>into</c-><c- o>-</c-><c- n>variant</c-><c- o>-</c-><c- n>type</c-></i> <c- o>=</c->
    <c- n>value_types_of_t</c-><c- o>&lt;</c-><c- n>Sndr</c-><c- p>,</c-> <c- n>Env</c-><c- o>></c-><c- p>;</c->
</pre>
    <li data-md>
     <p>The name <code class="highlight"><c- n>into_variant</c-></code> denotes a customization point object. For a
subexpression <code class="highlight"><c- n>sndr</c-></code>, let <code class="highlight"><c- n>Sndr</c-></code> be <code class="highlight"><c- k>decltype</c-><c- p>((</c-><c- n>sndr</c-><c- p>))</c-></code>. If <code class="highlight"><c- n>Sndr</c-></code> does not
satisfy <code class="highlight"><c- n>sender</c-></code>, <code class="highlight"><c- n>into_variant</c-><c- p>(</c-><c- n>sndr</c-><c- p>)</c-></code> is ill-formed.</p>
    <li data-md>
     <p>Otherwise, the expression <code class="highlight"><c- n>into_variant</c-><c- p>(</c-><c- n>sndr</c-><c- p>)</c-></code> is expression-equivalent to:</p>
<pre class="highlight"><c- n>transform_sender</c-><c- p>(</c->
  <i><c- n>get</c-><c- o>-</c-><c- n>domain</c-><c- o>-</c-><c- n>early</c-></i><c- p>(</c-><c- n>sndr</c-><c- p>),</c->
  <i><c- n>make</c-><c- o>-</c-><c- n>sender</c-></i><c- p>(</c-><c- n>into_variant</c-><c- p>,</c-> <c- p>{},</c-> <c- n>sndr</c-><c- p>))</c->
</pre>
    <li data-md>
     <p>The exposition-only class template <i><code class="highlight"><c- n>impls</c-><c- o>-</c-><c- k>for</c-></code></i> ([exec.snd.general]) is
specialized for <code class="highlight"><c- n>into_variant</c-></code> as follows:</p>
<pre class="highlight"><c- k>template</c-><c- o>&lt;></c->
<c- k>struct</c-> <i><c- nc>impls</c-><c- o>-</c-><c- k>for</c-></i><c- o>&lt;</c-><c- n>into_variant_t</c-><c- o>></c-> <c- o>:</c-> <i><c- k>default</c-><c- o>-</c-><c- n>impls</c-></i> <c- p>{</c->
  <c- k>static</c-> <c- k>constexpr</c-> <c- k>auto</c-> <i><c- n>get</c-><c- o>-</c-><c- n>state</c-></i> <c- o>=</c-> <i><c- n>see</c-> <c- n>below</c-></i><c- p>;</c->
  <c- k>static</c-> <c- k>constexpr</c-> <c- k>auto</c-> <i><c- n>complete</c-></i> <c- o>=</c-> <i><c- n>see</c-> <c- n>below</c-></i><c- p>;</c->
<c- p>};</c->
</pre>
     <ol>
      <li data-md>
       <p>The member <code class="highlight"><i><c- n>impls</c-><c- o>-</c-><c- k>for</c-></i><c- o>&lt;</c-><c- n>into_variant_t</c-><c- o>>::</c-><i><c- n>get</c-><c- o>-</c-><c- n>state</c-></i></code> is
initialized with a callable object equivalent to the following lambda:</p>
<pre class="highlight"><c- p>[]</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Sndr</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Rcvr</c-><c- o>></c-><c- p>(</c-><c- n>Sndr</c-><c- o>&amp;&amp;</c-> <c- n>sndr</c-><c- p>,</c-> <c- n>Rcvr</c-><c- o>&amp;</c-> <c- n>rcvr</c-><c- p>)</c-> <c- k>noexcept</c->
  <c- o>-></c-> <c- n>type_identity</c-><c- o>&lt;</c-><i><c- n>into</c-><c- o>-</c-><c- n>variant</c-><c- o>-</c-><c- n>type</c-></i><c- o>&lt;</c-><i><c- n>child</c-><c- o>-</c-><c- n>type</c-></i><c- o>&lt;</c-><c- n>Sndr</c-><c- o>></c-><c- p>,</c-> <c- n>env_of_t</c-><c- o>&lt;</c-><c- n>Rcvr</c-><c- o>>>></c-> <c- p>{</c->
  <c- k>return</c-> <c- p>{};</c->
<c- p>}</c->
</pre>
      <li data-md>
       <p>The member <code class="highlight"><i><c- n>impls</c-><c- o>-</c-><c- k>for</c-></i><c- o>&lt;</c-><c- n>into_variant_t</c-><c- o>>::</c-><i><c- n>complete</c-></i></code> is initialized with a callable object equivalent to the following lambda:</p>
<pre class="highlight"><c- p>[]</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>State</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Rcvr</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Tag</c-><c- p>,</c-> <c- k>class</c-><c- p>...</c-> <c- n>Args</c-><c- o>></c-><c- p>(</c->
    <c- k>auto</c-><c- p>,</c-> <c- n>State</c-><c- p>,</c-> <c- n>Rcvr</c-><c- o>&amp;</c-> <c- n>rcvr</c-><c- p>,</c-> <c- n>Tag</c-><c- p>,</c-> <c- n>Args</c-><c- o>&amp;&amp;</c-><c- p>...</c-> <c- n>args</c-><c- p>)</c-> <c- k>noexcept</c-> <c- p>{</c->
  <c- k>if</c-> <c- k>constexpr</c-> <c- p>(</c-><c- n>same_as</c-><c- o>&lt;</c-><c- n>Tag</c-><c- p>,</c-> <c- n>set_value_t</c-><c- o>></c-><c- p>)</c-> <c- p>{</c->
    <c- k>using</c-> <c- n>variant_type</c-> <c- o>=</c-> <c- k>typename</c-> <c- nc>State</c-><c- o>::</c-><c- n>type</c-><c- p>;</c->
    <c- k>using</c-> <c- n>tuple_type</c-> <c- o>=</c-> <i><c- n>decayed</c-><c- o>-</c-><c- n>tuple</c-></i><c- o>&lt;</c-><c- n>Args</c-><c- p>...</c-><c- o>></c-><c- p>;</c->
    <c- k>try</c-> <c- p>{</c->
      <c- n>set_value</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>rcvr</c-><c- p>),</c->
                <c- n>variant_type</c-><c- p>(</c-><c- n>tuple_type</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>Args</c-><c- o>></c-><c- p>(</c-><c- n>args</c-><c- p>)...)));</c->
    <c- p>}</c->
    <c- k>catch</c-> <c- p>(...)</c-> <c- p>{</c->
      <c- n>set_error</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>rcvr</c-><c- p>),</c-> <c- n>current_exception</c-><c- p>());</c->
    <c- p>}</c->
  <c- p>}</c-> <c- k>else</c-> <c- p>{</c->
    <c- n>Tag</c-><c- p>()(</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>rcvr</c-><c- p>),</c-> <c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>Args</c-><c- o>></c-><c- p>(</c-><c- n>args</c-><c- p>)...);</c->
  <c- p>}</c->
<c- p>}</c->
</pre>
     </ol>
   </ol>
   <h5 class="heading settled" data-level="11.9.10.12" id="spec-execution.senders.adapt.stopped_as_optional"><span class="secno">11.9.10.12. </span><span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>stopped_as_optional</c-></code> <b>[exec.stopped.as.optional]</b></span><a class="self-link" href="#spec-execution.senders.adapt.stopped_as_optional"></a></h5>
   <ol>
    <li data-md>
     <p><code class="highlight"><c- n>stopped_as_optional</c-></code> maps an input sender’s stopped completion operation into the value completion operation as an empty optional. The input sender’s value completion operation is also converted into an optional. The result is a sender that never completes with stopped, reporting cancellation by completing with an empty optional.</p>
    <li data-md>
     <p>The name <code class="highlight"><c- n>stopped_as_optional</c-></code> denotes a customization point object. For some subexpression <code class="highlight"><c- n>sndr</c-></code>, let <code class="highlight"><c- n>Sndr</c-></code> be <code class="highlight"><c- k>decltype</c-><c- p>((</c-><c- n>sndr</c-><c- p>))</c-></code>.
The expression <code class="highlight"><c- n>stopped_as_optional</c-><c- p>(</c-><c- n>sndr</c-><c- p>)</c-></code> is expression-equivalent to:</p>
<pre class="highlight"><c- n>transform_sender</c-><c- p>(</c->
  <i><c- n>get</c-><c- o>-</c-><c- n>sender</c-><c- o>-</c-><c- n>domain</c-></i><c- p>(</c-><c- n>sndr</c-><c- p>),</c->
  <i><c- n>make</c-><c- o>-</c-><c- n>sender</c-></i><c- p>(</c-><c- n>stopped_as_optional</c-><c- p>,</c-> <c- p>{},</c-> <c- n>sndr</c-><c- p>))</c->
</pre>
    <li data-md>
     <p>Let <code class="highlight"><c- n>sndr</c-></code> and <code class="highlight"><c- n>env</c-></code> be subexpressions such that <code class="highlight"><c- n>Sndr</c-></code> is <code class="highlight"><c- k>decltype</c-><c- p>((</c-><c- n>sndr</c-><c- p>))</c-></code> and <code class="highlight"><c- n>Env</c-></code> is <code class="highlight"><c- k>decltype</c-><c- p>((</c-><c- n>env</c-><c- p>))</c-></code>.
If either <code class="highlight"><i><c- n>sender</c-><c- o>-</c-><c- k>for</c-></i><c- o>&lt;</c-><c- n>Sndr</c-><c- p>,</c-> <c- n>stopped_as_optional_t</c-><c- o>></c-></code> or <code class="highlight"><i><c- n>single</c-><c- o>-</c-><c- n>sender</c-></i><c- o>&lt;</c-><c- n>Sndr</c-><c- p>,</c-> <c- n>Env</c-><c- o>></c-></code> is <code class="highlight">false</code> then the expression <code class="highlight"><c- n>stopped_as_optional</c-><c- p>.</c-><c- n>transform_sender</c-><c- p>(</c-><c- n>sndr</c-><c- p>,</c-> <c- n>env</c-><c- p>)</c-></code> is ill-formed; otherwise, it is equal to:</p>
<pre class="highlight"><c- k>auto</c-> <c- p>[</c-><c- n>tag</c-><c- p>,</c-> <c- n>data</c-><c- p>,</c-> <c- n>child</c-><c- p>]</c-> <c- o>=</c-> <c- n>sndr</c-><c- p>;</c->
<c- k>using</c-> <c- n>V</c-> <c- o>=</c-> <i><c- n>single</c-><c- o>-</c-><c- n>sender</c-><c- o>-</c-><c- n>value</c-><c- o>-</c-><c- n>type</c-></i><c- o>&lt;</c-><c- n>Sndr</c-><c- p>,</c-> <c- n>Env</c-><c- o>></c-><c- p>;</c->
<c- k>return</c-> <c- n>let_stopped</c-><c- p>(</c->
    <c- n>then</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>child</c-><c- p>),</c->
              <c- p>[]</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>T</c-><c- o>></c-><c- p>(</c-><c- n>T</c-><c- o>&amp;&amp;</c-> <c- n>t</c-><c- p>)</c-> <c- p>{</c-> <c- k>return</c-> <c- n>optional</c-><v><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>forward</c-><t><c- p>(</c-><c- n>t</c-><c- p>));</c-> <c- p>}),</c->
    <c- p>[]()</c-> <c- k>noexcept</c-> <c- p>{</c-> <c- k>return</c-> <c- n>just</c-><c- p>(</c-><c- n>optional</c-><v><c- p>());</c-> <c- p>});</c->
</v></t></v></pre>
   </ol>
   <h5 class="heading settled" data-level="11.9.10.13" id="spec-execution.senders.adapt.stopped_as_error"><span class="secno">11.9.10.13. </span><span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>stopped_as_error</c-></code> <b>[exec.stopped.as.error]</b></span><a class="self-link" href="#spec-execution.senders.adapt.stopped_as_error"></a></h5>
   <ol>
    <li data-md>
     <p><code class="highlight"><c- n>stopped_as_error</c-></code> maps an input sender’s stopped completion operation into
an error completion operation as a custom error type. The result is a sender
that never completes with stopped, reporting cancellation by completing with
an error.</p>
    <li data-md>
     <p>The name <code class="highlight"><c- n>stopped_as_error</c-></code> denotes a customization point object. For some subexpressions <code class="highlight"><c- n>sndr</c-></code> and <code class="highlight"><c- n>err</c-></code>, let <code class="highlight"><c- n>Sndr</c-></code> be <code class="highlight"><c- k>decltype</c-><c- p>((</c-><c- n>sndr</c-><c- p>))</c-></code> and let <code class="highlight"><c- n>Err</c-></code> be <code class="highlight"><c- k>decltype</c-><c- p>((</c-><c- n>err</c-><c- p>))</c-></code>. If the type <code class="highlight"><c- n>Sndr</c-></code> does not satisfy <code class="highlight"><c- n>sender</c-></code> or if the type <code class="highlight"><c- n>Err</c-></code> doesn’t satisfy <code class="highlight"><i><c- n>movable</c-><c- o>-</c-><c- n>value</c-></i></code>, <code class="highlight"><c- n>stopped_as_error</c-><c- p>(</c-><c- n>sndr</c-><c- p>,</c-> <c- n>err</c-><c- p>)</c-></code> is ill-formed. Otherwise, the expression <code class="highlight"><c- n>stopped_as_error</c-><c- p>(</c-><c- n>sndr</c-><c- p>,</c-> <c- n>err</c-><c- p>)</c-></code> is expression-equivalent to:</p>
<pre class="highlight"><c- n>transform_sender</c-><c- p>(</c->
  <i><c- n>get</c-><c- o>-</c-><c- n>sender</c-><c- o>-</c-><c- n>domain</c-></i><c- p>(</c-><c- n>sndr</c-><c- p>),</c->
  <i><c- n>make</c-><c- o>-</c-><c- n>sender</c-></i><c- p>(</c-><c- n>stopped_as_error</c-><c- p>,</c-> <c- n>err</c-><c- p>,</c-> <c- n>sndr</c-><c- p>))</c->
</pre>
    <li data-md>
     <p>Let <code class="highlight"><c- n>sndr</c-></code> and <code class="highlight"><c- n>env</c-></code> be subexpressions such that <code class="highlight"><c- n>Sndr</c-></code> is <code class="highlight"><c- k>decltype</c-><c- p>((</c-><c- n>sndr</c-><c- p>))</c-></code> and <code class="highlight"><c- n>Env</c-></code> is <code class="highlight"><c- k>decltype</c-><c- p>((</c-><c- n>env</c-><c- p>))</c-></code>.
If <code class="highlight"><i><c- n>sender</c-><c- o>-</c-><c- k>for</c-></i><c- o>&lt;</c-><c- n>Sndr</c-><c- p>,</c-> <c- n>stopped_as_error_t</c-><c- o>></c-></code> is <code class="highlight">false</code>, then the expression <code class="highlight"><c- n>stopped_as_error</c-><c- p>.</c-><c- n>transform_sender</c-><c- p>(</c-><c- n>sndr</c-><c- p>,</c-> <c- n>env</c-><c- p>)</c-></code> is ill-formed; otherwise, it is equal to:</p>
<pre class="highlight"><c- k>auto</c-> <c- p>[</c-><c- n>tag</c-><c- p>,</c-> <c- n>data</c-><c- p>,</c-> <c- n>child</c-><c- p>]</c-> <c- o>=</c-> <c- n>sndr</c-><c- p>;</c->
<c- k>return</c-> <c- n>let_stopped</c-><c- p>(</c->
    <c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>child</c-><c- p>),</c->
    <c- p>[</c-><c- n>err</c-> <c- o>=</c-> <c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>data</c-><c- p>)]()</c-> <c- k>mutable</c-> <c- p>{</c-> <c- k>return</c-> <c- n>just_error</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>err</c-><c- p>));</c-> <c- p>});</c->
</pre>
   </ol>
   <h4 class="heading settled" data-level="11.9.11" id="spec-execution.senders.consumers"><span class="secno">11.9.11. </span><span class="content">Sender consumers <b>[exec.consumers]</b></span><a class="self-link" href="#spec-execution.senders.consumers"></a></h4>
   <h5 class="heading settled" data-level="11.9.11.1" id="spec-execution.senders.consumers.start_detached"><span class="secno">11.9.11.1. </span><span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>start_detached</c-></code> <b>[exec.start.detached]</b></span><a class="self-link" href="#spec-execution.senders.consumers.start_detached"></a></h5>
   <ol>
    <li data-md>
     <p><code class="highlight"><c- n>start_detached</c-></code> eagerly starts a sender without the caller needing to manage
the lifetimes of any objects.</p>
    <li data-md>
     <p>The name <code class="highlight"><c- n>start_detached</c-></code> denotes a customization point object. For some
subexpression <code class="highlight"><c- n>sndr</c-></code>, let <code class="highlight"><c- n>Sndr</c-></code> be <code class="highlight"><c- k>decltype</c-><c- p>((</c-><c- n>sndr</c-><c- p>))</c-></code>. If <code class="highlight"><c- n>sender_in</c-><c- o>&lt;</c-><c- n>Sndr</c-><c- p>,</c-> <c- n>empty_env</c-><c- o>></c-></code> is <code class="highlight">false</code>, <code class="highlight"><c- n>start_detached</c-></code> is ill-formed.
Otherwise, the expression <code class="highlight"><c- n>start_detached</c-><c- p>(</c-><c- n>sndr</c-><c- p>)</c-></code> is expression-equivalent to:</p>
<pre class="highlight"><c- n>apply_sender</c-><c- p>(</c-><i><c- n>get</c-><c- o>-</c-><c- n>sender</c-><c- o>-</c-><c- n>domain</c-></i><c- p>(</c-><c- n>sndr</c-><c- p>),</c-> <c- n>start_detached</c-><c- p>,</c-> <c- n>sndr</c-><c- p>)</c->
</pre>
     <ul>
      <li data-md>
       <p><i>Mandates:</i> The type of the expression above is <code class="highlight"><c- b>void</c-></code>.</p>
     </ul>
     <p>If the expression above does not eagerly start the sender <code class="highlight"><c- n>sndr</c-></code> after
connecting it with a receiver that ignores value and stopped completion
operations and calls <code class="highlight"><c- n>terminate</c-><c- p>()</c-></code> on error completions, the behavior of
calling <code class="highlight"><c- n>start_detached</c-><c- p>(</c-><c- n>sndr</c-><c- p>)</c-></code> is undefined.</p>
    <li data-md>
     <p>Let <code class="highlight"><c- n>sndr</c-></code> be a subexpression such that <code class="highlight"><c- n>Sndr</c-></code> is <code class="highlight"><c- k>decltype</c-><c- p>((</c-><c- n>sndr</c-><c- p>))</c-></code>, and let <code class="highlight"><i><c- n>detached</c-><c- o>-</c-><c- n>receiver</c-></i></code> and <code class="highlight"><i><c- n>detached</c-><c- o>-</c-><c- n>operation</c-></i></code> be the following exposition-only
class types:</p>
<pre class="highlight"><c- k>struct</c-> <i><c- nc>detached</c-><c- o>-</c-><c- n>receiver</c-></i> <c- p>{</c->
  <c- k>using</c-> <c- n>receiver_concept</c-> <c- o>=</c-> <c- n>receiver_t</c-><c- p>;</c->
  <i><c- n>detached</c-><c- o>-</c-><c- n>operation</c-></i><c- o>*</c-> <i><c- n>op</c-></i><c- p>;</c-> <c- c1>// </c-><i><c- c1>exposition only</c-></i>

  <c- k>friend</c-> <c- b>void</c-> <c- nf>tag_invoke</c-><c- p>(</c-><c- n>set_value_t</c-><c- p>,</c-> <i><c- n>detached</c-><c- o>-</c-><c- n>receiver</c-></i><c- o>&amp;&amp;</c-> <c- n>self</c-><c- p>)</c-> <c- k>noexcept</c-> <c- p>{</c-> <c- k>delete</c-> <c- n>self</c-><c- p>.</c-><c- n>op</c-><c- p>;</c-> <c- p>}</c->
  <c- k>friend</c-> <c- b>void</c-> <c- nf>tag_invoke</c-><c- p>(</c-><c- n>set_error_t</c-><c- p>,</c-> <i><c- n>detached</c-><c- o>-</c-><c- n>receiver</c-></i><c- o>&amp;&amp;</c-><c- p>,</c-> <c- k>auto</c-><c- o>&amp;&amp;</c-><c- p>)</c-> <c- k>noexcept</c-> <c- p>{</c-> <c- n>terminate</c-><c- p>();</c-> <c- p>}</c->
  <c- k>friend</c-> <c- b>void</c-> <c- nf>tag_invoke</c-><c- p>(</c-><c- n>set_stopped_t</c-><c- p>,</c-> <i><c- n>detached</c-><c- o>-</c-><c- n>receiver</c-></i><c- o>&amp;&amp;</c-> <c- n>self</c-><c- p>)</c-> <c- k>noexcept</c-> <c- p>{</c-> <c- k>delete</c-> <c- n>self</c-><c- p>.</c-><c- n>op</c-><c- p>;</c-> <c- p>}</c->
  <c- k>friend</c-> <c- n>empty_env</c-> <c- nf>tag_invoke</c-><c- p>(</c-><c- n>get_env_t</c-><c- p>,</c-> <c- k>const</c-> <i><c- n>detached</c-><c- o>-</c-><c- n>receiver</c-></i><c- o>&amp;</c-><c- p>)</c-> <c- p>{</c-> <c- k>return</c-> <c- p>{};</c-> <c- p>}</c->
<c- p>};</c->

<c- k>struct</c-> <i><c- nc>detached</c-><c- o>-</c-><c- n>operation</c-></i> <c- p>{</c->
  <c- n>connect_result_t</c-><c- o>&lt;</c-><c- n>Sndr</c-><c- p>,</c-> <i><c- n>detached</c-><c- o>-</c-><c- n>receiver</c-></i><c- o>></c-> <c- n>op</c-><c- p>;</c-> <c- c1>// </c-><i><c- c1>exposition only</c-></i>

  <c- k>explicit</c-> <i><c- n>detached</c-><c- o>-</c-><c- n>operation</c-></i><c- p>(</c-><c- n>Sndr</c-><c- o>&amp;&amp;</c-> <c- n>sndr</c-><c- p>)</c->
    <c- o>:</c-> <c- n>op</c-><c- p>(</c-><c- n>connect</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>Sndr</c-><c- o>></c-><c- p>(</c-><c- n>sndr</c-><c- p>),</c-> <i><c- n>detached</c-><c- o>-</c-><c- n>receiver</c-></i><c- p>{</c-><c- k>this</c-><c- p>}))</c->
  <c- p>{}</c->
<c- p>};</c->
</pre>
    <li data-md>
     <p>If <code class="highlight"><c- n>sender_to</c-><c- o>&lt;</c-><c- n>Sndr</c-><c- p>,</c-> <i><c- n>detached</c-><c- o>-</c-><c- n>receiver</c-></i><c- o>></c-></code> is <code class="highlight">false</code>, the
expression <code class="highlight"><c- n>start_detached</c-><c- p>.</c-><c- n>apply_sender</c-><c- p>(</c-><c- n>sndr</c-><c- p>)</c-></code> is ill-formed; otherwise, it is
expression-equivalent to <code class="highlight"><c- n>start</c-><c- p>(</c-><c- o>*</c-><c- k>new</c-> <i><c- n>detached</c-><c- o>-</c-><c- n>operation</c-></i><c- p>(</c-><c- n>sndr</c-><c- p>))</c-></code>.</p>
   </ol>
   <h5 class="heading settled" data-level="11.9.11.2" id="spec-execution.senders.consumers.sync_wait"><span class="secno">11.9.11.2. </span><span class="content"><code class="highlight"><c- n>this_thread</c-><c- o>::</c-><c- n>sync_wait</c-></code> <b>[exec.sync.wait]</b></span><a class="self-link" href="#spec-execution.senders.consumers.sync_wait"></a></h5>
   <ol>
    <li data-md>
     <p><code class="highlight"><c- n>this_thread</c-><c- o>::</c-><c- n>sync_wait</c-></code> and <code class="highlight"><c- n>this_thread</c-><c- o>::</c-><c- n>sync_wait_with_variant</c-></code> are used
to block a current thread until a sender passed into it as an argument has
completed, and to obtain the values (if any) it completed with. <code class="highlight"><c- n>sync_wait</c-></code> requires that the input sender has exactly one value completion signature.</p>
    <li data-md>
     <p>For any receiver <code class="highlight"><c- n>rcvr</c-></code> created by an implementation of <code class="highlight"><c- n>sync_wait</c-></code> and <code class="highlight"><c- n>sync_wait_with_variant</c-></code>, the expressions <code class="highlight"><c- n>get_scheduler</c-><c- p>(</c-><c- n>get_env</c-><c- p>(</c-><c- n>rcvr</c-><c- p>))</c-></code> and <code class="highlight"><c- n>get_delegatee_scheduler</c-><c- p>(</c-><c- n>get_env</c-><c- p>(</c-><c- n>rcvr</c-><c- p>))</c-></code> shall be well-formed. For a receiver
created by the default implementation of <code class="highlight"><c- n>this_thread</c-><c- o>::</c-><c- n>sync_wait</c-></code>, these
expressions shall return a scheduler to the same thread-safe,
first-in-first-out queue of work such that tasks scheduled to the queue
execute on the thread of the caller of <code class="highlight"><c- n>sync_wait</c-></code>. [<i>Note:</i> The
scheduler for an instance of <code class="highlight"><c- n>run_loop</c-></code> that is a local variable
within <code class="highlight"><c- n>sync_wait</c-></code> is one valid implementation. -- <i>end note</i>]</p>
    <li data-md>
     <p>The templates <code class="highlight"><i><c- n>sync</c-><c- o>-</c-><c- n>wait</c-><c- o>-</c-><c- n>type</c-></i></code> and <code class="highlight"><i><c- n>sync</c-><c- o>-</c-><c- n>wait</c-><c- o>-</c-><c- n>with</c-><c- o>-</c-><c- n>variant</c-><c- o>-</c-><c- n>type</c-></i></code> are used to determine the
return types of <code class="highlight"><c- n>this_thread</c-><c- o>::</c-><c- n>sync_wait</c-></code> and <code class="highlight"><c- n>this_thread</c-><c- o>::</c-><c- n>sync_wait_with_variant</c-></code>. Let <code class="highlight"><i><c- n>sync</c-><c- o>-</c-><c- n>wait</c-><c- o>-</c-><c- n>env</c-></i></code> be the type of the expression <code class="highlight"><c- n>get_env</c-><c- p>(</c-><c- n>rcvr</c-><c- p>)</c-></code> where <code class="highlight"><c- n>rcvr</c-></code> is an instance of the
receiver created by the default implementation of <code class="highlight"><c- n>sync_wait</c-></code>.</p>
<pre class="highlight"><c- k>template</c-><c- o>&lt;</c-><c- n>sender_in</c-><c- o>&lt;</c-><i><c- n>sync</c-><c- o>-</c-><c- n>wait</c-><c- o>-</c-><c- n>env</c-></i><c- o>></c-> <c- n>Sndr</c-><c- o>></c->
  <c- k>using</c-> <i><c- n>sync</c-><c- o>-</c-><c- n>wait</c-><c- o>-</c-><c- n>type</c-></i> <c- o>=</c->
    <c- n>optional</c-><c- o>&lt;</c-><c- n>value_types_of_t</c-><c- o>&lt;</c-><c- n>Sndr</c-><c- p>,</c-> <i><c- n>sync</c-><c- o>-</c-><c- n>wait</c-><c- o>-</c-><c- n>env</c-></i><c- p>,</c-> <i><c- n>decayed</c-><c- o>-</c-><c- n>tuple</c-></i><c- p>,</c-> <c- n>type_identity_t</c-><c- o>>></c-><c- p>;</c->

<c- k>template</c-><c- o>&lt;</c-><c- n>sender_in</c-><c- o>&lt;</c-><i><c- n>sync</c-><c- o>-</c-><c- n>wait</c-><c- o>-</c-><c- n>env</c-></i><c- o>></c-> <c- n>Sndr</c-><c- o>></c->
  <c- k>using</c-> <i><c- n>sync</c-><c- o>-</c-><c- n>wait</c-><c- o>-</c-><c- n>with</c-><c- o>-</c-><c- n>variant</c-><c- o>-</c-><c- n>type</c-></i> <c- o>=</c-> <c- n>optional</c-><c- o>&lt;</c-><i><c- n>into</c-><c- o>-</c-><c- n>variant</c-><c- o>-</c-><c- n>type</c-></i><c- o>&lt;</c-><c- n>Sndr</c-><c- p>,</c-> <i><c- n>sync</c-><c- o>-</c-><c- n>wait</c-><c- o>-</c-><c- n>env</c-></i><c- o>>></c-><c- p>;</c->
</pre>
    <li data-md>
     <p>The name <code class="highlight"><c- n>this_thread</c-><c- o>::</c-><c- n>sync_wait</c-></code> denotes a customization point object. For
some subexpression <code class="highlight"><c- n>sndr</c-></code>, let <code class="highlight"><c- n>Sndr</c-></code> be <code class="highlight"><c- k>decltype</c-><c- p>((</c-><c- n>sndr</c-><c- p>))</c-></code>. If <code class="highlight"><c- n>sender_in</c-><c- o>&lt;</c-><c- n>Sndr</c-><c- p>,</c-> <i><c- n>sync</c-><c- o>-</c-><c- n>wait</c-><c- o>-</c-><c- n>env</c-></i><c- o>></c-></code> is <code class="highlight">false</code>,
or if the type <code class="highlight"><c- n>completion_signatures_of_t</c-><c- o>&lt;</c-><c- n>Sndr</c-><c- p>,</c-> <i><c- n>sync</c-><c- o>-</c-><c- n>wait</c-><c- o>-</c-><c- n>env</c-></i><c- p>,</c-> <i><c- n>type</c-><c- o>-</c-><c- n>list</c-></i><c- p>,</c-> <c- n>type_identity_t</c-><c- o>></c-></code> is ill-formed, <code class="highlight"><c- n>this_thread</c-><c- o>::</c-><c- n>sync_wait</c-><c- p>(</c-><c- n>sndr</c-><c- p>)</c-></code> is ill-formed.
Otherwise, <code class="highlight"><c- n>this_thread</c-><c- o>::</c-><c- n>sync_wait</c-><c- p>(</c-><c- n>sndr</c-><c- p>)</c-></code> is expression-equivalent to:</p>
<pre class="highlight"><c- n>apply_sender</c-><c- p>(</c-><i><c- n>get</c-><c- o>-</c-><c- n>domain</c-><c- o>-</c-><c- n>early</c-></i><c- p>(</c-><c- n>sndr</c-><c- p>),</c-> <c- n>sync_wait</c-><c- p>,</c-> <c- n>sndr</c-><c- p>)</c->
</pre>
     <ul>
      <li data-md>
       <p><i>Mandates:</i> The type of the expression above is <code class="highlight"><i><c- n>sync</c-><c- o>-</c-><c- n>wait</c-><c- o>-</c-><c- n>type</c-></i><c- o>&lt;</c-><c- n>Sndr</c-><c- p>,</c-> <i><c- n>sync</c-><c- o>-</c-><c- n>wait</c-><c- o>-</c-><c- n>env</c-></i><c- o>></c-></code>.</p>
     </ul>
    <li data-md>
     <p>Let <code class="highlight"><i><c- n>sync</c-><c- o>-</c-><c- n>wait</c-><c- o>-</c-><c- n>receiver</c-></i></code> be a class type that satisfies <code class="highlight"><c- n>receiver</c-></code>, let <code class="highlight"><c- n>rcvr</c-></code> be an xvalue of that type,
and let <code class="highlight"><c- n>crcvr</c-></code> be a const lvalue referring to <code class="highlight"><c- n>rcvr</c-></code> such that <code class="highlight"><c- n>get_env</c-><c- p>(</c-><c- n>crcvr</c-><c- p>)</c-></code> has type <code class="highlight"><i><c- n>sync</c-><c- o>-</c-><c- n>wait</c-><c- o>-</c-><c- n>env</c-></i></code>.
If <code class="highlight"><c- n>sender_in</c-><c- o>&lt;</c-><c- n>Sndr</c-><c- p>,</c-> <i><c- n>sync</c-><c- o>-</c-><c- n>wait</c-><c- o>-</c-><c- n>env</c-></i><c- o>></c-></code> is <code class="highlight">false</code>, or if the type <code class="highlight"><c- n>completion_signatures_of_t</c-><c- o>&lt;</c-><c- n>Sndr</c-><c- p>,</c-> <i><c- n>sync</c-><c- o>-</c-><c- n>wait</c-><c- o>-</c-><c- n>env</c-></i><c- p>,</c-> <i><c- n>type</c-><c- o>-</c-><c- n>list</c-></i><c- p>,</c-> <c- n>type_identity_t</c-><c- o>></c-></code> is ill-formed,
the expression <code class="highlight"><c- n>sync_wait_t</c-><c- p>().</c-><c- n>apply_sender</c-><c- p>(</c-><c- n>sndr</c-><c- p>)</c-></code> is ill-formed; otherwise it has the following effects:</p>
     <ol>
      <li data-md>
       <p>Calls <code class="highlight"><c- n>connect</c-><c- p>(</c-><c- n>sndr</c-><c- p>,</c-> <c- n>rcvr</c-><c- p>)</c-></code>, resulting in an operation state <code class="highlight"><c- n>op_state</c-></code>, then calls <code class="highlight"><c- n>start</c-><c- p>(</c-><c- n>op_state</c-><c- p>)</c-></code>.</p>
      <li data-md>
       <p>Blocks the current thread until a completion operation of <code class="highlight"><c- n>rcvr</c-></code> is executed. When it is:</p>
       <ol>
        <li data-md>
         <p>If <code class="highlight"><c- n>set_value</c-><c- p>(</c-><c- n>rcvr</c-><c- p>,</c-> <c- n>ts</c-><c- p>...)</c-></code> has been called, returns <code class="highlight"><i><c- n>sync</c-><c- o>-</c-><c- n>wait</c-><c- o>-</c-><c- n>type</c-></i><c- o>&lt;</c-><c- n>Sndr</c-><c- p>,</c-> <i><c- n>sync</c-><c- o>-</c-><c- n>wait</c-><c- o>-</c-><c- n>env</c-></i><c- o>></c-><c- p>{</c-><i><c- n>decayed</c-><c- o>-</c-><c- n>tuple</c-></i><c- o>&lt;</c-><c- k>decltype</c-><c- p>(</c-><c- n>ts</c-><c- p>)...</c-><c- o>></c-><c- p>{</c-><c- n>ts</c-><c- p>...}}</c-></code>. If that expression exits exceptionally, the exception is propagated to the caller of <code class="highlight"><c- n>sync_wait</c-></code>.</p>
        <li data-md>
         <p>If <code class="highlight"><c- n>set_error</c-><c- p>(</c-><c- n>rcvr</c-><c- p>,</c-> <c- n>err</c-><c- p>)</c-></code> has been called, let <code class="highlight"><c- n>Err</c-></code> be the decayed type of <code class="highlight"><c- n>err</c-></code>. If <code class="highlight"><c- n>Err</c-></code> is <code class="highlight"><c- n>exception_ptr</c-></code>, calls <code class="highlight"><c- n>rethrow_exception</c-><c- p>(</c-><c- n>err</c-><c- p>)</c-></code>. Otherwise, if the <code class="highlight"><c- n>Err</c-></code> is <code class="highlight"><c- n>error_code</c-></code>, throws <code class="highlight"><c- n>system_error</c-><c- p>(</c-><c- n>err</c-><c- p>)</c-></code>. Otherwise, throws <code class="highlight"><c- n>err</c-></code>.</p>
        <li data-md>
         <p>If <code class="highlight"><c- n>set_stopped</c-><c- p>(</c-><c- n>rcvr</c-><c- p>)</c-></code> has been called, returns <code class="highlight"><i><c- n>sync</c-><c- o>-</c-><c- n>wait</c-><c- o>-</c-><c- n>type</c-></i><c- o>&lt;</c-><c- n>Sndr</c-><c- p>,</c-> <i><c- n>sync</c-><c- o>-</c-><c- n>wait</c-><c- o>-</c-><c- n>env</c-></i><c- o>></c-><c- p>{}</c-></code>.</p>
       </ol>
     </ol>
    <li data-md>
     <p>The name <code class="highlight"><c- n>this_thread</c-><c- o>::</c-><c- n>sync_wait_with_variant</c-></code> denotes a customization point
object. For some subexpression <code class="highlight"><c- n>sndr</c-></code>, let <code class="highlight"><c- n>Sndr</c-></code> be the type of <code class="highlight"><c- n>into_variant</c-><c- p>(</c-><c- n>sndr</c-><c- p>)</c-></code>. If <code class="highlight"><c- n>sender_in</c-><c- o>&lt;</c-><c- n>Sndr</c-><c- p>,</c-> <i><c- n>sync</c-><c- o>-</c-><c- n>wait</c-><c- o>-</c-><c- n>env</c-></i><c- o>></c-></code> is <code class="highlight">false</code>, <code class="highlight"><c- n>this_thread</c-><c- o>::</c-><c- n>sync_wait_with_variant</c-><c- p>(</c-><c- n>sndr</c-><c- p>)</c-></code> is ill-formed. Otherwise, <code class="highlight"><c- n>this_thread</c-><c- o>::</c-><c- n>sync_wait_with_variant</c-><c- p>(</c-><c- n>sndr</c-><c- p>)</c-></code> is expression-equivalent to:</p>
<pre class="highlight"><c- n>apply_sender</c-><c- p>(</c-><i><c- n>get</c-><c- o>-</c-><c- n>sender</c-><c- o>-</c-><c- n>domain</c-></i><c- p>(</c-><c- n>sndr</c-><c- p>),</c-> <c- n>sync_wait_with_variant</c-><c- p>,</c-> <c- n>sndr</c-><c- p>)</c->
</pre>
     <ul>
      <li data-md>
       <p><i>Mandates:</i> The type of the expression above is <code class="highlight"><i><c- n>sync</c-><c- o>-</c-><c- n>wait</c-><c- o>-</c-><c- n>with</c-><c- o>-</c-><c- n>variant</c-><c- o>-</c-><c- n>type</c-></i><c- o>&lt;</c-><c- n>Sndr</c-><c- p>,</c-> <i><c- n>sync</c-><c- o>-</c-><c- n>wait</c-><c- o>-</c-><c- n>env</c-></i><c- o>></c-></code>.</p>
     </ul>
    <li data-md>
     <p>The expression <code class="highlight"><c- n>sync_wait_with_variant_t</c-><c- p>().</c-><c- n>apply_sender</c-><c- p>(</c-><c- n>sndr</c-><c- p>)</c-></code> is
equal to:</p>
<pre class="highlight"><c- k>if</c-> <c- p>(</c-><c- k>auto</c-> <c- n>opt_value</c-> <c- o>=</c-> <c- n>sync_wait</c-><c- p>(</c-><c- n>into_variant</c-><c- p>(</c-><c- n>sndr</c-><c- p>)))</c-> <c- p>{</c->
  <c- k>return</c-> <c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>get</c-><c- o>&lt;</c-><c- mi>0</c-><c- o>></c-><c- p>(</c-><c- o>*</c-><c- n>opt_value</c-><c- p>));</c->
<c- p>}</c->
<c- k>return</c-> <c- n>nullopt</c-><c- p>;</c->
</pre>
   </ol>
   <h3 class="heading settled" data-level="11.10" id="spec-execution.execute"><span class="secno">11.10. </span><span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>execute</c-></code> <b>[exec.execute]</b></span><a class="self-link" href="#spec-execution.execute"></a></h3>
   <ol>
    <li data-md>
     <p><code class="highlight"><c- n>execute</c-></code> creates fire-and-forget tasks on a specified scheduler.</p>
    <li data-md>
     <p>The name <code class="highlight"><c- n>execute</c-></code> denotes a customization point object. For some subexpressions <code class="highlight"><c- n>sch</c-></code> and <code class="highlight"><c- n>f</c-></code>, let <code class="highlight"><c- n>Sch</c-></code> be <code class="highlight"><c- k>decltype</c-><c- p>((</c-><c- n>sch</c-><c- p>))</c-></code> and <code class="highlight"><c- n>F</c-></code> be <code class="highlight"><c- k>decltype</c-><c- p>((</c-><c- n>f</c-><c- p>))</c-></code>. If <code class="highlight"><c- n>Sch</c-></code> does not satisfy <code class="highlight"><c- n>scheduler</c-></code> or <code class="highlight"><c- n>F</c-></code> does not satisfy <code class="highlight"><c- n>invocable</c-></code>, <code class="highlight"><c- n>execute</c-><c- p>(</c-><c- n>sch</c-><c- p>,</c-> <c- n>f</c-><c- p>)</c-></code> is ill-formed. Otherwise, <code class="highlight"><c- n>execute</c-><c- p>(</c-><c- n>sch</c-><c- p>,</c-> <c- n>f</c-><c- p>)</c-></code> is expression-equivalent to:</p>
<pre class="highlight"><c- n>apply_sender</c-><c- p>(</c->
  <i><c- n>query</c-><c- o>-</c-><c- n>or</c-><c- o>-</c-><c- k>default</c-></i><c- p>(</c-><c- n>get_domain</c-><c- p>,</c-> <c- n>sch</c-><c- p>,</c-> <c- n>default_domain</c-><c- p>()),</c->
  <c- n>execute</c-><c- p>,</c-> <c- n>schedule</c-><c- p>(</c-><c- n>sch</c-><c- p>),</c-> <c- n>f</c-><c- p>)</c->
</pre>
     <ul>
      <li data-md>
       <p><i>Mandates:</i> The type of the expression above is <code class="highlight"><c- b>void</c-></code>.</p>
     </ul>
    <li data-md>
     <p>For some subexpressions <code class="highlight"><c- n>sndr</c-></code> and <code class="highlight"><c- n>f</c-></code> where <code class="highlight"><c- n>F</c-></code> is <code class="highlight"><c- k>decltype</c-><c- p>((</c-><c- n>f</c-><c- p>))</c-></code>,
if <code class="highlight"><c- n>F</c-></code> does not satisfy <code class="highlight"><c- n>invocable</c-></code>, the expression <code class="highlight"><c- n>execute_t</c-><c- p>().</c-><c- n>apply_sender</c-><c- p>(</c-><c- n>sndr</c-><c- p>,</c-> <c- n>f</c-><c- p>)</c-></code> is ill-formed; otherwise it is
expression-equivalent to <code class="highlight"><c- n>start_detached</c-><c- p>(</c-><c- n>then</c-><c- p>(</c-><c- n>sndr</c-><c- p>,</c-> <c- n>f</c-><c- p>))</c-></code>.</p>
   </ol>
   <h3 class="heading settled" data-level="11.11" id="spec-execution.snd_rec_utils"><span class="secno">11.11. </span><span class="content">Sender/receiver utilities <b>[exec.utils]</b></span><a class="self-link" href="#spec-execution.snd_rec_utils"></a></h3>
   <ol>
    <li data-md>
     <p>This subclause makes use of the following exposition-only entities:</p>
<pre class="highlight"><c- c1>// [</c-><i><c- c1>Editorial note:</c-></i><c- c1> copy_cvref_t as in [[P1450R3]] -- </c-><i><c- c1>end note</c-></i><c- c1>]</c->
<c- c1>// Mandates: is_base_of_v&lt;T, remove_reference_t&lt;U>> is true</c->
<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>T</c-><c- p>,</c-> <c- k>class</c-> <c- nc>U</c-><c- o>></c->
  <c- n>copy_cvref_t</c-><c- o>&lt;</c-><c- n>U</c-><c- o>&amp;&amp;</c-><c- p>,</c-> <c- n>T</c-><c- o>></c-> <i><c- n>c</c-><c- o>-</c-><c- n>style</c-><c- o>-</c-><c- n>cast</c-></i><c- p>(</c-><c- n>U</c-><c- o>&amp;&amp;</c-> <c- n>u</c-><c- p>)</c-> <c- k>noexcept</c-> <c- k>requires</c-> <i><c- n>decays</c-><c- o>-</c-><c- n>to</c-></i><c- o>&lt;</c-><c- n>T</c-><c- p>,</c-> <c- n>T</c-><c- o>></c-> <c- p>{</c->
    <c- k>return</c-> <c- p>(</c-><c- n>copy_cvref_t</c-><c- o>&lt;</c-><c- n>U</c-><c- o>&amp;&amp;</c-><c- p>,</c-> <c- n>T</c-><c- o>></c-><c- p>)</c-> <c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>U</c-><c- o>></c-><c- p>(</c-><c- n>u</c-><c- p>);</c->
  <c- p>}</c->
</pre>
    <li data-md>
     <p>
      [<i>Note:</i> The C-style cast in 
      <tt><i>c-style-cast</i></tt>
       is to disable accessibility checks. -- <i>end note</i>]
     </p>
   </ol>
   <h4 class="heading settled" data-level="11.11.1" id="spec-execution.snd_rec_utils.rcvr_adptr"><span class="secno">11.11.1. </span><span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>receiver_adaptor</c-></code> <b>[exec.utils.rcvr.adptr]</b></span><a class="self-link" href="#spec-execution.snd_rec_utils.rcvr_adptr"></a></h4>
<pre class="highlight"><c- k>template</c-><c- o>&lt;</c->
    <i><c- k>class</c-><c- o>-</c-><c- n>type</c-></i> <c- n>Derived</c-><c- p>,</c->
    <c- n>receiver</c-> <c- n>Base</c-> <c- o>=</c-> <i><c- n>unspecified</c-></i><c- o>></c-> <c- c1>// arguments are not associated entities ([lib.tmpl-heads])</c->
  <c- k>class</c-> <c- nc>receiver_adaptor</c-><c- p>;</c->
</pre>
   <ol>
    <li data-md>
     <p><code class="highlight"><c- n>receiver_adaptor</c-></code> simplifies the implementation of one receiver type in terms of another. It defines <code class="highlight"><c- n>tag_invoke</c-></code> overloads that forward to named members if they exist, and to the adapted receiver otherwise.</p>
    <li data-md>
     <p>If <code class="highlight"><c- n>Base</c-></code> is an alias for the unspecified default template argument, then:</p>
     <ul>
      <li data-md>
       <p>Let <code class="highlight"><i><c- n>HAS</c-><c- o>-</c-><c- n>BASE</c-></i></code> be <code class="highlight">false</code>, and</p>
      <li data-md>
       <p>Let <code class="highlight"><i><c- n>GET</c-><c- o>-</c-><c- n>BASE</c-></i><c- p>(</c-><c- n>d</c-><c- p>)</c-></code> be <code class="highlight"><c- n>d</c-><c- p>.</c-><c- n>base</c-><c- p>()</c-></code>.</p>
     </ul>
     <p>otherwise, let:</p>
     <ul>
      <li data-md>
       <p>Let <code class="highlight"><i><c- n>HAS</c-><c- o>-</c-><c- n>BASE</c-></i></code> be <code class="highlight">true</code>, and</p>
      <li data-md>
       <p>Let <code class="highlight"><i><c- n>GET</c-><c- o>-</c-><c- n>BASE</c-></i><c- p>(</c-><c- n>d</c-><c- p>)</c-></code> be <code class="highlight"><i><c- n>c</c-><c- o>-</c-><c- n>style</c-><c- o>-</c-><c- n>cast</c-></i><c- o>&lt;</c-><c- n>receiver_adaptor</c-><c- o>&lt;</c-><c- n>Derived</c-><c- p>,</c-> <c- n>Base</c-><c- o>>></c-><c- p>(</c-><c- n>d</c-><c- p>).</c-><c- n>base</c-><c- p>()</c-></code>.</p>
     </ul>
     <p>Let <code class="highlight"><i><c- n>BASE</c-><c- o>-</c-><c- n>TYPE</c-></i><c- p>(</c-><c- n>D</c-><c- p>)</c-></code> be the type of <code class="highlight"><i><c- n>GET</c-><c- o>-</c-><c- n>BASE</c-></i><c- p>(</c-><c- n>declval</c-><c- o>&lt;</c-><c- n>D</c-><c- o>></c-><c- p>())</c-></code>.</p>
    <li data-md>
     <p><code class="highlight"><c- n>receiver_adaptor</c-><c- o>&lt;</c-><c- n>Derived</c-><c- p>,</c-> <c- n>Base</c-><c- o>></c-></code> is equivalent to the following:</p>
<pre class="highlight"><c- k>template</c-><c- o>&lt;</c->
  <i><c- k>class</c-><c- o>-</c-><c- n>type</c-></i> <c- n>Derived</c-><c- p>,</c->
  <c- n>receiver</c-> <c- n>Base</c-> <c- o>=</c-> <i><c- n>unspecified</c-></i><c- o>></c-> <c- c1>// arguments are not associated entities ([lib.tmpl-heads])</c->
<c- k>class</c-> <c- nc>receiver_adaptor</c-> <c- p>{</c->
  <c- k>friend</c-> <c- n>Derived</c-><c- p>;</c->
 <c- k>public</c-><c- o>:</c->
  <c- k>using</c-> <c- n>receiver_concept</c-> <c- o>=</c-> <c- n>receiver_t</c-><c- p>;</c->

  <c- c1>// Constructors</c->
  <c- n>receiver_adaptor</c-><c- p>()</c-> <c- o>=</c-> <c- k>default</c-><c- p>;</c->
  <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>B</c-><c- o>></c->
      <c- k>requires</c-> <i><c- n>HAS</c-><c- o>-</c-><c- n>BASE</c-></i> <c- o>&amp;&amp;</c-> <c- n>constructible_from</c-><c- o>&lt;</c-><c- n>Base</c-><c- p>,</c-> <c- n>B</c-><c- o>></c->
    <c- k>explicit</c-> <c- n>receiver_adaptor</c-><c- p>(</c-><c- n>B</c-><c- o>&amp;&amp;</c-> <c- n>base</c-><c- p>)</c-> <c- o>:</c-> <c- n>base_</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>B</c-><c- o>></c-><c- p>(</c-><c- n>base</c-><c- p>))</c-> <c- p>{}</c->

 <c- k>private</c-><c- o>:</c->
  <c- k>using</c-> <c- n>set_value</c-> <c- o>=</c-> <i><c- n>unspecified</c-></i><c- p>;</c->
  <c- k>using</c-> <c- n>set_error</c-> <c- o>=</c-> <i><c- n>unspecified</c-></i><c- p>;</c->
  <c- k>using</c-> <c- n>set_stopped</c-> <c- o>=</c-> <i><c- n>unspecified</c-></i><c- p>;</c->
  <c- k>using</c-> <c- n>get_env</c-> <c- o>=</c-> <i><c- n>unspecified</c-></i><c- p>;</c->

  <c- c1>// Member functions</c->
  <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Self</c-><c- o>></c->
    <c- k>requires</c-> <i><c- n>HAS</c-><c- o>-</c-><c- n>BASE</c-></i>
  <c- k>decltype</c-><c- p>(</c-><c- k>auto</c-><c- p>)</c-> <c- n>base</c-><c- p>(</c-><c- k>this</c-> <c- n>Self</c-><c- o>&amp;&amp;</c-> <c- n>self</c-><c- p>)</c-> <c- k>noexcept</c-> <c- p>{</c->
    <c- k>return</c-> <c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>Self</c-><c- o>></c-><c- p>(</c-><c- n>self</c-><c- p>).</c-><c- n>base_</c-><c- p>);</c->
  <c- p>}</c->

  <c- c1>// [exec.utils.rcvr.adptr.nonmembers] Non-member functions</c->
  <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-><c- p>...</c-> <c- n>As</c-><c- o>></c->
    <c- k>friend</c-> <c- b>void</c-> <c- n>tag_invoke</c-><c- p>(</c-><c- n>set_value_t</c-><c- p>,</c-> <c- n>Derived</c-><c- o>&amp;&amp;</c-> <c- n>self</c-><c- p>,</c-> <c- n>As</c-><c- o>&amp;&amp;</c-><c- p>...</c-> <c- n>as</c-><c- p>)</c-> <c- k>noexcept</c-><c- p>;</c->

  <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Err</c-><c- o>></c->
    <c- k>friend</c-> <c- b>void</c-> <c- n>tag_invoke</c-><c- p>(</c-><c- n>set_error_t</c-><c- p>,</c-> <c- n>Derived</c-><c- o>&amp;&amp;</c-> <c- n>self</c-><c- p>,</c-> <c- n>Err</c-><c- o>&amp;&amp;</c-> <c- n>err</c-><c- p>)</c-> <c- k>noexcept</c-><c- p>;</c->

  <c- k>friend</c-> <c- b>void</c-> <c- nf>tag_invoke</c-><c- p>(</c-><c- n>set_stopped_t</c-><c- p>,</c-> <c- n>Derived</c-><c- o>&amp;&amp;</c-> <c- n>self</c-><c- p>)</c-> <c- k>noexcept</c-><c- p>;</c->

  <c- k>friend</c-> <c- k>decltype</c-><c- p>(</c-><c- k>auto</c-><c- p>)</c-> <c- n>tag_invoke</c-><c- p>(</c-><c- n>get_env_t</c-><c- p>,</c-> <c- k>const</c-> <c- n>Derived</c-><c- o>&amp;</c-> <c- n>self</c-><c- p>)</c->
      <c- k>noexcept</c-><c- p>(</c-><i><c- n>see</c-> <c- n>below</c-></i><c- p>);</c->

  <c- p>[[</c-><c- n>no_unique_address</c-><c- p>]]</c-> <c- n>Base</c-> <c- n>base_</c-><c- p>;</c-> <c- c1>// present if and only if </c-><i><c- c1>HAS-BASE</c-></i><c- c1> is true</c->
<c- p>};</c->
</pre>
    <li data-md>
     <p>[<i>Note:</i> <code class="highlight"><c- n>receiver_adaptor</c-></code> provides <code class="highlight"><c- n>tag_invoke</c-></code> overloads on behalf of
the derived class <code class="highlight"><c- n>Derived</c-></code>, which is incomplete when <code class="highlight"><c- n>receiver_adaptor</c-></code> is
instantiated.]</p>
    <li data-md>
     <p>[<i>Example:</i></p>
<pre class="highlight"><c- k>using</c-> <c- n>_int_completion</c-> <c- o>=</c->
  <c- n>completion_signatures</c-><c- o>&lt;</c-><c- n>set_value_t</c-><c- p>(</c-><c- b>int</c-><c- p>)</c-><c- o>></c-><c- p>;</c->

<c- k>template</c-><c- o>&lt;</c-><c- n>receiver_of</c-><c- o>&lt;</c-><c- n>_int_completion</c-><c- o>></c-> <c- n>Rcvr</c-><c- o>></c->
  <c- k>class</c-> <c- nc>my_receiver</c-> <c- o>:</c-> <c- n>receiver_adaptor</c-><c- o>&lt;</c-><c- n>my_receiver</c-><c- o>&lt;</c-><c- n>Rcvr</c-><c- o>></c-><c- p>,</c-> <c- n>Rcvr</c-><c- o>></c-> <c- p>{</c->
    <c- k>friend</c-> <c- n>receiver_adaptor</c-><c- o>&lt;</c-><c- n>my_receiver</c-><c- p>,</c-> <c- n>Rcvr</c-><c- o>></c-><c- p>;</c->
    <c- b>void</c-> <c- nf>set_value</c-><c- p>()</c-> <c- o>&amp;&amp;</c-> <c- p>{</c->
      <c- n>set_value</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- o>*</c-><c- k>this</c-><c- p>).</c-><c- n>base</c-><c- p>(),</c-> <c- mi>42</c-><c- p>);</c->
    <c- p>}</c->
   <c- k>public</c-><c- o>:</c->
    <c- k>using</c-> <c- n>receiver_adaptor</c-><c- o>&lt;</c-><c- n>my_receiver</c-><c- p>,</c-> <c- n>Rcvr</c-><c- o>>::</c-><c- n>receiver_adaptor</c-><c- p>;</c->
  <c- p>};</c->
</pre>
     <p>-- <i>end example</i>]</p>
   </ol>
   <h5 class="heading settled" data-level="11.11.1.1" id="spec-execution.snd_rec_utils.receiver_adaptor.nonmembers"><span class="secno">11.11.1.1. </span><span class="content">Non-member functions <b>[exec.utils.rcvr.adptr.nonmembers]</b></span><a class="self-link" href="#spec-execution.snd_rec_utils.receiver_adaptor.nonmembers"></a></h5>
<pre class="highlight"><c- k>template</c-><c- o>&lt;</c-><c- k>class</c-><c- p>...</c-> <c- n>As</c-><c- o>></c->
  <c- k>friend</c-> <c- b>void</c-> <c- n>tag_invoke</c-><c- p>(</c-><c- n>set_value_t</c-><c- p>,</c-> <c- n>Derived</c-><c- o>&amp;&amp;</c-> <c- n>self</c-><c- p>,</c-> <c- n>As</c-><c- o>&amp;&amp;</c-><c- p>...</c-> <c- n>as</c-><c- p>)</c-> <c- k>noexcept</c-><c- p>;</c->
</pre>
   <ol>
    <li data-md>
     <p>Let <code class="highlight"><c- n>SET</c-><c- o>-</c-><c- n>VALUE</c-><c- o>-</c-><c- n>MBR</c-></code> be the expression <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>self</c-><c- p>).</c-><c- n>set_value</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>As</c-><c- o>></c-><c- p>(</c-><c- n>as</c-><c- p>)...)</c-></code>.</p>
    <li data-md>
     <p><i>Constraints:</i> Either <code class="highlight"><c- n>SET</c-><c- o>-</c-><c- n>VALUE</c-><c- o>-</c-><c- n>MBR</c-></code> is a valid expression or <code class="highlight"><c- k>typename</c-> <c- nc>Derived</c-><c- o>::</c-><c- n>set_value</c-></code> denotes a type and <code class="highlight"><i><c- n>callable</c-></i><c- o>&lt;</c-><c- n>set_value_t</c-><c- p>,</c-> <i><c- n>BASE</c-><c- o>-</c-><c- n>TYPE</c-></i><c- p>(</c-><c- n>Derived</c-><c- p>),</c-> <c- n>As</c-><c- p>...</c-><c- o>></c-></code> is <code class="highlight">true</code>.</p>
    <li data-md>
     <p><i>Mandates:</i> <code class="highlight"><c- n>SET</c-><c- o>-</c-><c- n>VALUE</c-><c- o>-</c-><c- n>MBR</c-></code>, if that expression is valid, is not potentially-throwing.</p>
    <li data-md>
     <p><i>Effects:</i> Equivalent to:</p>
     <ul>
      <li data-md>
       <p>If <code class="highlight"><c- n>SET</c-><c- o>-</c-><c- n>VALUE</c-><c- o>-</c-><c- n>MBR</c-></code> is a valid expression, <code class="highlight"><c- n>SET</c-><c- o>-</c-><c- n>VALUE</c-><c- o>-</c-><c- n>MBR</c-></code>;</p>
      <li data-md>
       <p>Otherwise, <code class="highlight"><c- n>set_value</c-><c- p>(</c-><i><c- n>GET</c-><c- o>-</c-><c- n>BASE</c-></i><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>self</c-><c- p>)),</c-> <c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>As</c-><c- o>></c-><c- p>(</c-><c- n>as</c-><c- p>)...)</c-></code>.</p>
     </ul>
   </ol>
<pre class="highlight"><c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Err</c-><c- o>></c->
  <c- k>friend</c-> <c- b>void</c-> <c- n>tag_invoke</c-><c- p>(</c-><c- n>set_error_t</c-><c- p>,</c-> <c- n>Derived</c-><c- o>&amp;&amp;</c-> <c- n>self</c-><c- p>,</c-> <c- n>Err</c-><c- o>&amp;&amp;</c-> <c- n>err</c-><c- p>)</c-> <c- k>noexcept</c-><c- p>;</c->
</pre>
   <ol>
    <li data-md>
     <p>Let <code class="highlight"><c- n>SET</c-><c- o>-</c-><c- n>ERROR</c-><c- o>-</c-><c- n>MBR</c-></code> be the expression <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>self</c-><c- p>).</c-><c- n>set_error</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>Err</c-><c- o>></c-><c- p>(</c-><c- n>err</c-><c- p>))</c-></code>.</p>
    <li data-md>
     <p><i>Constraints:</i> Either <code class="highlight"><c- n>SET</c-><c- o>-</c-><c- n>ERROR</c-><c- o>-</c-><c- n>MBR</c-></code> is a valid expression or <code class="highlight"><c- k>typename</c-> <c- nc>Derived</c-><c- o>::</c-><c- n>set_error</c-></code> denotes a type and <code class="highlight"><i><c- n>callable</c-></i><c- o>&lt;</c-><c- n>set_error_t</c-><c- p>,</c-> <i><c- n>BASE</c-><c- o>-</c-><c- n>TYPE</c-></i><c- p>(</c-><c- n>Derived</c-><c- p>),</c-> <c- n>Err</c-><c- o>></c-></code> is <code class="highlight">true</code>.</p>
    <li data-md>
     <p><i>Mandates:</i> <code class="highlight"><c- n>SET</c-><c- o>-</c-><c- n>ERROR</c-><c- o>-</c-><c- n>MBR</c-></code>, if that expression is valid, is not potentially-throwing.</p>
    <li data-md>
     <p><i>Effects:</i> Equivalent to:</p>
     <ul>
      <li data-md>
       <p>If <code class="highlight"><c- n>SET</c-><c- o>-</c-><c- n>ERROR</c-><c- o>-</c-><c- n>MBR</c-></code> is a valid expression, <code class="highlight"><c- n>SET</c-><c- o>-</c-><c- n>ERROR</c-><c- o>-</c-><c- n>MBR</c-></code>;</p>
      <li data-md>
       <p>Otherwise, <code class="highlight"><c- n>set_error</c-><c- p>(</c-><i><c- n>GET</c-><c- o>-</c-><c- n>BASE</c-></i><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>self</c-><c- p>)),</c-> <c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>Err</c-><c- o>></c-><c- p>(</c-><c- n>err</c-><c- p>))</c-></code>.</p>
     </ul>
   </ol>
<pre class="highlight"><c- k>friend</c-> <c- b>void</c-> <c- nf>tag_invoke</c-><c- p>(</c-><c- n>set_stopped_t</c-><c- p>,</c-> <c- n>Derived</c-><c- o>&amp;&amp;</c-> <c- n>self</c-><c- p>)</c-> <c- k>noexcept</c-><c- p>;</c->
</pre>
   <ol>
    <li data-md>
     <p>Let <code class="highlight"><c- n>SET</c-><c- o>-</c-><c- n>STOPPED</c-><c- o>-</c-><c- n>MBR</c-></code> be the expression <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>self</c-><c- p>).</c-><c- n>set_stopped</c-><c- p>()</c-></code>.</p>
    <li data-md>
     <p><i>Constraints:</i> Either <code class="highlight"><c- n>SET</c-><c- o>-</c-><c- n>STOPPED</c-><c- o>-</c-><c- n>MBR</c-></code> is a valid expression or <code class="highlight"><c- k>typename</c-> <c- nc>Derived</c-><c- o>::</c-><c- n>set_stopped</c-></code> denotes a type and <code class="highlight"><i><c- n>callable</c-></i><c- o>&lt;</c-><c- n>set_stopped_t</c-><c- p>,</c-> <i><c- n>BASE</c-><c- o>-</c-><c- n>TYPE</c-></i><c- p>(</c-><c- n>Derived</c-><c- p>)</c-><c- o>></c-></code> is <code class="highlight">true</code>.</p>
    <li data-md>
     <p><i>Mandates:</i> <code class="highlight"><c- n>SET</c-><c- o>-</c-><c- n>STOPPED</c-><c- o>-</c-><c- n>MBR</c-></code>, if that expression is valid, is not potentially-throwing.</p>
    <li data-md>
     <p><i>Effects:</i> Equivalent to:</p>
     <ul>
      <li data-md>
       <p>If <code class="highlight"><c- n>SET</c-><c- o>-</c-><c- n>STOPPED</c-><c- o>-</c-><c- n>MBR</c-></code> is a valid expression, <code class="highlight"><c- n>SET</c-><c- o>-</c-><c- n>STOPPED</c-><c- o>-</c-><c- n>MBR</c-></code>;</p>
      <li data-md>
       <p>Otherwise, <code class="highlight"><c- n>set_stopped</c-><c- p>(</c-><i><c- n>GET</c-><c- o>-</c-><c- n>BASE</c-></i><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>self</c-><c- p>)))</c-></code>.</p>
     </ul>
   </ol>
<pre class="highlight"><c- k>friend</c-> <c- k>decltype</c-><c- p>(</c-><c- k>auto</c-><c- p>)</c-> <c- n>tag_invoke</c-><c- p>(</c-><c- n>get_env_t</c-><c- p>,</c-> <c- k>const</c-> <c- n>Derived</c-><c- o>&amp;</c-> <c- n>self</c-><c- p>)</c->
  <c- k>noexcept</c-><c- p>(</c-><i><c- n>see</c-> <c- n>below</c-></i><c- p>);</c->
</pre>
   <ol>
    <li data-md>
     <p><i>Constraints:</i> Either <code class="highlight"><c- n>self</c-><c- p>.</c-><c- n>get_env</c-><c- p>()</c-></code> is a valid expression or <code class="highlight"><c- k>typename</c-> <c- nc>Derived</c-><c- o>::</c-><c- n>get_env</c-></code> denotes a type and <code class="highlight"><i><c- n>callable</c-></i><c- o>&lt;</c-><c- n>get_env_t</c-><c- p>,</c-> <i><c- n>BASE</c-><c- o>-</c-><c- n>TYPE</c-></i><c- p>(</c-><c- k>const</c-> <c- n>Derived</c-><c- o>&amp;</c-><c- p>)</c-><c- o>></c-></code> is <code class="highlight">true</code>.</p>
    <li data-md>
     <p><i>Effects:</i> Equivalent to:</p>
     <ul>
      <li data-md>
       <p>If <code class="highlight"><c- n>self</c-><c- p>.</c-><c- n>get_env</c-><c- p>()</c-></code> is a valid expression, <code class="highlight"><c- n>self</c-><c- p>.</c-><c- n>get_env</c-><c- p>()</c-></code>;</p>
      <li data-md>
       <p>Otherwise, <code class="highlight"><c- n>get_env</c-><c- p>(</c-><i><c- n>GET</c-><c- o>-</c-><c- n>BASE</c-></i><c- p>(</c-><c- n>self</c-><c- p>))</c-></code>.</p>
     </ul>
    <li data-md>
     <p><i>Remarks:</i> The expression in the <code class="highlight"><c- k>noexcept</c-></code> clause is:</p>
     <ul>
      <li data-md>
       <p>If <code class="highlight"><c- n>self</c-><c- p>.</c-><c- n>get_env</c-><c- p>()</c-></code> is a valid expression, <code class="highlight"><c- k>noexcept</c-><c- p>(</c-><c- n>self</c-><c- p>.</c-><c- n>get_env</c-><c- p>())</c-></code>;</p>
      <li data-md>
       <p>Otherwise, <code class="highlight"><c- k>noexcept</c-><c- p>(</c-><c- n>get_env</c-><c- p>(</c-><i><c- n>GET</c-><c- o>-</c-><c- n>BASE</c-></i><c- p>(</c-><c- n>self</c-><c- p>)))</c-></code>.</p>
     </ul>
   </ol>
   <h4 class="heading settled" data-level="11.11.2" id="spec-execution.snd_rec_utils.completion_sigs"><span class="secno">11.11.2. </span><span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>completion_signatures</c-></code> <b>[exec.utils.cmplsigs]</b></span><a class="self-link" href="#spec-execution.snd_rec_utils.completion_sigs"></a></h4>
   <ol>
    <li data-md>
     <p><code class="highlight"><c- n>completion_signatures</c-></code> is a type that encodes a set of completion signatures
([async.ops]).</p>
    <li data-md>
     <p>[<i>Example:</i></p>
<pre class="highlight"><c- k>class</c-> <c- nc>my_sender</c-> <c- p>{</c->
  <c- k>using</c-> <c- n>completion_signatures</c-> <c- o>=</c->
    <c- n>completion_signatures</c-><c- o>&lt;</c->
      <c- n>set_value_t</c-><c- p>(),</c->
      <c- n>set_value_t</c-><c- p>(</c-><c- b>int</c-><c- p>,</c-> <c- b>float</c-><c- p>),</c->
      <c- n>set_error_t</c-><c- p>(</c-><c- n>exception_ptr</c-><c- p>),</c->
      <c- n>set_error_t</c-><c- p>(</c-><c- n>error_code</c-><c- p>),</c->
      <c- n>set_stopped_t</c-><c- p>()</c-><c- o>></c-><c- p>;</c->
<c- p>};</c->

<c- c1>// Declares my_sender to be a sender that can complete by calling</c->
<c- c1>// one of the following for a receiver expression rcvr:</c->
<c- c1>//    set_value(rcvr)</c->
<c- c1>//    set_value(rcvr, int{...}, float{...})</c->
<c- c1>//    set_error(rcvr, exception_ptr{...})</c->
<c- c1>//    set_error(rcvr, error_code{...})</c->
<c- c1>//    set_stopped(rcvr)</c->
</pre>
     <p>-- <i>end example</i>]</p>
    <li data-md>
     <p>This subclause makes use of the following exposition-only entities:</p>
<pre class="highlight"><c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Fn</c-><c- o>></c->
  <c- k>concept</c-> <i><c- nc>completion</c-><c- o>-</c-><c- n>signature</c-></i> <c- o>=</c-> <i><c- n>see</c-> <c- n>below</c-></i><c- p>;</c->

<c- k>template</c-><c- o>&lt;</c-><c- b>bool</c-><c- o>></c->
  <c- k>struct</c-> <i><c- nc>indirect</c-><c- o>-</c-><c- n>meta</c-><c- o>-</c-><c- n>apply</c-></i> <c- p>{</c->
    <c- k>template</c-><c- o>&lt;</c-><c- k>template</c-><c- o>&lt;</c-><c- k>class</c-><c- p>...</c-><c- o>></c-> <c- k>class</c-> <c- nc>T</c-><c- p>,</c-> <c- k>class</c-><c- p>...</c-> <c- n>As</c-><c- o>></c->
      <c- k>using</c-> <i><c- n>meta</c-><c- o>-</c-><c- n>apply</c-></i> <c- o>=</c-> <c- n>T</c-><c- o>&lt;</c-><c- n>As</c-><c- p>...</c-><c- o>></c-><c- p>;</c-> <i><c- c1>// exposition only</c-></i>
  <c- p>};</c->

<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-><c- p>...</c-><c- o>></c->
  <c- k>concept</c-> <i><c- nc>always</c-><c- o>-</c->true</i> <c- o>=</c-> true<c- p>;</c-> <i><c- c1>// exposition only</c-></i>
</pre>
     <ol>
      <li data-md>
       <p>A type <code class="highlight"><c- n>Fn</c-></code> satisfies <code class="highlight"><i><c- n>completion</c-><c- o>-</c-><c- n>signature</c-></i></code> if and only if it is a function type with one of the following forms:</p>
       <ul>
        <li data-md>
         <p><code class="highlight"><c- n>set_value_t</c-><c- p>(</c-><i><c- n>Vs</c-></i><c- p>...)</c-></code>, where <code class="highlight"><i><c- n>Vs</c-></i></code> is an arbitrary parameter pack.</p>
        <li data-md>
         <p><code class="highlight"><c- n>set_error_t</c-><c- p>(</c-><i><c- n>Err</c-></i><c- p>)</c-></code>, where <code class="highlight"><i><c- n>Err</c-></i></code> is an arbitrary type.</p>
        <li data-md>
         <p><code class="highlight"><c- n>set_stopped_t</c-><c- p>()</c-></code></p>
       </ul>
     </ol>
<pre class="highlight"><c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Tag</c-><c- p>,</c->
          <i><c- n>valid</c-><c- o>-</c-><c- n>completion</c-><c- o>-</c-><c- n>signatures</c-></i> <c- n>Completions</c-><c- p>,</c->
          <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-><c- p>...</c-><c- o>></c-> <c- k>class</c-> <c- nc>Tuple</c-><c- p>,</c->
          <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-><c- p>...</c-><c- o>></c-> <c- k>class</c-> <c- nc>Variant</c-><c- o>></c->
  <c- k>using</c-> <i><c- n>gather</c-><c- o>-</c-><c- n>signatures</c-></i> <c- o>=</c-> <i><c- n>see</c-> <c- n>below</c-></i><c- p>;</c->
</pre>
     <ol start="2">
      <li data-md>
       <p>Let <code class="highlight"><c- n>Fns</c-><c- p>...</c-></code> be a template parameter pack of the arguments of the <code class="highlight"><c- n>completion_signatures</c-></code> specialization named by <code class="highlight"><c- n>Completions</c-></code>, let <code class="highlight"><i><c- n>TagFns</c-></i></code> be a
template parameter pack of the function types in <code class="highlight"><c- n>Fns</c-></code> whose return types
are <code class="highlight"><c- n>Tag</c-></code>, and let <code class="highlight"><i><c- n>Ts</c-><i><sub><c- n>n</c-></sub></i></i></code> be a template parameter
pack of the function argument types in the <code class="highlight"><i><c- n>n</c-></i></code>-th type
in <code class="highlight"><i><c- n>TagFns</c-></i></code>. Then, given two variadic templates <code class="highlight"><i><c- n>Tuple</c-></i></code> and <code class="highlight"><i><c- n>Variant</c-></i></code>, the type <code class="highlight"><i><c- n>gather</c-><c- o>-</c-><c- n>signatures</c-></i><c- o>&lt;</c-><c- n>Tag</c-><c- p>,</c-> <c- n>Completions</c-><c- p>,</c-> <i><c- n>Tuple</c-></i><c- p>,</c-> <i><c- n>Variant</c-></i><c- o>></c-></code> names the type <code class="highlight"><i><c- n>META</c-><c- o>-</c-><c- n>APPLY</c-></i><c- p>(</c-><i><c- n>Variant</c-></i><c- p>,</c-> <i><c- n>META</c-><c- o>-</c-><c- n>APPLY</c-></i><c- p>(</c-><i><c- n>Tuple</c-></i><c- p>,</c-> <i><c- n>Ts</c-><i><sub><c- n>0</c-></sub></i></i><c- p>...),</c-> <i><c- n>META</c-><c- o>-</c-><c- n>APPLY</c-></i><c- p>(</c-><i><c- n>Tuple</c-></i><c- p>,</c-> <i><c- n>Ts</c-><i><sub><c- n>1</c-></sub></i></i><c- p>...),</c-> <c- p>...</c-> <i><c- n>META</c-><c- o>-</c-><c- n>APPLY</c-></i><c- p>(</c-><i><c- n>Tuple</c-></i><c- p>,</c-> <i><c- n>Ts</c-><i><sub><c- n>m</c-><c- mf>-1</c-></sub></i></i><c- mf>.</c-><c- p>..))</c-></code>, where <code class="highlight"><i><c- n>m</c-></i></code> is the size of the parameter pack <code class="highlight"><i><c- n>TagFns</c-></i></code> and <code class="highlight"><i><c- n>META</c-><c- o>-</c-><c- n>APPLY</c-></i><c- p>(</c-><i><c- n>T</c-></i><c- p>,</c-> <i><c- n>As</c-></i><c- p>...)</c-></code> is
equivalent to:</p>
<pre class="highlight"><c- k>typename</c-> <i><c- nc>indirect</c-><c- o>-</c-><c- n>meta</c-><c- o>-</c-><c- n>apply</c-></i><c- o>&lt;</c-><i><c- n>always</c-><c- o>-</c->true</i><c- o>&lt;</c-><i><c- n>As</c-></i><c- p>...</c-><c- o>>>::</c-><c- k>template</c-> <i><c- n>meta</c-><c- o>-</c-><c- n>apply</c-></i><c- o>&lt;</c-><i><c- n>T</c-></i><c- p>,</c-> <i><c- n>As</c-></i><c- p>...</c-><c- o>></c-><c- p>;</c->
</pre>
      <li data-md>
       <p><span class="wg21note">The purpose of <code class="highlight"><i><c- n>META</c-><c- o>-</c-><c- n>APPLY</c-></i></code> is to make it
valid to use non-variadic templates as <code class="highlight"><i><c- n>Variant</c-></i></code> and <code class="highlight"><i><c- n>Tuple</c-></i></code> arguments to <code class="highlight"><i><c- n>gather</c-><c- o>-</c-><c- n>signatures</c-></i></code>.</span></p>
     </ol>
    <li data-md>
<pre class="highlight"><c- k>template</c-><c- o>&lt;</c-><i><c- n>completion</c-><c- o>-</c-><c- n>signature</c-></i><c- p>...</c-> <c- n>Fns</c-><c- o>></c->
  <c- k>struct</c-> <c- nc>completion_signatures</c-> <c- p>{};</c->

<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Sndr</c-><c- p>,</c->
          <c- k>class</c-> <c- nc>Env</c-> <c- o>=</c-> <c- n>empty_env</c-><c- p>,</c->
          <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-><c- p>...</c-><c- o>></c-> <c- k>class</c-> <c- nc>Tuple</c-> <c- o>=</c-> <i><c- n>decayed</c-><c- o>-</c-><c- n>tuple</c-></i><c- p>,</c->
          <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-><c- p>...</c-><c- o>></c-> <c- k>class</c-> <c- nc>Variant</c-> <c- o>=</c-> <i><c- n>variant</c-><c- o>-</c-><c- n>or</c-><c- o>-</c-><c- n>empty</c-></i><c- o>></c->
    <c- k>requires</c-> <c- n>sender_in</c-><c- o>&lt;</c-><c- n>Sndr</c-><c- p>,</c-> <c- n>Env</c-><c- o>></c->
  <c- k>using</c-> <c- n>value_types_of_t</c-> <c- o>=</c->
      <i><c- n>gather</c-><c- o>-</c-><c- n>signatures</c-></i><c- o>&lt;</c-><c- n>set_value_t</c-><c- p>,</c-> <c- n>completion_signatures_of_t</c-><c- o>&lt;</c-><c- n>Sndr</c-><c- p>,</c-> <c- n>Env</c-><c- o>></c-><c- p>,</c-> <c- n>Tuple</c-><c- p>,</c-> <c- n>Variant</c-><c- o>></c-><c- p>;</c->

<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Sndr</c-><c- p>,</c->
          <c- k>class</c-> <c- nc>Env</c-> <c- o>=</c-> <c- n>empty_env</c-><c- p>,</c->
          <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-><c- p>...</c-><c- o>></c-> <c- k>class</c-> <c- nc>Variant</c-> <c- o>=</c-> <i><c- n>variant</c-><c- o>-</c-><c- n>or</c-><c- o>-</c-><c- n>empty</c-></i><c- o>></c->
    <c- k>requires</c-> <c- n>sender_in</c-><c- o>&lt;</c-><c- n>Sndr</c-><c- p>,</c-> <c- n>Env</c-><c- o>></c->
  <c- k>using</c-> <c- n>error_types_of_t</c-> <c- o>=</c->
      <i><c- n>gather</c-><c- o>-</c-><c- n>signatures</c-></i><c- o>&lt;</c-><c- n>set_error_t</c-><c- p>,</c-> <c- n>completion_signatures_of_t</c-><c- o>&lt;</c-><c- n>Sndr</c-><c- p>,</c-> <c- n>Env</c-><c- o>></c-><c- p>,</c-> <c- n>type_identity_t</c-><c- p>,</c-> <c- n>Variant</c-><c- o>></c-><c- p>;</c->

<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Sndr</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Env</c-> <c- o>=</c-> <c- n>empty_env</c-><c- o>></c->
    <c- k>requires</c-> <c- n>sender_in</c-><c- o>&lt;</c-><c- n>Sndr</c-><c- p>,</c-> <c- n>Env</c-><c- o>></c->
  <c- kr>inline</c-> <c- k>constexpr</c-> <c- b>bool</c-> <c- n>sends_stopped</c-> <c- o>=</c->
      <c- o>!</c-><c- n>same_as</c-><c- o>&lt;</c->
        <i><c- n>type</c-><c- o>-</c-><c- n>list</c-></i><c- o>&lt;></c-><c- p>,</c->
        <i><c- n>gather</c-><c- o>-</c-><c- n>signatures</c-></i><c- o>&lt;</c-><c- n>set_stopped_t</c-><c- p>,</c-> <c- n>completion_signatures_of_t</c-><c- o>&lt;</c-><c- n>Sndr</c-><c- p>,</c-> <c- n>Env</c-><c- o>></c-><c- p>,</c-> <i><c- n>type</c-><c- o>-</c-><c- n>list</c-></i><c- p>,</c-> <i><c- n>type</c-><c- o>-</c-><c- n>list</c-></i><c- o>>></c-><c- p>;</c->
</pre>
   </ol>
   <h4 class="heading settled" data-level="11.11.3" id="spec-execution.snd_rec_utils.transform_completion_sigs"><span class="secno">11.11.3. </span><span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>transform_completion_signatures</c-></code> <b>[exec.utils.tfxcmplsigs]</b></span><a class="self-link" href="#spec-execution.snd_rec_utils.transform_completion_sigs"></a></h4>
   <ol>
    <li data-md>
     <p><code class="highlight"><c- n>transform_completion_signatures</c-></code> is an alias template used to transform one
set of completion signatures into another. It takes a set of completion
signatures and several other template arguments that apply modifications to
each completion signature in the set to generate a new specialization of <code class="highlight"><c- n>completion_signatures</c-></code>.</p>
    <li data-md>
     <p>[<i>Example:</i></p>
<pre class="highlight"><c- c1>// Given a sender Sndr and an environment Env, adapt the completion</c->
<c- c1>// signatures of Sndr by lvalue-ref qualifying the values, adding an additional</c->
<c- c1>// exception_ptr error completion if its not already there, and leaving the</c->
<c- c1>// other completion signatures alone.</c->
<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-><c- p>...</c-> <c- n>Args</c-><c- o>></c->
  <c- k>using</c-> <c- n>my_set_value_t</c-> <c- o>=</c->
    <c- n>completion_signatures</c-><c- o>&lt;</c->
      <c- n>set_value_t</c-><c- p>(</c-><c- n>add_lvalue_reference_t</c-><c- o>&lt;</c-><c- n>Args</c-><c- o>></c-><c- p>...)</c-><c- o>></c-><c- p>;</c->

<c- k>using</c-> <c- n>my_completion_signatures</c-> <c- o>=</c->
  <c- n>transform_completion_signatures</c-><c- o>&lt;</c->
    <c- n>completion_signatures_of_t</c-><c- o>&lt;</c-><c- n>Sndr</c-><c- p>,</c-> <c- n>Env</c-><c- o>></c-><c- p>,</c->
    <c- n>completion_signatures</c-><c- o>&lt;</c-><c- n>set_error_t</c-><c- p>(</c-><c- n>exception_ptr</c-><c- p>)</c-><c- o>></c-><c- p>,</c->
    <c- n>my_set_value_t</c-><c- o>></c-><c- p>;</c->
</pre>
     <p>-- <i>end example</i>]</p>
    <li data-md>
     <p>This subclause makes use of the following exposition-only entities:</p>
<pre class="highlight"><c- k>template</c-><c- o>&lt;</c-><c- k>class</c-><c- p>...</c-> <c- n>As</c-><c- o>></c->
  <c- k>using</c-> <i><c- k>default</c-><c- o>-</c-><c- n>set</c-><c- o>-</c-><c- n>value</c-></i> <c- o>=</c->
    <c- n>completion_signatures</c-><c- o>&lt;</c-><c- n>set_value_t</c-><c- p>(</c-><c- n>As</c-><c- p>...)</c-><c- o>></c-><c- p>;</c->

<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Err</c-><c- o>></c->
  <c- k>using</c-> <i><c- k>default</c-><c- o>-</c-><c- n>set</c-><c- o>-</c-><c- n>error</c-></i> <c- o>=</c->
    <c- n>completion_signatures</c-><c- o>&lt;</c-><c- n>set_error_t</c-><c- p>(</c-><c- n>Err</c-><c- p>)</c-><c- o>></c-><c- p>;</c->
</pre>
    <li data-md>
<pre class="highlight"><c- k>template</c-><c- o>&lt;</c-><i><c- n>valid</c-><c- o>-</c-><c- n>completion</c-><c- o>-</c-><c- n>signatures</c-></i> <c- n>InputSignatures</c-><c- p>,</c->
         <i><c- n>valid</c-><c- o>-</c-><c- n>completion</c-><c- o>-</c-><c- n>signatures</c-></i> <c- n>AdditionalSignatures</c-> <c- o>=</c->
             <c- n>completion_signatures</c-><c- o>&lt;></c-><c- p>,</c->
         <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-><c- p>...</c-><c- o>></c-> <c- k>class</c-> <c- nc>SetValue</c-> <c- o>=</c-> <i><c- k>default</c-><c- o>-</c-><c- n>set</c-><c- o>-</c-><c- n>value</c-></i><c- p>,</c->
         <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-><c- o>></c-> <c- k>class</c-> <c- nc>SetError</c-> <c- o>=</c-> <i><c- k>default</c-><c- o>-</c-><c- n>set</c-><c- o>-</c-><c- n>error</c-></i><c- p>,</c->
         <i><c- n>valid</c-><c- o>-</c-><c- n>completion</c-><c- o>-</c-><c- n>signatures</c-></i> <c- n>SetStopped</c-> <c- o>=</c->
             <c- n>completion_signatures</c-><c- o>&lt;</c-><c- n>set_stopped_t</c-><c- p>()</c-><c- o>>></c->
<c- k>using</c-> <c- n>transform_completion_signatures</c-> <c- o>=</c->
  <c- n>completion_signatures</c-><c- o>&lt;</c-><i><c- n>see</c-> <c- n>below</c-></i><c- o>></c-><c- p>;</c->
</pre>
     <ul>
      <li data-md>
       <p><code class="highlight"><c- n>SetValue</c-></code> shall name an alias template such that for any template
parameter pack <code class="highlight"><c- n>As</c-><c- p>...</c-></code>, the type <code class="highlight"><c- n>SetValue</c-><c- o>&lt;</c-><c- n>As</c-><c- p>...</c-><c- o>></c-></code> is either ill-formed
or else <code class="highlight"><i><c- n>valid</c-><c- o>-</c-><c- n>completion</c-><c- o>-</c-><c- n>signatures</c-></i><c- o>&lt;</c-><c- n>SetValue</c-><c- o>&lt;</c-><c- n>As</c-><c- p>...</c-><c- o>>></c-></code> is satisfied.</p>
      <li data-md>
       <p><code class="highlight"><c- n>SetError</c-></code> shall name an alias template such that for any type <code class="highlight"><c- n>Err</c-></code>, <code class="highlight"><c- n>SetError</c-><c- o>&lt;</c-><c- n>Err</c-><c- o>></c-></code> is either ill-formed or else <code class="highlight"><i><c- n>valid</c-><c- o>-</c-><c- n>completion</c-><c- o>-</c-><c- n>signatures</c-></i><c- o>&lt;</c-><c- n>SetError</c-><c- o>&lt;</c-><c- n>Err</c-><c- o>>></c-></code> is satisfied.</p>
     </ul>
     <p>Then:</p>
     <ul>
      <li data-md>
       <p>Let <code class="highlight"><c- n>Vs</c-><c- p>...</c-></code> be a pack of the types in the <code class="highlight"><i><c- n>type</c-><c- o>-</c-><c- n>list</c-></i></code> named
by <code class="highlight"><i><c- n>gether</c-><c- o>-</c-><c- n>signatures</c-></i><c- o>&lt;</c-><c- n>set_value_t</c-><c- p>,</c-> <c- n>InputSignatures</c-><c- p>,</c-> <c- n>SetValue</c-><c- p>,</c-> <i><c- n>type</c-><c- o>-</c-><c- n>list</c-></i><c- o>></c-></code>.</p>
      <li data-md>
       <p>Let <code class="highlight"><c- n>Es</c-><c- p>...</c-></code> be a pack of the types in the <code class="highlight"><i><c- n>type</c-><c- o>-</c-><c- n>list</c-></i></code> named by <code class="highlight"><i><c- n>gather</c-><c- o>-</c-><c- n>signatures</c-></i><c- o>&lt;</c-><c- n>set_error_t</c-><c- p>,</c-> <c- n>InputSignatures</c-><c- p>,</c-> <c- n>type_identity_t</c-><c- p>,</c-> <i><c- n>error</c-><c- o>-</c-><c- n>list</c-></i><c- o>></c-></code>, where <code class="highlight"><i><c- n>error</c-><c- o>-</c-><c- n>list</c-></i></code> is an
alias template such that <code class="highlight"><i><c- n>error</c-><c- o>-</c-><c- n>list</c-></i><c- o>&lt;</c-><c- n>Ts</c-><c- p>...</c-><c- o>></c-></code> names <code class="highlight"><i><c- n>type</c-><c- o>-</c-><c- n>list</c-></i><c- o>&lt;</c-><c- n>SetError</c-><c- o>&lt;</c-><c- n>Ts</c-><c- o>></c-><c- p>...</c-><c- o>></c-></code>.</p>
      <li data-md>
       <p>Let <code class="highlight"><c- n>Ss</c-></code> name the type <code class="highlight"><c- n>completion_signatures</c-><c- o>&lt;></c-></code> if <code class="highlight"><i><c- n>gather</c-><c- o>-</c-><c- n>signatures</c-></i><c- o>&lt;</c-><c- n>set_stopped_t</c-><c- p>,</c-> <c- n>InputSignatures</c-><c- p>,</c-> <i><c- n>type</c-><c- o>-</c-><c- n>list</c-></i><c- p>,</c-> <i><c- n>type</c-><c- o>-</c-><c- n>list</c-></i><c- o>></c-></code> is an alias for the type <code class="highlight"><i><c- n>type</c-><c- o>-</c-><c- n>list</c-></i><c- o>&lt;></c-></code>; otherwise, <code class="highlight"><c- n>SetStopped</c-></code>.</p>
     </ul>
     <p>Then:</p>
     <ol>
      <li data-md>
       <p>If any of the above types are ill-formed, then <code class="highlight"><c- n>transform_completion_signatures</c-><c- o>&lt;</c-><c- n>InputSignatures</c-><c- p>,</c-> <c- n>AdditionalSignatures</c-><c- p>,</c-> <c- n>SetValue</c-><c- p>,</c-> <c- n>SetError</c-><c- p>,</c-> <c- n>SetStopped</c-><c- o>></c-></code> is ill-formed,</p>
      <li data-md>
       <p>Otherwise, <code class="highlight"><c- n>transform_completion_signatures</c-><c- o>&lt;</c-><c- n>InputSignatures</c-><c- p>,</c-> <c- n>AdditionalSignatures</c-><c- p>,</c-> <c- n>SetValue</c-><c- p>,</c-> <c- n>SetError</c-><c- p>,</c-> <c- n>SetStopped</c-><c- o>></c-></code> names the type <code class="highlight"><c- n>completion_signatures</c-><c- o>&lt;</c-><c- n>Sigs</c-><c- p>...</c-><c- o>></c-></code> where <code class="highlight"><c- n>Sigs</c-><c- p>...</c-></code> is the unique set of types in all the template arguments
of all the <code class="highlight"><c- n>completion_signatures</c-></code> specializations in <code class="highlight"><c- p>[</c-><c- n>AdditionalSignatures</c-><c- p>,</c-> <c- n>Vs</c-><c- p>...,</c-> <c- n>Es</c-><c- p>...,</c-> <c- n>Ss</c-><c- p>]</c-></code>.</p>
     </ol>
   </ol>
   <h3 class="heading settled" data-level="11.12" id="spec-execution.contexts"><span class="secno">11.12. </span><span class="content">Execution contexts <b>[exec.ctx]</b></span><a class="self-link" href="#spec-execution.contexts"></a></h3>
   <ol>
    <li data-md>
     <p>This subclause specifies some execution resources on which work can be scheduled.</p>
   </ol>
   <h4 class="heading settled" data-level="11.12.1" id="spec-execution.contexts.run_loop"><span class="secno">11.12.1. </span><span class="content"><code class="highlight"><c- n>run_loop</c-></code> <b>[exec.run.loop]</b></span><a class="self-link" href="#spec-execution.contexts.run_loop"></a></h4>
   <ol>
    <li data-md>
     <p>A <code class="highlight"><c- n>run_loop</c-></code> is an execution resource on which work can be scheduled. It maintains a simple, thread-safe first-in-first-out queue of work. Its <code class="highlight"><c- n>run</c-><c- p>()</c-></code> member function removes elements from the queue and executes them in a loop on whatever thread of execution calls <code class="highlight"><c- n>run</c-><c- p>()</c-></code>.</p>
    <li data-md>
     <p>A <code class="highlight"><c- n>run_loop</c-></code> instance has an associated <i>count</i> that corresponds to the number of work items that are in its queue. Additionally, a <code class="highlight"><c- n>run_loop</c-></code> has an associated <i>state</i> that can be one of <i>starting</i>, <i>running</i>, or <i>finishing</i>.</p>
    <li data-md>
     <p>Concurrent invocations of the member functions of <code class="highlight"><c- n>run_loop</c-></code>, other than <code class="highlight"><c- n>run</c-></code> and its destructor, do not introduce data races. The member functions <code class="highlight"><c- n>pop_front</c-></code>, <code class="highlight"><c- n>push_back</c-></code>, and <code class="highlight"><c- n>finish</c-></code> execute atomically.</p>
    <li data-md>
     <p>[<i>Note:</i> Implementations are encouraged to use an intrusive queue of operation states to hold the work units to make scheduling allocation-free. — <i>end note</i>]</p>
<pre class="highlight"><c- k>class</c-> <c- nc>run_loop</c-> <c- p>{</c->
  <c- c1>// [exec.run.loop.types] Associated types</c->
  <c- k>class</c-> <i><c- nc>run</c-><c- o>-</c-><c- n>loop</c-><c- o>-</c-><c- n>scheduler</c-></i><c- p>;</c-> <c- c1>// exposition only</c->
  <c- k>class</c-> <i><c- nc>run</c-><c- o>-</c-><c- n>loop</c-><c- o>-</c-><c- n>sender</c-></i><c- p>;</c-> <c- c1>// exposition only</c->
  <c- k>struct</c-> <i><c- nc>run</c-><c- o>-</c-><c- n>loop</c-><c- o>-</c-><c- n>opstate</c-><c- o>-</c-><c- n>base</c-></i> <c- p>{</c-> <c- c1>// exposition only</c->
    <c- k>virtual</c-> <c- b>void</c-> <c- nf>execute</c-><c- p>()</c-> <c- o>=</c-> <c- mi>0</c-><c- p>;</c->
    <c- n>run_loop</c-><c- o>*</c-> <i><c- n>loop_</c-></i><c- p>;</c->
    <i><c- n>run</c-><c- o>-</c-><c- n>loop</c-><c- o>-</c-><c- n>opstate</c-><c- o>-</c-><c- n>base</c-></i><c- o>*</c-> <i><c- n>next_</c-></i><c- p>;</c->
  <c- p>};</c->
  <c- k>template</c-><c- o>&lt;</c-><c- n>receiver_of</c-><c- o>&lt;</c-><c- n>completion_signatures</c-><c- o>&lt;</c-><c- n>set_value_t</c-><c- p>()</c-><c- o>>></c-> <c- n>Rcvr</c-><c- o>></c->
    <c- k>using</c-> <i><c- n>run</c-><c- o>-</c-><c- n>loop</c-><c- o>-</c-><c- n>opstate</c-></i> <c- o>=</c-> <i><c- n>unspecified</c-></i><c- p>;</c-> <c- c1>// exposition only</c->

  <c- c1>// [exec.run.loop.members] Member functions:</c->
  <i><c- n>run</c-><c- o>-</c-><c- n>loop</c-><c- o>-</c-><c- n>opstate</c-><c- o>-</c-><c- n>base</c-></i><c- o>*</c-> <c- n>pop_front</c-><c- p>();</c-> <c- c1>// exposition only</c->
  <c- b>void</c-> <c- nf>push_back</c-><c- p>(</c-><i><c- n>run</c-><c- o>-</c-><c- n>loop</c-><c- o>-</c-><c- n>opstate</c-><c- o>-</c-><c- n>base</c-></i><c- o>*</c-><c- p>);</c-> <c- c1>// exposition only</c->

 <c- k>public</c-><c- o>:</c->
  <c- c1>// [exec.run.loop.ctor] construct/copy/destroy</c->
  <c- n>run_loop</c-><c- p>()</c-> <c- k>noexcept</c-><c- p>;</c->
  <c- n>run_loop</c-><c- p>(</c-><c- n>run_loop</c-><c- o>&amp;&amp;</c-><c- p>)</c-> <c- o>=</c-> <c- k>delete</c-><c- p>;</c->
  <c- o>~</c-><c- n>run_loop</c-><c- p>();</c->

  <c- c1>// [exec.run.loop.members] Member functions:</c->
  <i><c- n>run</c-><c- o>-</c-><c- n>loop</c-><c- o>-</c-><c- n>scheduler</c-></i> <c- n>get_scheduler</c-><c- p>();</c->
  <c- b>void</c-> <c- nf>run</c-><c- p>();</c->
  <c- b>void</c-> <c- nf>finish</c-><c- p>();</c->
<c- p>};</c->
</pre>
   </ol>
   <h5 class="heading settled" data-level="11.12.1.1" id="spec-execution.contexts.run_loop.types"><span class="secno">11.12.1.1. </span><span class="content">Associated types <b>[exec.run.loop.types]</b></span><a class="self-link" href="#spec-execution.contexts.run_loop.types"></a></h5>
<pre class="highlight"><c- k>class</c-> <i><c- nc>run</c-><c- o>-</c-><c- n>loop</c-><c- o>-</c-><c- n>scheduler</c-></i><c- p>;</c->
</pre>
   <ol>
    <li data-md>
     <p><code class="highlight"><i><c- n>run</c-><c- o>-</c-><c- n>loop</c-><c- o>-</c-><c- n>scheduler</c-></i></code> is an unspecified type that models the <code class="highlight"><c- n>scheduler</c-></code> concept.</p>
    <li data-md>
     <p>Instances of <code class="highlight"><i><c- n>run</c-><c- o>-</c-><c- n>loop</c-><c- o>-</c-><c- n>scheduler</c-></i></code> remain valid until the end of the lifetime of the <code class="highlight"><c- n>run_loop</c-></code> instance from which they were obtained.</p>
    <li data-md>
     <p>Two instances of <code class="highlight"><i><c- n>run</c-><c- o>-</c-><c- n>loop</c-><c- o>-</c-><c- n>scheduler</c-></i></code> compare equal if and only if they were obtained from the same <code class="highlight"><c- n>run_loop</c-></code> instance.</p>
    <li data-md>
     <p>Let <code class="highlight"><i><c- n>sch</c-></i></code> be an expression of type <code class="highlight"><i><c- n>run</c-><c- o>-</c-><c- n>loop</c-><c- o>-</c-><c- n>scheduler</c-></i></code>. The expression <code class="highlight"><c- n>schedule</c-><c- p>(</c-><i><c- n>sch</c-></i><c- p>)</c-></code> is not potentially-throwing and has type <code class="highlight"><i><c- n>run</c-><c- o>-</c-><c- n>loop</c-><c- o>-</c-><c- n>sender</c-></i></code>.</p>
   </ol>
<pre class="highlight"><c- k>class</c-> <i><c- nc>run</c-><c- o>-</c-><c- n>loop</c-><c- o>-</c-><c- n>sender</c-></i><c- p>;</c->
</pre>
   <ol>
    <li data-md>
     <p><code class="highlight"><i><c- n>run</c-><c- o>-</c-><c- n>loop</c-><c- o>-</c-><c- n>sender</c-></i></code> is an unspecified type such that <code class="highlight"><i><c- n>sender</c-><c- o>-</c-><c- n>of</c-></i><c- o>&lt;</c-><i><c- n>run</c-><c- o>-</c-><c- n>loop</c-><c- o>-</c-><c- n>sender</c-></i><c- o>></c-></code> is <code class="highlight">true</code>.
 Additionally, the types reported by its <code class="highlight"><c- n>error_types</c-></code> associated type is <code class="highlight"><c- n>exception_ptr</c-></code>, and the value of its <code class="highlight"><c- n>sends_stopped</c-></code> trait is <code class="highlight">true</code>.</p>
    <li data-md>
     <p>An instance of <code class="highlight"><i><c- n>run</c-><c- o>-</c-><c- n>loop</c-><c- o>-</c-><c- n>sender</c-></i></code> remains valid until the
 end of the lifetime of its associated <code class="highlight"><c- n>run_loop</c-></code> instance.</p>
    <li data-md>
     <p>Let <code class="highlight"><i><c- n>sndr</c-></i></code> be an expression of type <code class="highlight"><i><c- n>run</c-><c- o>-</c-><c- n>loop</c-><c- o>-</c-><c- n>sender</c-></i></code>, let <code class="highlight"><i><c- n>rcvr</c-></i></code> be an
 expression such that <code class="highlight"><c- k>decltype</c-><c- p>(</c-><i><c- n>rcvr</c-></i><c- p>)</c-></code> models the <code class="highlight"><c- n>receiver_of</c-></code> concept, and let <code class="highlight"><c- n>C</c-></code> be either <code class="highlight"><c- n>set_value_t</c-></code> or <code class="highlight"><c- n>set_stopped_t</c-></code>. Then:</p>
     <ul>
      <li data-md>
       <p>The expression <code class="highlight"><c- n>connect</c-><c- p>(</c-><i><c- n>sndr</c-></i><c- p>,</c-> <i><c- n>rcvr</c-></i><c- p>)</c-></code> has type <code class="highlight"><i><c- n>run</c-><c- o>-</c-><c- n>loop</c-><c- o>-</c-><c- n>opstate</c-></i><c- o>&lt;</c-><c- n>decay_t</c-><c- o>&lt;</c-><c- k>decltype</c-><c- p>(</c-><i><c- n>rcvr</c-></i><c- p>)</c-><c- o>>></c-></code> and is potentially-throwing if and only if the initialiation of <code class="highlight"><c- n>decay_t</c-><c- o>&lt;</c-><c- k>decltype</c-><c- p>(</c-><i><c- n>rcvr</c-></i><c- p>)</c-><c- o>></c-></code> from <code class="highlight"><i><c- n>rcvr</c-></i></code> is potentially-throwing.</p>
      <li data-md>
       <p>The expression <code class="highlight"><c- n>get_completion_scheduler</c-><c- o>&lt;</c-><c- n>C</c-><c- o>></c-><c- p>(</c-><c- n>get_env</c-><c- p>(</c-><i><c- n>sndr</c-></i><c- p>))</c-></code> is not potentially-throwing, has type <code class="highlight"><i><c- n>run</c-><c- o>-</c-><c- n>loop</c-><c- o>-</c-><c- n>scheduler</c-></i></code>, and compares equal to the <code class="highlight"><i><c- n>run</c-><c- o>-</c-><c- n>loop</c-><c- o>-</c-><c- n>scheduler</c-></i></code> instance from which <code class="highlight"><i><c- n>sndr</c-></i></code> was obtained.</p>
     </ul>
   </ol>
<pre class="highlight"><c- k>template</c-><c- o>&lt;</c-><c- n>receiver_of</c-><c- o>&lt;</c-><c- n>completion_signatures</c-><c- o>&lt;</c-><c- n>set_value_t</c-><c- p>()</c-><c- o>>></c-> <c- n>Rcvr</c-><c- o>></c-> <c- c1>// arguments are not associated entities ([lib.tmpl-heads])</c->
  <c- k>struct</c-> <i><c- nc>run</c-><c- o>-</c-><c- n>loop</c-><c- o>-</c-><c- n>opstate</c-></i><c- p>;</c->
</pre>
   <ol>
    <li data-md>
     <p><code class="highlight"><i><c- n>run</c-><c- o>-</c-><c- n>loop</c-><c- o>-</c-><c- n>opstate</c-></i><c- o>&lt;</c-><i><c- n>Rcvr</c-></i><c- o>></c-></code> inherits unambiguously from <code class="highlight"><i><c- n>run</c-><c- o>-</c-><c- n>loop</c-><c- o>-</c-><c- n>opstate</c-><c- o>-</c-><c- n>base</c-></i></code>.</p>
    <li data-md>
     <p>Let <code class="highlight"><i><c- n>o</c-></i></code> be a non-<code class="highlight"><c- k>const</c-></code> lvalue of type <code class="highlight"><i><c- n>run</c-><c- o>-</c-><c- n>loop</c-><c- o>-</c-><c- n>opstate</c-></i><c- o>&lt;</c-><c- n>Rcvr</c-><c- o>></c-></code>, and let <code class="highlight"><i><c- n>REC</c-></i><c- p>(</c-><i><c- n>o</c-></i><c- p>)</c-></code> be a non-<code class="highlight"><c- k>const</c-></code> lvalue reference to an instance of type <code class="highlight"><i><c- n>Rcvr</c-></i></code> that was initialized with the expression <code class="highlight"><i><c- n>rcvr</c-></i></code> passed to the invocation of <code class="highlight"><c- n>connect</c-></code> that returned <code class="highlight"><i><c- n>o</c-></i></code>. Then:</p>
     <ul>
      <li data-md>
       <p>The object to which <code class="highlight"><i><c- n>REC</c-></i><c- p>(</c-><i><c- n>o</c-></i><c- p>)</c-></code> refers remains valid for the lifetime of the object to which <code class="highlight"><i><c- n>o</c-></i></code> refers.</p>
      <li data-md>
       <p>The type <code class="highlight"><i><c- n>run</c-><c- o>-</c-><c- n>loop</c-><c- o>-</c-><c- n>opstate</c-></i><c- o>&lt;</c-><c- n>Rcvr</c-><c- o>></c-></code> overrides <code class="highlight"><i><c- n>run</c-><c- o>-</c-><c- n>loop</c-><c- o>-</c-><c- n>opstate</c-><c- o>-</c-><c- n>base</c-></i><c- o>::</c-><c- n>execute</c-><c- p>()</c-></code> such that <code class="highlight"><i><c- n>o</c-></i><c- p>.</c-><c- n>execute</c-><c- p>()</c-></code> is equivalent to the following:</p>
<pre class="highlight"><c- k>if</c-> <c- p>(</c-><c- n>get_stop_token</c-><c- p>(</c-><i><c- n>REC</c-></i><c- p>(</c-><i><c- n>o</c-></i><c- p>)).</c-><c- n>stop_requested</c-><c- p>())</c-> <c- p>{</c->
  <c- n>set_stopped</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><i><c- n>REC</c-></i><c- p>(</c-><i><c- n>o</c-></i><c- p>)));</c->
<c- p>}</c-> <c- k>else</c-> <c- p>{</c->
  <c- n>set_value</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><i><c- n>REC</c-></i><c- p>(</c-><i><c- n>o</c-></i><c- p>)));</c->
<c- p>}</c->
</pre>
      <li data-md>
       <p>The expression <code class="highlight"><c- n>start</c-><c- p>(</c-><i><c- n>o</c-></i><c- p>)</c-></code> is equivalent to the following:</p>
<pre class="highlight"><c- k>try</c-> <c- p>{</c->
  <i><c- n>o</c-></i><c- p>.</c-><i><c- n>loop_</c-></i><c- o>-></c-><c- n>push_back</c-><c- p>(</c-><c- o>&amp;</c-><i><c- n>o</c-></i><c- p>);</c->
<c- p>}</c-> <c- k>catch</c-><c- p>(...)</c-> <c- p>{</c->
  <c- n>set_error</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><i><c- n>REC</c-></i><c- p>(</c-><i><c- n>o</c-></i><c- p>)),</c-> <c- n>current_exception</c-><c- p>());</c->
<c- p>}</c->
</pre>
     </ul>
   </ol>
   <h5 class="heading settled" data-level="11.12.1.2" id="spec-execution.contexts.run_loop.ctor"><span class="secno">11.12.1.2. </span><span class="content">Constructor and destructor <b>[exec.run.loop.ctor]</b></span><a class="self-link" href="#spec-execution.contexts.run_loop.ctor"></a></h5>
<pre class="highlight"><c- n>run_loop</c-><c- o>::</c-><c- n>run_loop</c-><c- p>()</c-> <c- k>noexcept</c-><c- p>;</c->
</pre>
   <ol>
    <li data-md>
     <p><i>Postconditions:</i> <i>count</i> is <code class="highlight"><c- mi>0</c-></code> and <i>state</i> is <i>starting</i>.</p>
   </ol>
<pre class="highlight"><c- n>run_loop</c-><c- o>::~</c-><c- n>run_loop</c-><c- p>();</c->
</pre>
   <ol>
    <li data-md>
     <p><i>Effects:</i> If <i>count</i> is not <code class="highlight"><c- mi>0</c-></code> or if <i>state</i> is <i>running</i>, invokes <code class="highlight"><c- n>terminate</c-><c- p>()</c-></code>. Otherwise, has no effects.</p>
   </ol>
   <h5 class="heading settled" data-level="11.12.1.3" id="spec-execution.contexts.run_loop.members"><span class="secno">11.12.1.3. </span><span class="content">Member functions <b>[exec.run.loop.members]</b></span><a class="self-link" href="#spec-execution.contexts.run_loop.members"></a></h5>
<pre class="highlight"><i><c- n>run</c-><c- o>-</c-><c- n>loop</c-><c- o>-</c-><c- n>opstate</c-><c- o>-</c-><c- n>base</c-></i><c- o>*</c-> <c- n>run_loop</c-><c- o>::</c-><c- n>pop_front</c-><c- p>();</c->
</pre>
   <ol>
    <li data-md>
     <p><i>Effects:</i> Blocks ([defns.block]) until one of the following conditions is <code class="highlight">true</code>:</p>
     <ul>
      <li data-md>
       <p><i>count</i> is <code class="highlight"><c- mi>0</c-></code> and <i>state</i> is <i>finishing</i>, in which case <code class="highlight"><c- n>pop_front</c-></code> returns <code class="highlight"><c- k>nullptr</c-></code>; or</p>
      <li data-md>
       <p><i>count</i> is greater than <code class="highlight"><c- mi>0</c-></code>, in which case an item is removed from the front of the queue, <i>count</i> is decremented by <code class="highlight"><c- mi>1</c-></code>, and the removed item is returned.</p>
     </ul>
   </ol>
<pre class="highlight"><c- b>void</c-> <c- nf>run_loop::push_back</c-><c- p>(</c-><i><c- n>run</c-><c- o>-</c-><c- n>loop</c-><c- o>-</c-><c- n>opstate</c-><c- o>-</c-><c- n>base</c-></i><c- o>*</c-> <c- n>item</c-><c- p>);</c->
</pre>
   <ol>
    <li data-md>
     <p><i>Effects:</i> Adds <code class="highlight"><c- n>item</c-></code> to the back of the queue and increments <i>count</i> by <code class="highlight"><c- mi>1</c-></code>.</p>
    <li data-md>
     <p><i>Synchronization:</i> This operation synchronizes with the <code class="highlight"><c- n>pop_front</c-></code> operation that obtains <code class="highlight"><c- n>item</c-></code>.</p>
   </ol>
<pre class="highlight"><i><c- n>run</c-><c- o>-</c-><c- n>loop</c-><c- o>-</c-><c- n>scheduler</c-></i> <c- n>run_loop</c-><c- o>::</c-><c- n>get_scheduler</c-><c- p>();</c->
</pre>
   <ol>
    <li data-md>
     <p><i>Returns:</i> an instance of <code class="highlight"><i><c- n>run</c-><c- o>-</c-><c- n>loop</c-><c- o>-</c-><c- n>scheduler</c-></i></code> that can be used to schedule work onto this <code class="highlight"><c- n>run_loop</c-></code> instance.</p>
   </ol>
<pre class="highlight"><c- b>void</c-> <c- nf>run_loop::run</c-><c- p>();</c->
</pre>
   <ol>
    <li data-md>
     <p><i>Effects:</i> Equivalent to:</p>
<pre class="highlight"><c- k>while</c-> <c- p>(</c-><c- k>auto</c-><c- o>*</c-> <c- n>op</c-> <c- o>=</c-> <c- n>pop_front</c-><c- p>())</c-> <c- p>{</c->
  <c- n>op</c-><c- o>-></c-><c- n>execute</c-><c- p>();</c->
<c- p>}</c->
</pre>
    <li data-md>
     <p><i>Precondition:</i> <i>state</i> is <i>starting</i>.</p>
    <li data-md>
     <p><i>Postcondition:</i> <i>state</i> is <i>finishing</i>.</p>
    <li data-md>
     <p><i>Remarks:</i> While the loop is executing, <i>state</i> is <i>running</i>. When <i>state</i> changes, it does so without introducing data races.</p>
   </ol>
<pre class="highlight"><c- b>void</c-> <c- nf>run_loop::finish</c-><c- p>();</c->
</pre>
   <ol>
    <li data-md>
     <p><i>Effects:</i> Changes <i>state</i> to <i>finishing</i>.</p>
    <li data-md>
     <p><i>Synchronization:</i> This operation synchronizes with all <code class="highlight"><c- n>pop_front</c-></code> operations on this object.</p>
   </ol>
   <h3 class="heading settled" data-level="11.13" id="spec-execution.coro_utils"><span class="secno">11.13. </span><span class="content">Coroutine utilities <b>[exec.coro.utils]</b></span><a class="self-link" href="#spec-execution.coro_utils"></a></h3>
   <h4 class="heading settled" data-level="11.13.1" id="spec-execution.coro_utils.as_awaitable"><span class="secno">11.13.1. </span><span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>as_awaitable</c-></code> <b>[exec.as.awaitable]</b></span><a class="self-link" href="#spec-execution.coro_utils.as_awaitable"></a></h4>
   <ol>
    <li data-md>
     <p><code class="highlight"><c- n>as_awaitable</c-></code> transforms an object into one that is awaitable within a particular coroutine. This subclause makes use of the following exposition-only entities:</p>
<pre class="highlight"><c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Sndr</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Env</c-><c- o>></c->
  <c- k>using</c-> <i><c- n>single</c-><c- o>-</c-><c- n>sender</c-><c- o>-</c-><c- n>value</c-><c- o>-</c-><c- n>type</c-></i> <c- o>=</c-> <i><c- n>see</c-> <c- n>below</c-></i><c- p>;</c->

<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Sndr</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Env</c-><c- o>></c->
  <c- k>concept</c-> <i><c- nc>single</c-><c- o>-</c-><c- n>sender</c-></i> <c- o>=</c->
    <c- n>sender_in</c-><c- o>&lt;</c-><c- n>Sndr</c-><c- p>,</c-> <c- n>Env</c-><c- o>></c-> <c- o>&amp;&amp;</c->
    <c- k>requires</c-> <c- p>{</c-> <c- k>typename</c-> <i><c- nc>single</c-><c- o>-</c-><c- n>sender</c-><c- o>-</c-><c- n>value</c-><c- o>-</c-><c- n>type</c-></i><c- o>&lt;</c-><c- n>Sndr</c-><c- p>,</c-> <c- n>Env</c-><c- o>></c-><c- p>;</c-> <c- p>};</c->

<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Sndr</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Promise</c-><c- o>></c->
  <c- k>concept</c-> <i><c- nc>awaitable</c-><c- o>-</c-><c- n>sender</c-></i> <c- o>=</c->
    <i><c- n>single</c-><c- o>-</c-><c- n>sender</c-></i><c- o>&lt;</c-><c- n>Sndr</c-><c- p>,</c-> <c- n>env_of_t</c-><promise><c- o>></c-> <c- o>&amp;&amp;</c->
    <c- n>sender_to</c-><c- o>&lt;</c-><c- n>Sndr</c-><c- p>,</c-> <i><c- n>awaitable</c-><c- o>-</c-><c- n>receiver</c-></i><c- o>></c-> <c- o>&amp;&amp;</c-> <c- c1>// see below</c->
    <c- k>requires</c-> <c- p>(</c-><c- n>Promise</c-><c- o>&amp;</c-> <c- n>p</c-><c- p>)</c-> <c- p>{</c->
      <c- p>{</c-> <c- n>p</c-><c- p>.</c-><c- n>unhandled_stopped</c-><c- p>()</c-> <c- p>}</c-> <c- o>-></c-> <c- n>convertible_to</c-><c- o>&lt;</c-><c- n>coroutine_handle</c-><c- o>&lt;>></c-><c- p>;</c->
    <c- p>};</c->

<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Sndr</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Promise</c-><c- o>></c->
  <c- k>class</c-> <i><c- nc>sender</c-><c- o>-</c-><c- n>awaitable</c-></i><c- p>;</c->
</promise></pre>
     <ol>
      <li data-md>
       <p>Alias template <i>single-sender-value-type</i> is defined as follows:</p>
       <ol>
        <li data-md>
         <p>If <code class="highlight"><c- n>value_types_of_t</c-><c- o>&lt;</c-><c- n>Sndr</c-><c- p>,</c-> <c- n>Env</c-><c- p>,</c-> <c- n>Tuple</c-><c- p>,</c-> <c- n>Variant</c-><c- o>></c-></code> would have the form <code class="highlight"><c- n>Variant</c-><c- o>&lt;</c-><c- n>Tuple</c-><c- o>&lt;</c-><c- n>T</c-><c- o>>></c-></code>, then <code class="highlight"><i><c- n>single</c-><c- o>-</c-><c- n>sender</c-><c- o>-</c-><c- n>value</c-><c- o>-</c-><c- n>type</c-></i><c- o>&lt;</c-><c- n>Sndr</c-><c- p>,</c-> <c- n>Env</c-><c- o>></c-></code> is an alias for type <code class="highlight"><c- n>decay_t</c-><c- o>&lt;</c-><c- n>T</c-><c- o>></c-></code>.</p>
        <li data-md>
         <p>Otherwise, if <code class="highlight"><c- n>value_types_of_t</c-><c- o>&lt;</c-><c- n>Sndr</c-><c- p>,</c-> <c- n>Env</c-><c- p>,</c-> <c- n>Tuple</c-><c- p>,</c-> <c- n>Variant</c-><c- o>></c-></code> would have the form <code class="highlight"><c- n>Variant</c-><c- o>&lt;</c-><c- n>Tuple</c-><c- o>&lt;>></c-></code> or <code class="highlight"><c- n>Variant</c-><c- o>&lt;></c-></code>, then <code class="highlight"><i><c- n>single</c-><c- o>-</c-><c- n>sender</c-><c- o>-</c-><c- n>value</c-><c- o>-</c-><c- n>type</c-></i><c- o>&lt;</c-><c- n>Sndr</c-><c- p>,</c-> <c- n>Env</c-><c- o>></c-></code> is an alias for type <code class="highlight"><c- b>void</c-></code>.</p>
        <li data-md>
         <p>Otherwise, if <code class="highlight"><c- n>value_types_of_t</c-><c- o>&lt;</c-><c- n>Sndr</c-><c- p>,</c-> <c- n>Env</c-><c- p>,</c-> <c- n>Tuple</c-><c- p>,</c-> <c- n>Variant</c-><c- o>></c-></code> would have the form <code class="highlight"><c- n>Variant</c-><c- o>&lt;</c-><c- n>Tuple</c-><c- o>&lt;</c-><c- n>Ts</c-><c- p>...</c-><c- o>>></c-></code> where <code class="highlight"><c- n>Ts</c-></code> is a parameter pack, then <code class="highlight"><i><c- n>single</c-><c- o>-</c-><c- n>sender</c-><c- o>-</c-><c- n>value</c-><c- o>-</c-><c- n>type</c-></i><c- o>&lt;</c-><c- n>Sndr</c-><c- p>,</c-> <c- n>Env</c-><c- o>></c-></code> is an alias for type <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>tuple</c-><c- o>&lt;</c-><c- n>decay_t</c-><c- o>&lt;</c-><c- n>Ts</c-><c- o>></c-><c- p>...</c-><c- o>></c-></code>.</p>
        <li data-md>
         <p>Otherwise, <code class="highlight"><i><c- n>single</c-><c- o>-</c-><c- n>sender</c-><c- o>-</c-><c- n>value</c-><c- o>-</c-><c- n>type</c-></i><c- o>&lt;</c-><c- n>Sndr</c-><c- p>,</c-> <c- n>Env</c-><c- o>></c-></code> is ill-formed.</p>
       </ol>
      <li data-md>
       <p>The type <code class="highlight"><i><c- n>sender</c-><c- o>-</c-><c- n>awaitable</c-></i><c- o>&lt;</c-><c- n>Sndr</c-><c- p>,</c-> <c- n>Promise</c-><c- o>></c-></code> is equivalent to the following:</p>
<pre class="highlight"><c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Sndr</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Promise</c-><c- o>></c-> <c- c1>// arguments are not associated entities ([lib.tmpl-heads])</c->
<c- k>class</c-> <i><c- nc>sender</c-><c- o>-</c-><c- n>awaitable</c-></i> <c- p>{</c->
  <c- k>struct</c-> <c- nc>unit</c-> <c- p>{};</c->
  <c- k>using</c-> <c- n>value_t</c-> <c- o>=</c-> <i><c- n>single</c-><c- o>-</c-><c- n>sender</c-><c- o>-</c-><c- n>value</c-><c- o>-</c-><c- n>type</c-></i><c- o>&lt;</c-><c- n>Sndr</c-><c- p>,</c-> <c- n>env_of_t</c-><c- o>&lt;</c-><c- n>Promise</c-><c- o>>></c-><c- p>;</c->
  <c- k>using</c-> <c- n>result_t</c-> <c- o>=</c-> <c- n>conditional_t</c-><c- o>&lt;</c-><c- n>is_void_v</c-><c- o>&lt;</c-><c- n>value_t</c-><c- o>></c-><c- p>,</c-> <c- n>unit</c-><c- p>,</c-> <c- n>value_t</c-><c- o>></c-><c- p>;</c->
  <c- k>struct</c-> <i><c- nc>awaitable</c-><c- o>-</c-><c- n>receiver</c-></i><c- p>;</c->

  <c- n>variant</c-><c- o>&lt;</c-><c- n>monostate</c-><c- p>,</c-> <c- n>result_t</c-><c- p>,</c-> <c- n>exception_ptr</c-><c- o>></c-> <i><c- n>result_</c-></i><c- p>{};</c->
  <c- n>connect_result_t</c-><c- o>&lt;</c-><c- n>Sndr</c-><c- p>,</c-> <i><c- n>awaitable</c-><c- o>-</c-><c- n>receiver</c-></i><c- o>></c-> <i><c- n>state_</c-></i><c- p>;</c->

 <c- k>public</c-><c- o>:</c->
  <i><c- n>sender</c-><c- o>-</c-><c- n>awaitable</c-></i><c- p>(</c-><c- n>Sndr</c-><c- o>&amp;&amp;</c-> <c- n>sndr</c-><c- p>,</c-> <c- n>Promise</c-><c- o>&amp;</c-> <c- n>p</c-><c- p>);</c->
  <c- b>bool</c-> <c- nf>await_ready</c-><c- p>()</c-> <c- k>const</c-> <c- k>noexcept</c-> <c- p>{</c-> <c- k>return</c-> false<c- p>;</c-> <c- p>}</c->
  <c- b>void</c-> <c- nf>await_suspend</c-><c- p>(</c-><c- n>coroutine_handle</c-><c- o>&lt;</c-><c- n>Promise</c-><c- o>></c-><c- p>)</c-> <c- k>noexcept</c-> <c- p>{</c-> <c- n>start</c-><c- p>(</c-><i><c- n>state_</c-></i><c- p>);</c-> <c- p>}</c->
  <c- n>value_t</c-> <c- nf>await_resume</c-><c- p>();</c->
<c- p>};</c->
</pre>
       <ol>
        <li data-md>
         <p><code class="highlight"><i><c- n>awaitable</c-><c- o>-</c-><c- n>receiver</c-></i></code> is equivalent to the following:</p>
<pre class="highlight"><c- k>struct</c-> <i><c- nc>awaitable</c-><c- o>-</c-><c- n>receiver</c-></i> <c- p>{</c->
  <c- k>using</c-> <c- n>receiver_concept</c-> <c- o>=</c-> <c- n>receiver_t</c-><c- p>;</c->
  <c- n>variant</c-><c- o>&lt;</c-><c- n>monostate</c-><c- p>,</c-> <c- n>result_t</c-><c- p>,</c-> <c- n>exception_ptr</c-><c- o>>*</c-> <i><c- n>result_ptr_</c-></i><c- p>;</c->
  <c- n>coroutine_handle</c-><c- o>&lt;</c-><c- n>Promise</c-><c- o>></c-> <i><c- n>continuation_</c-></i><c- p>;</c->
  <c- c1>// ... </c-><i><c- c1>see below</c-></i>
<c- p>};</c->
</pre>
         <p>Let <code class="highlight"><c- n>rcvr</c-></code> be an rvalue expression of type <code class="highlight"><i><c- n>awaitable</c-><c- o>-</c-><c- n>receiver</c-></i></code>, let <code class="highlight"><c- n>crcvr</c-></code> be a <code class="highlight"><c- k>const</c-></code> lvalue that refers to <code class="highlight"><c- n>rcvr</c-></code>, let <code class="highlight"><c- n>vs</c-></code> be a parameter pack of types <code class="highlight"><c- n>Vs</c-><c- p>...</c-></code>, and let <code class="highlight"><c- n>err</c-></code> be an arbitrary expression of type <code class="highlight"><c- n>Err</c-></code>. Then:</p>
         <ol>
          <li data-md>
           <p>If <code class="highlight"><c- n>constructible_from</c-><c- o>&lt;</c-><c- n>result_t</c-><c- p>,</c-> <c- n>Vs</c-><c- p>...</c-><c- o>></c-></code> is satisfied, the expression <code class="highlight"><c- n>set_value</c-><c- p>(</c-><c- n>rcvr</c-><c- p>,</c-> <c- n>vs</c-><c- p>...)</c-></code> is equivalent to:</p>
<pre class="highlight"><c- k>try</c-> <c- p>{</c->
  <c- n>rcvr</c-><c- p>.</c-><i><c- n>result_ptr_</c-></i><c- o>-></c-><c- n>emplace</c-><c- o>&lt;</c-><c- mi>1</c-><c- o>></c-><c- p>(</c-><c- n>vs</c-><c- p>...);</c->
<c- p>}</c-> <c- k>catch</c-><c- p>(...)</c-> <c- p>{</c->
  <c- n>rcvr</c-><c- p>.</c-><i><c- n>result_ptr_</c-></i><c- o>-></c-><c- n>emplace</c-><c- o>&lt;</c-><c- mi>2</c-><c- o>></c-><c- p>(</c-><c- n>current_exception</c-><c- p>());</c->
<c- p>}</c->
<c- n>rcvr</c-><c- p>.</c-><i><c- n>continuation_</c-></i><c- p>.</c-><c- n>resume</c-><c- p>();</c->
</pre>
           <p>Otherwise, <code class="highlight"><c- n>set_value</c-><c- p>(</c-><c- n>rcvr</c-><c- p>,</c-> <c- n>vs</c-><c- p>...)</c-></code> is ill-formed.</p>
          <li data-md>
           <p>The expression <code class="highlight"><c- n>set_error</c-><c- p>(</c-><c- n>rcvr</c-><c- p>,</c-> <c- n>err</c-><c- p>)</c-></code> is equivalent to:</p>
<pre class="highlight"><c- n>rcvr</c-><c- p>.</c-><i><c- n>result_ptr_</c-></i><c- o>-></c-><c- n>emplace</c-><c- o>&lt;</c-><c- mi>2</c-><c- o>></c-><c- p>(</c-><i><c- n>AS</c-><c- o>-</c-><c- n>EXCEPT</c-><c- o>-</c-><c- n>PTR</c-></i><c- p>(</c-><c- n>err</c-><c- p>));</c->
<c- n>rcvr</c-><c- p>.</c-><i><c- n>continuation_</c-></i><c- p>.</c-><c- n>resume</c-><c- p>();</c->
</pre>
           <p>where <code class="highlight"><i><c- n>AS</c-><c- o>-</c-><c- n>EXCEPT</c-><c- o>-</c-><c- n>PTR</c-></i><c- p>(</c-><c- n>err</c-><c- p>)</c-></code> is:</p>
           <ol>
            <li data-md>
             <p><code class="highlight"><c- n>err</c-></code> if <code class="highlight"><c- n>decay_t</c-><c- o>&lt;</c-><c- n>Err</c-><c- o>></c-></code> names the same type as <code class="highlight"><c- n>exception_ptr</c-></code>,</p>
            <li data-md>
             <p>Otherwise, <code class="highlight"><c- n>make_exception_ptr</c-><c- p>(</c-><c- n>system_error</c-><c- p>(</c-><c- n>err</c-><c- p>))</c-></code> if <code class="highlight"><c- n>decay_t</c-><c- o>&lt;</c-><c- n>Err</c-><c- o>></c-></code> names the same type as <code class="highlight"><c- n>error_code</c-></code>,</p>
            <li data-md>
             <p>Otherwise, <code class="highlight"><c- n>make_exception_ptr</c-><c- p>(</c-><c- n>err</c-><c- p>)</c-></code>.</p>
           </ol>
          <li data-md>
           <p>The expression <code class="highlight"><c- n>set_stopped</c-><c- p>(</c-><c- n>rcvr</c-><c- p>)</c-></code> is equivalent to <code class="highlight"><c- k>static_cast</c-><c- o>&lt;</c-><c- n>coroutine_handle</c-><c- o>&lt;>></c-><c- p>(</c-><c- n>rcvr</c-><c- p>.</c-><i><c- n>continuation_</c-></i><c- p>.</c-><c- n>promise</c-><c- p>().</c-><c- n>unhandled_stopped</c-><c- p>()).</c-><c- n>resume</c-><c- p>()</c-></code>.</p>
          <li data-md>
           <p>For any expression <code class="highlight"><c- n>tag</c-></code> whose type satisfies <code class="highlight"><i><c- n>forwarding</c-><c- o>-</c-><c- n>query</c-></i></code> and for any pack of subexpressions <code class="highlight"><c- n>as</c-></code>, <code class="highlight"><c- n>tag_invoke</c-><c- p>(</c-><c- n>tag</c-><c- p>,</c-> <c- n>get_env</c-><c- p>(</c-><c- n>crcvr</c-><c- p>),</c-> <c- n>as</c-><c- p>...)</c-></code> is expression-equivalent to <code class="highlight"><c- n>tag</c-><c- p>(</c-><c- n>get_env</c-><c- p>(</c-><c- n>as_const</c-><c- p>(</c-><c- n>crcvr</c-><c- p>.</c-><i><c- n>continuation_</c-></i><c- p>.</c-><c- n>promise</c-><c- p>())),</c-> <c- n>as</c-><c- p>...)</c-></code> when that expression is well-formed.</p>
         </ol>
        <li data-md>
         <p><b><code class="highlight"><i><c- n>sender</c-><c- o>-</c-><c- n>awaitable</c-></i><c- o>::</c-><i><c- n>sender</c-><c- o>-</c-><c- n>awaitable</c-></i><c- p>(</c-><c- n>Sndr</c-><c- o>&amp;&amp;</c-> <c- n>sndr</c-><c- p>,</c-> <c- n>Promise</c-><c- o>&amp;</c-> <c- n>p</c-><c- p>)</c-></code></b></p>
         <ul>
          <li data-md>
           <p><i>Effects:</i> initializes <i><code class="highlight"><c- n>state_</c-></code></i> with <code class="highlight"><c- n>connect</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>Sndr</c-><c- o>></c-><c- p>(</c-><c- n>sndr</c-><c- p>),</c-> <i><c- n>awaitable</c-><c- o>-</c-><c- n>receiver</c-></i><c- p>{</c-><c- o>&amp;</c-><i><c- n>result_</c-></i><c- p>,</c-> <c- n>coroutine_handle</c-><c- o>&lt;</c-><c- n>Promise</c-><c- o>>::</c-><c- n>from_promise</c-><c- p>(</c-><c- n>p</c-><c- p>)})</c-></code>.</p>
         </ul>
        <li data-md>
         <p><b><code class="highlight"><c- n>value_t</c-> <i><c- n>sender</c-><c- o>-</c-><c- n>awaitable</c-></i><c- o>::</c-><c- n>await_resume</c-><c- p>()</c-></code></b></p>
         <ul>
          <li data-md>
           <p><i>Effects:</i> equivalent to:</p>
<pre class="highlight"><c- k>if</c-> <c- p>(</c-><i><c- n>result_</c-></i><c- p>.</c-><c- n>index</c-><c- p>()</c-> <c- o>==</c-> <c- mi>2</c-><c- p>)</c->
  <c- n>rethrow_exception</c-><c- p>(</c-><c- n>get</c-><c- o>&lt;</c-><c- mi>2</c-><c- o>></c-><c- p>(</c-><i><c- n>result_</c-></i><c- p>));</c->
<c- k>if</c-> <c- k>constexpr</c-> <c- p>(</c-><c- o>!</c-><c- n>is_void_v</c-><c- o>&lt;</c-><c- n>value_t</c-><c- o>></c-><c- p>)</c->
  <c- k>return</c-> <c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>value_t</c-><c- o>></c-><c- p>(</c-><c- n>get</c-><c- o>&lt;</c-><c- mi>1</c-><c- o>></c-><c- p>(</c-><i><c- n>result_</c-></i><c- p>));</c->
</pre>
         </ul>
       </ol>
     </ol>
    <li data-md>
     <p><code class="highlight"><c- n>as_awaitable</c-></code> is a customization point object. For some subexpressions <code class="highlight"><c- n>expr</c-></code> and <code class="highlight"><c- n>p</c-></code> where <code class="highlight"><c- n>p</c-></code> is an lvalue, <code class="highlight"><c- n>Expr</c-></code> names the type <code class="highlight"><c- k>decltype</c-><c- p>((</c-><c- n>expr</c-><c- p>))</c-></code> and <code class="highlight"><c- n>Promise</c-></code> names the type <code class="highlight"><c- k>decltype</c-><c- p>((</c-><c- n>p</c-><c- p>))</c-></code>, <code class="highlight"><c- n>as_awaitable</c-><c- p>(</c-><c- n>expr</c-><c- p>,</c-> <c- n>p</c-><c- p>)</c-></code> is expression-equivalent to the following:</p>
     <ol>
      <li data-md>
       <p><code class="highlight"><c- n>tag_invoke</c-><c- p>(</c-><c- n>as_awaitable</c-><c- p>,</c-> <c- n>expr</c-><c- p>,</c-> <c- n>p</c-><c- p>)</c-></code> if that expression is well-formed.</p>
       <ul>
        <li data-md>
         <p><i>Mandates:</i> <code class="highlight"><i><c- n>is</c-><c- o>-</c-><c- n>awaitable</c-></i><c- o>&lt;</c-><c- n>A</c-><c- p>,</c-> <c- n>Promise</c-><c- o>></c-></code> is <code class="highlight">true</code>, where <code class="highlight"><c- n>A</c-></code> is the type of the <code class="highlight"><c- n>tag_invoke</c-></code> expression above.</p>
       </ul>
      <li data-md>
       <p>Otherwise, <code class="highlight"><c- n>expr</c-></code> if <code class="highlight"><i><c- n>is</c-><c- o>-</c-><c- n>awaitable</c-></i><c- o>&lt;</c-><c- n>Expr</c-><c- p>,</c-> <i><c- n>U</c-></i><c- o>></c-></code> is <code class="highlight">true</code>, where <code class="highlight"><i><c- n>U</c-></i></code> is an unspecified class type that
lacks a member named <code class="highlight"><c- n>await_transform</c-></code>. <span class="wg21note">The
condition is not <code class="highlight"><i><c- n>is</c-><c- o>-</c-><c- n>awaitable</c-></i><c- o>&lt;</c-><c- n>Expr</c-><c- p>,</c-> <c- n>Promise</c-><c- o>></c-></code> as that
creates the potential for constraint recursion.</span></p>
       <ul>
        <li data-md>
         <p><i>Preconditions:</i> <code class="highlight"><i><c- n>is</c-><c- o>-</c-><c- n>awaitable</c-></i><c- o>&lt;</c-><c- n>Expr</c-><c- p>,</c-> <c- n>Promise</c-><c- o>></c-></code> is <code class="highlight">true</code> and the expression <code class="highlight"><c- k>co_await</c-> <c- n>expr</c-></code> in a coroutine with promise
type <code class="highlight"><i><c- n>U</c-></i></code> is expression-equivalent to the same
expression in a coroutine with promise type <code class="highlight"><c- n>Promise</c-></code>.</p>
       </ul>
      <li data-md>
       <p>Otherwise, <code class="highlight"><i><c- n>sender</c-><c- o>-</c-><c- n>awaitable</c-></i><c- p>{</c-><c- n>expr</c-><c- p>,</c-> <c- n>p</c-><c- p>}</c-></code> if <code class="highlight"><i><c- n>awaitable</c-><c- o>-</c-><c- n>sender</c-></i><c- o>&lt;</c-><c- n>Expr</c-><c- p>,</c-> <c- n>Promise</c-><c- o>></c-></code> is <code class="highlight">true</code>.</p>
      <li data-md>
       <p>Otherwise, <code class="highlight"><c- n>expr</c-></code>.</p>
     </ol>
   </ol>
   <h4 class="heading settled" data-level="11.13.2" id="spec-execution.coro_utils.with_awaitable_senders"><span class="secno">11.13.2. </span><span class="content"><code class="highlight"><c- n>execution</c-><c- o>::</c-><c- n>with_awaitable_senders</c-></code> <b>[exec.with.awaitable.senders]</b></span><a class="self-link" href="#spec-execution.coro_utils.with_awaitable_senders"></a></h4>
   <ol>
    <li data-md>
     <p><code class="highlight"><c- n>with_awaitable_senders</c-></code>, when used as the base class of a coroutine promise type, makes senders awaitable in that coroutine type.</p>
     <p>In addition, it provides a default implementation of <code class="highlight"><c- n>unhandled_stopped</c-><c- p>()</c-></code> such that if a sender completes by calling <code class="highlight"><c- n>set_stopped</c-></code>, it is treated as if an uncatchable "stopped" exception were thrown from the <i>await-expression</i>. In practice, the coroutine is never resumed, and the <code class="highlight"><c- n>unhandled_stopped</c-></code> of the coroutine caller’s promise type is called.</p>
<pre class="highlight"><c- k>template</c-><c- o>&lt;</c-><i><c- k>class</c-><c- o>-</c-><c- n>type</c-></i> <c- n>Promise</c-><c- o>></c->
  <c- k>struct</c-> <c- nc>with_awaitable_senders</c-> <c- p>{</c->
    <c- k>template</c-><c- o>&lt;</c-><c- n>OtherPromise</c-><c- o>></c->
      <c- k>requires</c-> <c- p>(</c-><c- o>!</c-><c- n>same_as</c-><c- o>&lt;</c-><c- n>OtherPromise</c-><c- p>,</c-> <c- b>void</c-><c- o>></c-><c- p>)</c->
    <c- b>void</c-> <c- n>set_continuation</c-><c- p>(</c-><c- n>coroutine_handle</c-><c- o>&lt;</c-><c- n>OtherPromise</c-><c- o>></c-> <c- n>h</c-><c- p>)</c-> <c- k>noexcept</c-><c- p>;</c->

    <c- n>coroutine_handle</c-><c- o>&lt;></c-> <c- n>continuation</c-><c- p>()</c-> <c- k>const</c-> <c- k>noexcept</c-> <c- p>{</c-> <c- k>return</c-> <i><c- n>continuation_</c-></i><c- p>;</c-> <c- p>}</c->

    <c- n>coroutine_handle</c-><c- o>&lt;></c-> <c- n>unhandled_stopped</c-><c- p>()</c-> <c- k>noexcept</c-> <c- p>{</c->
      <c- k>return</c-> <i><c- n>stopped_handler_</c-></i><c- p>(</c-><i><c- n>continuation_</c-></i><c- p>.</c-><c- n>address</c-><c- p>());</c->
    <c- p>}</c->

    <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Value</c-><c- o>></c->
    <i><c- n>see</c-> <c- n>below</c-></i> <c- n>await_transform</c-><c- p>(</c-><c- n>Value</c-><c- o>&amp;&amp;</c-> <c- n>value</c-><c- p>);</c->

   <c- k>private</c-><c- o>:</c->
    <c- c1>// exposition only</c->
    <c- p>[[</c-><c- n>noreturn</c-><c- p>]]</c-> <c- k>static</c-> <c- n>coroutine_handle</c-><c- o>&lt;></c-> <c- n>default_unhandled_stopped</c-><c- p>(</c-><c- b>void</c-><c- o>*</c-><c- p>)</c-> <c- k>noexcept</c-> <c- p>{</c->
      <c- n>terminate</c-><c- p>();</c->
    <c- p>}</c->
    <c- n>coroutine_handle</c-><c- o>&lt;></c-> <i><c- n>continuation_</c-></i><c- p>{};</c-> <c- c1>// exposition only</c->
    <c- c1>// exposition only</c->
    <c- n>coroutine_handle</c-><c- o>&lt;></c-> <c- p>(</c-><c- o>*</c-><i><c- n>stopped_handler_</c-></i><c- p>)(</c-><c- b>void</c-><c- o>*</c-><c- p>)</c-> <c- k>noexcept</c-> <c- o>=</c-> <c- o>&amp;</c-><c- n>default_unhandled_stopped</c-><c- p>;</c->
  <c- p>};</c->
</pre>
    <li data-md>
     <p><b><code class="highlight"><c- b>void</c-> <c- n>set_continuation</c-><c- p>(</c-><c- n>coroutine_handle</c-><c- o>&lt;</c-><c- n>OtherPromise</c-><c- o>></c-> <c- n>h</c-><c- p>)</c-> <c- k>noexcept</c-></code></b></p>
     <ul>
      <li data-md>
       <p><i>Effects:</i> equivalent to:</p>
<pre class="highlight"><i><c- n>continuation_</c-></i> <c- o>=</c-> <c- n>h</c-><c- p>;</c->
<c- k>if</c-> <c- k>constexpr</c-> <c- p>(</c-> <c- k>requires</c-><c- p>(</c-><c- n>OtherPromise</c-><c- o>&amp;</c-> <c- n>other</c-><c- p>)</c-> <c- p>{</c-> <c- n>other</c-><c- p>.</c-><c- n>unhandled_stopped</c-><c- p>();</c-> <c- p>}</c-> <c- p>)</c-> <c- p>{</c->
  <i><c- n>stopped_handler_</c-></i> <c- o>=</c-> <c- p>[](</c-><c- b>void</c-><c- o>*</c-> <c- n>p</c-><c- p>)</c-> <c- k>noexcept</c-> <c- o>-></c-> <c- n>coroutine_handle</c-><c- o>&lt;></c-> <c- p>{</c->
    <c- k>return</c-> <c- n>coroutine_handle</c-><c- o>&lt;</c-><c- n>OtherPromise</c-><c- o>>::</c-><c- n>from_address</c-><c- p>(</c-><c- n>p</c-><c- p>)</c->
      <c- p>.</c-><c- n>promise</c-><c- p>().</c-><c- n>unhandled_stopped</c-><c- p>();</c->
  <c- p>};</c->
<c- p>}</c-> <c- k>else</c-> <c- p>{</c->
  <i><c- n>stopped_handler_</c-></i> <c- o>=</c-> <c- n>default_unhandled_stopped</c-><c- p>;</c->
<c- p>}</c->
</pre>
     </ul>
    <li data-md>
     <p><b><code class="highlight"><i><c- n>call</c-><c- o>-</c-><c- n>result</c-><c- o>-</c-><c- n>t</c-></i><c- o>&lt;</c-><c- n>as_awaitable_t</c-><c- p>,</c-> <c- n>Value</c-><c- p>,</c-> <c- n>Promise</c-><c- o>&amp;></c-> <c- n>await_transform</c-><c- p>(</c-><c- n>Value</c-><c- o>&amp;&amp;</c-> <c- n>value</c-><c- p>)</c-></code></b></p>
     <ul>
      <li data-md>
       <p><i>Effects:</i> equivalent to:</p>
<pre class="highlight"><c- k>return</c-> <c- n>as_awaitable</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>Value</c-><c- o>></c-><c- p>(</c-><c- n>value</c-><c- p>),</c-> <c- k>static_cast</c-><c- o>&lt;</c-><c- n>Promise</c-><c- o>&amp;></c-><c- p>(</c-><c- o>*</c-><c- k>this</c-><c- p>));</c->
</pre>
     </ul>
   </ol>
  </main>
<script>
(function() {
  "use strict";
  var collapseSidebarText = '<span aria-hidden="true">←</span> '
                          + '<span>Collapse Sidebar</span>';
  var expandSidebarText   = '<span aria-hidden="true">→</span> '
                          + '<span>Pop Out Sidebar</span>';
  var tocJumpText         = '<span aria-hidden="true">↑</span> '
                          + '<span>Jump to Table of Contents</span>';

  var sidebarMedia = window.matchMedia('screen and (min-width: 78em)');
  var autoToggle   = function(e){ toggleSidebar(e.matches) };
  if(sidebarMedia.addListener) {
    sidebarMedia.addListener(autoToggle);
  }

  function toggleSidebar(on) {
    if (on == undefined) {
      on = !document.body.classList.contains('toc-sidebar');
    }

    /* Don’t scroll to compensate for the ToC if we’re above it already. */
    var headY = 0;
    var head = document.querySelector('.head');
    if (head) {
      // terrible approx of "top of ToC"
      headY += head.offsetTop + head.offsetHeight;
    }
    var skipScroll = window.scrollY < headY;

    var toggle = document.getElementById('toc-toggle');
    var tocNav = document.getElementById('toc');
    if (on) {
      var tocHeight = tocNav.offsetHeight;
      document.body.classList.add('toc-sidebar');
      document.body.classList.remove('toc-inline');
      toggle.innerHTML = collapseSidebarText;
      if (!skipScroll) {
        window.scrollBy(0, 0 - tocHeight);
      }
      tocNav.focus();
      sidebarMedia.addListener(autoToggle); // auto-collapse when out of room
    }
    else {
      document.body.classList.add('toc-inline');
      document.body.classList.remove('toc-sidebar');
      toggle.innerHTML = expandSidebarText;
      if (!skipScroll) {
        window.scrollBy(0, tocNav.offsetHeight);
      }
      if (toggle.matches(':hover')) {
        /* Unfocus button when not using keyboard navigation,
           because I don’t know where else to send the focus. */
        toggle.blur();
      }
    }
  }

  function createSidebarToggle() {
    /* Create the sidebar toggle in JS; it shouldn’t exist when JS is off. */
    var toggle = document.createElement('a');
      /* This should probably be a button, but appearance isn’t standards-track.*/
    toggle.id = 'toc-toggle';
    toggle.class = 'toc-toggle';
    toggle.href = '#toc';
    toggle.innerHTML = collapseSidebarText;

    sidebarMedia.addListener(autoToggle);
    var toggler = function(e) {
      e.preventDefault();
      sidebarMedia.removeListener(autoToggle); // persist explicit off states
      toggleSidebar();
      return false;
    }
    toggle.addEventListener('click', toggler, false);


    /* Get <nav id=toc-nav>, or make it if we don’t have one. */
    var tocNav = document.getElementById('toc-nav');
    if (!tocNav) {
      tocNav = document.createElement('p');
      tocNav.id = 'toc-nav';
      /* Prepend for better keyboard navigation */
      document.body.insertBefore(tocNav, document.body.firstChild);
    }
    /* While we’re at it, make sure we have a Jump to Toc link. */
    var tocJump = document.getElementById('toc-jump');
    if (!tocJump) {
      tocJump = document.createElement('a');
      tocJump.id = 'toc-jump';
      tocJump.href = '#toc';
      tocJump.innerHTML = tocJumpText;
      tocNav.appendChild(tocJump);
    }

    tocNav.appendChild(toggle);
  }

  var toc = document.getElementById('toc');
  if (toc) {
    createSidebarToggle();
    toggleSidebar(sidebarMedia.matches);

    /* If the sidebar has been manually opened and is currently overlaying the text
       (window too small for the MQ to add the margin to body),
       then auto-close the sidebar once you click on something in there. */
    toc.addEventListener('click', function(e) {
      if(e.target.tagName.toLowerCase() == "a" && document.body.classList.contains('toc-sidebar') && !sidebarMedia.matches) {
        toggleSidebar(false);
      }
    }, false);
  }
  else {
    console.warn("Can’t find Table of Contents. Please use <nav id='toc'> around the ToC.");
  }

  /* Wrap tables in case they overflow */
  var tables = document.querySelectorAll(':not(.overlarge) > table.data, :not(.overlarge) > table.index');
  var numTables = tables.length;
  for (var i = 0; i < numTables; i++) {
    var table = tables[i];
    var wrapper = document.createElement('div');
    wrapper.className = 'overlarge';
    table.parentNode.insertBefore(wrapper, table);
    wrapper.appendChild(table);
  }

})();
</script>
  <h2 class="no-num no-ref heading settled" id="index"><span class="content">Index</span><a class="self-link" href="#index"></a></h2>
  <h3 class="no-num no-ref heading settled" id="index-defined-here"><span class="content">Terms defined by this specification</span><a class="self-link" href="#index-defined-here"></a></h3>
  <ul class="index">
   <li><a href="#asychronous-operation-lifetime">asychronous operation lifetime</a><span>, in § 11.3</span>
   <li><a href="#asynchronous-operation">asynchronous operation</a><span>, in § 11.3</span>
   <li><a href="#async-lifetime">async lifetime</a><span>, in § 11.3</span>
   <li><a href="#async-result">async result</a><span>, in § 11.3</span>
   <li><a href="#attributes">attributes</a><span>, in § 11.3</span>
   <li><a href="#awaitable">awaitable</a><span>, in § 11.9.3</span>
   <li><a href="#caller">caller</a><span>, in § 11.3</span>
   <li><a href="#child-operations">child operations</a><span>, in § 11.3</span>
   <li><a href="#child-sender">child sender</a><span>, in § 11.3</span>
   <li><a href="#complete">complete</a><span>, in § 11.3</span>
   <li><a href="#completion-function">completion function</a><span>, in § 11.3</span>
   <li><a href="#completion-operation">completion operation</a><span>, in § 11.3</span>
   <li><a href="#completion-scheduler">completion scheduler</a><span>, in § 11.3</span>
   <li><a href="#completion-signature">completion signature</a><span>, in § 11.3</span>
   <li><a href="#completion-tag">completion tag</a><span>, in § 11.3</span>
   <li><a href="#connect">connect</a><span>, in § 11.3</span>
   <li><a href="#decay-copied-from">decay-copied from</a><span>, in § 8</span>
   <li><a href="#disposition">disposition</a><span>, in § 11.3</span>
   <li><a href="#environment">environment</a><span>, in § 11.3</span>
   <li><a href="#error-completion">error completion</a><span>, in § 11.3</span>
   <li><a href="#execution-resource">execution resource</a><span>, in § 11.3</span>
   <li><a href="#multi-shot-sender">multi-shot sender</a><span>, in § 4.7</span>
   <li><a href="#operation-state">operation state</a><span>, in § 11.3</span>
   <li><a href="#parent-operation">parent operation</a><span>, in § 11.3</span>
   <li><a href="#parent-sender">parent sender</a><span>, in § 11.3</span>
   <li><a href="#permissible-completion">permissible completion</a><span>, in § 11.9.2</span>
   <li><a href="#pipeable">pipeable</a><span>, in § 4.12</span>
   <li><a href="#piped">piped</a><span>, in § 4.12</span>
   <li><a href="#query">query</a><span>, in § 11.2.1</span>
   <li><a href="#queryable-object">queryable object</a><span>, in § 11.2.1</span>
   <li><a href="#query-object">query object</a><span>, in § 11.2.1</span>
   <li><a href="#receive">receive</a><span>, in § 11.3</span>
   <li><a href="#receiver">receiver</a><span>, in § 11.3</span>
   <li><a href="#schedule-expression">schedule-expression</a><span>, in § 11.3</span>
   <li><a href="#scheduler">scheduler</a><span>, in § 11.3</span>
   <li><a href="#schedule-sender">schedule sender</a><span>, in § 11.3</span>
   <li><a href="#send">send</a><span>, in § 11.3</span>
   <li><a href="#sender">sender</a><span>, in § 11.3</span>
   <li><a href="#sender-adaptor">sender adaptor</a><span>, in § 11.3</span>
   <li><a href="#sender-algorithm">sender algorithm</a><span>, in § 11.3</span>
   <li><a href="#sender-consumer">sender consumer</a><span>, in § 11.3</span>
   <li><a href="#sender-factory">sender factory</a><span>, in § 11.3</span>
   <li><a href="#single-shot-sender">single-shot sender</a><span>, in § 4.7</span>
   <li><a href="#start">start</a><span>, in § 11.3</span>
   <li><a href="#stopped-completion">stopped completion</a><span>, in § 11.3</span>
   <li><a href="#strictly-lazy-submission">Strictly lazy submission</a><span>, in § 5.5</span>
   <li><a href="#value-completion">value completion</a><span>, in § 11.3</span>
  </ul>
  <h2 class="no-num no-ref heading settled" id="references"><span class="content">References</span><a class="self-link" href="#references"></a></h2>
  <h3 class="no-num no-ref heading settled" id="informative"><span class="content">Informative References</span><a class="self-link" href="#informative"></a></h3>
  <dl>
   <dt id="biblio-cwg2517">[CWG2517]
   <dd>Richard Smith. <a href="https://wg21.link/cwg2517"><cite>Useless restriction on use of parameter in constraint-expression</cite></a>. 10 June 2019. open. URL: <a href="https://wg21.link/cwg2517">https://wg21.link/cwg2517</a>
   <dt id="biblio-hpx">[HPX]
   <dd>Hartmut Kaiser; et al. <a href="https://doi.org/10.21105/joss.02352"><cite>HPX - The C++ Standard Library for Parallelism and Concurrency</cite></a>. URL: <a href="https://doi.org/10.21105/joss.02352">https://doi.org/10.21105/joss.02352</a>
   <dt id="biblio-n4885">[N4885]
   <dd>Thomas Köppe. <a href="https://wg21.link/n4885"><cite>Working Draft, Standard for Programming Language C++</cite></a>. 17 March 2021. URL: <a href="https://wg21.link/n4885">https://wg21.link/n4885</a>
   <dt id="biblio-p0443r14">[P0443R14]
   <dd>Jared Hoberock, Michael Garland, Chris Kohlhoff, Chris Mysen, H. Carter Edwards, Gordon Brown, D. S. Hollman. <a href="https://wg21.link/p0443r14"><cite>A Unified Executors Proposal for C++</cite></a>. 15 September 2020. URL: <a href="https://wg21.link/p0443r14">https://wg21.link/p0443r14</a>
   <dt id="biblio-p0981r0">[P0981R0]
   <dd>Richard Smith, Gor Nishanov. <a href="https://wg21.link/p0981r0"><cite>Halo: coroutine Heap Allocation eLision Optimization: the joint response</cite></a>. 18 March 2018. URL: <a href="https://wg21.link/p0981r0">https://wg21.link/p0981r0</a>
   <dt id="biblio-p1056r1">[P1056R1]
   <dd>Lewis Baker, Gor Nishanov. <a href="https://wg21.link/p1056r1"><cite>Add lazy coroutine (coroutine task) type</cite></a>. 7 October 2018. URL: <a href="https://wg21.link/p1056r1">https://wg21.link/p1056r1</a>
   <dt id="biblio-p1895r0">[P1895R0]
   <dd>Lewis Baker, Eric Niebler, Kirk Shoop. <a href="https://wg21.link/p1895r0"><cite>tag_invoke: A general pattern for supporting customisable functions</cite></a>. 8 October 2019. URL: <a href="https://wg21.link/p1895r0">https://wg21.link/p1895r0</a>
   <dt id="biblio-p1897r3">[P1897R3]
   <dd>Lee Howes. <a href="https://wg21.link/p1897r3"><cite>Towards C++23 executors: A proposal for an initial set of algorithms</cite></a>. 16 May 2020. URL: <a href="https://wg21.link/p1897r3">https://wg21.link/p1897r3</a>
   <dt id="biblio-p2175r0">[P2175R0]
   <dd>Lewis Baker. <a href="https://wg21.link/p2175r0"><cite>Composable cancellation for sender-based async operations</cite></a>. 15 December 2020. URL: <a href="https://wg21.link/p2175r0">https://wg21.link/p2175r0</a>
   <dt id="biblio-p2280r2">[P2280r2]
   <dd>Barry Revzin. <a href="https://wg21.link/p2280r2"><cite>Using unknown references in constant expressions</cite></a>. 15 May 2021. URL: <a href="https://wg21.link/p2280r2">https://wg21.link/p2280r2</a>
  </dl>
  <aside class="dfn-panel" data-for="execution-resource">
   <b><a href="#execution-resource">#execution-resource</a></b><b>Referenced in:</b>
   <ul>
    <li><a href="#ref-for-execution-resource">4.1. Execution resources describe the place of execution</a>
   </ul>
  </aside>
  <aside class="dfn-panel" data-for="start">
   <b><a href="#start">#start</a></b><b>Referenced in:</b>
   <ul>
    <li><a href="#ref-for-start">4.20. User-facing sender adaptors</a>
   </ul>
  </aside>
  <aside class="dfn-panel" data-for="operation-state">
   <b><a href="#operation-state">#operation-state</a></b><b>Referenced in:</b>
   <ul>
    <li><a href="#ref-for-operation-state">5.2. Operation states represent work</a>
   </ul>
  </aside>
  <aside class="dfn-panel" data-for="receiver">
   <b><a href="#receiver">#receiver</a></b><b>Referenced in:</b>
   <ul>
    <li><a href="#ref-for-receiver">5.1. Receivers serve as glue between senders</a>
   </ul>
  </aside>
  <aside class="dfn-panel" data-for="sender">
   <b><a href="#sender">#sender</a></b><b>Referenced in:</b>
   <ul>
    <li><a href="#ref-for-sender">4.3. Senders describe work</a>
   </ul>
  </aside>
  <aside class="dfn-panel" data-for="connect">
   <b><a href="#connect">#connect</a></b><b>Referenced in:</b>
   <ul>
    <li><a href="#ref-for-connect">4.20.12. execution::ensure_started</a>
    <li><a href="#ref-for-connect①">5.3. execution::connect</a>
   </ul>
  </aside>
  <aside class="dfn-panel" data-for="send">
   <b><a href="#send">#send</a></b><b>Referenced in:</b>
   <ul>
    <li><a href="#ref-for-send">4.5.1. execution::get_completion_scheduler</a>
    <li><a href="#ref-for-send①">4.19.2. execution::just</a>
    <li><a href="#ref-for-send②">4.20.2. execution::then</a>
    <li><a href="#ref-for-send③">4.20.4. execution::let_*</a>
    <li><a href="#ref-for-send④">5.8. All senders are typed</a>
   </ul>
  </aside>
  <aside class="dfn-panel" data-for="scheduler">
   <b><a href="#scheduler">#scheduler</a></b><b>Referenced in:</b>
   <ul>
    <li><a href="#ref-for-scheduler">4.2. Schedulers represent execution resources</a>
   </ul>
  </aside>
  <aside class="dfn-panel" data-for="completion-scheduler">
   <b><a href="#completion-scheduler">#completion-scheduler</a></b><b>Referenced in:</b>
   <ul>
    <li><a href="#ref-for-completion-scheduler">4.5. Senders can propagate completion schedulers</a>
    <li><a href="#ref-for-completion-scheduler①">4.6. Execution resource transitions are explicit</a>
    <li><a href="#ref-for-completion-scheduler②">4.19.2. execution::just</a>
    <li><a href="#ref-for-completion-scheduler③">4.19.3. execution::just_error</a>
    <li><a href="#ref-for-completion-scheduler④">4.19.4. execution::just_stopped</a>
    <li><a href="#ref-for-completion-scheduler⑤">4.20.5. execution::on</a>
    <li><a href="#ref-for-completion-scheduler⑥">4.20.11. execution::when_all</a>
    <li><a href="#ref-for-completion-scheduler⑦">5.4. Sender algorithms are customizable</a>
   </ul>
  </aside>
  <aside class="dfn-panel" data-for="sender-algorithm">
   <b><a href="#sender-algorithm">#sender-algorithm</a></b><b>Referenced in:</b>
   <ul>
    <li><a href="#ref-for-sender-algorithm">4.3. Senders describe work</a>
    <li><a href="#ref-for-sender-algorithm①">4.4. Senders are composable through sender algorithms</a>
   </ul>
  </aside>
  <aside class="dfn-panel" data-for="sender-factory">
   <b><a href="#sender-factory">#sender-factory</a></b><b>Referenced in:</b>
   <ul>
    <li><a href="#ref-for-sender-factory">4.4. Senders are composable through sender algorithms</a>
    <li><a href="#ref-for-sender-factory①">4.19. User-facing sender factories</a>
   </ul>
  </aside>
  <aside class="dfn-panel" data-for="sender-adaptor">
   <b><a href="#sender-adaptor">#sender-adaptor</a></b><b>Referenced in:</b>
   <ul>
    <li><a href="#ref-for-sender-adaptor">4.4. Senders are composable through sender algorithms</a>
    <li><a href="#ref-for-sender-adaptor①">4.20. User-facing sender adaptors</a>
    <li><a href="#ref-for-sender-adaptor②">5.4. Sender algorithms are customizable</a>
   </ul>
  </aside>
  <aside class="dfn-panel" data-for="sender-consumer">
   <b><a href="#sender-consumer">#sender-consumer</a></b><b>Referenced in:</b>
   <ul>
    <li><a href="#ref-for-sender-consumer">4.4. Senders are composable through sender algorithms</a>
    <li><a href="#ref-for-sender-consumer①">4.21. User-facing sender consumers</a>
    <li><a href="#ref-for-sender-consumer②">5.4. Sender algorithms are customizable</a>
   </ul>
  </aside>
<script>/* script-dfn-panel */

document.body.addEventListener("click", function(e) {
    var queryAll = function(sel) { return [].slice.call(document.querySelectorAll(sel)); }
    // Find the dfn element or panel, if any, that was clicked on.
    var el = e.target;
    var target;
    var hitALink = false;
    while(el.parentElement) {
        if(el.tagName == "A") {
            // Clicking on a link in a <dfn> shouldn't summon the panel
            hitALink = true;
        }
        if(el.classList.contains("dfn-paneled")) {
            target = "dfn";
            break;
        }
        if(el.classList.contains("dfn-panel")) {
            target = "dfn-panel";
            break;
        }
        el = el.parentElement;
    }
    if(target != "dfn-panel") {
        // Turn off any currently "on" or "activated" panels.
        queryAll(".dfn-panel.on, .dfn-panel.activated").forEach(function(el){
            el.classList.remove("on");
            el.classList.remove("activated");
        });
    }
    if(target == "dfn" && !hitALink) {
        // open the panel
        var dfnPanel = document.querySelector(".dfn-panel[data-for='" + el.id + "']");
        if(dfnPanel) {
            dfnPanel.classList.add("on");
            var rect = el.getBoundingClientRect();
            dfnPanel.style.left = window.scrollX + rect.right + 5 + "px";
            dfnPanel.style.top = window.scrollY + rect.top + "px";
            var panelRect = dfnPanel.getBoundingClientRect();
            var panelWidth = panelRect.right - panelRect.left;
            if(panelRect.right > document.body.scrollWidth && (rect.left - (panelWidth + 5)) > 0) {
                // Reposition, because the panel is overflowing
                dfnPanel.style.left = window.scrollX + rect.left - (panelWidth + 5) + "px";
            }
        } else {
            console.log("Couldn't find .dfn-panel[data-for='" + el.id + "']");
        }
    } else if(target == "dfn-panel") {
        // Switch it to "activated" state, which pins it.
        el.classList.add("activated");
        el.style.left = null;
        el.style.top = null;
    }

});
</script>