<!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>P3481R5: std::execution::bulk() issues</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;
			border-bottom: 3px solid transparent;
			margin-bottom: -3px;
		}
		#toc .content:hover,
		#toc .content:focus {
			background: rgba(75%, 75%, 75%, .25);
			background: var(--a-hover-bg);
			border-bottom-color: #054572;
			border-bottom-color: var(--toclink-underline);
		}
		#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 6270e4735, updated Tue Aug 6 12:12:30 2024 -0700" name="generator">
  <link href="http://wg21.link/P3481R5" rel="canonical">
  <link href="https://isocpp.org/favicon.ico" rel="icon">
  <meta content="a8c86d42df1808c718be9d4d6176ea639face47b" name="revision">
  <meta content="dark light" name="color-scheme">
<style>
div.ed-note, span.ed-note {
  color: light-dark(blue, cornflowerblue) !important;
  font: initial;
  font-family: sans-serif;
}
div.ed-note:before, span.ed-note:before {
  content: "[Editorial note: ";
  font-style: italic;
}
div.ed-note:after, span.ed-note:after {
  content: " — end note]";
  font-style: italic;
}
.ins, ins, ins *, span.ins, span.ins * {
  background-color: light-dark(#cfc, hsl(120, 100.00%, 15%));
  color: light-dark(#000, #ddd);
  text-decoration: none;
}
.del, del, del *, span.del, span.del * {
  background-color: light-dark(#fcc,hsl(0, 100.00%, 20%));
  color: light-dark(#000, #ddd);
  text-decoration: line-through;
  text-decoration-color: #c00;
}
div.ed-note *, span.ed-note * {
  color: blue !important;
  margin-top: 0em;
  margin-bottom: 0em;
}
div.ed-note blockquote {
  margin-left: 2em;
}
div.block-insert, div.block-insert {
  background-color: light-dark(#cfc, hsl(120, 100.00%, 15%));
  padding-left: 0;
  padding-right: 1.6em;
}
div.block-insert pre.highlight {
  background-color: transparent;
}
</style>
<style>/* Boilerplate: 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;
}

@media (prefers-color-scheme: dark) {
    :root {
        --selflink-text: black;
        --selflink-bg: silver;
        --selflink-hover-text: white;
    }
}
</style>
<style>/* Boilerplate: 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;
}

@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; }
}
</style>
<style>/* Boilerplate: 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>/* Boilerplate: style-issues */
a[href].issue-return {
    float: right;
    float: inline-end;
    color: var(--issueheading-text);
    font-weight: bold;
    text-decoration: none;
}
</style>
<style>/* Boilerplate: 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>/* Boilerplate: 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%;
}
.example > a.self-link,
.note > a.self-link,
.issue > a.self-link {
    /* These blocks are overflow:auto, so positioning outside
       doesn't work. */
    left: auto;
    right: 0;
}
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>/* Boilerplate: 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 */

@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">P3481R5<br><code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>execution</c-><c- o>::</c-><c- n>bulk</c-><c- p>()</c-></code> issues</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="2025-06-18">2025-06-18</time></span></h2>
   <div data-fill-with="spec-metadata">
    <dl>
     <dt>This version:
     <dd><a class="u-url" href="http://wg21.link/P3481R5">http://wg21.link/P3481R5</a>
     <dt class="editor">Authors:
     <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> (<span class="p-org org">Garmin</span>)
     <dd class="editor p-author h-card vcard"><a class="p-name fn u-email email" href="mailto:ruslan.arutyunyan@intel.com">Ruslan Arutyunyan</a> (<span class="p-org org">Intel</span>)
     <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:mhoemmen@nvidia.com">Mark Hoemmen</a> (<span class="p-org org">NVIDIA</span>)
     <dt>Audience:
     <dd>LWG
     <dt>Project:
     <dd>ISO/IEC 14882 Programming Languages — C++, ISO/IEC JTC1/SC22/WG21
    </dl>
   </div>
   <div data-fill-with="warning"></div>
   <hr title="Separator for header">
  </div>
  <div class="p-summary" data-fill-with="abstract">
   <h2 class="no-num no-toc no-ref heading settled" id="abstract"><span class="content">Abstract</span></h2>
   <p>This paper explores the issues with <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>execution</c-><c- o>::</c-><c- n>bulk</c-></code> algorithm and proposes a way to address them,
making the API better for the users.</p>
  </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="#history"><span class="secno">1</span> <span class="content">Changes history</span></a>
     <ol class="toc">
      <li><a href="#r5"><span class="secno">1.1</span> <span class="content">R5</span></a>
      <li><a href="#r4"><span class="secno">1.2</span> <span class="content">R4</span></a>
      <li><a href="#r3"><span class="secno">1.3</span> <span class="content">R3</span></a>
      <li><a href="#r2"><span class="secno">1.4</span> <span class="content">R2</span></a>
      <li><a href="#r1"><span class="secno">1.5</span> <span class="content">R1</span></a>
     </ol>
    <li>
     <a href="#motivation"><span class="secno">2</span> <span class="content">Motivation</span></a>
     <ol class="toc">
      <li><a href="#motivation.allowed"><span class="secno">2.1</span> <span class="content">Allowed behavior for <code class="highlight"><c- n>bulk</c-></code> customizations</span></a>
      <li><a href="#motivation.policy"><span class="secno">2.2</span> <span class="content">Execution policy for the given functor</span></a>
      <li><a href="#motivation.chunking"><span class="secno">2.3</span> <span class="content">Chunking</span></a>
     </ol>
    <li><a href="#api"><span class="secno">3</span> <span class="content">API</span></a>
    <li>
     <a href="#design"><span class="secno">4</span> <span class="content">Design discussions</span></a>
     <ol class="toc">
      <li><a href="#design.chunked"><span class="secno">4.1</span> <span class="content">Use chunked version as a basis operation</span></a>
      <li><a href="#design.unchunked"><span class="secno">4.2</span> <span class="content">Also define an unchunked version</span></a>
      <li><a href="#design.policies"><span class="secno">4.3</span> <span class="content">Using execution policies</span></a>
      <li><a href="#design.conflict.policies"><span class="secno">4.4</span> <span class="content">Conflicting execution policies</span></a>
      <li><a href="#design.expectations"><span class="secno">4.5</span> <span class="content">Expectations on customizations</span></a>
      <li><a href="#design.exceptions"><span class="secno">4.6</span> <span class="content">Exception handling</span></a>
     </ol>
    <li>
     <a href="#specification"><span class="secno">5</span> <span class="content">Specification</span></a>
     <ol class="toc">
      <li><a href="#specification.syn"><span class="secno">5.1</span> <span class="content">In [execution.syn]</span></a>
      <li><a href="#specification.bulk"><span class="secno">5.2</span> <span class="content">In [exec.bulk]</span></a>
     </ol>
    <li><a href="#acknowledgements"><span class="secno">6</span> <span class="content">Acknowledgements</span></a>
    <li>
     <a href="#polls"><span class="secno">7</span> <span class="content">Polls</span></a>
     <ol class="toc">
      <li><a href="#sg1.austria.2025"><span class="secno">7.1</span> <span class="content">SG1, Hagenberg, Austria, 2025</span></a>
      <li><a href="#sg1.poland.2024"><span class="secno">7.2</span> <span class="content">SG1, Wrocław, Poland, 2024</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="history"><span class="secno">1. </span><span class="content">Changes history</span><a class="self-link" href="#history"></a></h2>
   <h3 class="heading settled" data-level="1.1" id="r5"><span class="secno">1.1. </span><span class="content">R5</span><a class="self-link" href="#r5"></a></h3>
   <ul>
    <li data-md>
     <p>Apply LWG review feedback from Bulgaria, 2025</p>
   </ul>
   <h3 class="heading settled" data-level="1.2" id="r4"><span class="secno">1.2. </span><span class="content">R4</span><a class="self-link" href="#r4"></a></h3>
   <ul>
    <li data-md>
     <p>Improve wording.</p>
    <li data-md>
     <p>Add execution policy to <code class="highlight"><c- n>bulk_unchunked</c-></code>.</p>
    <li data-md>
     <p>remove extra check in <code class="highlight"><c- n>bulk_unchunked</c-></code> for concurrent schedulers</p>
   </ul>
   <h3 class="heading settled" data-level="1.3" id="r3"><span class="secno">1.3. </span><span class="content">R3</span><a class="self-link" href="#r3"></a></h3>
   <ul>
    <li data-md>
     <p>Improve wording.</p>
   </ul>
   <h3 class="heading settled" data-level="1.4" id="r2"><span class="secno">1.4. </span><span class="content">R2</span><a class="self-link" href="#r2"></a></h3>
   <ul>
    <li data-md>
     <p>Incorporate to the feedback from SG1 review, Austria, 2025.</p>
     <ul>
      <li data-md>
       <p>Incorporate the changes from <a data-link-type="biblio" href="#biblio-p3564r0" title="Make the concurrent forward progress guarantee usable in `bulk`">[P3564R0]</a>: Make calling un-customized <code class="highlight"><c- n>bulk_unchunked</c-></code> ill-formed on a scheduler with concurrent forward progress.</p>
      <li data-md>
       <p>Remove <code class="highlight"><c- n>bulk_unchunked</c-></code>’s execution policy parameter.</p>
      <li data-md>
       <p>Specify an error for the "lack of resources" case.</p>
     </ul>
   </ul>
   <h3 class="heading settled" data-level="1.5" id="r1"><span class="secno">1.5. </span><span class="content">R1</span><a class="self-link" href="#r1"></a></h3>
   <ul>
    <li data-md>
     <p>Incorporate to the feedback from SG1 review, Poland, 2024.</p>
    <li data-md>
     <p>Add wording section.</p>
   </ul>
   <h2 class="heading settled" data-level="2" id="motivation"><span class="secno">2. </span><span class="content">Motivation</span><a class="self-link" href="#motivation"></a></h2>
   <p>When <a data-link-type="biblio" href="#biblio-p2300r10" title="`std::execution`">[P2300R10]</a> was merged into the working draft, a subsequent review of the github issue tracker discovered several
outstanding issues relating to the use of the <code class="highlight"><c- n>bulk</c-></code> algorithm that was in <a data-link-type="biblio" href="#biblio-p2300r10" title="`std::execution`">[P2300R10]</a> which were not addressed during the
LEWG review. These issues mostly account for better expressing what <code class="highlight"><c- n>bulk</c-></code> can and cannot do.</p>
   <p>For most algorithms defined in <a data-link-type="biblio" href="#biblio-p2300r10" title="`std::execution`">[P2300R10]</a>, the default implementation typically describes the desired behavior.
However, this is not the case for <code class="highlight"><c- n>bulk</c-></code>.</p>
   <p>The expectation for <code class="highlight"><c- n>bulk</c-></code> is that it will be customized for most use cases.
The default implementation is a common-denominator solution that is not necessarily optimal for the majority of scenarios.</p>
   <p>The description in <a data-link-type="biblio" href="#biblio-execbulk" title="Working Draft: Programming Languages — C++ -- `execution::bulk`">[exec.bulk]</a> specifies the default implementation but does not outline any requirements for customizations.
This creates uncertainty for users regarding what they can expect when invoking <code class="highlight"><c- n>bulk</c-></code>.</p>
   <p>This paper addresses this issue by specifying what is permissible in a customization of <code class="highlight"><c- n>bulk</c-></code>.</p>
   <p>A second issue this paper seeks to resolve is the lack of an execution policy for the provided functor.
For example, imagine that we have scheduler that supports <code class="highlight"><c- n>par_unseq</c-></code> execution policy only for parallelism (certain GPU
schedulers) and it wants to customize <code class="highlight"><c- n>bulk</c-></code>. If the functor is unsuitable for the <code class="highlight"><c- n>par_unseq</c-></code> execution policy, there is
currently no mechanism for users to express this with the current API shape.</p>
   <p>A third issue this paper addresses is the absence of chunking in the default implementation of <code class="highlight"><c- n>bulk</c-></code>.
Invoking the functor for every element in a range can lead to performance challenges in certain use cases.</p>
   <h3 class="heading settled" data-level="2.1" id="motivation.allowed"><span class="secno">2.1. </span><span class="content">Allowed behavior for <code class="highlight"><c- n>bulk</c-></code> customizations</span><a class="self-link" href="#motivation.allowed"></a></h3>
   <p>From the specification of bulk in <a data-link-type="biblio" href="#biblio-execbulk" title="Working Draft: Programming Languages — C++ -- `execution::bulk`">[exec.bulk]</a>, if we have customized <code class="highlight"><c- n>bulk</c-></code>, the following are unclear:</p>
   <ul>
    <li data-md>
     <p>Can <code class="highlight"><c- n>bulk</c-></code> invoke the given functor concurrently?</p>
    <li data-md>
     <p>Can <code class="highlight"><c- n>bulk</c-></code> create decayed copies of the given functor?</p>
    <li data-md>
     <p>Can <code class="highlight"><c- n>bulk</c-></code> create decayed copies of the values produced by the previous sender?</p>
    <li data-md>
     <p>Can <code class="highlight"><c- n>bulk</c-></code> handle cancellation within the algorithm?</p>
    <li data-md>
     <p>How should <code class="highlight"><c- n>bulk</c-></code> respond to exceptions thrown by the given functor?</p>
   </ul>
   <h3 class="heading settled" data-level="2.2" id="motivation.policy"><span class="secno">2.2. </span><span class="content">Execution policy for the given functor</span><a class="self-link" href="#motivation.policy"></a></h3>
   <p>Similar to <code class="highlight"><c- n>for_each</c-></code> (<a data-link-type="biblio" href="#biblio-algforeach" title="Working Draft: Programming Languages — C++ -- For each">[alg.foreach]</a>) users might expect the <code class="highlight"><c- n>bulk</c-></code> algorithm to take an execution policy as argument.
The execution policy would define the execution capabilities of the given function.</p>
   <p>There are two main reasons for wanting an execution policy to accompany the function passed to <code class="highlight"><c- n>bulk</c-></code>:</p>
   <ol>
    <li data-md>
     <p>To better tailor the algorithm to the available hardware.</p>
    <li data-md>
     <p>To improve usage in generic code.</p>
   </ol>
   <p>Currently, we have hardware that supports both <code class="highlight"><c- n>par</c-></code> and <code class="highlight"><c- n>par_unseq</c-></code> execution policy semantics, as well as hardware that only supports <code class="highlight"><c- n>par_unseq</c-></code>.
Standardizing the API without execution policies implies that the language chooses a default execution policy for <code class="highlight"><c- n>bulk</c-></code>.
This decision could favor certain hardware vendors over others.</p>
   <p>From a generic programming perspective, consider a scenario where a user implements a function like the following:</p>
<pre class="language-cpp highlight"><c- b>void</c-> <c- nf>process</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;</c-> <c- n>data</c-><c- p>,</c-> <c- k>auto</c-> <c- n>std</c-><c- o>::</c-><c- n>invocable</c-><c- o>&lt;</c-><c- b>int</c-><c- o>></c-> <c- n>f</c-><c- p>)</c-> <c- p>{</c->
  <c- c1>// call `f` for each element in `data`; try using `bulk`.</c->
  <c- c1>// can we call `f` concurrently?</c->
<c- p>}</c->
</pre>
   <p>In the body of the generic function process, we do not know the constraints imposed on <code class="highlight"><c- n>f</c-></code>.
Can we assume that <code class="highlight"><c- n>f</c-></code> can be invoked with the <code class="highlight"><c- n>par_unseq</c-></code> execution policy?
Can it be invoked with the <code class="highlight"><c- n>par</c-></code> execution policy?
Or should we default to the <code class="highlight"><c- n>seq</c-></code> execution policy?</p>
   <p>Since there is no way to infer the execution policy that should apply to <code class="highlight"><c- n>f</c-></code>, the implementation of process must be conservative and default to the <code class="highlight"><c- n>seq</c-></code> execution policy.
However, in most cases, the <code class="highlight"><c- n>par</c-></code> or <code class="highlight"><c- n>par_unseq</c-></code> execution policy would likely be more appropriate.</p>
   <h3 class="heading settled" data-level="2.3" id="motivation.chunking"><span class="secno">2.3. </span><span class="content">Chunking</span><a class="self-link" href="#motivation.chunking"></a></h3>
   <p>The current specification of <code class="highlight"><c- n>bulk</c-></code> (<a data-link-type="biblio" href="#biblio-execbulk" title="Working Draft: Programming Languages — C++ -- `execution::bulk`">[exec.bulk]</a>) does not support chunking.
This limitation presents a performance issue for certain use cases.</p>
   <p>If two iterations can potentially be executed together more efficiently than in isolation, chunking would provide a performance benefit.</p>
   <p>Let us take an example:</p>
<pre class="language-cpp highlight"><c- n>std</c-><c- o>::</c-><c- n>atomic</c-><c- o>&lt;</c-><c- n>std</c-><c- o>::</c-><c- b>uint32_t</c-><c- o>></c-> <c- n>sum</c-><c- p>{</c-><c- mi>0</c-><c- p>};</c->
<c- n>std</c-><c- o>::</c-><c- n>vector</c-><c- o>&lt;</c-><c- n>std</c-><c- o>::</c-><c- b>uint32_t</c-><c- o>></c-> <c- n>data</c-><c- p>;</c->
<c- n>ex</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>s</c-> <c- o>=</c-> <c- n>ex</c-><c- o>::</c-><c- n>bulk</c-><c- p>(</c-><c- n>ex</c-><c- o>::</c-><c- n>just</c-><c- p>(),</c-> <c- n>std</c-><c- o>::</c-><c- n>execution</c-><c- o>::</c-><c- n>par</c-><c- p>,</c-> <c- mi>100'000</c-><c- p>,</c->
  <c- p>[</c-><c- o>&amp;</c-><c- n>sum</c-><c- p>,</c-><c- o>&amp;</c-><c- n>data</c-><c- p>](</c-><c- n>std</c-><c- o>::</c-><c- b>uint32_t</c-> <c- n>idx</c-><c- p>)</c-> <c- p>{</c->
    <c- n>sum</c-><c- p>.</c-><c- n>fetch_add</c-><c- p>(</c-><c- n>data</c-><c- p>[</c-><c- n>idx</c-><c- p>]);</c->
  <c- p>});</c->
</pre>
   <p>In this example, we perform 100,000 atomic operations.
A more efficient implementation would allow a single atomic operation for each chunk of work, enabling each chunk to perform local summation. This approach might look like:</p>
<pre class="language-cpp highlight"><c- n>std</c-><c- o>::</c-><c- n>atomic</c-><c- o>&lt;</c-><c- n>std</c-><c- o>::</c-><c- b>uint32_t</c-><c- o>></c-> <c- n>sum</c-><c- p>{</c-><c- mi>0</c-><c- p>};</c->
<c- n>ex</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>s</c-> <c- o>=</c-> <c- n>ex</c-><c- o>::</c-><c- n>bulk_chunked</c-><c- p>(</c-><c- n>ex</c-><c- o>::</c-><c- n>just</c-><c- p>(),</c-> <c- n>std</c-><c- o>::</c-><c- n>execution</c-><c- o>::</c-><c- n>par</c-><c- p>,</c-> <c- mi>100'000</c-><c- p>,</c->
  <c- p>[</c-><c- o>&amp;</c-><c- n>sum</c-><c- p>,</c-><c- o>&amp;</c-><c- n>data</c-><c- p>](</c-><c- n>std</c-><c- o>::</c-><c- b>uint32_t</c-> <c- n>begin</c-><c- p>,</c-> <c- n>std</c-><c- o>::</c-><c- b>uint32_t</c-> <c- n>end</c-><c- p>)</c-> <c- p>{</c->
    <c- n>std</c-><c- o>::</c-><c- b>uint32_t</c-> <c- n>partial_sum</c-> <c- o>=</c-> <c- mi>0</c-><c- p>;</c->
    <c- k>while</c-> <c- p>(</c-><c- n>begin</c-> <c- o>!=</c-> <c- n>end</c-><c- p>)</c-> <c- p>{</c->
      <c- n>partial_sum</c-> <c- o>+=</c-> <c- n>data</c-><c- p>[</c-><c- n>idx</c-><c- p>];</c->
    <c- p>}</c->
    <c- n>sum</c-><c- p>.</c-><c- n>fetch_add</c-><c- p>(</c-><c- n>partial_sum</c-><c- p>);</c->
  <c- p>});</c->
</pre>
   <p>Other similar examples exist where grouping operations together can improve performance.
This is particularly important when the functor passed to <code class="highlight"><c- n>bulk</c-></code> cannot be inlined or when the functor is expensive to invoke.</p>
   <h2 class="heading settled" data-level="3" id="api"><span class="secno">3. </span><span class="content">API</span><a class="self-link" href="#api"></a></h2>
   <p>Define <code class="highlight"><c- n>bulk</c-></code> to match the following API:</p>
<pre class="language-cpp highlight"><c- c1>// NEW: algorithm to be used as a default basis operation</c->
<c- k>template</c-><c- o>&lt;</c-><c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- n>Predecessor</c-><c- p>,</c->
         <c- k>typename</c-> <c- nc>ExecutionPolicy</c-><c- p>,</c->
         <c- n>std</c-><c- o>::</c-><c- n>integral</c-> <c- n>Size</c-><c- p>,</c->
         <c- n>std</c-><c- o>::</c-><c- n>invocable</c-><c- o>&lt;</c-><c- n>Size</c-><c- p>,</c-> <c- n>Size</c-><c- p>,</c-> <c- n>values</c-><c- o>-</c-><c- n>sent</c-><c- o>-</c-><c- n>by</c-><c- p>(</c-><c- n>Predecessor</c-><c- p>)...</c-><c- o>></c-> <c- n>Func</c->
<c- o>></c->
<c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>bulk_chunked</c-><c- p>(</c-><c- n>Predecessor</c-> <c- n>pred</c-><c- p>,</c->
                                    <c- n>ExecutionPolicy</c-><c- o>&amp;&amp;</c-> <c- n>pol</c-><c- p>,</c->
                                    <c- n>Size</c-> <c- n>size</c-><c- p>,</c->
                                    <c- n>Func</c-> <c- n>f</c-><c- p>);</c->

<c- c1>// NEW: algorithm to be used when one execution agent per iteration is desired</c->
<c- k>template</c-><c- o>&lt;</c-><c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- n>Predecessor</c-><c- p>,</c->
         <c- k>typename</c-> <c- nc>ExecutionPolicy</c-><c- p>,</c->
         <c- n>std</c-><c- o>::</c-><c- n>integral</c-> <c- n>Size</c-><c- p>,</c->
         <c- n>std</c-><c- o>::</c-><c- n>invocable</c-><c- o>&lt;</c-><c- n>Size</c-><c- p>,</c-> <c- n>values</c-><c- o>-</c-><c- n>sent</c-><c- o>-</c-><c- n>by</c-><c- p>(</c-><c- n>Predecessor</c-><c- p>)...</c-><c- o>></c-> <c- n>Func</c->
<c- o>></c->
<c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- k>auto</c-> <c- n>bulk_unchunked</c-><c- p>(</c-><c- n>Predecessor</c-> <c- n>pred</c-><c- p>,</c->
                                      <c- n>ExecutionPolicy</c-><c- o>&amp;&amp;</c-> <c- n>pol</c-><c- p>,</c->
                                      <c- n>Size</c-> <c- n>size</c-><c- p>,</c->
                                      <c- n>Func</c-> <c- n>f</c-><c- p>);</c->

<c- k>template</c-><c- o>&lt;</c-><c- n>execution</c-><c- o>::</c-><c- n>sender</c-> <c- n>Predecessor</c-><c- p>,</c->
         <c- k>typename</c-> <c- nc>ExecutionPolicy</c-><c- p>,</c->
         <c- n>std</c-><c- o>::</c-><c- n>integral</c-> <c- n>Size</c-><c- p>,</c->
         <c- n>std</c-><c- o>::</c-><c- n>invocable</c-><c- o>&lt;</c-><c- n>Size</c-><c- p>,</c-> <c- n>values</c-><c- o>-</c-><c- n>sent</c-><c- o>-</c-><c- n>by</c-><c- p>(</c-><c- n>Predecessor</c-><c- p>)...</c-><c- o>></c-> <c- n>Func</c->
<c- o>></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>Predecessor</c-> <c- n>pred</c-><c- p>,</c->
                            <c- n>ExecutionPolicy</c-><c- o>&amp;&amp;</c-> <c- n>pol</c-><c- p>,</c-> <c- c1>// NEW</c->
                            <c- n>Size</c-> <c- n>size</c-><c- p>,</c->
                            <c- n>Func</c-> <c- n>f</c-><c- p>)</c-> <c- p>{</c->
    <c- c1>// Default implementation</c->
    <c- k>return</c-> <c- n>bulk_chunked</c-><c- p>(</c->
        <c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>pred</c-><c- p>),</c->
        <c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>ExecutionPolicy</c-><c- o>></c-><c- p>(</c-><c- n>pol</c-><c- p>),</c->
        <c- n>size</c-><c- p>,</c->
        <c- p>[</c-><c- n>func</c-><c- o>=</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>func</c-><c- p>)]</c-><c- o>&lt;</c-><c- k>typename</c-><c- p>...</c-> <c- n>Vs</c-><c- o>></c-><c- p>(</c->
            <c- n>Size</c-> <c- n>begin</c-><c- p>,</c-> <c- n>Size</c-> <c- n>end</c-><c- p>,</c-> <c- n>Vs</c-><c- o>&amp;&amp;</c-><c- p>...</c-> <c- n>vs</c-><c- p>)</c->
            <c- k>noexcept</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>is_nothrow_invocable_v</c-><c- o>&lt;</c-><c- n>Func</c-><c- p>,</c-> <c- n>Size</c-><c- p>,</c-> <c- n>Vs</c-><c- o>&amp;&amp;</c-><c- p>...</c-><c- o>></c-><c- p>)</c-> <c- p>{</c->
            <c- k>while</c-> <c- p>(</c-><c- n>begin</c-> <c- o>!=</c-> <c- n>end</c-><c- p>)</c-> <c- p>{</c->
                <c- n>f</c-><c- p>(</c-><c- n>begin</c-><c- o>++</c-><c- p>,</c-> <c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>Vs</c-><c- o>></c-><c- p>(</c-><c- n>vs</c-><c- p>)...);</c->
            <c- p>}</c->
        <c- p>});</c->
<c- p>}</c->
</pre>
   <h2 class="heading settled" data-level="4" id="design"><span class="secno">4. </span><span class="content">Design discussions</span><a class="self-link" href="#design"></a></h2>
   <h3 class="heading settled" data-level="4.1" id="design.chunked"><span class="secno">4.1. </span><span class="content">Use chunked version as a basis operation</span><a class="self-link" href="#design.chunked"></a></h3>
   <p>To address the performance problem described in the motivation, we propose to add a chunked version for <code class="highlight"><c- n>bulk</c-></code>.
This allows implementations to process the iteration space in chunks, and take advantage of the locality of the chunk processing.
This is useful when publishing the effects of the functor may be expensive (the example from the motivation) and when the given functor cannot be inlined.</p>
   <p>The implementation of <code class="highlight"><c- n>bulk_chunked</c-></code> can use dynamically sized chunks that adapt to the workload at hand.
For example, computing the results of a Mandelbrot fractal on a line is an unbalanced process.
Some values can be computed very fast, while others take longer to compute.</p>
   <p>Passing a range as parameters to the functor passed to <code class="highlight"><c- n>bulk_chunked</c-></code> is similar to the way Intel TBB’s <code class="highlight"><c- n>parallel_for</c-></code> functions (see <a data-link-type="biblio" href="#biblio-parallel_for" title="Intel® oneAPI Threading Building Blocks Developer Guide and API Reference -- parallel_for">[parallel_for]</a>).</p>
   <p>An implementation of <code class="highlight"><c- n>bulk</c-></code> can be easily built on top of <code class="highlight"><c- n>bulk_chunked</c-></code> without losing performance (as shown in the Proposal section).</p>
   <h3 class="heading settled" data-level="4.2" id="design.unchunked"><span class="secno">4.2. </span><span class="content">Also define an unchunked version</span><a class="self-link" href="#design.unchunked"></a></h3>
   <p><a data-link-type="biblio" href="#biblio-p3564r0" title="Make the concurrent forward progress guarantee usable in `bulk`">[P3564R0]</a> explains the necessity
of having a version of <code class="highlight"><c- n>bulk</c-></code> that executes each loop iteration
on a distinct execution agent:</p>
   <ol>
    <li data-md>
     <p>For schedulers that promise concurrent forward progress, users need a way to take advantage of concurrent forward
 progress. Since <code class="highlight"><c- n>bulk</c-></code> execution can do chunking, it cannot promise anything stronger than parallel forward progress.</p>
    <li data-md>
     <p>Even for schedulers with a weaker forward progress guarantee, users sometimes have performance reasons
 to control the distribution of loop iterations to execution agents.</p>
   </ol>
   <p>Revisions R2 and R3 originally incorporated this design suggestion from <a data-link-type="biblio" href="#biblio-p3564r0" title="Make the concurrent forward progress guarantee usable in `bulk`">[P3564R0]</a> into this paper and name this API <code class="highlight"><c- n>bulk_unchunked</c-></code>.
After further discussions in Sofia 2025, we realized that these two directions do not overlap well, and that it likely deserve separate APIs for the two design aspects.
We decided that we can have <code class="highlight"><c- n>bulk_unchunked</c-></code> as an algorithm to be used when the user wants to execute each iteration on a distinct execution agent, and a new algorithm <code class="highlight"><c- n>bulk_concurrent</c-></code> that explicitly deals with concurrent forward progress guarantee.</p>
   <p>This paper proposes <code class="highlight"><c- n>bulk_unchunked</c-></code>, but does not propose <code class="highlight"><c- n>bulk_concurrent</c-></code>, leaving this for future work.</p>
   <h3 class="heading settled" data-level="4.3" id="design.policies"><span class="secno">4.3. </span><span class="content">Using execution policies</span><a class="self-link" href="#design.policies"></a></h3>
   <p>As discussed in the <a href="#motivation">§ 2 Motivation</a> section, not having the possibility to specify execution policies for the <code class="highlight"><c- n>bulk</c-></code> algorithm is a downside.
On the one hand, defaulting to any policy other than <code class="highlight"><c- n>seq</c-></code> might lead to deadlocks.
On the other hand, defaulting to <code class="highlight"><c- n>seq</c-></code> would not match users' expectations
that <code class="highlight"><c- n>bulk</c-></code> would take advantage of parallel execution resources.
Thus, <code class="highlight"><c- n>bulk</c-></code> has to have an execution policy parameter.</p>
   <p>One criticism of this solution is that each invocation of <code class="highlight"><c- n>bulk</c-></code> needs to contain an extra parameter that is typically verbose to type.</p>
   <p>The idea considered by the authors to solve it is to provide versions of the algorithms that have the execution policies
already baked in.
Something like:</p>
<pre class="language-cpp highlight"><c- k>auto</c-> <c- n>bulk_seq</c-><c- p>(</c-><c- k>auto</c-> <c- n>prev</c-><c- p>,</c-> <c- k>auto</c-> <c- n>size</c-><c- p>,</c-> <c- k>auto</c-> <c- n>f</c-><c- p>);</c->
<c- k>auto</c-> <c- n>bulk_unseq</c-><c- p>(</c-><c- k>auto</c-> <c- n>prev</c-><c- p>,</c-> <c- k>auto</c-> <c- n>size</c-><c- p>,</c-> <c- k>auto</c-> <c- n>f</c-><c- p>);</c->
<c- k>auto</c-> <c- n>bulk_par</c-><c- p>(</c-><c- k>auto</c-> <c- n>prev</c-><c- p>,</c-> <c- k>auto</c-> <c- n>size</c-><c- p>,</c-> <c- k>auto</c-> <c- n>f</c-><c- p>);</c->
<c- k>auto</c-> <c- n>bulk_par_unseq</c-><c- p>(</c-><c- k>auto</c-> <c- n>prev</c-><c- p>,</c-> <c- k>auto</c-> <c- n>size</c-><c- p>,</c-> <c- k>auto</c-> <c- n>f</c-><c- p>);</c->

<c- k>auto</c-> <c- n>bulk_chunked_seq</c-><c- p>(</c-><c- k>auto</c-> <c- n>prev</c-><c- p>,</c-> <c- k>auto</c-> <c- n>size</c-><c- p>,</c-> <c- k>auto</c-> <c- n>f</c-><c- p>);</c->
<c- k>auto</c-> <c- n>bulk_chunked_unseq</c-><c- p>(</c-><c- k>auto</c-> <c- n>prev</c-><c- p>,</c-> <c- k>auto</c-> <c- n>size</c-><c- p>,</c-> <c- k>auto</c-> <c- n>f</c-><c- p>);</c->
<c- k>auto</c-> <c- n>bulk_chunked_par</c-><c- p>(</c-><c- k>auto</c-> <c- n>prev</c-><c- p>,</c-> <c- k>auto</c-> <c- n>size</c-><c- p>,</c-> <c- k>auto</c-> <c- n>f</c-><c- p>);</c->
<c- k>auto</c-> <c- n>bulk_chunked_par_unseq</c-><c- p>(</c-><c- k>auto</c-> <c- n>prev</c-><c- p>,</c-> <c- k>auto</c-> <c- n>size</c-><c- p>,</c-> <c- k>auto</c-> <c- n>f</c-><c- p>);</c->
</pre>
   <p>We dropped this idea, as this isn’t scalable.</p>
   <p>On the other hand, it’s quite easy to write a thin wrapper on top of <code class="highlight"><c- n>bulk</c-></code> / <code class="highlight"><c- n>bulk_chunked</c-></code> / <code class="highlight"><c- n>bulk_unchunked</c-></code> on the user side that calls the algorithm
with the execution policy of choice.
Something like:</p>
<pre class="language-cpp highlight"><c- k>auto</c-> <c- n>user_bulk_par</c-><c- p>(</c-><c- k>auto</c-> <c- n>prev</c-><c- p>,</c-> <c- k>auto</c-> <c- n>size</c-><c- p>,</c-> <c- k>auto</c-> <c- n>f</c-><c- p>)</c-> <c- p>{</c->
  <c- k>return</c-> <c- n>std</c-><c- o>::</c-><c- n>execution</c-><c- o>::</c-><c- n>bulk</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>execution</c-><c- o>::</c-><c- n>par</c-><c- p>,</c-> <c- n>prev</c-><c- p>,</c-> <c- n>size</c-><c- p>,</c-> <c- n>f</c-><c- p>);</c->
<c- p>}</c->
</pre>
   <h3 class="heading settled" data-level="4.4" id="design.conflict.policies"><span class="secno">4.4. </span><span class="content">Conflicting execution policies</span><a class="self-link" href="#design.conflict.policies"></a></h3>
   <p>For <a data-link-type="biblio" href="#biblio-p2500r2" title="C++ parallel algorithms and P2300">[P2500R2]</a> design we previously agreed that there might be an execution policy attached to a <code class="highlight"><c- n>scheduler</c-></code>. The
question that comes to mind is what should we do if we have execution policy passed via <code class="highlight"><c- n>bulk</c-></code> parameters that conflicts with
execution policy attached to a scheduler?</p>
   <p>This is another area to explore. It’s quite obvious that execution policy passed to <code class="highlight"><c- n>bulk</c-></code> describes possible parallelization
ways of <code class="highlight"><c- n>bulk</c-></code> callable object, while it’s not 100% obvious what execution policy attached to a scheduler means outside of <a data-link-type="biblio" href="#biblio-p2500r2" title="C++ parallel algorithms and P2300">[P2500R2]</a> proposal.</p>
   <p>We might choose different strategies (not all of them are mutually exclusive):</p>
   <ul>
    <li data-md>
     <p>Reconsider the decisions we made for <a data-link-type="biblio" href="#biblio-p2500r2" title="C++ parallel algorithms and P2300">[P2500R2]</a> by stopping attaching policies to schedulers.</p>
    <li data-md>
     <p>Reduce policies: choose the most conservative one. For example, for the passed policy <code class="highlight"><c- n>par</c-></code> and attached policy <code class="highlight"><c- n>seq</c-></code> we
reduce it the resulting policy to <code class="highlight"><c- n>seq</c-></code> because it’s the most conservative one.</p>
     <ul>
      <li data-md>
       <p>For "peer" conflicting policies: <code class="highlight"><c- n>par</c-></code> and <code class="highlight"><c- n>unseq</c-></code> we might either want to reduce it to <code class="highlight"><c- n>seq</c-></code> or might want to give a
compile-time error.</p>
     </ul>
    <li data-md>
     <p>Give a compile-time error right away for any pair of conflicting policies.</p>
   </ul>
   <p>Anyway, exploration of this problem is out of scope of this paper.
For the purpose of this paper, we need to ensure that the way the given function is called is compatible with the execution policy passed to <code class="highlight"><c- n>bulk</c-></code>.</p>
   <h3 class="heading settled" data-level="4.5" id="design.expectations"><span class="secno">4.5. </span><span class="content">Expectations on customizations</span><a class="self-link" href="#design.expectations"></a></h3>
   <p>The current specification of <code class="highlight"><c- n>bulk</c-></code> in <a data-link-type="biblio" href="#biblio-execbulk" title="Working Draft: Programming Languages — C++ -- `execution::bulk`">[exec.bulk]</a> doesn’t define any constraints/expectations for the customization of the algorithm.
The default implementation (a serial version of <code class="highlight"><c- n>bulk</c-></code>) is expected to be very different that its customizations.</p>
   <p>Having customizations in mind, we need to define the minimal expectations for calling <code class="highlight"><c- n>bulk</c-></code>.
We propose the following:</p>
   <ul>
    <li data-md>
     <p>Mandate <code class="highlight"><c- n>f</c-></code> to be copy-constructible.</p>
    <li data-md>
     <p>Allow <code class="highlight"><c- n>f</c-></code> to be invoked according to the specified execution policy (and don’t assume it’s going to be called serially).</p>
    <li data-md>
     <p>Allow the values produced by the previous sender to be decay copied (if the values produced are copyable).</p>
    <li data-md>
     <p>Allow the algorithm to handle cancellation requests, but don’t mandate it.</p>
   </ul>
   <p>We want to require that the given functor be copy-constructible so that <code class="highlight"><c- n>bulk</c-></code> requires the same type of function as a <code class="highlight"><c- n>for_each</c-></code> with an execution policy.
Adding an execution policy to <code class="highlight"><c- n>bulk</c-></code>/<code class="highlight"><c- n>bulk_chunked</c-></code> would also align them with <code class="highlight"><c- n>for_each</c-></code>.</p>
   <p>If <code class="highlight"><c- n>f</c-></code> is allowed to be invoked concurrently, then implementations may want to copy the arguments passed to it.</p>
   <p>Another important point for a <code class="highlight"><c- n>bulk</c-></code> operation is how it should react to cancellation requests.
We want to specify that <code class="highlight"><c- n>bulk</c-></code> should be able to react to cancellation requests, but not make this mandatory.
It shall be also possible for vendors to completely ignore cancellation requests (if, for example, supporting cancellation would actually slow down the main uses-cases that the vendor is optimizing for).
Also, the way cancellation is implemented should be left unspecified.</p>
   <p>Checking the cancellation token every iteration may be expensive for certain cases.
A cancellation check requires an acquire memory barrier (which may be too much for really small functors), and might prevent vectorization.
Thus, implementations may want to check the cancellation every <em>N</em> iterations; <em>N</em> can be a statically known number, or can be dynamically determined.</p>
   <p>As <code class="highlight"><c- n>bulk</c-></code>, <code class="highlight"><c- n>bulk_chunked</c-></code>, and <code class="highlight"><c- n>bulk_unchunked</c-></code> are customization points, we need to specify these constraints to all three of them.</p>
   <h3 class="heading settled" data-level="4.6" id="design.exceptions"><span class="secno">4.6. </span><span class="content">Exception handling</span><a class="self-link" href="#design.exceptions"></a></h3>
   <p>While there are multiple solutions to specify which errors can be thrown by <code class="highlight"><c- n>bulk</c-></code>, the most sensible ones seem to be:</p>
   <ol>
    <li data-md>
     <p>pick an arbitrary exception thrown by one of the invocations of <code class="highlight"><c- n>f</c-></code> (maybe using a atomic operations to select the first thrown exception),</p>
    <li data-md>
     <p>reduce the exceptions to another exception that can carry one or more of the thrown exceptions using a user-defined reduction operation (similar to using <code class="highlight"><c- n>exception_list</c-></code> as discussed by <a data-link-type="biblio" href="#biblio-p0333r0" title="Improving Parallel Algorithm Exception Handling">[P0333R0]</a>),</p>
    <li data-md>
     <p>allow implementations to produce a new exception type (e.g., to represent failures outside of <code class="highlight"><c- n>f</c-></code>, or to represent failure to transmit the original exception to the receiver)</p>
   </ol>
   <p>One should note that option 2 can be seen as a particular case of option 3.</p>
   <p>Also, option 2 seems to be more complex than option 1, without providing any palpable benefits to the users.</p>
   <p>The third option is very useful when implementations may fail outside of the calls to the given functor.
Also, there may be cases in which exceptions cannot be transported from the place they were thrown to the place they need to be reported.</p>
   <p>Based on the experience with the existing parallel frameworks we incline to recommend the option one because</p>
   <ul>
    <li data-md>
     <p>In a parallel execution the common behavior is non-deterministic by nature.
Thus, we can peak arbitrary exception to throw</p>
    <li data-md>
     <p>Catching any exception already indicates that something went wrong, thus a good implementation might initiate a cancellation mechanism to finish already failed work as soon as possible.</p>
   </ul>
   <p>On top of that, for special cases we also want to allow option 3.</p>
   <h2 class="heading settled" data-level="5" id="specification"><span class="secno">5. </span><span class="content">Specification</span><a class="self-link" href="#specification"></a></h2>
   <h3 class="heading settled" data-level="5.1" id="specification.syn"><span class="secno">5.1. </span><span class="content">In [execution.syn]</span><a class="self-link" href="#specification.syn"></a></h3>
<pre class="highlight"><c- k>struct</c-> <c- nc>let_value_t</c-> <c- p>{</c-> <c- n>unspecified</c-> <c- p>};</c->
<c- k>struct</c-> <c- nc>let_error_t</c-> <c- p>{</c-> <c- n>unspecified</c-> <c- p>};</c->
<c- k>struct</c-> <c- nc>let_stopped_t</c-> <c- p>{</c-> <c- n>unspecified</c-> <c- p>};</c->
<c- k>struct</c-> <c- nc>bulk_t</c-> <c- p>{</c-> <c- n>unspecified</c-> <c- p>};</c->
</pre>
   <div class="block-insert">
<pre class="highlight"><c- k>struct</c-> <c- nc>bulk_chunked_t</c-> <c- p>{</c-> <c- n>unspecified</c-> <c- p>};</c->
<c- k>struct</c-> <c- nc>bulk_unchunked_t</c-> <c- p>{</c-> <c- n>unspecified</c-> <c- p>};</c->
</pre>
   </div>
    [...] 
<pre class="highlight"><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->
</pre>
   <div class="block-insert">
<pre class="highlight"><c- kr>inline</c-> <c- k>constexpr</c-> <c- n>bulk_chunked_t</c-> <c- n>bulk_chunked</c-><c- p>{};</c->
<c- kr>inline</c-> <c- k>constexpr</c-> <c- n>bulk_unchunked_t</c-> <c- n>bulk_unchunked</c-><c- p>{};</c->
</pre>
   </div>
   <h3 class="heading settled" data-level="5.2" id="specification.bulk"><span class="secno">5.2. </span><span class="content">In [exec.bulk]</span><a class="self-link" href="#specification.bulk"></a></h3>
   <p><span class="ed-note">Rename the title of the section from “execution::bulk” to “execution::bulk, execution::bulk_chunked, and execution::bulk_unchunked”.</span></p>
   <p><span class="ed-note">Apply the following changes (no track changes for paragraph numbering):</span></p>
   <ol>
    <li data-md>
     <p>
      <code class="highlight"><c- n>bulk</c-></code>
      <ins>, <code class="highlight"><c- n>bulk_chunked</c-></code>, and <code class="highlight"><c- n>bulk_unchunked</c-></code></ins>
       run
      <del>s</del>
       a task repeatedly for every index in an index space.
     </p>
    <li data-md>
     <p>
      The 
      <del>name</del>
      <ins>names</ins>
       <code class="highlight"><c- n>bulk</c-></code>
      <ins>, <code class="highlight"><c- n>bulk_chunked</c-></code>, and <code class="highlight"><c- n>bulk_unchunked</c-></code></ins>
      <del>denotes a</del>
      <ins>denote</ins>
       pipeable sender adaptor 
      <del>object</del>
      <ins>objects</ins>
      .
      <ins> Let <i><code class="highlight"><c- n>bulk</c-><c- o>-</c-><c- n>algo</c-></code></i> be either <code class="highlight"><c- n>bulk</c-></code>, <code class="highlight"><c- n>bulk_chunked</c-></code>, or <code class="highlight"><c- n>bulk_unchunked</c-></code>.</ins>
       For subexpressions <code class="highlight"><c- n>sndr</c-></code>, 
      <ins><code class="highlight"><c- n>policy</c-></code>,</ins>
       <code class="highlight"><c- n>shape</c-></code>, and <code class="highlight"><c- n>f</c-></code>, let 
      <ins><code class="highlight"><c- n>Policy</c-></code> be <code class="highlight"><c- n>remove_cvref_t</c-><c- o>&lt;</c-><c- k>decltype</c-><c- p>(</c-><c- n>policy</c-><c- p>)</c-><c- o>></c-></code>,</ins>
       <code class="highlight"><c- n>Shape</c-></code> be <code class="highlight"><c- k>decltype</c-><c- p>(</c-><c- k>auto</c-><c- p>(</c-><c- n>shape</c-><c- p>))</c-></code> 
      <ins>, and <code class="highlight"><c- n>Func</c-></code> be <code class="highlight"><c- n>decay_t</c-><c- o>&lt;</c-><c- k>decltype</c-><c- p>((</c-><c- n>f</c-><c- p>))</c-><c- o>></c-></code></ins>
      .
If
     </p>
     <ul>
      <li data-md>
       <p><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>, or</p>
      <li data-md>
       <ins><code class="highlight"><c- n>is_execution_policy_v</c-><c- o>&lt;</c-><c- n>Policy</c-><c- o>></c-></code> is <code class="highlight">false</code>, or</ins>
      <li data-md>
       <p><code class="highlight"><c- n>Shape</c-></code> does not satisfy <code class="highlight"><c- n>integral</c-></code>, or</p>
      <li data-md>
       <del><code class="highlight"><c- k>decltype</c-><c- p>((</c-><c- n>f</c-><c- p>))</c-></code></del>
       <ins><code class="highlight"><c- n>Func</c-></code></ins>
        does not 
       <del>satisfy <i><code class="highlight"><c- n>movable</c-><c- o>-</c-><c- n>value</c-></code></i></del>
       <ins>model <code class="highlight"><c- n>copy_constructible</c-></code></ins>
       , 
     </ul>
     <del>bulk(sndr, shape, f)</del>
     <ins><i><code class="highlight"><c- n>bulk</c-><c- o>-</c-><c- n>algo</c-></code></i><code class="highlight"><c- p>(</c-><c- n>sndr</c-><c- p>,</c-> <c- n>policy</c-><c- p>,</c-> <c- n>shape</c-><c- p>,</c-> <c- n>f</c-><c- p>)</c-></code></ins>
      is ill-formed. 
    <li data-md>
     <p>
      Otherwise, the expression 
      <del><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></del>
      <ins><i><code class="highlight"><c- n>bulk</c-><c- o>-</c-><c- n>algo</c-></code></i><code class="highlight"><c- p>(</c-><c- n>sndr</c-><c- p>,</c-> <c- n>policy</c-><c- p>,</c-> <c- n>shape</c-><c- p>,</c-> <c- n>f</c-><c- p>)</c-></code></ins>
       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-><del><c- n>bulk</c-></del><ins><i><c- n>bulk</c-><c- o>-</c-><c- n>algo</c-></i></ins><c- p>,</c-> <i><c- n>product</c-><c- o>-</c-><c- n>type</c-></i><ins><c- o>&lt;</c-><i><c- n>see</c-> <c- n>below</c-></i><c- p>,</c-> <c- n>Shape</c-><c- p>,</c-> <c- n>Func</c-><c- o>></c-></ins><c- p>{</c-><ins><c- n>policy</c-><c- p>,</c-> </ins><c- n>shape</c-><c- p>,</c-> <c- n>f</c-><c- p>},</c-> <c- n>sndr</c-><c- p>))</c->
</pre>
     <p>except that <code class="highlight"><c- n>sndr</c-></code> is evaluated only once.</p>
     <div class="block-insert"> 3.1. The first template argument of <i><code class="highlight"><c- n>product</c-><c- o>-</c-><c- n>type</c-></code></i> is <code class="highlight"><c- n>Policy</c-></code> if <code class="highlight"><c- n>Policy</c-></code> models <code class="highlight"><c- n>copy_constructible</c-></code>, and <code class="highlight"><c- k>const</c-> <c- n>Policy</c-><c- o>&amp;</c-></code> otherwise. </div>
   </ol>
   <div class="block-insert">
    <ol start="4">
     <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 <i><code class="highlight"><c- n>sender</c-><c- o>-</c-><c- k>for</c-></code></i><code class="highlight"><c- o>&lt;</c-><c- n>Sndr</c-><c- p>,</c-> <c- n>bulk_t</c-><c- o>></c-></code> is <code class="highlight">false</code>, then the expression <code class="highlight"><c- n>bulk</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 equivalent to:</p>
<pre class="highlight"><c- k>auto</c-> <c- p>[</c-><c- n>_</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>&amp;</c-> <c- p>[</c-><c- n>policy</c-><c- p>,</c-> <c- n>shape</c-><c- p>,</c-> <c- n>f</c-><c- p>]</c-> <c- o>=</c-> <c- n>data</c-><c- p>;</c->
<c- k>auto</c-> <c- n>new_f</c-> <c- o>=</c-> <c- p>[</c-><c- n>func</c-><c- o>=</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>f</c-><c- p>)](</c-><c- n>Shape</c-> <c- n>begin</c-><c- p>,</c-> <c- n>Shape</c-> <c- n>end</c-><c- p>,</c-> <c- k>auto</c-><c- o>&amp;&amp;</c-><c- p>...</c-> <c- n>vs</c-><c- p>)</c->
    <c- k>noexcept</c-><c- p>(</c-><c- k>noexcept</c-><c- p>(</c-><c- n>f</c-><c- p>(</c-><c- n>begin</c-><c- p>,</c-> <c- n>vs</c-><c- p>...)))</c-> <c- p>{</c->
  <c- k>while</c-> <c- p>(</c-><c- n>begin</c-> <c- o>!=</c-> <c- n>end</c-><c- p>)</c-> <c- n>func</c-><c- p>(</c-><c- n>begin</c-><c- o>++</c-><c- p>,</c-> <c- n>vs</c-><c- p>...);</c->
<c- p>}</c->
<c- k>return</c-> <c- n>bulk_chunked</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- n>policy</c-><c- p>,</c-> <c- n>shape</c-><c- p>,</c-> <c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>new_f</c-><c- p>));</c->
</pre>
      <p><i>[Note ?</i>: This causes the <code class="highlight"><c- n>bulk</c-><c- p>(</c-><c- n>sndr</c-><c- p>,</c-> <c- n>policy</c-><c- p>,</c-> <c- n>shape</c-><c- p>,</c-> <c- n>f</c-><c- p>)</c-></code> sender to be expressed in terms of <code class="highlight"><c- n>bulk_chunked</c-><c- p>(</c-><c- n>sndr</c-><c- p>,</c-> <c- n>policy</c-><c- p>,</c-> <c- n>shape</c-><c- p>,</c-> <c- n>f</c-><c- p>)</c-></code> when it is connected to a receiver whose execution domain does not customize <code class="highlight"><c- n>bulk</c-></code>. <i> — end note]</i></p>
    </ol>
   </div>
   <div class="block-insert">
    <ol start="5">
     <li data-md>
      <p>The exposition-only class template <code class="highlight"><c- n>impls</c-><c- o>-</c-><c- k>for</c-></code> ([exec.snd.general]) is specialized for <code class="highlight"><c- n>bulk_chunked_t</c-></code> as follows:</p>
<pre class="highlight"><c- k>namespace</c-> <c- nn>std</c-><c- o>::</c-><c- nn>execution</c-> <c- p>{</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>bulk_chunked_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>complete</c-></i> <c- o>=</c-> <i><c- n>see</c-> <c- n>below</c-></i><c- p>;</c->
  <c- p>};</c->
<c- p>}</c->
</pre>
      <p>5.1. 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_chunked_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>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>policy</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- 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>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>f</c-><c- p>(</c-><c- k>static_cast</c-><c- o>&lt;</c-><c- k>decltype</c-><c- p>(</c-><c- k>auto</c-><c- p>(</c-><c- n>shape</c-><c- p>))</c-><c- o>></c-><c- p>(</c-><c- mi>0</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->
        <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>
      <p>5.1.1. 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- 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>
   </div>
   <ol start="6">
    <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 
      <del><code class="highlight"><c- n>bulk_t</c-></code></del>
      <ins><code class="highlight"><c- n>bulk_unchunked_t</c-></code></ins>
       as follows:
     </p>
<pre class="highlight"><c- k>namespace</c-> <c- nn>std</c-><c- o>::</c-><c- nn>execution</c-> <c- p>{</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-><del><c- n>bulk_t</c-></del><ins><c- n>bulk_unchunked_t</c-></ins><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>complete</c-></i> <c- o>=</c-> <i><c- n>see</c-> <c- n>below</c-></i><c- p>;</c->
  <c- p>};</c->
<c- p>}</c->
</pre>
     <p>6.1. The member <code class="highlight"><i><c- n>impls</c-><c- o>-</c-><c- k>for</c-></i><c- o>&lt;</c-><del><c- n>bulk_t</c-></del><ins><c- n>bulk_unchunked_t</c-></ins><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>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>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>decltype</c-><c- p>(</c-><c- k>auto</c-><c- p>(</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>shape</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>
     <p>6.1.1. 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>
    <li data-md>
     <p>
      Let the subexpression <code class="highlight"><c- n>out_sndr</c-></code> denote the result of the invocation 
      <del><code class="highlight"><c- n>bulk</c-></code></del>
      <ins><i><code class="highlight"><c- n>bulk</c-><c- o>-</c-><c- n>algo</c-></code></i></ins>
      <code class="highlight"><c- p>(</c-><c- n>sndr</c-><c- p>,</c-> </code>
      <ins><code class="highlight"><c- n>policy</c-><c- p>,</c-></code></ins>
      <code class="highlight"> <c- n>shape</c-><c- p>,</c-> <c- n>f</c-><c- p>)</c-></code> or an object equal to 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>
       <del>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</del>
      <li data-md>
       <del>
        propagates all completion operations sent by <code class="highlight"><c- n>sndr</c-></code>.
        <del></del>
       </del>
     </ul>
     <ins>
      <ul>
       <li data-md>
        <p>If <code class="highlight"><c- n>sndr</c-></code> has a successful completion, where <code class="highlight"><c- n>args</c-></code> is a pack of lvalue subexpressions referring to the value completion result datums of <code class="highlight"><c- n>sndr</c-></code>, or decayed copies of those values if they model <code class="highlight"><c- n>copy_constructible</c-></code>, then:</p>
        <ul>
         <li data-md>
          <p>If <code class="highlight"><c- n>out_sndr</c-></code> also completes successfully, then:</p>
          <ul>
           <li data-md>
            <p>for <code class="highlight"><c- n>bulk</c-></code>, 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>;</p>
           <li data-md>
            <p>for <code class="highlight"><c- n>bulk_unchunked</c-></code>, 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>;</p>
            <ul>
             <li data-md>
              <p><i>Recommended practice: </i> The underlying scheduler should execute each iteration on a distinct execution agent.</p>
            </ul>
           <li data-md>
            <p>for <code class="highlight"><c- n>bulk_chunked</c-></code>, invokes <code class="highlight"><c- n>f</c-><c- p>(</c-><c- n>b</c-><c- p>,</c-> <c- n>e</c-><c- p>,</c-> <c- n>args</c-><c- p>...)</c-></code> zero or more times with pairs of <code class="highlight"><c- n>b</c-></code> and <code class="highlight"><c- n>e</c-></code> of type <code class="highlight"><c- n>Shape</c-></code> in range <code class="highlight"><c- p>[</c-><c- mi>0</c-><c- p>,</c-> <c- n>shape</c-><c- p>]</c-></code>, such that <code class="highlight"><c- n>b</c-> <c- o>&lt;</c-> <c- n>e</c-></code> and 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>, there is exactly one invocation with a pair <code class="highlight"><c- n>b</c-></code> and <code class="highlight"><c- n>e</c-></code>, such that <code class="highlight"><c- n>i</c-></code> is in the range <code class="highlight"><c- p>[</c-><c- n>b</c-><c- p>,</c-> <c- n>e</c-><c- p>)</c-></code>.</p>
          </ul>
         <li data-md>
          <p>If <code class="highlight"><c- n>out_sndr</c-></code> completes with <code class="highlight"><c- n>set_error</c-><c- p>(</c-><c- n>rcvr</c-><c- p>,</c-> <c- n>eptr</c-><c- p>)</c-></code>, then the asynchronous operation may invoke a subset of the invocations of <code class="highlight"><c- n>f</c-></code> before the error completion handler is called, and <code class="highlight"><c- n>eptr</c-></code> is an <code class="highlight"><c- n>exception_ptr</c-></code> containing  either:</p>
          <ul>
           <li data-md>
            <p>an exception thrown by an invocation of <code class="highlight"><c- n>f</c-></code>, or</p>
           <li data-md>
            <p>a <code class="highlight"><c- n>bad_alloc</c-></code> exception if the implementation fails to allocate required resources, or</p>
           <li data-md>
            <p>an exception derived from <code class="highlight"><c- n>runtime_error</c-></code>.</p>
          </ul>
         <li data-md>
          <p>If <code class="highlight"><c- n>out_sndr</c-></code> completes with <code class="highlight"><c- n>set_stopped</c-><c- p>(</c-><c- n>rcvr</c-><c- p>)</c-></code>, then the asynchronous operation may invoke a subset of the invocations of <code class="highlight"><c- n>f</c-></code> before the stopped completion handler.</p>
        </ul>
       <li data-md>
        <p>If <code class="highlight"><c- n>sndr</c-></code> does not complete with <code class="highlight"><c- n>set_value</c-></code>, then the completion is forwarded to <code class="highlight"><c- n>recv</c-></code>.</p>
       <li data-md>
        <p>For <i><code class="highlight"><c- n>bulk</c-><c- o>-</c-><c- n>algo</c-></code></i>, the parameter <code class="highlight"><c- n>policy</c-></code> describes the manner in which the execution of the asynchronous operations corresponding to these algorithms may be parallelized and the manner in which they apply <code class="highlight"><c- n>f</c-></code>. Permissions and requirements on parallel algorithm element access functions ([algorithms.parallel.exec]) apply to <code class="highlight"><c- n>f</c-></code>.</p>
      </ul>
     </ins>
   </ol>
   <div class="block-insert">
    <ol start="8">
     <li data-md>
      <p><i>[Note: </i> The asynchronous operation corresponding to <i><code class="highlight"><c- n>bulk</c-><c- o>-</c-><c- n>algo</c-></code></i><code class="highlight"><c- p>(</c-><c- n>sndr</c-><c- p>,</c-> <c- n>policy</c-><c- p>,</c-> <c- n>shape</c-><c- p>,</c-> <c- n>f</c-><c- p>)</c-></code> can complete with <code class="highlight"><c- n>set_stopped</c-></code> if cancellation is requested or ignore cancellation requests. <i> — end note]</i></p>
    </ol>
   </div>
   <h2 class="heading settled" data-level="6" id="acknowledgements"><span class="secno">6. </span><span class="content">Acknowledgements</span><a class="self-link" href="#acknowledgements"></a></h2>
   <p>Special thanks to Christian Trott and Tom Scogland for a very productive discussion on <code class="highlight"><c- n>bulk_unchunked</c-></code> and help on working improvements.</p>
   <h2 class="heading settled" data-level="7" id="polls"><span class="secno">7. </span><span class="content">Polls</span><a class="self-link" href="#polls"></a></h2>
   <h3 class="heading settled" data-level="7.1" id="sg1.austria.2025"><span class="secno">7.1. </span><span class="content">SG1, Hagenberg, Austria, 2025</span><a class="self-link" href="#sg1.austria.2025"></a></h3>
   <p>Summary: Forward P3481R1 with the following notes:</p>
   <ul>
    <li data-md>
     <p><code class="highlight"><c- n>bulk_unchunked</c-></code> should not have an execution policy</p>
    <li data-md>
     <p>Calling an un-customized <code class="highlight"><c- n>bulk_unchunked</c-></code> is ill-formed on a concurrent scheduler</p>
    <li data-md>
     <p>The next revision of this paper (before LWG) needs wording for its error model</p>
   </ul>
<pre class="highlight"><c- o>|</c-> <c- n>SF</c-> <c- o>|</c-> <c- n>F</c-> <c- o>|</c-> <c- n>N</c-> <c- o>|</c-> <c- n>A</c-> <c- o>|</c-> <c- n>SA</c-> <c- o>|</c->
<c- o>|</c-> <c- mi>8</c->  <c- o>|</c-> <c- mi>2</c-> <c- o>|</c-> <c- mi>2</c-> <c- o>|</c-> <c- mi>0</c-> <c- o>|</c-> <c- mi>0</c->  <c- o>|</c->
</pre>
   <p>Consensus</p>
   <h3 class="heading settled" data-level="7.2" id="sg1.poland.2024"><span class="secno">7.2. </span><span class="content">SG1, Wrocław, Poland, 2024</span><a class="self-link" href="#sg1.poland.2024"></a></h3>
   <p><a data-link-type="biblio" href="#biblio-p3481r0" title="Summarizing std::execution::bulk() issues">[P3481R0]</a> was presented at the SG1 meeting in November 2024 in Wrocław, Poland.
SG1 provided the following feedback in the form of polls:</p>
   <ol>
    <li data-md>
     <p>If we have chunking, we need to expose a control on the chunk size.</p>
<pre class="highlight"><c- o>|</c-> <c- n>SF</c-> <c- o>|</c-> <c- n>F</c-> <c- o>|</c-> <c- n>N</c-> <c- o>|</c-> <c- n>A</c-> <c- o>|</c-> <c- n>SA</c-> <c- o>|</c->
<c- o>|</c-> <c- mi>1</c->  <c- o>|</c-> <c- mi>2</c-> <c- o>|</c-> <c- mi>3</c-> <c- o>|</c-> <c- mi>1</c-> <c- o>|</c-> <c- mi>1</c->  <c- o>|</c->
</pre>
     <p>No consensus</p>
    <li data-md>
     <p>We need a version of the <code class="highlight"><c- n>bulk</c-></code> API that presents the chunk to the callable in order to implement the parallel algorithms</p>
<pre class="highlight"><c- o>|</c-> <c- n>SF</c-> <c- o>|</c-> <c- n>F</c-> <c- o>|</c-> <c- n>N</c-> <c- o>|</c-> <c- n>A</c-> <c- o>|</c-> <c- n>SA</c-> <c- o>|</c->
<c- o>|</c-> <c- mi>4</c->  <c- o>|</c-> <c- mi>2</c-> <c- o>|</c-> <c- mi>1</c-> <c- o>|</c-> <c- mi>0</c-> <c- o>|</c-> <c- mi>1</c->  <c- o>|</c->
</pre>
     <p>Consensus in favor</p>
    <li data-md>
     <p>We need a version of the bulk API that creates an execution agent per iteration.</p>
<pre class="highlight"><c- o>|</c-> <c- n>SF</c-> <c- o>|</c-> <c- n>F</c-> <c- o>|</c-> <c- n>N</c-> <c- o>|</c-> <c- n>A</c-> <c- o>|</c-> <c- n>SA</c-> <c- o>|</c->
<c- o>|</c-> <c- mi>2</c->  <c- o>|</c-> <c- mi>3</c-> <c- o>|</c-> <c- mi>3</c-> <c- o>|</c-> <c- mi>0</c-> <c- o>|</c-> <c- mi>0</c->  <c- o>|</c->
</pre>
     <p>Unanimous consent</p>
    <li data-md>
     <p>We believe / desire:</p>
     <ol>
      <li data-md>
       <p>Bulk needs an execution policy to describe the callable, IF the scheduler also has an execution
policy (for debugging for example) then a conservative choice should be used (<code class="highlight"><c- n>seq</c-></code> is more
conservative than <code class="highlight"><c- n>par</c-></code>)</p>
      <li data-md>
       <p>No SG1 concerns with the proposed exception handling</p>
      <li data-md>
       <p>No change to status quo on default implementation of bulk being serial</p>
      <li data-md>
       <p>No change to status quo on bulk having a predecessor</p>
      <li data-md>
       <p>Forms of bulk needed:</p>
       <ul>
        <li data-md>
         <p><code class="highlight"><c- n>bulk</c-></code> -> <code class="highlight"><c- n>f</c-><c- p>(</c-><c- n>i</c-><c- p>)</c-></code> -> <code class="highlight"><c- n>bulk_chunked</c-></code></p>
        <li data-md>
         <p><code class="highlight"><c- n>bulk_chunked</c-></code> -> <code class="highlight"><c- n>f</c-><c- p>(</c-><c- n>b</c-><c- p>,</c-> <c- n>e</c-><c- p>)</c-></code></p>
        <li data-md>
         <p><code class="highlight"><c- n>bulk_unchunked</c-></code> -> <code class="highlight"><c- n>f</c-><c- p>(</c-><c- n>i</c-><c- p>)</c-></code> "execution agent per iteration"</p>
       </ul>
     </ol>
<pre class="highlight"><c- o>|</c-> <c- n>SF</c-> <c- o>|</c-> <c- n>F</c-> <c- o>|</c-> <c- n>N</c-> <c- o>|</c-> <c- n>A</c-> <c- o>|</c-> <c- n>SA</c-> <c- o>|</c->
<c- o>|</c-> <c- mi>5</c->  <c- o>|</c-> <c- mi>2</c-> <c- o>|</c-> <c- mi>1</c-> <c- o>|</c-> <c- mi>0</c-> <c- o>|</c-> <c- mi>0</c->  <c- o>|</c->
</pre>
     <p>Unanimous consent</p>
   </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="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-algforeach">[ALG.FOREACH]
   <dd>ISO WG21. <a href="https://eel.is/c++draft/alg.foreach"><cite>Working Draft: Programming Languages — C++ -- For each</cite></a>. URL: <a href="https://eel.is/c++draft/alg.foreach">https://eel.is/c++draft/alg.foreach</a>
   <dt id="biblio-execbulk">[EXEC.BULK]
   <dd>ISO WG21. <a href="https://eel.is/c++draft/exec.bulk"><cite>Working Draft: Programming Languages — C++ -- `execution::bulk`</cite></a>. URL: <a href="https://eel.is/c++draft/exec.bulk">https://eel.is/c++draft/exec.bulk</a>
   <dt id="biblio-p0333r0">[P0333R0]
   <dd>Bryce Lelbach. <a href="https://wg21.link/p0333r0"><cite>Improving Parallel Algorithm Exception Handling</cite></a>. 15 May 2016. URL: <a href="https://wg21.link/p0333r0">https://wg21.link/p0333r0</a>
   <dt id="biblio-p2300r10">[P2300R10]
   <dd>Eric Niebler, Michał Dominiak, Georgy Evtushenko, Lewis Baker, Lucian Radu Teodorescu, Lee Howes, Kirk Shoop, Michael Garland, Bryce Adelstein Lelbach. <a href="https://wg21.link/p2300r10"><cite>`std::execution`</cite></a>. 28 June 2024. URL: <a href="https://wg21.link/p2300r10">https://wg21.link/p2300r10</a>
   <dt id="biblio-p2500r2">[P2500R2]
   <dd>Ruslan Arutyunyan, Alexey Kukanov. <a href="https://wg21.link/p2500r2"><cite>C++ parallel algorithms and P2300</cite></a>. 15 October 2023. URL: <a href="https://wg21.link/p2500r2">https://wg21.link/p2500r2</a>
   <dt id="biblio-p3481r0">[P3481R0]
   <dd>Lucian Radu Teodorescu, Lewis Baker, Ruslan Arutyunyan. <a href="https://wg21.link/p3481r0"><cite>Summarizing std::execution::bulk() issues</cite></a>. 16 October 2024. URL: <a href="https://wg21.link/p3481r0">https://wg21.link/p3481r0</a>
   <dt id="biblio-p3564r0">[P3564R0]
   <dd>Mark Hoemmen, Bryce Adelstein Lelbach,Michael Garland. <a href="https://wg21.link/p3564r0"><cite>Make the concurrent forward progress guarantee usable in `bulk`</cite></a>. 13 January 2025. URL: <a href="https://wg21.link/p3564r0">https://wg21.link/p3564r0</a>
   <dt id="biblio-parallel_for">[PARALLEL_FOR]
   <dd>Intel. <a href="https://www.intel.com/content/www/us/en/docs/onetbb/developer-guide-api-reference/2021-6/parallel-for.html"><cite>Intel® oneAPI Threading Building Blocks Developer Guide and API Reference -- parallel_for</cite></a>. URL: <a href="https://www.intel.com/content/www/us/en/docs/onetbb/developer-guide-api-reference/2021-6/parallel-for.html">https://www.intel.com/content/www/us/en/docs/onetbb/developer-guide-api-reference/2021-6/parallel-for.html</a>
  </dl>