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

/* color variables included separately for reliability */

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

	html {
	}

	body {
		counter-reset: example figure issue;

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

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

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


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

	p {
		margin: 1em 0;
	}

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

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

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

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

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

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

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

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

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


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

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

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

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

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

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

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

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

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

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

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

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

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

	/* Do something nice. */

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

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

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

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

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

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

	img {
		border-style: none;
	}

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

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

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

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

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

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

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


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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


/*
Alternate table alignment rules

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

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

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

Possible extra rowspan handling

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

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

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


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

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

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

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

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

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

		.toc li {
			clear: both;
		}

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

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

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


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

	/* Index Lists: Layout */
	ul.index	  { margin-left: 0; columns: 15em; text-indent: 1em hanging; }
	ul.index li	{ margin-left: 0; list-style: none; break-inside: avoid; }
	ul.index li li { margin-left: 1em; }
	ul.index dl	{ margin-top: 0; }
	ul.index dt	{ margin: .2em 0 .2em 20px;}
	ul.index dd	{ margin: .2em 0 .2em 40px;}
	/* Index Lists: Typography */
	ul.index ul,
	ul.index dl { font-size: smaller; }
	@media not print {
		ul.index li span:not(.dfn-paneled) {
			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 type="text/css">
    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 4f053d00e, updated Tue Aug 10 14:13:32 2021 -0700" name="generator">
  <link href="https://wg21.link/p2408r1" rel="canonical">
  <link href="https://isocpp.org/favicon.ico" rel="icon">
<style>
.ins, ins, ins *, span.ins, span.ins * {
  background-color: rgb(200, 250, 200);
  color: rgb(0, 136, 0);
  text-decoration: underline;
}
.del, del, del *, span.del, span.del * {
  background-color: rgb(250, 200, 200);
  color: rgb(255, 0, 0);
  text-decoration: line-through;
  text-decoration-color: rgb(255, 0, 0);
}
ul {
  list-style-type: "- ";
}
blockquote {
  counter-reset: paragraph;
}
div.numbered, div.newnumbered {
  margin-left: 2em;
  margin-top: 1em;
  margin-bottom: 1em;
}
div.numbered:before, div.newnumbered:before {
  position: absolute;
  margin-left: -2em;
  display-style: block;
}
div.numbered:before {
  content: counter(paragraph);
  counter-increment: paragraph;
}
div.newnumbered:before {
  content: "�";
}
div.numbered ul, div.newnumbered ul {
  counter-reset: list_item;
}
div.numbered li, div.newnumbered li {
  margin-left: 3em;
}
div.numbered li:before, div.newnumbered li:before {
  position: absolute;
  margin-left: -4.8em;
  display-style: block;
}
div.numbered li:before {
  content: "(" counter(paragraph) "." counter(list_item) ")";
  counter-increment: list_item;
}
div.newnumbered li:before {
  content: "(�." counter(list_item) ")";
  counter-increment: list_item;
}
</style>
<style>/* style-autolinks */

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

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

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

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

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

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

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

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

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

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

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

    --heading-text: #005a9c;

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

    --algo-border: #def;

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

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

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

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

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

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

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

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

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

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

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

    --datacell-border: silver;

    --indexinfo-text: #707070;

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

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

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

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

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

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

            #hidedel:checked ~ del, #hidedel:checked ~ * del { display:none; }
            #hidedel ~ #hidedel-label::before, #hidedel ~ * #hidedel-label::before { content: "☐ "; }
            #hidedel:checked ~ #hidedel-label::before, #hidedel:checked ~ * #hidedel-label::before { content: "☑ "; }
        </style>
<style>/* style-md-lists */

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

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

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

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

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

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

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

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

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

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

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

        --heading-text: #8af;

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

        --algo-border: #456;

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

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

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

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

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

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

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

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

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

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

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

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

        --datacell-border: silver;

        --indexinfo-text: #aaa;

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

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

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

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

    c-[a] { color: #d33682 } /* Keyword.Declaration */
    c-[b] { color: #d33682 } /* Keyword.Type */
    c-[c] { color: #2aa198 } /* Comment */
    c-[d] { color: #2aa198 } /* Comment.Multiline */
    c-[e] { color: #268bd2 } /* Name.Attribute */
    c-[f] { color: #b58900 } /* Name.Tag */
    c-[g] { color: #cb4b16 } /* Name.Variable */
    c-[k] { color: #d33682 } /* Keyword */
    c-[l] { color: #657b83 } /* Literal */
    c-[m] { color: #657b83 } /* Literal.Number */
    c-[n] { color: #268bd2 } /* Name */
    c-[o] { color: #657b83 } /* Operator */
    c-[p] { color: #657b83 } /* Punctuation */
    c-[s] { color: #6c71c4 } /* Literal.String */
    c-[t] { color: #6c71c4 } /* Literal.String.Single */
    c-[u] { color: #6c71c4 } /* Literal.String.Double */
    c-[ch] { color: #2aa198 } /* Comment.Hashbang */
    c-[cp] { color: #2aa198 } /* Comment.Preproc */
    c-[cpf] { color: #2aa198 } /* Comment.PreprocFile */
    c-[c1] { color: #2aa198 } /* Comment.Single */
    c-[cs] { color: #2aa198 } /* Comment.Special */
    c-[kc] { color: #d33682 } /* Keyword.Constant */
    c-[kn] { color: #d33682 } /* Keyword.Namespace */
    c-[kp] { color: #d33682 } /* Keyword.Pseudo */
    c-[kr] { color: #d33682 } /* Keyword.Reserved */
    c-[ld] { color: #657b83 } /* Literal.Date */
    c-[nc] { color: #268bd2 } /* Name.Class */
    c-[no] { color: #268bd2 } /* Name.Constant */
    c-[nd] { color: #268bd2 } /* Name.Decorator */
    c-[ni] { color: #268bd2 } /* Name.Entity */
    c-[ne] { color: #268bd2 } /* Name.Exception */
    c-[nf] { color: #268bd2 } /* Name.Function */
    c-[nl] { color: #268bd2 } /* Name.Label */
    c-[nn] { color: #268bd2 } /* Name.Namespace */
    c-[py] { color: #268bd2 } /* Name.Property */
    c-[ow] { color: #657b83 } /* Operator.Word */
    c-[mb] { color: #657b83 } /* Literal.Number.Bin */
    c-[mf] { color: #657b83 } /* Literal.Number.Float */
    c-[mh] { color: #657b83 } /* Literal.Number.Hex */
    c-[mi] { color: #657b83 } /* Literal.Number.Integer */
    c-[mo] { color: #657b83 } /* Literal.Number.Oct */
    c-[sa] { color: #6c71c4 } /* Literal.String.Affix */
    c-[sb] { color: #6c71c4 } /* Literal.String.Backtick */
    c-[sc] { color: #6c71c4 } /* Literal.String.Char */
    c-[dl] { color: #6c71c4 } /* Literal.String.Delimiter */
    c-[sd] { color: #6c71c4 } /* Literal.String.Doc */
    c-[se] { color: #6c71c4 } /* Literal.String.Escape */
    c-[sh] { color: #6c71c4 } /* Literal.String.Heredoc */
    c-[si] { color: #6c71c4 } /* Literal.String.Interpol */
    c-[sx] { color: #6c71c4 } /* Literal.String.Other */
    c-[sr] { color: #6c71c4 } /* Literal.String.Regex */
    c-[ss] { color: #6c71c4 } /* Literal.String.Symbol */
    c-[fm] { color: #268bd2 } /* Name.Function.Magic */
    c-[vc] { color: #cb4b16 } /* Name.Variable.Class */
    c-[vg] { color: #cb4b16 } /* Name.Variable.Global */
    c-[vi] { color: #cb4b16 } /* Name.Variable.Instance */
    c-[vm] { color: #cb4b16 } /* Name.Variable.Magic */
    c-[il] { color: #657b83 } /* Literal.Number.Integer.Long */
}
</style>
 <body class="h-entry">
  <input id="hidedel" style="display:none" type="checkbox">
  <div class="head">
   <p data-fill-with="logo"></p>
   <h1 class="p-name no-ref" id="title">P2408R1<br>Ranges views as inputs to non-Ranges algorithms</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="2021-08-31">2021-08-31</time></span></h2>
   <div data-fill-with="spec-metadata">
    <dl>
     <dt>This version:
     <dd><a class="u-url" href="https://wg21.link/p2408r1">https://wg21.link/p2408r1</a>
     <dt>Issue Tracking:
     <dd><a href="#issues-index">Inline In Spec</a>
     <dt class="editor">Author:
     <dd class="editor p-author h-card vcard"><a class="p-name fn u-email email" href="mailto:dolsen@nvidia.com">David Olsen</a> (<span class="p-org org">NVIDIA</span>)
     <dt>Audience:
     <dd>LEWG
     <dt>Toggle Diffs:
     <dd>
      <label for="hidedel" id="hidedel-label">Hide deleted text</label>
     <dt>Project:
     <dd>ISO/IEC JTC1/SC22/WG21 14882: Programming Language — C++
    </dl>
   </div>
   <div data-fill-with="warning"></div>
   <hr title="Separator for header">
  </div>
  <nav data-fill-with="table-of-contents" id="toc">
   <h2 class="no-num no-toc no-ref" id="contents">Table of Contents</h2>
   <ol class="toc" role="directory">
    <li><a href="#abstract"><span class="secno">1</span> <span class="content">Abstract</span></a>
    <li>
     <a href="#revisions"><span class="secno">2</span> <span class="content">Revision history</span></a>
     <ol class="toc">
      <li><a href="#r0"><span class="secno">2.1</span> <span class="content">R0</span></a>
      <li><a href="#r1"><span class="secno">2.2</span> <span class="content">R1</span></a>
     </ol>
    <li><a href="#motivation"><span class="secno">3</span> <span class="content">Motivation</span></a>
    <li>
     <a href="#analysis"><span class="secno">4</span> <span class="content">Analysis</span></a>
     <ol class="toc">
      <li><a href="#current-impl"><span class="secno">4.1</span> <span class="content">Current situation</span></a>
     </ol>
    <li>
     <a href="#solutions"><span class="secno">5</span> <span class="content">Possible Solutions</span></a>
     <ol class="toc">
      <li><a href="#no-action"><span class="secno">5.1</span> <span class="content">Do nothing</span></a>
      <li><a href="#change-existing"><span class="secno">5.2</span> <span class="content">Relax the <i>Cpp17</i> iterator requirements</span></a>
      <li><a href="#require-concept"><span class="secno">5.3</span> <span class="content">Algorithms require concepts instead of categories</span></a>
     </ol>
    <li>
     <a href="#impact"><span class="secno">6</span> <span class="content">Impact and Details</span></a>
     <ol class="toc">
      <li><a href="#changes"><span class="secno">6.1</span> <span class="content">Changes</span></a>
      <li><a href="#relaxed"><span class="secno">6.2</span> <span class="content">Relaxed requirements</span></a>
      <li><a href="#elsewhere"><span class="secno">6.3</span> <span class="content">Other uses</span></a>
      <li><a href="#impl-impact"><span class="secno">6.4</span> <span class="content">Implementation impact</span></a>
      <li><a href="#user-impact"><span class="secno">6.5</span> <span class="content">User impact</span></a>
     </ol>
    <li><a href="#sentinels"><span class="secno">7</span> <span class="content">Sentinels</span></a>
    <li><a href="#experience"><span class="secno">8</span> <span class="content">Implementation Experience</span></a>
    <li><a href="#feature-macro"><span class="secno">9</span> <span class="content">Feature Test Macro</span></a>
    <li><a href="#wording"><span class="secno">10</span> <span class="content">Wording</span></a>
    <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>
    <li><a href="#issues-index"><span class="secno"></span> <span class="content">Issues Index</span></a>
   </ol>
  </nav>
  <main>
   <h2 class="heading settled" data-level="1" id="abstract"><span class="secno">1. </span><span class="content">Abstract</span><a class="self-link" href="#abstract"></a></h2>
   <p>Change the iterator requirements for non-Ranges algorithms.  Instead of requiring that iterators meet certain <em>Cpp17Iterator</em> requirements, require that the iterators model certain iterator concepts.  This makes iterators from several standard views usable with non-Ranges algorithms.</p>
   <h2 class="heading settled" data-level="2" id="revisions"><span class="secno">2. </span><span class="content">Revision history</span><a class="self-link" href="#revisions"></a></h2>
   <h3 class="heading settled" data-level="2.1" id="r0"><span class="secno">2.1. </span><span class="content">R0</span><a class="self-link" href="#r0"></a></h3>
   <p>This paper arose out of a private e-mail discussion where Bryce Adelstein Lelbach questioned why code that is similar to the first example in <a href="#motivation">§ 3 Motivation</a> didn’t compile with MSVC.</p>
   <h3 class="heading settled" data-level="2.2" id="r1"><span class="secno">2.2. </span><span class="content">R1</span><a class="self-link" href="#r1"></a></h3>
   <p>Add the section <a href="#sentinels">§ 7 Sentinels</a> based on <a href="https://wiki.edg.com/bin/view/Wg21telecons2021/P2408r0-20210809">discussion</a> in SG9 (Ranges) on 9 Aug 2021.  This is just background information; there is no change to what is being proposed.</p>
   <h2 class="heading settled" data-level="3" id="motivation"><span class="secno">3. </span><span class="content">Motivation</span><a class="self-link" href="#motivation"></a></h2>
   <p>These two snippets of code should be well-formed:</p>
<pre class="highlight"><c- n>std</c-><c- o>::</c-><c- n>vector</c-><c- o>&lt;</c-><c- b>int</c-><c- o>></c-> <c- n>data</c-> <c- o>=</c-> <c- p>...;</c->
<c- k>auto</c-> <c- n>v</c-> <c- o>=</c-> <c- n>data</c-> <c- o>|</c-> <c- n>std</c-><c- o>::</c-><c- n>views</c-><c- o>::</c-><c- n>transform</c-><c- p>([](</c-><c- b>int</c-> <c- n>x</c-><c- p>){</c-> <c- k>return</c-> <c- n>x</c-> <c- o>*</c-> <c- n>x</c-><c- p>;</c-> <c- p>});</c->
<c- b>int</c-> <c- n>sum_of_squares</c-> <c- o>=</c-> <c- n>std</c-><c- o>::</c-><c- n>reduce</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>begin</c-><c- p>(</c-><c- n>v</c-><c- p>),</c-> <c- n>end</c-><c- p>(</c-><c- n>v</c-><c- p>));</c->
</pre>
<pre class="highlight"><c- k>auto</c-> <c- n>idxs</c-> <c- o>=</c-> <c- n>std</c-><c- o>::</c-><c- n>views</c-><c- o>::</c-><c- n>iota</c-><c- p>(</c-><c- mi>0</c-><c- p>,</c-> <c- n>N</c-><c- p>);</c->
<c- n>std</c-><c- o>::</c-><c- n>transform</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>begin</c-><c- p>(</c-><c- n>idxs</c-><c- p>),</c-> <c- n>end</c-><c- p>(</c-><c- n>idxs</c-><c- p>),</c-> <c- n>begin</c-><c- p>(</c-><c- n>sqrts</c-><c- p>),</c->
               <c- p>[](</c-><c- b>int</c-> <c- n>x</c-><c- p>)</c-> <c- p>{</c-> <c- k>return</c-> <c- n>std</c-><c- o>::</c-><c- n>sqrt</c-><c- p>(</c-><c- b>float</c-><c- p>(</c-><c- n>x</c-><c- p>));</c-> <c- p>});</c->
</pre>
   <p>It should be possible, in most cases, to use the iterators from ranges and views as the inputs to C++17 parallel algorithms and to other algorithms that require forward iterators or greater.</p>
   <h2 class="heading settled" data-level="4" id="analysis"><span class="secno">4. </span><span class="content">Analysis</span><a class="self-link" href="#analysis"></a></h2>
   <p><code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>reduce</c-></code> requires that its iterator parameters satisfy the requirements of <em>Cpp17ForwardIterator</em>.  One of those requirements is that <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>iterator_traits</c-><c- o>&lt;</c-><c- n>I</c-><c- o>>::</c-><c- n>reference</c-></code> be a reference type, either <code class="highlight"><c- n>T</c-><c- o>&amp;</c-></code> or <code class="highlight"><c- k>const</c-> <c- n>T</c-><c- o>&amp;</c-></code>.  (<a href="http://eel.is/c++draft/iterator.cpp17#forward.iterators-1.3">[forward.iterators]/p1.3</a>)  The iterator category of <code class="highlight"><c- n>transform_view</c-><c- o>::</c-><c- n>iterator</c-></code> matches the iterator category of the underlying range only if the transformation function returns an lvalue reference.  If the return type of the transformation function is a value rather than a reference, the iterator category of <code class="highlight"><c- n>transform_view</c-><c- o>::</c-><c- n>iterator</c-></code> is <code class="highlight"><c- n>input_iterator_tag</c-></code>, because the iterator’s <code class="highlight"><c- n>reference</c-></code> type alias can’t be a reference type.  (<a href="http://eel.is/c++draft/range.transform.iterator#2">[range.transform.iterator]/p2</a>)</p>
   <p>In this example, the lambda transformation function returns a value, so the iterators passed to <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>reduce</c-></code> are only input iterators in the classic iterator taxonomy used by the non-Ranges algorithms, even though the iterators satisfy the <code class="highlight"><c- n>random_access_iterator</c-></code> concept in the Ranges iterator taxonomy.</p>
   <p>Several other views have the same issue, where the <code class="highlight"><c- n>iterator_category</c-></code> is <code class="highlight"><c- n>input_iterator_tag</c-></code> even when the <code class="highlight"><c- n>iterator_concept</c-></code> is something else.</p>
   <ul>
    <li data-md>
     <p><code class="highlight"><c- n>iota_view</c-></code>'s <code class="highlight"><c- n>iterator_category</c-></code> is always <code class="highlight"><c- n>input_iterator_tag</c-></code> while its <code class="highlight"><c- n>iterator_concept</c-></code> is often <code class="highlight"><c- n>random_access_iterator_tag</c-></code>. <a href="http://eel.is/c++draft/range.iota.iterator">[range.iota.iterator]</a></p>
    <li data-md>
     <p><code class="highlight"><c- n>lazy_split_view</c-></code>'s <code class="highlight"><c- n>iterator_category</c-></code> is always <code class="highlight"><c- n>input_iterator_tag</c-></code> while its <code class="highlight"><c- n>iterator_concept</c-></code> is <code class="highlight"><c- n>forward_iterator_tag</c-></code> if the underlying range is a forward range. <a href="http://eel.is/c++draft/range.lazy.split.outer">[range.lazy.split.outer]</a></p>
    <li data-md>
     <p><code class="highlight"><c- n>split_view</c-></code>'s <code class="highlight"><c- n>iterator_category</c-></code> is always <code class="highlight"><c- n>input_iterator_tag</c-></code> and its <code class="highlight"><c- n>iterator_concept</c-></code> is always <code class="highlight"><c- n>forward_iterator_tag</c-></code>. <a href="http://eel.is/c++draft/range.split.iterator">[range.split.iterator]</a></p>
    <li data-md>
     <p><code class="highlight"><c- n>elements_view</c-></code> is similar to <code class="highlight"><c- n>transform_view</c-></code> in that the <code class="highlight"><c- n>iterator_category</c-></code> depends on the value category of the return type of the <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>get</c-><c- o>&lt;</c-><c- n>N</c-><c- o>></c-></code> function used to extract the element. <code class="highlight"><c- n>iterator_category</c-></code> is <code class="highlight"><c- n>input_iterator_tag</c-></code> if <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>get</c-><c- o>&lt;</c-><c- n>N</c-><c- o>></c-></code> returns an rvalue, and (mostly) matches the iterator category of the base range otherwise.  The <code class="highlight"><c- n>iterator_concept</c-></code> depends only on the base range, not the <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>get</c-><c- o>&lt;</c-><c- n>N</c-><c- o>></c-></code> function. <a href="http://eel.is/c++draft/range.elements#iterator-2">[range.elements.iterator]/p2</a></p>
   </ul>
   <h3 class="heading settled" data-level="4.1" id="current-impl"><span class="secno">4.1. </span><span class="content">Current situation</span><a class="self-link" href="#current-impl"></a></h3>
   <p>MSVC checks that iterator arguments to parallel algorithms have the correct iterator category.  If either of the code snippets in <a href="#motivation">§ 3 Motivation</a> are compiled, the compilation will fail with "error C2338: Parallel algorithms require forward iterators or stronger."</p>
   <p>libstd++ does not do any up-front checking of the iterator category of algorithm arguments.  Its implementation of algorithms will accept iterators of any category as long as the iterators support the operations that are actually used in the implementation.  The code snippets in <a href="#motivation">§ 3 Motivation</a> can be successfully compiled with GCC 11.1.</p>
   <h2 class="heading settled" data-level="5" id="solutions"><span class="secno">5. </span><span class="content">Possible Solutions</span><a class="self-link" href="#solutions"></a></h2>
   <h3 class="heading settled" data-level="5.1" id="no-action"><span class="secno">5.1. </span><span class="content">Do nothing</span><a class="self-link" href="#no-action"></a></h3>
   <p>We could simply wait for parallel versions of Range-based algorithms to make their way into the standard.  Until then, users who want to use certain view iterators as inputs to parallel algorithms are out of luck.</p>
   <p>This solution might be worth considering if parallel Range-based algorithms were on track for C++23.  But <a data-link-type="biblio" href="#biblio-p2214">[P2214]</a> "A Plan for C++23 Ranges" puts parallel Range-based algorithms in Tier 2 of Ranges work, with the caveat that the work needs to be coordinated with Executors to make sure the interface is correct.  That pushes the work well past C++23.</p>
   <p>Even if parallel Range-based algorithms were already in the draft IS, it would still be worth investigating how to get Ranges iterators to work better with non-Ranges algorithms, in the interest of having the various parts of the Standard work well together.</p>
   <h3 class="heading settled" data-level="5.2" id="change-existing"><span class="secno">5.2. </span><span class="content">Relax the <i>Cpp17</i> iterator requirements</span><a class="self-link" href="#change-existing"></a></h3>
   <p>We could change the definition of <em>Cpp17ForwardIterator</em> (<a href="http://eel.is/c++draft/forward.iterators">[forward.iterators]</a>), removing the requirement that <code class="highlight"><c- n>reference</c-></code> be defined for constant iterators. <code class="highlight"><c- n>reference</c-></code> would still need to be defined, and be <code class="highlight"><c- n>T</c-><c- o>&amp;</c-></code>, for mutable iterators.</p>
   <p>The authors do not consider this option to be feasible.  This change would break existing code that assumes that <code class="highlight"><c- n>iterator_traits</c-><c- o>&lt;</c-><c- n>I</c-><c- o>>::</c-><c- n>reference</c-></code> exists and is a reference type if the iterator category is <code class="highlight"><c- n>forward_iterator_tag</c-></code> or greater.  There are other possible solutions that don’t break existing code.</p>
   <h3 class="heading settled" data-level="5.3" id="require-concept"><span class="secno">5.3. </span><span class="content">Algorithms require concepts instead of categories</span><a class="self-link" href="#require-concept"></a></h3>
   <p>We could change the wording in <a href="http://eel.is/c++draft/algorithms.requirements">[algorithms.requirements]</a> to say that the template arguments of the algorithms shall model an iterator concept rather than meet a set of <em>Cpp17</em> requirements.  For example:</p>
   <blockquote>
     If an algorithm’s template parameter is named <code class="highlight"><c- n>ForwardIterator</c-></code>, <code class="highlight"><c- n>ForwardIterator1</c-></code>, or <code class="highlight"><c- n>ForwardIterator2</c-></code>, the template argument shall 
    <del>meet the <em>Cpp17ForwardIterator</em> requirements ([forward.iterators])</del>
    <ins>model <code class="highlight"><c- n>forward_iterator</c-></code> ([iterator.concept.forward])</ins>
    . 
   </blockquote>
   <p>This change relaxes the requirements on the template arguments for non-Ranges algorithms.  Implementations may need to change to no longer depend on requirements that are no longer required.  It is not expected that this will be a big burden, since a well-written algorithm shouldn’t be depending on <code class="highlight"><c- n>iterator_traits</c-><c- o>&lt;</c-><c- n>I</c-><c- o>>::</c-><c- n>reference</c-></code> being a reference type for an iterator that is only used for input.</p>
   <p>This change will not break any existing code because the iterator concept imposes fewer requirements on the type than the corresponding <em>Cpp17...Iterator</em> requirements.  Any well-formed program will continue to be well-formed and have the same behavior.  Some programs that were not well-formed may become well-formed, such as the two motivating examples in this paper; these will have reasonable, non-surprising behavior.</p>
   <p>This is the solution proposed by this paper.  See immediately below for more details and analysis of this solution.</p>
   <h2 class="heading settled" data-level="6" id="impact"><span class="secno">6. </span><span class="content">Impact and Details</span><a class="self-link" href="#impact"></a></h2>
   <h3 class="heading settled" data-level="6.1" id="changes"><span class="secno">6.1. </span><span class="content">Changes</span><a class="self-link" href="#changes"></a></h3>
   <p>In every bullet of [algorithms.requirements]/p4 except for the one about <code class="highlight"><c- n>InputIterator</c-></code>, change the requirement on the iterator from meeting a set of <em>Cpp17...Iterator</em> requirements to modeling the corresponding iterator concept.</p>
   <p>For <code class="highlight"><c- n>InputIterator</c-></code>, the iterator shall model both the <code class="highlight"><c- n>input_iterator</c-></code> and <code class="highlight"><c- n>equality_comparable</c-></code> concepts.  The <code class="highlight"><c- n>input_iterator</c-></code> concept does not require equality comparisons, because in Ranges input iterators are often compared with a sentinel rather than with another iterator.  Classic algorithms, however, take iterator pairs rather than iterator/sentinel, so any input iterator must be equality comparable.</p>
   <p>This <code class="highlight"><c- n>equality_comparable</c-></code> exception applies only to input iterators because:</p>
   <ul>
    <li data-md>
     <p>Concept <code class="highlight"><c- n>forward_iterator</c-></code> requires <code class="highlight"><c- n>equality_comparable</c-></code> via <code class="highlight"><c- n>incrementable</c-></code> and <code class="highlight"><c- n>regular</c-></code>.  That also covers bidirectional, random access, and contiguous iterators because they all require <code class="highlight"><c- n>forward_iterator</c-></code>.</p>
    <li data-md>
     <p>Output iterators are generally not compared for equality with other iterators in well-behaved algorithms.</p>
   </ul>
   <h3 class="heading settled" data-level="6.2" id="relaxed"><span class="secno">6.2. </span><span class="content">Relaxed requirements</span><a class="self-link" href="#relaxed"></a></h3>
   <p>The <em>Cpp17...Iterator</em> requirements and the iterator concepts are worded very differently, making it challenging to compare them directly.  As far as I can determine, no iterator concept requires anything of its type that is not also required by the corresponding <em>Cpp17...Iterator</em> set of requirements.  In the other direction, these are the things required by the <em>Cpp17...Iterator</em> requirements that are not required by the concepts:</p>
   <ul>
    <li data-md>
     <p><em>Cpp17InputIterator</em> and <em>Cpp17OutputIterator</em> require that the iterator be copyable, but <code class="highlight"><c- n>input_iterator</c-></code> and <code class="highlight"><c- n>output_iterator</c-></code> only require that it be movable.</p>
    <li data-md>
     <p><em>Cpp17InputIterator</em> requires that the iterator be <em>Cpp17EqualityComparable</em>, but <code class="highlight"><c- n>input_iterator</c-></code> does not require <code class="highlight"><c- n>equality_comparable</c-></code>.  (See <a href="#changes">§ 6.1 Changes</a> for how this is dealt with.)</p>
    <li data-md>
     <p><em>Cpp17ForwardIterator</em> requires that <code class="highlight"><c- n>reference</c-></code> be a reference type, either <code class="highlight"><c- n>T</c-><c- o>&amp;</c-></code> or <code class="highlight"><c- k>const</c-> <c- n>T</c-><c- o>&amp;</c-></code>. <code class="highlight"><c- n>forward_iterator</c-></code> requires that <code class="highlight"><c- n>iter_reference_t</c-><c- o>&lt;</c-><c- n>I</c-><c- o>></c-></code> exist but doesn’t require that it be a reference type.  This same difference also applies to bidirectional iterators and random access iterators.  (This difference is the root cause of the problems, and the reason for this paper.)</p>
   </ul>
   <h3 class="heading settled" data-level="6.3" id="elsewhere"><span class="secno">6.3. </span><span class="content">Other uses</span><a class="self-link" href="#elsewhere"></a></h3>
   <p>The <em>Cpp17...Iterator</em> requirements are used in several other places in the standard besides [algorithms.requirements].  It is proposed that in places where the requirements are on iterator types that the program passes to standard algorithms, the wording is changed from meeting <em>Cpp17...Iterator</em> requirements to modeling an iterator concept, just like is being done for [algorithms.requirements].  See <a href="#wording">§ 10 Wording</a> for all the places where this happens.</p>
   <p>Other uses of <em>Cpp17...Iterator</em> requirements are not changed by this proposal.  In some of those cases the requirement is on a standard iterator, not a program iterator, so relaxing the requirements could break existing code.  The other uses are in [sequence.reqmts], [associative.reqmts.general], [move.iter.requirements], [locale.category], [fs.req], [fs.path.req], [fs.class.directory.iterator.general], [time.zone.db.list], [reverse.iter.requirements], [allocator.requirements.general], [stacktrace.basic.obs], [string.view.iterators], [container.requirements.general], [span.iterators], [iterator.operations], [alg.equal], and [valarray.range].</p>
   <h3 class="heading settled" data-level="6.4" id="impl-impact"><span class="secno">6.4. </span><span class="content">Implementation impact</span><a class="self-link" href="#impl-impact"></a></h3>
   <p>If any standard algorithm implementations rely on the requirements listed in <a href="#relaxed">§ 6.2 Relaxed requirements</a>, those implementations will have to change to not rely on those requirements.  It is assumed, though not yet verified, that not many algorithm implementations will have to change, and that the changes will not be difficult to make.  The hardest part might be identifying places that need to be changed.</p>
   <p>Any implementation that checks the iterator category of algorithm iterator arguments, such as MSVC, will have to change the way those checks happen.  That should be a straightforward, if somewhat tedious, change.</p>
   <h3 class="heading settled" data-level="6.5" id="user-impact"><span class="secno">6.5. </span><span class="content">User impact</span><a class="self-link" href="#user-impact"></a></h3>
   <p>No well-formed programs will become ill-formed or have different behavior as a result of this change.  Some ill-formed programs will become well-formed with the behaviors users would expect.  This change will reduce the number of surprises by making code that users reasonably expect to be well-formed actually well-formed.  It is not expected that any users would be negatively impacted by this change.</p>
   <h2 class="heading settled" data-level="7" id="sentinels"><span class="secno">7. </span><span class="content">Sentinels</span><a class="self-link" href="#sentinels"></a></h2>
   <p>Many ranges use iterator/sentinel pairs, rather than a pair of iterators, as the bounds of the range.  Non-Ranges algorithms always require a pair of iterators that have the same type, and will not work with iterator/sentinel pairs.  If this proposal is adopted, more ranges than before will be usable with classic algorithms, but the sentinel issue will still prevent some ranges from being useful as inputs to classic algorithms.</p>
   <p>The two examples in <a href="#motivation">§ 3 Motivation</a> use iterator pairs and don’t suffer from the sentinel issue. <code class="highlight"><c- n>transform_view</c-><c- o>::</c-><c- n>end</c-><c- p>()</c-></code> returns an iterator rather than a sentinel if the base range is a common range.  In the example, the base range is <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>vector</c-></code>, which is a common range. <code class="highlight"><c- n>iota_view</c-><c- o>::</c-><c- n>end</c-><c- p>()</c-></code> returns an iterator rather than a sentinel when the range has an upper bound of the same type as the lower bound.  It is primarily unbounded <code class="highlight"><c- n>iota_view</c-></code>s that use a sentinel.  Passing an unbounded <code class="highlight"><c- n>iota_view</c-></code> to any classic algorithm function as a first/last pair isn’t going to work well, even if first and last are of the same type.  I don’t think <code class="highlight"><c- n>iota_view</c-></code>'s use of sentinels will be a problem in practice in this area.</p>
   <p>If a range with iterator/sentinel pairs needs to be used with a classic algorithm, there is a good chance that the user can simply wrap the range in a <code class="highlight"><c- n>common_view</c-></code>.  The <code class="highlight"><c- n>common_view</c-></code>'s iterators will be random access if the base range is random access and sized, and will be forward iterators if the base range’s iterator is at least forward.  That will allow the <code class="highlight"><c- n>common_view</c-></code> to be used in most places where the base range would have been usable if it had used an iterator rather than a sentinel.</p>
   <p>I am in favor of changing the non-Ranges algorithms to use iterator/sentinel pairs.  But that change can be done independently, not as part of this paper.  Both changes are useful on their own, independent of the other, and wouldn’t benefit from being tied together.</p>
   <h2 class="heading settled" data-level="8" id="experience"><span class="secno">8. </span><span class="content">Implementation Experience</span><a class="self-link" href="#experience"></a></h2>
   <p>None so far.  Some implementation experience will be attempted if LEWG likes the proposal and is considering forwarding it on.</p>
   <p>Because this is a change to a specification that is not directly implemented in code, it is not a simple matter to make the change to a standard library implementation and test it.  I want to find out if the committee is at all interested in this idea before spending much time on implementing it.</p>
   <h2 class="heading settled" data-level="9" id="feature-macro"><span class="secno">9. </span><span class="content">Feature Test Macro</span><a class="self-link" href="#feature-macro"></a></h2>
   <p>This change affects the well-formed-ness of certain code.  Some users might want to write their code two different ways based on whether or not a standard library has implemented this change.  Therefore, I believe that the benefit to users of a feature test macro is greater than the cost to implementers of defining it.  This proposal adds the new macro <code class="highlight"><c- n>__cpp_lib_algorithm_iterator_requirements</c-></code>.</p>
   <h2 class="heading settled" data-level="10" id="wording"><span class="secno">10. </span><span class="content">Wording</span><a class="self-link" href="#wording"></a></h2>
   <p>Changes are relative to N4888 from June 2021.</p>
   <p>Change <strong>25.2 "Algorithms requirements" [algorithms.requirements] paragraph 4</strong> as follows:</p>
   <blockquote>
     Throughout this Clause, where the template parameters are not constrained, the names of template parameters are used to express type requirements. 
    <ul>
     <li data-md>
      <p>
       If an algorithm’s template parameter is named <code class="highlight"><c- n>InputIterator</c-></code>, <code class="highlight"><c- n>InputIterator1</c-></code>, or <code class="highlight"><c- n>InputIterator2</c-></code>, the template argument shall 
       <del>meet the <em>Cpp17InputIterator</em> requirements ([input.iterators])</del>
       <ins>model <code class="highlight"><c- n>input_iterator</c-></code> ([iterator.concept.input]) and <code class="highlight"><c- n>equality_comparable</c-></code> ([concept.equality.comparable])</ins>
       .
      </p>
     <li data-md>
      <p>
       If an algorithm’s template parameter is named <code class="highlight"><c- n>OutputIterator</c-></code>, <code class="highlight"><c- n>OutputIterator1</c-></code>, or <code class="highlight"><c- n>OutputIterator2</c-></code>, the template argument shall 
       <del>meet the <em>Cpp17OutputIterator</em> requirements ([output.iterators])</del>
       <ins>model <code class="highlight"><c- n>output_iterator</c-></code> ([iterator.concept.output])</ins>
       .
      </p>
     <li data-md>
      <p>
       If an algorithm’s template parameter is named <code class="highlight"><c- n>ForwardIterator</c-></code>, <code class="highlight"><c- n>ForwardIterator1</c-></code>, or <code class="highlight"><c- n>ForwardIterator2</c-></code>, the template argument shall 
       <del>meet the <em>Cpp17ForwardIterator</em> requirements ([forward.iterators])</del>
       <ins>model <code class="highlight"><c- n>forward_iterator</c-></code> ([iterator.concept.forward])</ins>
       .
      </p>
     <li data-md>
      <p>
       If an algorithm’s template parameter is named <code class="highlight"><c- n>NoThrowForwardIterator</c-></code>, the template argument shall 
       <del>meet the <em>Cpp17ForwardIterator</em> requirements ([forward.iterators])</del>
       <ins>model <code class="highlight"><c- n>forward_iterator</c-></code></ins>
       , and is required to have the property that no exceptions are thrown from increment, assignment, or comparison of, or indirection through, valid iterators.
      </p>
     <li data-md>
      <p>
       If an algorithm’s template parameter is named <code class="highlight"><c- n>BidirectionalIterator</c-></code>, <code class="highlight"><c- n>BidirectionalIterator1</c-></code>, or <code class="highlight"><c- n>BidirectionalIterator2</c-></code>, the template argument shall 
       <del>meet the <em>Cpp17BidirectionalIterator</em> requirements ([bidirectional.iterators])</del>
       <ins>model <code class="highlight"><c- n>bidirectional_iterator</c-></code> ([iterator.concept.bidir])</ins>
       .
      </p>
     <li data-md>
      <p>
       If an algorithm’s template parameter is named <code class="highlight"><c- n>RandomAccessIterator</c-></code>, <code class="highlight"><c- n>RandomAccessIterator1</c-></code>, or <code class="highlight"><c- n>RandomAccessIterator2</c-></code>, the template argument shall 
       <del>meet the <em>Cpp17RandomAccessIterator</em> requirements ([random.access.iterators])</del>
       <ins>model <code class="highlight"><c- n>random_access_iterator</c-></code> ([iterator.concept.random.access])</ins>
       .
      </p>
    </ul>
   </blockquote>
   <p class="issue" id="issue-7f91f122"><a class="self-link" href="#issue-7f91f122"></a> As currently worded, before these changes, the implementation is required to issue a diagnostic if the iterator type doesn’t meet the given requirements.  The requirements contain some semantic elements, which the implementation cannot reliably check at compile time, making it difficult to always issue the required diagnostic.  The proposed wording change does not fix this issue, since the concepts also have semantic requirements that can’t be reliably checked at compile time.  Should the wording be changed to make the failure to meet the iterator requirements IFNDR or undefined behavior?</p>
   <p>Change <strong>25.7.12 "Sample" [alg.random.sample] paragraphs 2 and 5</strong> as follows:</p>
   <p>Paragraph 2:</p>
   <blockquote>
    <p><em>Preconditions</em>: <code class="highlight"><c- n>out</c-></code> is not in the range <code class="highlight"><c- p>[</c-><c- n>first</c-><c- p>,</c-> <c- n>last</c-><c- p>)</c-></code>.  For the overload in namespace <code class="highlight"><c- n>std</c-></code>:</p>
    <ul>
     <li data-md>
      <p>
       <code class="highlight"><c- n>PopulationIterator</c-></code> 
       <del>meets the <em>Cpp17InputIterator</em> requirements ([input.iterators])</del>
       <ins>models <code class="highlight"><c- n>input_iterator</c-></code>([iterator.concept.input]) and <code class="highlight"><c- n>equality_comparable</c-></code> ([concept.equality.comparable])</ins>
       .
      </p>
     <li data-md>
      <p>
       <code class="highlight"><c- n>SampleIterator</c-></code> 
       <del>meets the <em>Cpp17OutputIterator</em> requirements ([output.iterators])</del>
       <ins>models <code class="highlight"><c- n>output_iterator</c-></code> ([iterator.concept.output])</ins>
       .
      </p>
     <li data-md>
      <p>
       <code class="highlight"><c- n>SampleIterator</c-></code> 
       <del>meets the <em>Cpp17RandomAccessIterator</em> requirements ([random.access.iterators])</del>
       <ins>models <code class="highlight"><c- n>random_access_iterator</c-></code> ([iterator.concept.random.access])</ins>
        unless <code class="highlight"><c- n>PopulationIterator</c-></code> 
       <del>meets the <em>Cpp17ForwardIterator</em> requirements ([forward.iterators])</del>
       <ins>models <code class="highlight"><c- n>forward_iterator</c-></code>([iterator.concept.forward]).</ins>
      </p>
     <li data-md>
      <p><code class="highlight"><c- n>remove_reference_t</c-><c- o>&lt;</c-><c- n>UniformRandomBitGenerator</c-><c- o>></c-></code> meets the requirements of a uniform random bit generator type ([rand.req.urng]).</p>
    </ul>
   </blockquote>
   <p>Paragraph 5:</p>
   <blockquote>
    <p><em>Remarks</em>:</p>
    <ul>
     <li data-md>
      <p>
       For the overload in namespace <code class="highlight"><c- n>std</c-></code>, stable if and only if <code class="highlight"><c- n>PopulationIterator</c-></code> 
       <del>meets the <em>Cpp17ForwardIterator</em> requirements</del>
       <ins>models <code class="highlight"><c- n>forward_iterator</c-></code></ins>
       .  For the first overload in namespace <code class="highlight"><c- n>ranges</c-></code>, stable if and only if <code class="highlight"><c- n>I</c-></code> models <code class="highlight"><c- n>forward_iterator</c-></code>.
      </p>
     <li data-md>
      <p>To the extent that the implementation of this function makes use of random numbers, the object <code class="highlight"><c- n>g</c-></code> serves as the implementation’s source of randomness.</p>
    </ul>
   </blockquote>
   <p>Change <b>26.6.8.1 "Class <code class="highlight"><c- n>seed_seq</c-></code>" [rand.util.seedseq] paragraphs 6, 9, and 15</b> as follows:</p>
   <p>Paragraph 6:</p>
   <blockquote>
    <p>
     <em>Preconditions</em>: <code class="highlight"><c- n>InputIterator</c-></code> 
     <del>meets the <em>Cpp17InputIterator</em> requirements ([input.iterators])</del>
     <ins>models <code class="highlight"><c- n>input_iterator</c-></code> ([iterator.concept.input]) and <code class="highlight"><c- n>equality_comparable</c-></code> ([concept.equality.comparable])</ins>
     .
    </p>
   </blockquote>
   <p>Paragraph 9:</p>
   <blockquote>
    <p>
     <em>Preconditions</em>: <code class="highlight"><c- n>RandomAccessIterator</c-></code> 
     <del>meets the <em>Cpp17RandomAccessIterator</em> requirements ([random.access.iterators]) and</del>
     <ins>models <code class="highlight"><c- n>random_access_iterator</c-></code> ([iterator.concept.random.access]) and meets</ins>
      the requirements of a mutable iterator.
    </p>
   </blockquote>
   <p>Paragraph 15:</p>
   <blockquote>
    <p>
     <em>Preconditions</em>: <code class="highlight"><c- n>OutputIterator</c-></code> 
     <del>meets the <em>Cpp17OutputIterator</em> requirements ([output.iterators])</del>
     <ins>models <code class="highlight"><c- n>output_iterator</c-></code> ([iterator.concept.output])</ins>
     .
    </p>
   </blockquote>
   <p>Change <b>26.6.9.6.1 "Class template <code class="highlight"><c- n>discrete_distribution</c-></code>" [rand.dist.samp.discrete] paragraph 5</b> as follows:</p>
   <blockquote>
    <p>
     <em>Preconditions</em>: <code class="highlight"><c- n>InputIterator</c-></code> 
     <del>meets the <em>Cpp17InputIterator</em> requirements ([input.iterators])</del>
     <ins>models <code class="highlight"><c- n>input_iterator</c-></code> ([iterator.concept.input]) and <code class="highlight"><c- n>equality_comparable</c-></code> ([concept.equality.comparable])</ins>
     . If <code class="highlight"><c- n>firstW</c-> <c- o>==</c-> <c- n>lastW</c-></code>, let <em>n</em> = 1 and <em>w0</em> = 1.  Otherwise, <code class="highlight"><c- p>[</c-><c- n>firstW</c-><c- p>,</c-><c- n>lastW</c-><c- p>)</c-></code> forms a sequence w of length <em>n</em> > 0.
    </p>
   </blockquote>
   <p>Change <b>26.6.9.2 "Class template <code class="highlight"><c- n>piecewise_constant_distribution</c-></code>" [rand.dist.samp.pconst] paragraph 5</b> as follows:</p>
   <blockquote>
    <p>
     <em>Preconditions</em>: <code class="highlight"><c- n>InputIteratorB</c-></code> and <code class="highlight"><c- n>InputIteratorW</c-></code> each 
     <del>meet the <em>Cpp17InputIterator</em> requirements ([input.iterators])</del>
     <ins>model <code class="highlight"><c- n>input_iterator</c-></code> ([iterator.concept.input]). <code class="highlight"><c- n>InputIteratorB</c-></code> models <code class="highlight"><c- n>equality_comparable</c-></code> ([concept.equality.comparable])</ins>
     . If <code class="highlight"><c- n>firstB</c-> <c- o>==</c-> <c- n>lastB</c-></code> or <code class="highlight"><c- o>++</c-><c- n>firstB</c-> <c- o>==</c-> <c- n>lastB</c-></code>, let <em>n</em> = 1, <em>w0</em> = 1, <em>b0</em> = 0, and <em>b1</em> = 1. Otherwise, <code class="highlight"><c- p>[</c-><c- n>firstB</c-><c- p>,</c-><c- n>lastB</c-><c- p>)</c-></code> forms a sequence <em>b</em> of length <em>n</em> + 1, the length of the sequence <em>w</em> starting from <code class="highlight"><c- n>firstW</c-></code> is at least <em>n</em>, and any <em>wk</em> for <em>k</em> ≥ <em>n</em> are ignored by the distribution.
    </p>
   </blockquote>
   <p>Change <b>26.6.9.3 "Class template <code class="highlight"><c- n>piecewise_linear_distribution</c-></code>" [rand.dist.samp.plinear] paragraph 5</b> as follows:</p>
   <blockquote>
    <p>
     <em>Preconditions</em>: <code class="highlight"><c- n>InputIteratorB</c-></code> and <code class="highlight"><c- n>InputIteratorW</c-></code> each 
     <del>meet the <em>Cpp17InputIterator</em> requirements ([input.iterators])</del>
     <ins>model <code class="highlight"><c- n>input_iterator</c-></code> ([iterator.concept.input]) <code class="highlight"><c- n>InputIteratorB</c-></code> models <code class="highlight"><c- n>equality_comparable</c-></code> ([concept.equality.comparable])</ins>
     . If <code class="highlight"><c- n>firstB</c-> <c- o>==</c-> <c- n>lastB</c-></code> or <code class="highlight"><c- o>++</c-><c- n>firstB</c-> <c- o>==</c-> <c- n>lastB</c-></code>, let <em>n</em> = 1, <em>ρ0</em> = <em>ρ1</em> = 1, <em>b0</em> = 0, and <em>b1</em> = 1. Otherwise, <code class="highlight"><c- p>[</c-><c- n>firstB</c-><c- p>,</c-><c- n>lastB</c-><c- p>)</c-></code> forms a sequence <em>b</em> of length <em>n</em> + 1, the length of the sequence <em>w</em> starting from <code class="highlight"><c- n>firstW</c-></code> is at least <em>n</em> + 1, and any <em>wk</em> for <em>k</em> ≥ <em>n</em> + 1 are ignored by the distribution.
    </p>
   </blockquote>
   <p>Change <b>25.7.9 "Unique" [alg.unique] paragraph 8.2.2</b> as follows:</p>
   <blockquote>
    <ul>
     <li data-md>
      <p>
       For the overloads with no <code class="highlight"><c- n>ExecutionPolicy</c-></code>, let <code class="highlight"><c- n>T</c-></code> be the value type of <code class="highlight"><c- n>InputIterator</c-></code>. If <code class="highlight"><c- n>InputIterator</c-></code> 
       <del>meets the <em>Cpp17ForwardIterator</em> requirements</del>
       <ins>models <code class="highlight"><c- n>forward_iterator</c-></code> ([iterator.concept.forward])</ins>
       , then there are no additional requirements for <code class="highlight"><c- n>T</c-></code>. Otherwise, if <code class="highlight"><c- n>OutputIterator</c-></code> 
       <del>meets the <em>Cpp17ForwardIterator</em> requirements</del>
       <ins>models <code class="highlight"><c- n>forward_iterator</c-></code></ins>
        and its value type is the same as <code class="highlight"><c- n>T</c-></code>, then <code class="highlight"><c- n>T</c-></code> meets the <em>Cpp17CopyAssignable</em> (Table 31) requirements. Otherwise, <code class="highlight"><c- n>T</c-></code> meets both the <em>Cpp17CopyConstructible</em> (Table 29) and <em>Cpp17CopyAssignable</em> requirements.
      </p>
    </ul>
   </blockquote>
   <p>Change <b>25.7.14 "Shift" [alg.shift] paragraphs 5 and 6</b> as follows:</p>
   <blockquote>
    <p>
     <em>Preconditions</em>: <code class="highlight"><c- n>n</c-> <c- o>>=</c-> <c- mi>0</c-></code> is <code class="highlight">true</code>. The type of <code class="highlight"><c- o>*</c-><c- n>first</c-></code> meets the <em>Cpp17MoveAssignable</em> requirements. <code class="highlight"><c- n>ForwardIterator</c-></code> 
     <del>meets the <em>Cpp17BidirectionalIterator</em> requirements ([bidirectional.iterators]) or</del>
     <ins>models <code class="highlight"><c- n>bidirectional_iterator</c-></code> ([iterator.concept.bidir]) or meets</ins>
      the <em>Cpp17ValueSwappable</em> requirements.
    </p>
    <p>
     <em>Effects</em>: If <code class="highlight"><c- n>n</c-> <c- o>==</c-> <c- mi>0</c-></code> or <code class="highlight"><c- n>n</c-> <c- o>>=</c-> <c- n>last</c-> <c- o>-</c-> <c- n>first</c-></code>, does nothing. Otherwise, moves the element from position <code class="highlight"><c- n>first</c-> <c- o>+</c-> <c- n>i</c-></code> into position <code class="highlight"><c- n>first</c-> <c- o>+</c-> <c- n>n</c-> <c- o>+</c-> <c- n>i</c-></code> for each non-negative integer <code class="highlight"><c- n>i</c-> <c- o>&lt;</c-> <c- p>(</c-><c- n>last</c-> <c- o>-</c-> <c- n>first</c-><c- p>)</c-> <c- o>-</c-> <c- n>n</c-></code>. In the first overload case, if <code class="highlight"><c- n>ForwardIterator</c-></code> 
     <del>meets the <code class="highlight"><c- n>Cpp17BidirectionalIterator</c-></code> requirements</del>
     <ins>models <code class="highlight"><c- n>bidirectional_iterator</c-></code>, does so in order starting from <code class="highlight"><c- n>i</c-> <c- o>=</c-> <c- p>(</c-><c- n>last</c-> <c- o>-</c-> <c- n>first</c-><c- p>)</c-> <c- o>-</c-> <c- n>n</c-> <c- o>-</c-> <c- mi>1</c-></code> and proceeding to <code class="highlight"><c- n>i</c-> <c- o>=</c-> <c- mi>0</c-></code>.</ins>
    </p>
   </blockquote>
   <p>Change <b>25.8.5 "Partitions" [alg.partitions] paragraph 8.1</b> as follows:</p>
   <blockquote>
    <ul>
     <li data-md>
      <p>
       For the overload with no <code class="highlight"><c- n>ExecutionPolicy</c-></code>, exactly <em>N</em> applications of the predicate and projection. At most <em>N/2</em> swaps if the type of <code class="highlight"><c- n>first</c-></code> 
       <del>meets the <em>Cpp17BidirectionalIterator</em> requirements for the overloads in namespace <code class="highlight"><c- n>std</c-></code> or</del>
        models <code class="highlight"><c- n>bidirectional_iterator</c-></code> 
       <del>for the overloads in namespace <code class="highlight"><c- n>ranges</c-></code></del>
       , and at most <em>N</em> swaps otherwise.
      </p>
    </ul>
   </blockquote>
   <p>Change <b>30.9.6 "Formatting" [re.results.form] paragraph 1</b> as follows:</p>
   <blockquote>
    <p>
     <em>Preconditions</em>: <code class="highlight"><c- n>ready</c-><c- p>()</c-> <c- o>==</c-> true</code> and <code class="highlight"><c- n>OutputIter</c-></code> 
     <del>meets the requirements for a <em>Cpp17OutputIterator</em> ([output.iterators])</del>
     <ins>models <code class="highlight"><c- n>output_iterator</c-></code> ([iterator.concept.output])</ins>
     .
    </p>
   </blockquote>
   <p>Change <b>30.10.2 "<code class="highlight"><c- n>regex_match</c-></code>" [re.alg.match] paragraph 1</b> as follows:</p>
   <blockquote>
    <p>
     <em>Preconditions</em>: <code class="highlight"><c- n>BidirectionalIterator</c-></code> 
     <del>meets the <em>Cpp17BidirectionalIterator</em> requirements ([bidirectional.iterators])</del>
     <ins>models <code class="highlight"><c- n>bidirectional_iterator</c-></code> ([iterator.concept.bidir])</ins>
     .
    </p>
   </blockquote>
   <p>Change <b>30.10.3 "<code class="highlight"><c- n>regex_search</c-></code>" [re.alg.search] paragraph 1</b> as follows:</p>
   <blockquote>
    <p>
     <em>Preconditions</em>: <code class="highlight"><c- n>BidirectionalIterator</c-></code> 
     <del>meets the <em>Cpp17BidirectionalIterator</em> requirements ([bidirectional.iterators])</del>
     <ins>models <code class="highlight"><c- n>bidirectional_iterator</c-></code> ([iterator.concept.bidir])</ins>
     .
    </p>
   </blockquote>
   <p>Add the following feature test macro to <strong>[version.syn]</strong>:</p>
   <blockquote> <code class="highlight"><c- cp>#define __cpp_lib_algorithm_iterator_requirements</c-></code> <em>date</em> <em>// also in</em> <code class="highlight"><c- o>&lt;</c-><c- n>algorithm</c-><c- o>></c-></code>, <code class="highlight"><c- o>&lt;</c-><c- n>numeric</c-><c- o>></c-></code>, <code class="highlight"><c- o>&lt;</c-><c- n>memory</c-><c- o>></c-></code> </blockquote>
  </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-p2214">[P2214]
   <dd>Barry Rezvin; Conor Hoekstra; Tim Song. <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p2214r0.html"><cite>A Plan for C++23 Ranges</cite></a>. URL: <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p2214r0.html">http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p2214r0.html</a>
  </dl>
  <h2 class="no-num no-ref heading settled" id="issues-index"><span class="content">Issues Index</span><a class="self-link" href="#issues-index"></a></h2>
  <div style="counter-reset:issue">
   <div class="issue"> As currently worded, before these changes, the implementation is required to issue a diagnostic if the iterator type doesn’t meet the given requirements.  The requirements contain some semantic elements, which the implementation cannot reliably check at compile time, making it difficult to always issue the required diagnostic.  The proposed wording change does not fix this issue, since the concepts also have semantic requirements that can’t be reliably checked at compile time.  Should the wording be changed to make the failure to meet the iterator requirements IFNDR or undefined behavior?<a href="#issue-7f91f122"> ↵ </a></div>
  </div>