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

/* color variables included separately for reliability */

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

	html {
	}

	body {
		counter-reset: example figure issue;

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

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

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


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

	p {
		margin: 1em 0;
	}

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

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

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

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

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

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

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

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

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


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

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

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

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

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

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

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

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

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

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

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

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

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

	/* Do something nice. */

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

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

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

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

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

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

	img {
		border-style: none;
	}

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

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

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

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

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

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

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


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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


/*
Alternate table alignment rules

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

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

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

Possible extra rowspan handling

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

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

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


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

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

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

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

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

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

		.toc li {
			clear: both;
		}

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

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

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


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

.outdated-warning span {
	display: block;
}

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

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

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

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

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



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

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

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

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

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

    del { background: #fcc; color: #000; text-decoration: line-through; }
    ins { background: #cfc; color: #000; }
    blockquote .highlight:not(.idl) { background: initial; margin: initial; padding: 0.5em }
    blockquote ul { background: inherit; }
    blockquote code.highlight:not(.idl) { padding: initial; }
    blockquote c-[a] { color: inherit; } /* Keyword.Declaration */
    blockquote c-[b] { color: inherit; } /* Keyword.Type */
    blockquote c-[c] { color: inherit; } /* Comment */
    blockquote c-[d] { color: inherit; } /* Comment.Multiline */
    blockquote c-[e] { color: inherit; } /* Name.Attribute */
    blockquote c-[f] { color: inherit; } /* Name.Tag */
    blockquote c-[g] { color: inherit; } /* Name.Variable */
    blockquote c-[k] { color: inherit; } /* Keyword */
    blockquote c-[l] { color: inherit; } /* Literal */
    blockquote c-[m] { color: inherit; } /* Literal.Number */
    blockquote c-[n] { color: inherit; } /* Name */
    blockquote c-[o] { color: inherit; } /* Operator */
    blockquote c-[p] { color: inherit; } /* Punctuation */
    blockquote c-[s] { color: inherit; } /* Literal.String */
    blockquote c-[t] { color: inherit; } /* Literal.String.Single */
    blockquote c-[u] { color: inherit; } /* Literal.String.Double */
    blockquote c-[cp] { color: inherit; } /* Comment.Preproc */
    blockquote c-[c1] { color: inherit; } /* Comment.Single */
    blockquote c-[cs] { color: inherit; } /* Comment.Special */
    blockquote c-[kc] { color: inherit; } /* Keyword.Constant */
    blockquote c-[kn] { color: inherit; } /* Keyword.Namespace */
    blockquote c-[kp] { color: inherit; } /* Keyword.Pseudo */
    blockquote c-[kr] { color: inherit; } /* Keyword.Reserved */
    blockquote c-[ld] { color: inherit; } /* Literal.Date */
    blockquote c-[nc] { color: inherit; } /* Name.Class */
    blockquote c-[no] { color: inherit; } /* Name.Constant */
    blockquote c-[nd] { color: inherit; } /* Name.Decorator */
    blockquote c-[ni] { color: inherit; } /* Name.Entity */
    blockquote c-[ne] { color: inherit; } /* Name.Exception */
    blockquote c-[nf] { color: inherit; } /* Name.Function */
    blockquote c-[nl] { color: inherit; } /* Name.Label */
    blockquote c-[nn] { color: inherit; } /* Name.Namespace */
    blockquote c-[py] { color: inherit; } /* Name.Property */
    blockquote c-[ow] { color: inherit; } /* Operator.Word */
    blockquote c-[mb] { color: inherit; } /* Literal.Number.Bin */
    blockquote c-[mf] { color: inherit; } /* Literal.Number.Float */
    blockquote c-[mh] { color: inherit; } /* Literal.Number.Hex */
    blockquote c-[mi] { color: inherit; } /* Literal.Number.Integer */
    blockquote c-[mo] { color: inherit; } /* Literal.Number.Oct */
    blockquote c-[sb] { color: inherit; } /* Literal.String.Backtick */
    blockquote c-[sc] { color: inherit; } /* Literal.String.Char */
    blockquote c-[sd] { color: inherit; } /* Literal.String.Doc */
    blockquote c-[se] { color: inherit; } /* Literal.String.Escape */
    blockquote c-[sh] { color: inherit; } /* Literal.String.Heredoc */
    blockquote c-[si] { color: inherit; } /* Literal.String.Interpol */
    blockquote c-[sx] { color: inherit; } /* Literal.String.Other */
    blockquote c-[sr] { color: inherit; } /* Literal.String.Regex */
    blockquote c-[ss] { color: inherit; } /* Literal.String.Symbol */
    blockquote c-[vc] { color: inherit; } /* Name.Variable.Class */
    blockquote c-[vg] { color: inherit; } /* Name.Variable.Global */
    blockquote c-[vi] { color: inherit; } /* Name.Variable.Instance */
    blockquote c-[il] { color: inherit; } /* Literal.Number.Integer.Long */
  </style>
  <meta content="Bikeshed version 4416b18d5, updated Tue Jan 2 15:52:39 2024 -0800" name="generator">
  <link href="http://wg21.link/P1729R4" rel="canonical">
  <link href="https://isocpp.org/favicon.ico" rel="icon">
  <meta content="ae39a55c23ed541b171e5721debe258bdc7a8b89" name="revision">
<style>/* Boilerplate: style-autolinks */
.css.css, .property.property, .descriptor.descriptor {
    color: var(--a-normal-text);
    font-size: inherit;
    font-family: inherit;
}
.css::before, .property::before, .descriptor::before {
    content: "‘";
}
.css::after, .property::after, .descriptor::after {
    content: "’";
}
.property, .descriptor {
    /* Don't wrap property and descriptor names */
    white-space: nowrap;
}
.type { /* CSS value <type> */
    font-style: italic;
}
pre .property::before, pre .property::after {
    content: "";
}
[data-link-type="property"]::before,
[data-link-type="propdesc"]::before,
[data-link-type="descriptor"]::before,
[data-link-type="value"]::before,
[data-link-type="function"]::before,
[data-link-type="at-rule"]::before,
[data-link-type="selector"]::before,
[data-link-type="maybe"]::before {
    content: "‘";
}
[data-link-type="property"]::after,
[data-link-type="propdesc"]::after,
[data-link-type="descriptor"]::after,
[data-link-type="value"]::after,
[data-link-type="function"]::after,
[data-link-type="at-rule"]::after,
[data-link-type="selector"]::after,
[data-link-type="maybe"]::after {
    content: "’";
}

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

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

[data-link-type=biblio] {
    white-space: pre;
}

@media (prefers-color-scheme: dark) {
    :root {
        --selflink-text: black;
        --selflink-bg: silver;
        --selflink-hover-text: white;
    }
}
</style>
<style>/* Boilerplate: style-colors */
/* Any --*-text not paired with a --*-bg is assumed to have a transparent bg */
:root {
    color-scheme: light dark;

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

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

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

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

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

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

    --heading-text: #005a9c;

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

    --algo-border: #def;

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

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

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

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

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

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

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

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

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

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

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

    --datacell-border: silver;

    --indexinfo-text: #707070;

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

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

    --editedrec-bg: darkorange;
}

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

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

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

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

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

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

        --heading-text: #8af;

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

        --algo-border: #456;

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

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

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

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

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

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

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

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

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

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

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

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

        --datacell-border: silver;

        --indexinfo-text: #aaa;

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

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

        --editedrec-bg: darkorange;
    }
    /* In case a transparent-bg image doesn't expect to be on a dark bg,
       which is quite common in practice... */
    img { background: white; }
}
</style>
<style>/* Boilerplate: style-counters */
body {
    counter-reset: example figure issue;
}
.issue {
    counter-increment: issue;
}
.issue:not(.no-marker)::before {
    content: "Issue " counter(issue);
}

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

figcaption {
    counter-increment: figure;
}
figcaption:not(.no-marker)::before {
    content: "Figure " counter(figure) " ";
}
</style>
<style>/* Boilerplate: style-issues */
a[href].issue-return {
    float: right;
    float: inline-end;
    color: var(--issueheading-text);
    font-weight: bold;
    text-decoration: none;
}
</style>
<style>/* Boilerplate: style-md-lists */
/* This is a weird hack for me not yet following the commonmark spec
   regarding paragraph and lists. */
[data-md] > :first-child {
    margin-top: 0;
}
[data-md] > :last-child {
    margin-bottom: 0;
}
</style>
<style>/* Boilerplate: style-selflinks */
:root {
    --selflink-text: white;
    --selflink-bg: gray;
    --selflink-hover-text: black;
}
.heading, .issue, .note, .example, li, dt {
    position: relative;
}
a.self-link {
    position: absolute;
    top: 0;
    left: calc(-1 * (3.5rem - 26px));
    width: calc(3.5rem - 26px);
    height: 2em;
    text-align: center;
    border: none;
    transition: opacity .2s;
    opacity: .5;
}
a.self-link:hover {
    opacity: 1;
}
.heading > a.self-link {
    font-size: 83%;
}
.example > a.self-link,
.note > a.self-link,
.issue > a.self-link {
    /* These blocks are overflow:auto, so positioning outside
       doesn't work. */
    left: auto;
    right: 0;
}
li > a.self-link {
    left: calc(-1 * (3.5rem - 26px) - 2em);
}
dfn > a.self-link {
    top: auto;
    left: auto;
    opacity: 0;
    width: 1.5em;
    height: 1.5em;
    background: var(--selflink-bg);
    color: var(--selflink-text);
    font-style: normal;
    transition: opacity .2s, background-color .2s, color .2s;
}
dfn:hover > a.self-link {
    opacity: 1;
}
dfn > a.self-link:hover {
    color: var(--selflink-hover-text);
}

a.self-link::before            { content: "¶"; }
.heading > a.self-link::before { content: "§"; }
dfn > a.self-link::before      { content: "#"; }
</style>
<style>/* Boilerplate: style-syntax-highlighting */
code.highlight { padding: .1em; border-radius: .3em; }
pre.highlight, pre > code.highlight { display: block; padding: 1em; margin: .5em 0; overflow: auto; border-radius: 0; }

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

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

    c-[a] { color: #d33682 } /* Keyword.Declaration */
    c-[b] { color: #d33682 } /* Keyword.Type */
    c-[c] { color: #2aa198 } /* Comment */
    c-[d] { color: #2aa198 } /* Comment.Multiline */
    c-[e] { color: #268bd2 } /* Name.Attribute */
    c-[f] { color: #b58900 } /* Name.Tag */
    c-[g] { color: #cb4b16 } /* Name.Variable */
    c-[k] { color: #d33682 } /* Keyword */
    c-[l] { color: #657b83 } /* Literal */
    c-[m] { color: #657b83 } /* Literal.Number */
    c-[n] { color: #268bd2 } /* Name */
    c-[o] { color: #657b83 } /* Operator */
    c-[p] { color: #657b83 } /* Punctuation */
    c-[s] { color: #6c71c4 } /* Literal.String */
    c-[t] { color: #6c71c4 } /* Literal.String.Single */
    c-[u] { color: #6c71c4 } /* Literal.String.Double */
    c-[ch] { color: #2aa198 } /* Comment.Hashbang */
    c-[cp] { color: #2aa198 } /* Comment.Preproc */
    c-[cpf] { color: #2aa198 } /* Comment.PreprocFile */
    c-[c1] { color: #2aa198 } /* Comment.Single */
    c-[cs] { color: #2aa198 } /* Comment.Special */
    c-[kc] { color: #d33682 } /* Keyword.Constant */
    c-[kn] { color: #d33682 } /* Keyword.Namespace */
    c-[kp] { color: #d33682 } /* Keyword.Pseudo */
    c-[kr] { color: #d33682 } /* Keyword.Reserved */
    c-[ld] { color: #657b83 } /* Literal.Date */
    c-[nc] { color: #268bd2 } /* Name.Class */
    c-[no] { color: #268bd2 } /* Name.Constant */
    c-[nd] { color: #268bd2 } /* Name.Decorator */
    c-[ni] { color: #268bd2 } /* Name.Entity */
    c-[ne] { color: #268bd2 } /* Name.Exception */
    c-[nf] { color: #268bd2 } /* Name.Function */
    c-[nl] { color: #268bd2 } /* Name.Label */
    c-[nn] { color: #268bd2 } /* Name.Namespace */
    c-[py] { color: #268bd2 } /* Name.Property */
    c-[ow] { color: #657b83 } /* Operator.Word */
    c-[mb] { color: #657b83 } /* Literal.Number.Bin */
    c-[mf] { color: #657b83 } /* Literal.Number.Float */
    c-[mh] { color: #657b83 } /* Literal.Number.Hex */
    c-[mi] { color: #657b83 } /* Literal.Number.Integer */
    c-[mo] { color: #657b83 } /* Literal.Number.Oct */
    c-[sa] { color: #6c71c4 } /* Literal.String.Affix */
    c-[sb] { color: #6c71c4 } /* Literal.String.Backtick */
    c-[sc] { color: #6c71c4 } /* Literal.String.Char */
    c-[dl] { color: #6c71c4 } /* Literal.String.Delimiter */
    c-[sd] { color: #6c71c4 } /* Literal.String.Doc */
    c-[se] { color: #6c71c4 } /* Literal.String.Escape */
    c-[sh] { color: #6c71c4 } /* Literal.String.Heredoc */
    c-[si] { color: #6c71c4 } /* Literal.String.Interpol */
    c-[sx] { color: #6c71c4 } /* Literal.String.Other */
    c-[sr] { color: #6c71c4 } /* Literal.String.Regex */
    c-[ss] { color: #6c71c4 } /* Literal.String.Symbol */
    c-[fm] { color: #268bd2 } /* Name.Function.Magic */
    c-[vc] { color: #cb4b16 } /* Name.Variable.Class */
    c-[vg] { color: #cb4b16 } /* Name.Variable.Global */
    c-[vi] { color: #cb4b16 } /* Name.Variable.Instance */
    c-[vm] { color: #cb4b16 } /* Name.Variable.Magic */
    c-[il] { color: #657b83 } /* Literal.Number.Integer.Long */
}
</style>
 <script src="P1729R4%20Text%20Parsing_files/page-script.js" id="bw-fido2-page-script"></script></head><body class="h-entry toc-sidebar"><p id="toc-nav"><a id="toc-jump" href="#toc"><span aria-hidden="true">↑</span> <span>Jump to Table of Contents</span></a><a id="toc-toggle" href="#toc"><span aria-hidden="true">←</span> <span>Collapse Sidebar</span></a></p>
  <div class="head">
   <p data-fill-with="logo"></p>
   <h1 class="p-name no-ref" id="title">P1729R4<br>Text Parsing</h1>
   <h2 class="no-num no-toc no-ref heading settled" id="profile-and-date"><span class="content">Published Proposal, <time class="dt-updated" datetime="2024-02-07">2024-02-07</time></span></h2>
   <div data-fill-with="spec-metadata">
    <dl>
     <dt>This version:
     </dt><dd><a class="u-url" href="http://wg21.link/P1729R4">http://wg21.link/P1729R4</a>
     </dd><dt class="editor">Authors:
     </dt><dd class="editor p-author h-card vcard"><a class="p-name fn u-email email" href="mailto:isocpp@eliaskosunen.com">Elias Kosunen</a>
     </dd><dd class="editor p-author h-card vcard"><a class="p-name fn u-email email" href="mailto:victor.zverovich@gmail.com">Victor Zverovich</a>
     </dd><dt>Audience:
     </dt><dd>LEWG, SG9, SG16
     </dd><dt>Project:
     </dt><dd>ISO/IEC 14882 Programming Languages — C++, ISO/IEC JTC1/SC22/WG21
    </dd></dl>
   </div>
   <div data-fill-with="warning"></div>
   <hr title="Separator for header">
  </div>
  <div class="p-summary" data-fill-with="abstract">
   <h2 class="no-num no-toc no-ref heading settled" id="abstract"><span class="content">Abstract</span></h2>
   <p>This paper discusses a new text parsing facility to complement the text
formatting functionality of <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">format</c-></code>, proposed in <a data-link-type="biblio" href="#biblio-p0645" title="Text Formatting">[P0645]</a>.</p>
  </div>
  <nav data-fill-with="table-of-contents" id="toc">
   <h2 class="no-num no-toc no-ref" id="contents">Table of Contents</h2>
   <ol class="toc" role="directory">
    <li>
     <a href="#history"><span class="secno">1</span> <span class="content">Revision history</span></a>
     <ol class="toc">
      <li><a href="#history-since-r3"><span class="secno">1.1</span> <span class="content">Changes since R3</span></a>
      </li><li><a href="#history-since-r2"><span class="secno">1.2</span> <span class="content">Changes since R2</span></a>
      </li><li><a href="#history-since-r1"><span class="secno">1.3</span> <span class="content">Changes since R1</span></a>
     </li></ol>
    </li><li><a href="#introduction"><span class="secno">2</span> <span class="content">Introduction</span></a>
    </li><li>
     <a href="#examples"><span class="secno">3</span> <span class="content">Examples</span></a>
     <ol class="toc">
      <li><a href="#example-basic"><span class="secno">3.1</span> <span class="content">Basic example</span></a>
      </li><li><a href="#example-multiple"><span class="secno">3.2</span> <span class="content">Reading multiple values at once</span></a>
      </li><li><a href="#example-range"><span class="secno">3.3</span> <span class="content">Reading from a range</span></a>
      </li><li><a href="#example-loop"><span class="secno">3.4</span> <span class="content">Reading multiple values in a loop</span></a>
      </li><li><a href="#example-alt-error"><span class="secno">3.5</span> <span class="content">Alternative error handling</span></a>
      </li><li><a href="#example-userdef"><span class="secno">3.6</span> <span class="content">Scanning a user-defined type</span></a>
     </li></ol>
    </li><li>
     <a href="#design"><span class="secno">4</span> <span class="content">Design</span></a>
     <ol class="toc">
      <li><a href="#overview"><span class="secno">4.1</span> <span class="content">Overview</span></a>
      </li><li><a href="#format-strings"><span class="secno">4.2</span> <span class="content">Format strings</span></a>
      </li><li><a href="#format-string-specifiers"><span class="secno">4.3</span> <span class="content">Format string specifiers</span></a>
      </li><li><a href="#ranges"><span class="secno">4.4</span> <span class="content">Ranges</span></a>
      </li><li><a href="#argument-passing"><span class="secno">4.5</span> <span class="content">Argument passing, and return type of <code class="highlight"><c- n="">scan</c-></code></span></a>
      </li><li><a href="#error-handling"><span class="secno">4.6</span> <span class="content">Error handling</span></a>
      </li><li><a href="#binary-footprint"><span class="secno">4.7</span> <span class="content">Binary footprint and type erasure</span></a>
      </li><li><a href="#safety"><span class="secno">4.8</span> <span class="content">Safety</span></a>
      </li><li><a href="#extensibility"><span class="secno">4.9</span> <span class="content">Extensibility</span></a>
      </li><li><a href="#locales"><span class="secno">4.10</span> <span class="content">Locales</span></a>
      </li><li><a href="#encoding"><span class="secno">4.11</span> <span class="content">Encoding</span></a>
      </li><li><a href="#performance"><span class="secno">4.12</span> <span class="content">Performance</span></a>
      </li><li><a href="#chrono"><span class="secno">4.13</span> <span class="content">Integration with chrono</span></a>
      </li><li><a href="#deep-impact"><span class="secno">4.14</span> <span class="content">Impact on existing code</span></a>
     </li></ol>
    </li><li><a href="#existing-work"><span class="secno">5</span> <span class="content">Existing work</span></a>
    </li><li>
     <a href="#future"><span class="secno">6</span> <span class="content">Future extensions</span></a>
     <ol class="toc">
      <li><a href="#stdio-integration"><span class="secno">6.1</span> <span class="content">Integration with <code class="highlight"><c- n="">stdio</c-></code></span></a>
      </li><li><a href="#char-set-match"><span class="secno">6.2</span> <span class="content"><code class="highlight"><c- n="">scanf</c-></code>-like <code class="highlight"><c- p="">[</c-><c- n="">character</c-> <c- n="">set</c-><c- p="">]</c-></code> matching</span></a>
      </li><li><a href="#scan-code-point"><span class="secno">6.3</span> <span class="content">Reading code points (or even grapheme clusters?)</span></a>
      </li><li><a href="#scan-transcode"><span class="secno">6.4</span> <span class="content">Reading strings and chars of different width</span></a>
      </li><li><a href="#range-scanning"><span class="secno">6.5</span> <span class="content">Scanning of ranges</span></a>
      </li><li><a href="#default-values"><span class="secno">6.6</span> <span class="content">Default values for scanned values</span></a>
      </li><li><a href="#discard"><span class="secno">6.7</span> <span class="content">Assignment suppression / discarding values</span></a>
     </li></ol>
    </li><li>
     <a href="#spec"><span class="secno">7</span> <span class="content">Specification</span></a>
     <ol class="toc">
      <li><a href="#spec-ranges-syn"><span class="secno">7.1</span> <span class="content">Modify "Header <code class="highlight"><c- o="">&lt;</c-><c- n="">ranges</c-><c- o="">&gt;</c-></code> synopsis" [ranges.syn]</span></a>
      </li><li><a href="#spec-range-dangling"><span class="secno">7.2</span> <span class="content">Modify "Dangling iterator handling", paragraph 3 [range.dangling]</span></a>
      </li><li><a href="#spec-header-synopsis"><span class="secno">7.3</span> <span class="content">Header <code class="highlight"><c- o="">&lt;</c-><c- n="">scan</c-><c- o="">&gt;</c-></code> synopsis</span></a>
      </li><li><a href="#spec-scan-error-synopsis"><span class="secno">7.4</span> <span class="content">Class <code class="highlight"><c- n="">scan_error</c-></code> synopsis</span></a>
      </li><li><a href="#spec-scan-result-synopsis"><span class="secno">7.5</span> <span class="content">Class template <code class="highlight"><c- n="">scan_result</c-></code> synopsis</span></a>
      </li><li><a href="#spec-scan-format-string-synopsis"><span class="secno">7.6</span> <span class="content">Class template <code class="highlight"><c- n="">basic_scan_format_string</c-></code> synopsis</span></a>
      </li><li><a href="#spec-scan-context-synopsis"><span class="secno">7.7</span> <span class="content">Class template <code class="highlight"><c- n="">basic_scan_context</c-></code> synopsis</span></a>
      </li><li><a href="#spec-scan-args-synopsis"><span class="secno">7.8</span> <span class="content">Class template <code class="highlight"><c- n="">basic_scan_args</c-></code> synopsis</span></a>
      </li><li><a href="#spec-scannable"><span class="secno">7.9</span> <span class="content">Concept <code class="highlight"><c- n="">scannable</c-></code></span></a>
      </li><li><a href="#spec-scan-arg-synopsis"><span class="secno">7.10</span> <span class="content">Class template <code class="highlight"><c- n="">basic_scan_arg</c-></code> synopsis</span></a>
      </li><li><a href="#spec-scan-arg-store"><span class="secno">7.11</span> <span class="content">Exposition-only class template <code class="highlight"><i><c- n="">scan</c-><c- o="">-</c-><c- n="">arg</c-><c- o="">-</c-><c- n="">store</c-></i></code> synopsis</span></a>
     </li></ol>
    </li><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>
     </li></ol>
   </li></ol>
  </nav>
  <main>
   <h2 class="heading settled" data-level="1" id="history"><span class="secno">1. </span><span class="content">Revision history</span><a class="self-link" href="#history"></a></h2>
   <h3 class="heading settled" data-level="1.1" id="history-since-r3"><span class="secno">1.1. </span><span class="content">Changes since R3</span><a class="self-link" href="#history-since-r3"></a></h3>
   <ul>
    <li data-md="">
     <p>Replace <code class="highlight"><c- n="">scan_args_for</c-></code> with <code class="highlight"><c- n="">scan_args</c-></code> and <code class="highlight"><c- n="">wscan_args</c-></code> for consistency with <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">format</c-></code>.</p>
    </li><li data-md="">
     <p>Rename <code class="highlight"><c- n="">borrowed_ssubrange_t</c-></code> to <code class="highlight"><c- n="">borrowed_tail_subrange_t</c-></code> partly based on the naming from ranges-v3 (<code class="highlight"><c- n="">tail_view</c-></code>).</p>
    </li><li data-md="">
     <p>Replace <code class="highlight"><c- n="">format_string</c-></code> with <code class="highlight"><c- n="">scan_format_string</c-></code>, with a <code class="highlight"><c- n="">Range</c-></code> template parameter.</p>
    </li><li data-md="">
     <p>Enables compile-time checking for compatibility of the source range, and arguments to scan</p>
    </li><li data-md="">
     <p>Make <code class="highlight"><c- p="">[</c-><c- n="">v</c-><c- p="">]</c-><c- n="">scan_result_type</c-></code> (the return types of <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">scan</c-></code> and <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">vscan</c-></code>) exposition only.</p>
    </li><li data-md="">
     <p>Remove <code class="highlight"><c- n="">visit_scan_arg</c-></code>: follow <a data-link-type="biblio" href="#biblio-p2637" title="Member `visit`">[P2637]</a> and use <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">variant</c-><c- o="">::</c-><c- n="">visit</c-></code>, instead.</p>
    </li><li data-md="">
     <p>Add discussion on <code class="highlight"><c- n="">stdin</c-></code> support, guided by SG9 polls.</p>
    </li><li data-md="">
     <p>Make encoding errors be errors for strings, instead of garbage-in-garbage-out.</p>
    </li><li data-md="">
     <p>Add further discussion on field widths.</p>
    </li><li data-md="">
     <p>Add example as rationale for mandating <code class="highlight"><c- n="">forward_range</c-></code>.</p>
   </li></ul>
   <h3 class="heading settled" data-level="1.2" id="history-since-r2"><span class="secno">1.2. </span><span class="content">Changes since R2</span><a class="self-link" href="#history-since-r2"></a></h3>
   <ul>
    <li data-md="">
     <p>Return a <code class="highlight"><c- n="">subrange</c-></code> from <code class="highlight"><c- n="">scan</c-></code>, instead of just an iterator: discussion in <a href="#argument-passing">§ 4.5 Argument passing, and return type of scan</a>.</p>
    </li><li data-md="">
     <p>Default <code class="highlight"><c- n="">CharT</c-></code> to <code class="highlight"><c- b="">char</c-></code> in <code class="highlight"><c- n="">scanner</c-></code> for consistency with <code class="highlight"><c- n="">formatter</c-></code> (previously no default for <code class="highlight"><c- n="">CharT</c-></code>).</p>
    </li><li data-md="">
     <p>Add design discussion about thousands separators in <a href="#fmt-localized-discussion-grouping">§ 4.3.5.1 Design discussion: Thousands separator grouping checking</a> and <a href="#fmt-localized-discussion-thsepflag">§ 4.3.5.2 Design discussion: Separate flag for thousands separators</a>.</p>
    </li><li data-md="">
     <p>Add design discussion about additional error information in <a href="#error-handling-discussion-detail">§ 4.6.2 Design discussion: Additional information</a>.</p>
    </li><li data-md="">
     <p>Add clarification about field width calculation in <a href="#fmt-width-precision">§ 4.3.4 Width and precision</a>.</p>
    </li><li data-md="">
     <p>Add note about scope at the end of <a href="#introduction">§ 2 Introduction</a>.</p>
    </li><li data-md="">
     <p>Fix/clarify error handling in example <a href="#example-alt-error">§ 3.5 Alternative error handling</a>.</p>
    </li><li data-md="">
     <p>Address SG16 feedback:</p>
     <ul>
      <li data-md="">
       <p>Add definition of "whitespace", and clarify matching of non-whitespace literal characters, in <a href="#format-strings">§ 4.2 Format strings</a>.</p>
      </li><li data-md="">
       <p>Add section about text encoding <a href="#encoding">§ 4.11 Encoding</a>, and an example about handing reading code units <a href="#fmt-type-char">§ 4.3.8 Type specifiers: CharT</a>.</p>
      </li><li data-md="">
       <p>Add example about using locales in <a href="#locales">§ 4.10 Locales</a>.</p>
      </li><li data-md="">
       <p>Add potential future extension: <a href="#scan-code-point">§ 6.3 Reading code points (or even grapheme clusters?)</a></p>
     </li></ul>
   </li></ul>
   <h3 class="heading settled" data-level="1.3" id="history-since-r1"><span class="secno">1.3. </span><span class="content">Changes since R1</span><a class="self-link" href="#history-since-r1"></a></h3>
   <ul>
    <li data-md="">
     <p>Thoroughly describe the design</p>
    </li><li data-md="">
     <p>Add examples</p>
    </li><li data-md="">
     <p>Add specification (synopses only)</p>
    </li><li data-md="">
     <p>Design changes:</p>
     <ul>
      <li data-md="">
       <p>Return an <code class="highlight"><c- n="">expected</c-></code> containing a <code class="highlight"><c- n="">tuple</c-></code> from <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">scan</c-></code>, instead of using output parameters</p>
      </li><li data-md="">
       <p>Make <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">scan</c-></code> take a range instead of a <code class="highlight"><c- n="">string_view</c-></code></p>
      </li><li data-md="">
       <p>Remove support for partial successes</p>
     </li></ul>
   </li></ul>
   <h2 class="heading settled" data-level="2" id="introduction"><span class="secno">2. </span><span class="content">Introduction</span><a class="self-link" href="#introduction"></a></h2>
   <p>With the introduction of <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">format</c-></code> <a data-link-type="biblio" href="#biblio-p0645" title="Text Formatting">[P0645]</a>,
standard C++ has a convenient, safe, performant, extensible,
and elegant facility for text formatting,
over <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">ostream</c-></code> and the <code class="highlight"><c- n="">printf</c-></code>-family of functions.
The story is different for simple text parsing: the standard only
provides <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">istream</c-></code> and the <code class="highlight"><c- n="">scanf</c-></code> family, both of which have issues.
This asymmetry is also arguably an inconsistency in the standard library.</p>
   <p>According to <a data-link-type="biblio" href="#biblio-codesearch" title="Code search engine website">[CODESEARCH]</a>, a C and C++ codesearch engine based on the ACTCD19
dataset, there are 389,848 calls to <code class="highlight"><c- n="">sprintf</c-></code> and 87,815 calls to <code class="highlight"><c- n="">sscanf</c-></code> at
the time of writing. So although formatted input functions are less popular than
their output counterparts, they are still widely used.</p>
   <p>The lack of a general-purpose parsing facility based on format strings has been
raised in <a data-link-type="biblio" href="#biblio-p1361" title="Integration of chrono with text formatting">[P1361]</a> in the context of formatting and parsing of dates and times.</p>
   <p>This paper proposes adding a symmetric parsing facility, <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">scan</c-></code>, to
complement <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">format</c-></code>. This facility is based on the same design principles
and shares many features with <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">format</c-></code>.</p>
   <p>This facility is not a parser per se, as it is probably not sufficient
for parsing something more complicated, e.g. JSON.
This is not a parser combinator library.
This is intended to be an almost-drop-in replacement for <code class="highlight"><c- n="">sscanf</c-></code>,
capable of being a building block for a more complicated parser.</p>
   <h2 class="heading settled" data-level="3" id="examples"><span class="secno">3. </span><span class="content">Examples</span><a class="self-link" href="#examples"></a></h2>
   <h3 class="heading settled" data-level="3.1" id="example-basic"><span class="secno">3.1. </span><span class="content">Basic example</span><a class="self-link" href="#example-basic"></a></h3>
<pre class="language-c++ highlight"><c- k="">if</c-> <c- p="">(</c-><c- k="">auto</c-> <c- n="">result</c-> <c- o="">=</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">scan</c-><c- o="">&lt;</c-><c- n="">std</c-><c- o="">::</c-><c- n="">string</c-><c- p="">,</c-> <c- b="">int</c-><c- o="">&gt;</c-><c- p="">(</c-><c- s="">"answer = 42"</c-><c- p="">,</c-> <c- s="">"{} = {}"</c-><c- p="">))</c-> <c- p="">{</c->
  <c- c1="">//                        ~~~~~~~~~~~~~~~~   ~~~~~~~~~~~    ~~~~~~~</c->
  <c- c1="">//                          output types        input        format</c->
  <c- c1="">//                                                           string</c->

  <c- k="">const</c-> <c- k="">auto</c-><c- o="">&amp;</c-> <c- p="">[</c-><c- n="">key</c-><c- p="">,</c-> <c- n="">value</c-><c- p="">]</c-> <c- o="">=</c-> <c- n="">result</c-><c- o="">-&gt;</c-><c- n="">values</c-><c- p="">();</c->
  <c- c1="">//           ~~~~~~~~~~</c->
  <c- c1="">//            scanned</c->
  <c- c1="">//            values</c->

  <c- c1="">// result is a std::expected&lt;std::scan_result&lt;...&gt;&gt;.</c->
  <c- c1="">// result-&gt;range() gives an empty range.</c->
  <c- c1="">// result-&gt;begin() == result-&gt;end()</c->
  <c- c1="">// key == "answer"</c->
  <c- c1="">// value == 42</c->
<c- p="">}</c-> <c- k="">else</c-> <c- p="">{</c->
  <c- c1="">// We would end up here if we had an error.</c->
  <c- n="">std</c-><c- o="">::</c-><c- n="">scan_error</c-> <c- n="">error</c-> <c- o="">=</c-> <c- n="">result</c-><c- p="">.</c-><c- n="">error</c-><c- p="">();</c->
<c- p="">}</c->
</pre>
   <h3 class="heading settled" data-level="3.2" id="example-multiple"><span class="secno">3.2. </span><span class="content">Reading multiple values at once</span><a class="self-link" href="#example-multiple"></a></h3>
<pre class="language-c++ highlight"><c- k="">auto</c-> <c- n="">input</c-> <c- o="">=</c-> <c- s="">"25 54.32E-1 Thompson 56789 0123"</c-><c- p="">;</c->

<c- k="">auto</c-> <c- n="">result</c-> <c- o="">=</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">scan</c-><c- o="">&lt;</c-><c- b="">int</c-><c- p="">,</c-> <c- b="">float</c-><c- p="">,</c-> <c- n="">string_view</c-><c- p="">,</c-> <c- b="">int</c-><c- p="">,</c-> <c- b="">float</c-><c- p="">,</c-> <c- b="">int</c-><c- o="">&gt;</c-><c- p="">(</c->
  <c- n="">input</c-><c- p="">,</c-> <c- s="">"{:d}{:f}{:9}{:2i}{:g}{:o}"</c-><c- p="">);</c->

<c- c1="">// result is a std::expected, operator-&gt; will throw if it doesn't contain a value</c->
<c- k="">auto</c-> <c- p="">[</c-><c- n="">i</c-><c- p="">,</c-> <c- n="">x</c-><c- p="">,</c-> <c- n="">str</c-><c- p="">,</c-> <c- n="">j</c-><c- p="">,</c-> <c- n="">y</c-><c- p="">,</c-> <c- n="">k</c-><c- p="">]</c-> <c- o="">=</c-> <c- n="">result</c-><c- o="">-&gt;</c-><c- n="">values</c-><c- p="">();</c->

<c- c1="">// i == 25</c->
<c- c1="">// x == 54.32e-1</c->
<c- c1="">// str == "Thompson"</c->
<c- c1="">// j == 56</c->
<c- c1="">// y == 789.0</c->
<c- c1="">// k == 0123</c->
</pre>
   <h3 class="heading settled" data-level="3.3" id="example-range"><span class="secno">3.3. </span><span class="content">Reading from a range</span><a class="self-link" href="#example-range"></a></h3>
<pre class="language-c++ highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">string</c-> <c- n="">input</c-><c- p="">{</c-><c- s="">"123 456"</c-><c- p="">};</c->
<c- k="">if</c-> <c- p="">(</c-><c- k="">auto</c-> <c- n="">result</c-> <c- o="">=</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">scan</c-><c- o="">&lt;</c-><c- b="">int</c-><c- o="">&gt;</c-><c- p="">(</c-><c- n="">std</c-><c- o="">::</c-><c- n="">views</c-><c- o="">::</c-><c- n="">reverse</c-><c- p="">(</c-><c- n="">input</c-><c- p="">),</c-> <c- s="">"{}"</c-><c- p="">))</c-> <c- p="">{</c->
  <c- c1="">// If only a single value is returned, it can be accessed with result-&gt;value()</c->
  <c- c1="">// result-&gt;value() == 654</c->
<c- p="">}</c->
</pre>
   <h3 class="heading settled" data-level="3.4" id="example-loop"><span class="secno">3.4. </span><span class="content">Reading multiple values in a loop</span><a class="self-link" href="#example-loop"></a></h3>
<pre class="language-c++ highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">vector</c-><c- o="">&lt;</c-><c- b="">int</c-><c- o="">&gt;</c-> <c- n="">read_values</c-><c- p="">;</c->
<c- n="">std</c-><c- o="">::</c-><c- n="">ranges</c-><c- o="">::</c-><c- n="">forward_range</c-> <c- k="">auto</c-> <c- n="">range</c-> <c- o="">=</c-> <c- p="">...;</c->

<c- k="">auto</c-> <c- n="">input</c-> <c- o="">=</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">ranges</c-><c- o="">::</c-><c- n="">subrange</c-><c- p="">{</c-><c- n="">range</c-><c- p="">};</c->

<c- k="">while</c-> <c- p="">(</c-><c- k="">auto</c-> <c- n="">result</c-> <c- o="">=</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">scan</c-><c- o="">&lt;</c-><c- b="">int</c-><c- o="">&gt;</c-><c- p="">(</c-><c- n="">input</c-><c- p="">,</c-> <c- s="">"{}"</c-><c- p="">))</c-> <c- p="">{</c->
  <c- n="">read_values</c-><c- p="">.</c-><c- n="">push_back</c-><c- p="">(</c-><c- n="">result</c-><c- o="">-&gt;</c-><c- n="">value</c-><c- p="">());</c->
  <c- n="">input</c-> <c- o="">=</c-> <c- n="">result</c-><c- o="">-&gt;</c-><c- n="">range</c-><c- p="">();</c->
<c- p="">}</c->
</pre>
   <h3 class="heading settled" data-level="3.5" id="example-alt-error"><span class="secno">3.5. </span><span class="content">Alternative error handling</span><a class="self-link" href="#example-alt-error"></a></h3>
<pre class="highlight"><c- c1="">// Since std::scan returns a std::expected,</c->
<c- c1="">// its monadic interface can be used</c->

<c- k="">auto</c-> <c- n="">result</c-> <c- o="">=</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">scan</c-><c- o="">&lt;</c-><c- b="">int</c-><c- o="">&gt;</c-><c- p="">(...,</c-> <c- s="">"{}"</c-><c- p="">)</c->
  <c- p="">.</c-><c- n="">transform</c-><c- p="">([](</c-><c- k="">auto</c-> <c- n="">result</c-><c- p="">)</c-> <c- p="">{</c->
    <c- k="">return</c-> <c- n="">result</c-><c- p="">.</c-><c- n="">value</c-><c- p="">();</c->
  <c- p="">});</c->
<c- k="">if</c-> <c- p="">(</c-><c- o="">!</c-><c- n="">result</c-><c- p="">)</c-> <c- p="">{</c->
  <c- c1="">// handle error</c->
<c- p="">}</c->
<c- b="">int</c-> <c- n="">num</c-> <c- o="">=</c-> <c- o="">*</c-><c- n="">result</c-><c- p="">;</c->

<c- c1="">// With [</c-><a data-link-type="biblio" href="#biblio-p2561" title="A control flow operator"><c- c1="">P2561</c-></a><c- c1="">]:</c->
<c- b="">int</c-> <c- n="">num</c-> <c- o="">=</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">scan</c-><c- o="">&lt;</c-><c- b="">int</c-><c- o="">&gt;</c-><c- p="">(...,</c-> <c- s="">"{}"</c-><c- p="">).</c-><c- k="">try</c-><c- o="">?</c-><c- p="">.</c-><c- n="">value</c-><c- p="">();</c->
</pre>
   <h3 class="heading settled" data-level="3.6" id="example-userdef"><span class="secno">3.6. </span><span class="content">Scanning a user-defined type</span><a class="self-link" href="#example-userdef"></a></h3>
<pre class="language-c++ highlight"><c- k="">struct</c-> <c- nc="">mytype</c-> <c- p="">{</c->
  <c- b="">int</c-> <c- n="">a</c-><c- p="">{},</c-> <c- n="">b</c-><c- p="">{};</c->
<c- p="">};</c->

<c- c1="">// Specialize std::scanner to add support for user-defined types.</c->
<c- c1="">// Inherit from std::scanner&lt;std::string&gt; to get format string parsing</c->
<c- c1="">// (scanner::parse()) from it.</c->
<c- n="">template</c-> <c- o="">&lt;&gt;</c->
<c- k="">struct</c-> <c- nc="">std</c-><c- o="">::</c-><c- n="">scanner</c-><c- o="">&lt;</c-><c- n="">mytype</c-><c- o="">&gt;</c-> <c- o="">:</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">scanner</c-><c- o="">&lt;</c-><c- n="">std</c-><c- o="">::</c-><c- n="">string</c-><c- o="">&gt;</c-> <c- p="">{</c->
  <c- n="">template</c-> <c- o="">&lt;</c-><c- n="">typename</c-> <c- n="">Context</c-><c- o="">&gt;</c->
  <c- k="">auto</c-> <c- n="">scan</c-><c- p="">(</c-><c- n="">mytype</c-><c- o="">&amp;</c-> <c- n="">val</c-><c- p="">,</c-> <c- n="">Context</c-><c- o="">&amp;</c-> <c- n="">ctx</c-><c- p="">)</c-> <c- k="">const</c->
      <c- o="">-&gt;</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">expected</c-><c- o="">&lt;</c-><c- n="">typename</c-> <c- n="">Context</c-><c- o="">::</c-><c- n="">iterator</c-><c- p="">,</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">scan_error</c-><c- o="">&gt;</c-> <c- p="">{</c->
    <c- k="">return</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">scan</c-><c- o="">&lt;</c-><c- b="">int</c-><c- p="">,</c-> <c- b="">int</c-><c- o="">&gt;</c-><c- p="">(</c-><c- n="">ctx</c-><c- p="">.</c-><c- n="">range</c-><c- p="">(),</c-> <c- s="">"[{}, {}]"</c-><c- p="">)</c->
      <c- p="">.</c-><c- n="">transform</c-><c- p="">([</c-><c- o="">&amp;</c-><c- n="">val</c-><c- p="">](</c-><c- k="">const</c-> <c- k="">auto</c-><c- o="">&amp;</c-> <c- n="">result</c-><c- p="">)</c-> <c- p="">{</c->
        <c- n="">std</c-><c- o="">::</c-><c- n="">tie</c-><c- p="">(</c-><c- n="">val</c-><c- p="">.</c-><c- n="">a</c-><c- p="">,</c-> <c- n="">val</c-><c- p="">.</c-><c- n="">b</c-><c- p="">)</c-> <c- o="">=</c-> <c- n="">result</c-><c- p="">.</c-><c- n="">values</c-><c- p="">();</c->
        <c- k="">return</c-> <c- n="">result</c-><c- p="">.</c-><c- n="">begin</c-><c- p="">();</c->
      <c- p="">});</c->
  <c- p="">}</c->
<c- p="">};</c->

<c- k="">auto</c-> <c- n="">result</c-> <c- o="">=</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">scan</c-><c- o="">&lt;</c-><c- n="">mytype</c-><c- o="">&gt;</c-><c- p="">(</c-><c- s="">"[123, 456]"</c-><c- p="">,</c-> <c- s="">"{}"</c-><c- p="">);</c->
<c- c1="">// result-&gt;value().a == 123</c->
<c- c1="">// result-&gt;value().b == 456</c->
</pre>
   <h2 class="heading settled" data-level="4" id="design"><span class="secno">4. </span><span class="content">Design</span><a class="self-link" href="#design"></a></h2>
   <p>The new parsing facility is intended to complement the existing C++ I/O streams
library, integrate well with the chrono library, and provide an API similar to <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">format</c-></code>. This section discusses the major features of its design.</p>
   <h3 class="heading settled" data-level="4.1" id="overview"><span class="secno">4.1. </span><span class="content">Overview</span><a class="self-link" href="#overview"></a></h3>
   <p>The main user-facing part of the library described in this paper,
is the function template <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">scan</c-></code>, the input counterpart of <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">format</c-></code>.
The signature of <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">scan</c-></code> is as follows:</p>
<pre class="language-c++ highlight"><c- n="">template</c-> <c- o="">&lt;</c-><c- n="">class</c-><c- p="">...</c-> <c- n="">Args</c-><c- p="">,</c-> <c- n="">scannable_range</c-><c- o="">&lt;</c-><c- b="">char</c-><c- o="">&gt;</c-> <c- n="">Range</c-><c- o="">&gt;</c->
<c- k="">auto</c-> <c- n="">scan</c-><c- p="">(</c-><c- n="">Range</c-><c- o="">&amp;&amp;</c-> <c- n="">range</c-><c- p="">,</c-> <c- n="">scan_format_string</c-><c- o="">&lt;</c-><c- n="">Range</c-><c- p="">,</c-> <c- n="">Args</c-><c- p="">...</c-><c- o="">&gt;</c-> <c- n="">fmt</c-><c- p="">)</c->
  <c- o="">-&gt;</c-> <c- n="">expected</c-><c- o="">&lt;</c-><c- n="">scan_result</c-><c- o="">&lt;</c-><c- n="">ranges</c-><c- o="">::</c-><c- n="">borrowed_tail_subrange_t</c-><c- o="">&lt;</c-><c- n="">Range</c-><c- o="">&gt;</c-><c- p="">,</c-> <c- n="">Args</c-><c- p="">...</c-><c- o="">&gt;</c-><c- p="">,</c-> <c- n="">scan_error</c-><c- o="">&gt;</c-><c- p="">;</c->

<c- n="">template</c-> <c- o="">&lt;</c-><c- n="">class</c-><c- p="">...</c-> <c- n="">Args</c-><c- p="">,</c-> <c- n="">scannable_range</c-><c- o="">&lt;</c-><c- b="">wchar_t</c-><c- o="">&gt;</c-> <c- n="">Range</c-><c- o="">&gt;</c->
<c- k="">auto</c-> <c- n="">scan</c-><c- p="">(</c-><c- n="">Range</c-><c- o="">&amp;&amp;</c-> <c- n="">range</c-><c- p="">,</c-> <c- n="">wscan_format_string</c-><c- o="">&lt;</c-><c- n="">Range</c-><c- p="">,</c-> <c- n="">Args</c-><c- p="">...</c-><c- o="">&gt;</c-> <c- n="">fmt</c-><c- p="">)</c->
  <c- o="">-&gt;</c-> <c- n="">expected</c-><c- o="">&lt;</c-><c- n="">scan_result</c-><c- o="">&lt;</c-><c- n="">ranges</c-><c- o="">::</c-><c- n="">borrowed_tail_subrange_t</c-><c- o="">&lt;</c-><c- n="">Range</c-><c- o="">&gt;</c-><c- p="">,</c-> <c- n="">Args</c-><c- p="">...</c-><c- o="">&gt;</c-><c- p="">,</c-> <c- n="">scan_error</c-><c- o="">&gt;</c-><c- p="">;</c->
</pre>
   <p><code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">scan</c-></code> reads values of type <code class="highlight"><c- n="">Args</c-><c- p="">...</c-></code> from the <code class="highlight"><c- n="">range</c-></code> it’s given,
according to the instructions given to it in the format string, <code class="highlight"><c- n="">fmt</c-></code>. <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">scan</c-></code> returns a <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">expected</c-></code>, containing either a <code class="highlight"><c- n="">scan_result</c-></code>, or a <code class="highlight"><c- n="">scan_error</c-></code>.
The <code class="highlight"><c- n="">scan_result</c-></code> object contains a <code class="highlight"><c- n="">subrange</c-></code> pointing to the unparsed input,
and a <code class="highlight"><c- n="">tuple</c-></code> of <code class="highlight"><c- n="">Args</c-><c- p="">...</c-></code>, containing the scanned values.</p>
   <h3 class="heading settled" data-level="4.2" id="format-strings"><span class="secno">4.2. </span><span class="content">Format strings</span><a class="self-link" href="#format-strings"></a></h3>
   <p>As with <code class="highlight"><c- n="">printf</c-></code>, the <code class="highlight"><c- n="">scanf</c-></code> syntax has the advantage of being familiar to many
programmers. However, it has similar limitations:</p>
   <ul>
    <li data-md="">
     <p>Many format specifiers like <code class="highlight"><c- n="">hh</c-></code>, <code class="highlight"><c- n="">h</c-></code>, <code class="highlight"><c- n="">l</c-></code>, <code class="highlight"><c- n="">j</c-></code>, etc. are used only to
convey type information. They are redundant in type-safe parsing and would
unnecessarily complicate specification and parsing.</p>
    </li><li data-md="">
     <p>There is no standard way to extend the syntax for user-defined types.</p>
    </li><li data-md="">
     <p>Using <code class="highlight"><c- sc="">'%'</c-></code> in a custom format specifier poses difficulties, e.g. for <code class="highlight"><c- n="">get_time</c-></code>-like time parsing.</p>
   </li></ul>
   <p>Therefore, we propose a syntax based on <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">format</c-></code> and <a data-link-type="biblio" href="#biblio-parse" title="Python `parse` package">[PARSE]</a>. This syntax
employs <code class="highlight"><c- sc="">'{'</c-></code> and <code class="highlight"><c- sc="">'}'</c-></code> as replacement field delimiters instead of <code class="highlight"><c- sc="">'%'</c-></code>. It
will provide the following advantages:</p>
   <ul>
    <li data-md="">
     <p>An easy-to-parse mini-language focused on the data format rather than
conveying the type information</p>
    </li><li data-md="">
     <p>Extensibility for user-defined types</p>
    </li><li data-md="">
     <p>Positional arguments</p>
    </li><li data-md="">
     <p>Support for both locale-specific and locale-independent parsing (see <a href="#locales">§ 4.10 Locales</a>)</p>
    </li><li data-md="">
     <p>Consistency with <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">format</c-></code>.</p>
   </li></ul>
   <p>At the same time, most of the specifiers will remain quite similar to the ones
in <code class="highlight"><c- n="">scanf</c-></code>, which can simplify a, possibly automated, migration.</p>
   <p>Maintaining similarity with <code class="highlight"><c- n="">scanf</c-></code>, for any literal non-whitespace character in
the format string, an identical character is consumed from the input range.
For whitespace characters, all available whitespace characters are consumed.</p>
   <p>In this proposal, "whitespace" is defined to be the Unicode code points
with the Pattern_White_Space property, as defined by UAX #31 (UAX31-R3a).
Those code points are currently:</p>
   <ul>
    <li data-md="">
     <p>ASCII whitespace characters (U+0009 to U+000D, U+0020)</p>
    </li><li data-md="">
     <p>U+0085 (next line)</p>
    </li><li data-md="">
     <p>U+200E and U+200F (LEFT-TO-RIGHT MARK and RIGHT-TO-LEFT MARK)</p>
    </li><li data-md="">
     <p>U+2028 and U+2029 (LINE SEPARATOR and PARAGRAPH SEPARATOR)</p>
   </li></ul>
   <p>Unicode defines a lot of different things
in the realm of whitespace, all for different kinds of use cases.
The Pattern_White_Space-property is chosen for its stability (it’s guaranteed to not change),
and because its intended use is for classifying things that should be treated as
whitespace in machine-readable syntaxes. <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">isspace</c-></code> is insufficient for usage in a Unicode world,
because it only accepts a single code unit as input.</p>
   <div class="example" id="example-ed0e931a">
    <a class="self-link" href="#example-ed0e931a"></a> 
<pre class="language-c++ highlight"><c- k="">auto</c-> <c- n="">r0</c-> <c- o="">=</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">scan</c-><c- o="">&lt;</c-><c- b="">char</c-><c- o="">&gt;</c-><c- p="">(</c-><c- s="">"abcd"</c-><c- p="">,</c-> <c- s="">"ab{}d"</c-><c- p="">);</c-> <c- c1="">// r0-&gt;value() == 'c'</c->

<c- k="">auto</c-> <c- n="">r1</c-> <c- o="">=</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">scan</c-><c- o="">&lt;</c-><c- n="">string</c-><c- p="">,</c-> <c- n="">string</c-><c- o="">&gt;</c-><c- p="">(</c-><c- s="">"abc </c-><c- se="">\n</c-><c- s=""> def"</c-><c- p="">,</c-> <c- s="">"{} {}"</c-><c- p="">);</c->
<c- k="">const</c-> <c- k="">auto</c-><c- o="">&amp;</c-> <c- p="">[</c-><c- n="">s1</c-><c- p="">,</c-> <c- n="">s2</c-><c- p="">]</c-> <c- o="">=</c-> <c- n="">r1</c-><c- o="">-&gt;</c-><c- n="">values</c-><c- p="">();</c-> <c- c1="">// s1 == "abc", s2 == "def"</c->
</pre>
   </div>
   <p>As mentioned above, the format string syntax consists of replacement fields
delimited by curly brackets (<code class="highlight"><c- p="">{</c-></code> and <code class="highlight"><c- p="">}</c-></code>).
Each of these replacement fields corresponds to a value to be scanned from the input range.
The replacement field syntax is quite similar to <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">format</c-></code>, as can be seen in the table below.
Elements that are in one but not the other are highlighted.</p>
   <table>
    <thead>
     <tr>
      <th><code class="highlight"><c- n="">scan</c-></code> replacement field syntax
      </th><th><code class="highlight"><c- n="">format</c-></code> replacement field syntax
    </th></tr></thead><tbody>
     <tr>
      <td>
<pre class="highlight"><c- n="">replacement</c-><c- o="">-</c-><c- n="">field</c-> <c- o="">::=</c-> <c- sc="">'{'</c-> <c- p="">[</c-><c- n="">arg</c-><c- o="">-</c-><c- n="">id</c-><c- p="">]</c-> <c- p="">[</c-><c- sc="">':'</c-> <c- n="">format</c-><c- o="">-</c-><c- n="">spec</c-><c- p="">]</c-> <c- sc="">'}'</c->
<c- n="">format</c-><c- o="">-</c-><c- n="">spec</c->       <c- o="">::=</c-> <c- p="">[</c-><c- n="">fill</c-><c- o="">-</c-><c- k="">and</c-><c- o="">-</c-><c- n="">align</c-><c- p="">]</c->
                      
                      <c- p="">[</c-><c- n="">width</c-><c- p="">]</c->
                      <c- p="">[</c-><c- sc="">'L'</c-><c- p="">]</c-> <c- p="">[</c-><c- n="">type</c-><c- p="">]</c->
<c- n="">fill</c-><c- o="">-</c-><c- k="">and</c-><c- o="">-</c-><c- n="">align</c->    <c- o="">::=</c-> <c- p="">[</c-><c- n="">fill</c-><c- p="">]</c-> <c- n="">align</c->
<c- n="">fill</c->              <c- o="">::=</c-> <i><c- n="">any</c-> <c- n="">character</c-> <c- n="">other</c-> <c- n="">than</c-></i>
                      <c- sc="">'{'</c-> <i><c- k="">or</c-></i> <c- sc="">'}'</c->
<c- n="">align</c->             <c- o="">::=</c-> <i><c- n="">one</c-> <c- n="">of</c-></i> <c- sc="">'&lt;'</c-> <c- sc="">'&gt;'</c-> <c- sc="">'^'</c->

<c- n="">width</c->             <c- o="">::=</c-> <c- n="">positive</c-><c- o="">-</c-><c- n="">integer</c->



<c- n="">type</c->              <c- o="">::=</c-> <i><c- n="">one</c-> <c- n="">of</c-></i>
                      <c- sc="">'a'</c-> <c- sc="">'A'</c->
                      <c- sc="">'b'</c-> <c- sc="">'B'</c->
                      <c- sc="">'c'</c->
                      <c- sc="">'d'</c->
                      <c- sc="">'e'</c-> <c- sc="">'E'</c->
                      <c- sc="">'f'</c-> <c- sc="">'F'</c->
                      <c- sc="">'g'</c-> <c- sc="">'G'</c->
                      <c- sc="">'o'</c->
                      <c- sc="">'p'</c->
                      <c- sc="">'s'</c->
                      <c- sc="">'x'</c-> <c- sc="">'X'</c->
                      <c- sc="">'?'</c->
                      <ins><c- sc="">'i'</c-></ins>
                      <ins><c- sc="">'u'</c-></ins>
</pre>
      </td><td>
<pre class="highlight"><c- n="">replacement</c-><c- o="">-</c-><c- n="">field</c-> <c- o="">::=</c-> <c- sc="">'{'</c-> <c- p="">[</c-><c- n="">arg</c-><c- o="">-</c-><c- n="">id</c-><c- p="">]</c-> <c- p="">[</c-><c- sc="">':'</c-> <c- n="">format</c-><c- o="">-</c-><c- n="">spec</c-><c- p="">]</c-> <c- sc="">'}'</c->
<c- n="">format</c-><c- o="">-</c-><c- n="">spec</c->       <c- o="">::=</c-> <c- p="">[</c-><c- n="">fill</c-><c- o="">-</c-><c- k="">and</c-><c- o="">-</c-><c- n="">align</c-><c- p="">]</c->
                      <ins><c- p="">[</c-><c- n="">sign</c-><c- p="">]</c-> <c- p="">[</c-><c- sc="">'#'</c-><c- p="">]</c-> <c- p="">[</c-><c- sc="">'0'</c-><c- p="">]</c-></ins>
                      <c- p="">[</c-><c- n="">width</c-><c- p="">]</c-> <ins><c- p="">[</c-><c- n="">precision</c-><c- p="">]</c-></ins>
                      <c- p="">[</c-><c- sc="">'L'</c-><c- p="">]</c-> <c- p="">[</c-><c- n="">type</c-><c- p="">]</c->
<c- n="">fill</c-><c- o="">-</c-><c- k="">and</c-><c- o="">-</c-><c- n="">align</c->    <c- o="">::=</c-> <c- p="">[</c-><c- n="">fill</c-><c- p="">]</c-> <c- n="">align</c->
<c- n="">fill</c->              <c- o="">::=</c-> <i><c- n="">any</c-> <c- n="">character</c-> <c- n="">other</c-> <c- n="">than</c-></i>
                      <c- sc="">'{'</c-> <i><c- k="">or</c-></i> <c- sc="">'}'</c->
<c- n="">align</c->             <c- o="">::=</c-> <i><c- n="">one</c-> <c- n="">of</c-></i> <c- sc="">'&lt;'</c-> <c- sc="">'&gt;'</c-> <c- sc="">'^'</c->
<ins><c- n="">sign</c->              <c- o="">::=</c-> <i><c- n="">one</c-> <c- n="">of</c-></i> <c- sc="">'+'</c-> <c- sc="">'-'</c-> <c- sc="">' '</c-></ins>
<c- n="">width</c->             <c- o="">::=</c-> <c- n="">positive</c-><c- o="">-</c-><c- n="">integer</c->
                      <ins><i><c- n="">OR</c-></i> <c- sc="">'{'</c-> <c- p="">[</c-><c- n="">arg</c-><c- o="">-</c-><c- n="">id</c-><c- p="">]</c-> <c- sc="">'}'</c-></ins>
<ins><c- n="">precision</c->         <c- o="">::=</c-> <c- sc="">'.'</c-> <c- n="">nonnegative</c-><c- o="">-</c-><c- n="">integer</c->
                      <i><c- n="">OR</c-></i> <c- sc="">'.'</c-> <c- sc="">'{'</c-> <c- p="">[</c-><c- n="">arg</c-><c- o="">-</c-><c- n="">id</c-><c- p="">]</c-> <c- sc="">'}'</c-></ins>
<c- n="">type</c->              <c- o="">::=</c-> <i><c- n="">one</c-> <c- n="">of</c-></i>
                      <c- sc="">'a'</c-> <c- sc="">'A'</c->
                      <c- sc="">'b'</c-> <c- sc="">'B'</c->
                      <c- sc="">'c'</c->
                      <c- sc="">'d'</c->
                      <c- sc="">'e'</c-> <c- sc="">'E'</c->
                      <c- sc="">'f'</c-> <c- sc="">'F'</c->
                      <c- sc="">'g'</c-> <c- sc="">'G'</c->
                      <c- sc="">'o'</c->
                      <c- sc="">'p'</c->
                      <c- sc="">'s'</c->
                      <c- sc="">'x'</c-> <c- sc="">'X'</c->
                      <c- sc="">'?'</c->


</pre>
   </td></tr></tbody></table>
   <h3 class="heading settled" data-level="4.3" id="format-string-specifiers"><span class="secno">4.3. </span><span class="content">Format string specifiers</span><a class="self-link" href="#format-string-specifiers"></a></h3>
   <p>Below is a somewhat detailed description of each of the specifiers
in a <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">scan</c-></code> replacement field.
This design attempts to maintain decent compatibility with <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">format</c-></code> whenever practical, while also bringing in some ideas from <code class="highlight"><c- n="">scanf</c-></code>.</p>
   <h4 class="heading settled" data-level="4.3.1" id="fmt-arg-id"><span class="secno">4.3.1. </span><span class="content">Manual indexing</span><a class="self-link" href="#fmt-arg-id"></a></h4>
<pre class="highlight"><c- n="">replacement</c-><c- o="">-</c-><c- n="">field</c-> <c- o="">::=</c-> <c- sc="">'{'</c-> <c- p="">[</c-><c- n="">arg</c-><c- o="">-</c-><c- n="">id</c-><c- p="">]</c-> <c- p="">[</c-><c- sc="">':'</c-> <c- n="">format</c-><c- o="">-</c-><c- n="">spec</c-><c- p="">]</c-> <c- sc="">'}'</c->
</pre>
   <p>Like <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">format</c-></code>, <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">scan</c-></code> supports manual indexing of
arguments in format strings. If manual indexing is used,
all of the argument indices have to be spelled out.
Different from <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">format</c-></code>, the same index can only be used once.</p>
   <div class="example" id="example-7342d0ac">
    <a class="self-link" href="#example-7342d0ac"></a> 
<pre class="language-c++ highlight"><c- k="">auto</c-> <c- n="">r</c-> <c- o="">=</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">scan</c-><c- o="">&lt;</c-><c- b="">int</c-><c- p="">,</c-> <c- b="">int</c-><c- p="">,</c-> <c- b="">int</c-><c- o="">&gt;</c-><c- p="">(</c-><c- s="">"0 1 2"</c-><c- p="">,</c-> <c- s="">"{1} {0} {2}"</c-><c- p="">);</c->
<c- k="">auto</c-> <c- p="">[</c-><c- n="">i0</c-><c- p="">,</c-> <c- n="">i1</c-><c- p="">,</c-> <c- n="">i2</c-><c- p="">]</c-> <c- o="">=</c-> <c- n="">r</c-><c- o="">-&gt;</c-><c- n="">values</c-><c- p="">();</c->
<c- c1="">// i0 == 1, i1 == 0, i2 == 2</c->
</pre>
   </div>
   <h4 class="heading settled" data-level="4.3.2" id="fmt-fill-and-align"><span class="secno">4.3.2. </span><span class="content">Fill and align</span><a class="self-link" href="#fmt-fill-and-align"></a></h4>
<pre class="highlight"><c- n="">fill</c-><c- o="">-</c-><c- k="">and</c-><c- o="">-</c-><c- n="">align</c->  <c- o="">::=</c-> <c- p="">[</c-><c- n="">fill</c-><c- p="">]</c-> <c- n="">align</c->
<c- n="">fill</c->            <c- o="">::=</c-> <i><c- n="">any</c-> <c- n="">character</c-> <c- n="">other</c-> <c- n="">than</c-></i>
                    <c- sc="">'{'</c-> <i><c- k="">or</c-></i> <c- sc="">'}'</c->
<c- n="">align</c->           <c- o="">::=</c-> <i><c- n="">one</c-> <c- n="">of</c-></i> <c- sc="">'&lt;'</c-> <c- sc="">'&gt;'</c-> <c- sc="">'^'</c->
</pre>
   <p>The fill and align options are valid for all argument types.
The fill character is denoted by the <code class="highlight"><c- n="">fill</c-></code>-option, or if it is absent,
the space character <code class="highlight"><c- sc="">' '</c-></code>.
The fill character can be any single Unicode scalar value.
The field width is determined the same way as it is for <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">format</c-></code>.</p>
   <p>If an alignment is specified, the value to be parsed is assumed to be properly
aligned with the specified fill character.</p>
   <p>If a field width is specified, it will be the maximum number of characters
to be consumed from the input range.
In that case, if no alignment is specified, the default alignment for the type
is considered (see <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">format</c-></code>).</p>
   <p>For the <code class="highlight"><c- sc="">'^'</c-></code> alignment, the number of fill characters needs to be
the same as if formatted with <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">format</c-></code>: <code class="highlight"><c- n="">floor</c-><c- p="">(</c-><c- n="">n</c-><c- o="">/</c-><c- mi="">2</c-><c- p="">)</c-></code> characters before, <code class="highlight"><c- n="">ceil</c-><c- p="">(</c-><c- n="">n</c-><c- o="">/</c-><c- mi="">2</c-><c- p="">)</c-></code> characters after the value,
where <code class="highlight"><c- n="">n</c-></code> is the field width.
If no field width is specified, an equal number of alignment characters on both
sides are assumed.</p>
   <p>This spec is compatible with <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">format</c-></code>,
i.e., the same format string (wrt. fill and align)
can be used with both <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">format</c-></code> and <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">scan</c-></code>,
with round-trip semantics.</p>
   <p class="note" role="note"><span class="marker">Note:</span> For format type specifiers other than <code class="highlight"><c- sc="">'c'</c-></code> (default for <code class="highlight"><c- b="">char</c-></code> and <code class="highlight"><c- b="">wchar_t</c-></code>, can be specified for <code class="highlight"><c- n="">basic_string</c-></code> and <code class="highlight"><c- n="">basic_string_view</c-></code>),
leading whitespace is skipped regardless of alignment specifiers.</p>
   <div class="example" id="example-4783cbd9">
    <a class="self-link" href="#example-4783cbd9"></a> 
<pre class="language-c++ highlight"><c- k="">auto</c-> <c- n="">r0</c-> <c- o="">=</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">scan</c-><c- o="">&lt;</c-><c- b="">int</c-><c- o="">&gt;</c-><c- p="">(</c-><c- s="">"   42"</c-><c- p="">,</c-> <c- s="">"{}"</c-><c- p="">);</c-> <c- c1="">// r0-&gt;value() == 42, r0-&gt;range() == ""</c->
<c- k="">auto</c-> <c- n="">r1</c-> <c- o="">=</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">scan</c-><c- o="">&lt;</c-><c- b="">char</c-><c- o="">&gt;</c-><c- p="">(</c-><c- s="">"   x"</c-><c- p="">,</c-> <c- s="">"{}"</c-><c- p="">);</c-> <c- c1="">// r1-&gt;value() == ' ', r1-&gt;range() == "  x"</c->
<c- k="">auto</c-> <c- n="">r2</c-> <c- o="">=</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">scan</c-><c- o="">&lt;</c-><c- b="">char</c-><c- o="">&gt;</c-><c- p="">(</c-><c- s="">"x   "</c-><c- p="">,</c-> <c- s="">"{}"</c-><c- p="">);</c-> <c- c1="">// r2-&gt;value() == 'x', r2-&gt;range() == "   "</c->

<c- k="">auto</c-> <c- n="">r3</c-> <c- o="">=</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">scan</c-><c- o="">&lt;</c-><c- b="">int</c-><c- o="">&gt;</c-><c- p="">(</c-><c- s="">"    42"</c-><c- p="">,</c-> <c- s="">"{:6}"</c-><c- p="">);</c->  <c- c1="">// r3-&gt;value() == 42, r3-&gt;range() == ""</c->
<c- k="">auto</c-> <c- n="">r4</c-> <c- o="">=</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">scan</c-><c- o="">&lt;</c-><c- b="">char</c-><c- o="">&gt;</c-><c- p="">(</c-><c- s="">"x     "</c-><c- p="">,</c-> <c- s="">"{:6}"</c-><c- p="">);</c-> <c- c1="">// r4-&gt;value() == 'x', r4-&gt;range() == ""</c->

<c- k="">auto</c-> <c- n="">r5</c-> <c- o="">=</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">scan</c-><c- o="">&lt;</c-><c- b="">int</c-><c- o="">&gt;</c-><c- p="">(</c-><c- s="">"***42"</c-><c- p="">,</c-> <c- s="">"{:*&gt;}"</c-><c- p="">);</c->  <c- c1="">// r5-&gt;value() == 42</c->
<c- k="">auto</c-> <c- n="">r6</c-> <c- o="">=</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">scan</c-><c- o="">&lt;</c-><c- b="">int</c-><c- o="">&gt;</c-><c- p="">(</c-><c- s="">"***42"</c-><c- p="">,</c-> <c- s="">"{:*&gt;5}"</c-><c- p="">);</c-> <c- c1="">// r6-&gt;value() == 42</c->
<c- k="">auto</c-> <c- n="">r7</c-> <c- o="">=</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">scan</c-><c- o="">&lt;</c-><c- b="">int</c-><c- o="">&gt;</c-><c- p="">(</c-><c- s="">"***42"</c-><c- p="">,</c-> <c- s="">"{:*&gt;4}"</c-><c- p="">);</c-> <c- c1="">// r7-&gt;value() == 4</c->
<c- k="">auto</c-> <c- n="">r8</c-> <c- o="">=</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">scan</c-><c- o="">&lt;</c-><c- b="">int</c-><c- o="">&gt;</c-><c- p="">(</c-><c- s="">"42"</c-><c- p="">,</c-> <c- s="">"{:*&gt;}"</c-><c- p="">);</c->     <c- c1="">// r8-&gt;value() == 42</c->
<c- k="">auto</c-> <c- n="">r9</c-> <c- o="">=</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">scan</c-><c- o="">&lt;</c-><c- b="">int</c-><c- o="">&gt;</c-><c- p="">(</c-><c- s="">"42"</c-><c- p="">,</c-> <c- s="">"{:*&gt;5}"</c-><c- p="">);</c->    <c- c1="">// ERROR (mismatching field width)</c->

<c- k="">auto</c-> <c- n="">rA</c-> <c- o="">=</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">scan</c-><c- o="">&lt;</c-><c- b="">int</c-><c- o="">&gt;</c-><c- p="">(</c-><c- s="">"42***"</c-><c- p="">,</c-> <c- s="">"{:*&lt;}"</c-><c- p="">);</c->  <c- c1="">// rA-&gt;value() == 42, rA-&gt;range() == ""</c->
<c- k="">auto</c-> <c- n="">rB</c-> <c- o="">=</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">scan</c-><c- o="">&lt;</c-><c- b="">int</c-><c- o="">&gt;</c-><c- p="">(</c-><c- s="">"42***"</c-><c- p="">,</c-> <c- s="">"{:*&lt;5}"</c-><c- p="">);</c-> <c- c1="">// rB-&gt;value() == 42, rB-&gt;range() == ""</c->
<c- k="">auto</c-> <c- n="">rC</c-> <c- o="">=</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">scan</c-><c- o="">&lt;</c-><c- b="">int</c-><c- o="">&gt;</c-><c- p="">(</c-><c- s="">"42***"</c-><c- p="">,</c-> <c- s="">"{:*&lt;4}"</c-><c- p="">);</c-> <c- c1="">// rC-&gt;value() == 42, rC-&gt;range() == "*"</c->
<c- k="">auto</c-> <c- n="">rD</c-> <c- o="">=</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">scan</c-><c- o="">&lt;</c-><c- b="">int</c-><c- o="">&gt;</c-><c- p="">(</c-><c- s="">"42"</c-><c- p="">,</c-> <c- s="">"{:*&lt;}"</c-><c- p="">);</c->     <c- c1="">// rD-&gt;value() == 42</c->
<c- k="">auto</c-> <c- n="">rE</c-> <c- o="">=</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">scan</c-><c- o="">&lt;</c-><c- b="">int</c-><c- o="">&gt;</c-><c- p="">(</c-><c- s="">"42"</c-><c- p="">,</c-> <c- s="">"{:*&lt;5}"</c-><c- p="">);</c->    <c- c1="">// ERROR (mismatching field width)</c->

<c- k="">auto</c-> <c- n="">rF</c-> <c- o="">=</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">scan</c-><c- o="">&lt;</c-><c- b="">int</c-><c- o="">&gt;</c-><c- p="">(</c-><c- s="">"42"</c-><c- p="">,</c-> <c- s="">"{:*^}"</c-><c- p="">);</c->    <c- c1="">// rF-&gt;value() == 42, rF-&gt;range() == ""</c->
<c- k="">auto</c-> <c- n="">rG</c-> <c- o="">=</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">scan</c-><c- o="">&lt;</c-><c- b="">int</c-><c- o="">&gt;</c-><c- p="">(</c-><c- s="">"*42*"</c-><c- p="">,</c-> <c- s="">"{:*^}"</c-><c- p="">);</c->  <c- c1="">// rG-&gt;value() == 42, rG-&gt;range() == ""</c->
<c- k="">auto</c-> <c- n="">rH</c-> <c- o="">=</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">scan</c-><c- o="">&lt;</c-><c- b="">int</c-><c- o="">&gt;</c-><c- p="">(</c-><c- s="">"*42**"</c-><c- p="">,</c-> <c- s="">"{:*^}"</c-><c- p="">);</c-> <c- c1="">// rH-&gt;value() == 42, rH-&gt;range() == "*"</c->
<c- k="">auto</c-> <c- n="">rI</c-> <c- o="">=</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">scan</c-><c- o="">&lt;</c-><c- b="">int</c-><c- o="">&gt;</c-><c- p="">(</c-><c- s="">"**42*"</c-><c- p="">,</c-> <c- s="">"{:*^}"</c-><c- p="">);</c-> <c- c1="">// ERROR (not enough fill characters after value)</c->

<c- k="">auto</c-> <c- n="">rJ</c-> <c- o="">=</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">scan</c-><c- o="">&lt;</c-><c- b="">int</c-><c- o="">&gt;</c-><c- p="">(</c-><c- s="">"**42**"</c-><c- p="">,</c-> <c- s="">"{:*^6}"</c-><c- p="">);</c-> <c- c1="">// rJ-&gt;value() == 42, rJ-&gt;range() == ""</c->
<c- k="">auto</c-> <c- n="">rK</c-> <c- o="">=</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">scan</c-><c- o="">&lt;</c-><c- b="">int</c-><c- o="">&gt;</c-><c- p="">(</c-><c- s="">"*42**"</c-><c- p="">,</c-> <c- s="">"{:*^5}"</c-><c- p="">);</c->  <c- c1="">// rK-&gt;value() == 42, rK-&gt;range() == ""</c->
<c- k="">auto</c-> <c- n="">rL</c-> <c- o="">=</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">scan</c-><c- o="">&lt;</c-><c- b="">int</c-><c- o="">&gt;</c-><c- p="">(</c-><c- s="">"**42*"</c-><c- p="">,</c-> <c- s="">"{:*^6}"</c-><c- p="">);</c-> <c- c1="">// ERROR (not enough fill characters after value)</c->
<c- k="">auto</c-> <c- n="">rM</c-> <c- o="">=</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">scan</c-><c- o="">&lt;</c-><c- b="">int</c-><c- o="">&gt;</c-><c- p="">(</c-><c- s="">"**42*"</c-><c- p="">,</c-> <c- s="">"{:*^5}"</c-><c- p="">);</c-> <c- c1="">// ERROR (not enough fill characters after value)</c->
</pre>
   </div>
   <p class="note" role="note"><span class="marker">Note:</span> This behavior, while compatible with <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">format</c-></code>,
is very complicated, and potentially hard to understand for users.
Since <code class="highlight"><c- n="">scanf</c-></code> doesn’t support parsing of fill characters this way,
it’s possible to leave this feature out for v1, and come back to this later:
it’s not a breaking change to add formatting specifiers that add new behavior.</p>
   <h4 class="heading settled" data-level="4.3.3" id="fmt-sign-hash-0"><span class="secno">4.3.3. </span><span class="content">Sign, <code class="highlight"><c- cp="">#</c-></code>, and <code class="highlight"><c- mi="">0</c-></code></span><a class="self-link" href="#fmt-sign-hash-0"></a></h4>
<pre class="highlight"><c- n="">format</c-><c- o="">-</c-><c- n="">spec</c-> <c- o="">::=</c-> <c- p="">...</c->
                <del><c- p="">[</c-><c- n="">sign</c-><c- p="">]</c-> <c- p="">[</c-><c- sc="">'#'</c-><c- p="">]</c-> <c- p="">[</c-><c- sc="">'0'</c-><c- p="">]</c-></del>
                <c- p="">...</c->
<del><c- n="">sign</c->        <c- o="">::=</c-> <i><c- n="">one</c-> <c- n="">of</c-></i> <c- sc="">'+'</c-> <c- sc="">'-'</c-> <c- sc="">' '</c-></del>
</pre>
   <p>These flags would have no effect in <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">scan</c-></code>, so they are disabled.
Signs (both <code class="highlight"><c- o="">+</c-></code> and <code class="highlight"><c- o="">-</c-></code>), base prefixes, trailing decimal points, and leading zeroes
are always allowed for arithmetic values.
Disabling them would be a bad default for a higher-level facility
like <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">scan</c-></code>, so flags explicitly enabling them are not needed.</p>
   <p class="note" role="note"><span class="marker">Note:</span> This is incompatible with <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">format</c-></code> format strings.</p>
   <h4 class="heading settled" data-level="4.3.4" id="fmt-width-precision"><span class="secno">4.3.4. </span><span class="content">Width and precision</span><a class="self-link" href="#fmt-width-precision"></a></h4>
<pre class="highlight"><c- n="">width</c->     <c- o="">::=</c-> <c- n="">positive</c-><c- o="">-</c-><c- n="">integer</c->
              <del><i><c- n="">OR</c-></i> <c- sc="">'{'</c-> <c- p="">[</c-><c- n="">arg</c-><c- o="">-</c-><c- n="">id</c-><c- p="">]</c-> <c- sc="">'}'</c-></del>
<del><c- n="">precision</c-> <c- o="">::=</c-> <c- sc="">'.'</c-> <c- n="">nonnegative</c-><c- o="">-</c-><c- n="">integer</c->
              <i><c- n="">OR</c-></i> <c- sc="">'.'</c-> <c- sc="">'{'</c-> <c- p="">[</c-><c- n="">arg</c-><c- o="">-</c-><c- n="">id</c-><c- p="">]</c-> <c- sc="">'}'</c-></del>
</pre>
   <p>The width specifier is valid for all argument types.
The meaning of this specifier somewhat deviates from <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">format</c-></code>.
The width and precision specifiers of it are combined into
a single width specifier in <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">scan</c-></code>.
This specifier indicates the expected field width of the value to be
scanned, taking into account possible fill characters used for alignment.
If no fill characters are expected, it specifies the maximum width for the field.</p>
   <div class="note" role="note">
     To clarify,
in <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">format</c-></code> the width-field provides the minimum, and the precision-field the maximum
width for a value. In <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">scan</c-></code>, the width-field provides the maximum. 
<pre class="language-c++ highlight"><c- k="">auto</c-> <c- n="">str</c-> <c- o="">=</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">format</c-><c- p="">(</c-><c- s="">"{:2}"</c-><c- p="">,</c-> <c- mi="">123</c-><c- p="">);</c->
<c- c1="">// str == "123"</c->
<c- c1="">// because only the minimum width was set by the format string</c->

<c- k="">auto</c-> <c- n="">result</c-> <c- o="">=</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">scan</c-><c- o="">&lt;</c-><c- b="">int</c-><c- o="">&gt;</c-><c- p="">(</c-><c- n="">str</c-><c- p="">,</c-> <c- s="">"{:2}"</c-><c- p="">);</c->
<c- c1="">// result-&gt;value() == 12</c->
<c- c1="">// result-&gt;range() == "3"</c->
<c- c1="">// because the maximum width was set to 2 by the format string</c->
</pre>
   </div>
   <p>For compatibility with <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">format</c-></code>,
the width specifier is in <i>field width units</i>,
which is specified to be 1 per Unicode (extended) grapheme cluster,
except some grapheme clusters are 2 ([format.string.std] ¶ 13):</p>
   <blockquote>
    <p>For a sequence of characters in UTF-8, UTF-16, or UTF-32,
an implementation should use as its field width the sum of the field widths
of the first code point of each extended grapheme cluster.
Extended grapheme clusters are defined by UAX #29 of the Unicode Standard.
The following code points have a field width of 2:</p>
    <ul>
     <li data-md="">
      <p>any code point with the East_Asian_Width="W" or East_Asian_Width="F"
Derived Extracted Property as described by UAX #44 of the Unicode Standard</p>
     </li><li data-md="">
      <p>U+4dc0 – U+4dff (Yijing Hexagram Symbols)</p>
     </li><li data-md="">
      <p>U+1f300 – U+1f5ff (Miscellaneous Symbols and Pictographs)</p>
     </li><li data-md="">
      <p>U+1f900 – U+1f9ff (Supplemental Symbols and Pictographs)</p>
    </li></ul>
    <p>The field width of all other code points is 1.</p>
    <p>For a sequence of characters in neither UTF-8, UTF-16, nor UTF-32, the field width is unspecified.</p>
   </blockquote>
   <p>This essentially maps 1 field width unit = 1 user perceived character.
It should be noted, that with this definition, grapheme clusters like emoji have a field width of 2.
This behavior is present in <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">format</c-></code> today, but can potentially be surprising to users.</p>
   <p>This meaning for the width specifier is different from <code class="highlight"><c- n="">scanf</c-></code>, where the width means
the number of code units to read. This is because the purpose of that specifier in <code class="highlight"><c- n="">scanf</c-></code> is to prevent buffer overflow. Because the current interface of the proposed <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">scan</c-></code> doesn’t
allow reading into an user-defined buffer, this isn’t a concern.</p>
   <div class="note" role="note">
     Other options can be considered, if compatibility with <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">format</c-></code> can be set aside.
These options include: 
    <ul>
     <li data-md="">
      <p>Plain bytes or code units</p>
     </li><li data-md="">
      <p>Unicode code points</p>
     </li><li data-md="">
      <p>Unicode (extended) grapheme clusters</p>
     </li><li data-md="">
      <p><code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">format</c-></code>-like field width units, except only looking at code points, instead of grapheme clusters</p>
     </li><li data-md="">
      <p>Exclusively using UAX #11 (East Asian Width) widths</p>
    </li></ul>
   </div>
   <p>Specifying the width with another argument, like in <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">format</c-></code>, is disallowed.</p>
   <h4 class="heading settled" data-level="4.3.5" id="fmt-localized"><span class="secno">4.3.5. </span><span class="content">Localized (<code class="highlight"><c- n="">L</c-></code>)</span><a class="self-link" href="#fmt-localized"></a></h4>
<pre class="highlight"><c- n="">format</c-><c- o="">-</c-><c- n="">spec</c-> <c- o="">::=</c-> <c- p="">...</c->
                <c- p="">[</c-><c- sc="">'L'</c-><c- p="">]</c->
                <c- p="">...</c->
</pre>
   <p>Enables scanning of values in locale-specific forms.</p>
   <ul>
    <li data-md="">
     <p>For integer types, allows for digit group separator characters,
equivalent to <code class="highlight"><c- n="">numpunct</c-><c- o="">::</c-><c- n="">thousands_sep</c-></code> of the used locale.
If digit group separator characters are used, their grouping
must match <code class="highlight"><c- n="">numpunct</c-><c- o="">::</c-><c- n="">grouping</c-></code>.</p>
    </li><li data-md="">
     <p>For floating-point types, the same as above.
In addition, the locale-specific radix separator character is used,
from <code class="highlight"><c- n="">numpunct</c-><c- o="">::</c-><c- n="">decimal_point</c-></code>.</p>
    </li><li data-md="">
     <p>For <code class="highlight"><c- b="">bool</c-></code>, the textual representation uses the appropriate strings
from <code class="highlight"><c- n="">numpunct</c-><c- o="">::</c-><c- n="">truename</c-></code> and <code class="highlight"><c- n="">numpunct</c-><c- o="">::</c-><c- n="">falsename</c-></code>.</p>
   </li></ul>
   <h5 class="heading settled" data-level="4.3.5.1" id="fmt-localized-discussion-grouping"><span class="secno">4.3.5.1. </span><span class="content">Design discussion: Thousands separator grouping checking</span><a class="self-link" href="#fmt-localized-discussion-grouping"></a></h5>
   <p>As proposed, when using localized scanning, the grouping of thousands
separators in the input must exactly match the value retrieved from <code class="highlight"><c- n="">numpunct</c-><c- o="">::</c-><c- n="">grouping</c-></code>. This behavior is consistent with iostreams.
It may, however, be undesirable: it is possible, that the user
would supply values with incorrect thousands separator grouping,
but that may need not be an error. The number is still unambiguously
parseable, with the check for grouping only done after parsing.</p>
   <div class="example" id="example-819a5adb">
    <a class="self-link" href="#example-819a5adb"></a> 
<pre class="language-c++ highlight"><c- k="">struct</c-> <c- nc="">custom_numpunct</c-> <c- o="">:</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">numpunct</c-><c- o="">&lt;</c-><c- b="">char</c-><c- o="">&gt;</c-> <c- p="">{</c->
  <c- n="">std</c-><c- o="">::</c-><c- n="">string</c-> <c- nf="">do_grouping</c-><c- p="">()</c-> <c- k="">const</c-> <c- n="">override</c-> <c- p="">{</c->
    <c- k="">return</c-> <c- s="">"</c-><c- se="">\3</c-><c- s="">"</c-><c- p="">;</c->
  <c- p="">}</c->

  <c- b="">char</c-> <c- nf="">do_thousands_sep</c-><c- p="">()</c-> <c- k="">const</c-> <c- n="">override</c-> <c- p="">{</c->
    <c- k="">return</c-> <c- sc="">','</c-><c- p="">;</c->
  <c- p="">}</c->
<c- p="">};</c->

<c- k="">auto</c-> <c- n="">loc</c-> <c- o="">=</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">locale</c-><c- p="">(</c-><c- n="">std</c-><c- o="">::</c-><c- n="">locale</c-><c- o="">::</c-><c- n="">classic</c-><c- p="">(),</c-> <c- n="">new</c-> <c- n="">custom_numpunct</c-><c- p="">);</c->

<c- c1="">// As proposed:</c->
<c- c1="">// Check grouping, error if invalid</c->
<c- k="">auto</c-> <c- n="">r0</c-> <c- o="">=</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">scan</c-><c- o="">&lt;</c-><c- b="">int</c-><c- o="">&gt;</c-><c- p="">(</c-><c- n="">loc</c-><c- p="">,</c-> <c- s="">"123,45"</c-><c- p="">,</c-> <c- s="">"{:L}"</c-><c- p="">);</c->
<c- c1="">// r0.has_value() == false</c->

<c- c1="">// ALTERNATIVE:</c->
<c- c1="">// Do not check grouping, only skip it</c->
<c- k="">auto</c-> <c- n="">r1</c-> <c- o="">=</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">scan</c-><c- o="">&lt;</c-><c- b="">int</c-><c- o="">&gt;</c-><c- p="">(</c-><c- n="">loc</c-><c- p="">,</c-> <c- s="">"123,45"</c-><c- p="">,</c-> <c- s="">"{:L}"</c-><c- p="">);</c->
<c- c1="">// r1.has_value() == true</c->
<c- c1="">// r1-&gt;value() == 12345</c->

<c- c1="">// Current proposed behavior, _somewhat_ consistent with iostreams:</c->
<c- n="">istringstream</c-> <c- n="">iss</c-><c- p="">{</c-><c- s="">"123,45"</c-><c- p="">};</c->
<c- n="">iss</c-><c- p="">.</c-><c- n="">imbue</c-><c- p="">(</c-><c- n="">locale</c-><c- p="">(</c-><c- n="">locale</c-><c- o="">::</c-><c- n="">classic</c-><c- p="">(),</c-> <c- n="">new</c-> <c- n="">custom_numpunct</c-><c- p="">));</c->

<c- b="">int</c-> <c- n="">i</c-><c- p="">{};</c->
<c- n="">iss</c-> <c- o="">&gt;&gt;</c-> <c- n="">i</c-><c- p="">;</c->
<c- c1="">// i == 12345</c->
<c- c1="">// iss.fail() == !iss == true</c->
</pre>
   </div>
   <p>This highlights a problem with using <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">expected</c-></code>: we can either have a value, or an error.
IOStreams can both return an error, and a value.
This issue is also present with range errors with ints and floats,
see <a href="#error-handling-discussion-detail">§ 4.6.2 Design discussion: Additional information</a> for more.</p>
   <h5 class="heading settled" data-level="4.3.5.2" id="fmt-localized-discussion-thsepflag"><span class="secno">4.3.5.2. </span><span class="content">Design discussion: Separate flag for thousands separators</span><a class="self-link" href="#fmt-localized-discussion-thsepflag"></a></h5>
   <p>It may also be desirable to split up the behavior of skipping and checking
of thousands separators from the realm of localization. For example,
in the POSIX-extended version of <code class="highlight"><c- n="">sscanf</c-></code>, there’s the <code class="highlight">'</code> format specifier,
which allows opting-into reading of thousands separators.</p>
   <p>When a locale isn’t used, a set of options similar to the thousands separator
options used with the <code class="highlight"><c- n="">en_US</c-></code> locale (i.e. <code class="highlight"><c- p="">,</c-></code> with <code class="highlight"><c- s="">"</c-><c- se="">\3</c-><c- s="">"</c-></code> grouping).
This would enable skipping of thousands separators without involving locale.</p>
   <div class="example" id="example-d9a97c4b">
    <a class="self-link" href="#example-d9a97c4b"></a> 
<pre class="language-c++ highlight"><c- c1="">// NOT PROPOSED,</c->
<c- c1="">// hypothetical example, with a ' format specifier</c->

<c- k="">auto</c-> <c- n="">r</c-> <c- o="">=</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">scan</c-><c- o="">&lt;</c-><c- b="">int</c-><c- o="">&gt;</c-><c- p="">(</c-><c- s="">"123,456"</c-><c- p="">,</c-> <c- s="">"{:'}"</c-><c- p="">);</c->
<c- c1="">// r-&gt;value() == 123456</c->
</pre>
   </div>
   <h4 class="heading settled" data-level="4.3.6" id="fmt-type-string"><span class="secno">4.3.6. </span><span class="content">Type specifiers: strings</span><a class="self-link" href="#fmt-type-string"></a></h4>
   <table>
    <tbody>
     <tr>
      <th>Type 
      </th><th>Meaning 
     </th></tr><tr>
      <td>none,&nbsp;<code class="highlight"><c- n="">s</c-></code> 
      </td><td>Copies from the input until a whitespace character is encountered. 
     </td></tr><tr>
      <td><code class="highlight"><c- o="">?</c-></code> 
      </td><td>Copies an escaped string from the input. 
     </td></tr><tr>
      <td><code class="highlight"><c- n="">c</c-></code> 
      </td><td>Copies from the input until the field width is exhausted.
Does not skip preceding whitespace.
Errors, if no field width is provided. 
   </td></tr></tbody></table>
   <div class="note" role="note">
     The <code class="highlight"><c- n="">s</c-></code> specifier is consistent with <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">istream</c-></code> and <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">string</c-></code>: 
<pre class="language-c++ highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">string</c-> <c- n="">word</c-><c- p="">;</c->
<c- n="">std</c-><c- o="">::</c-><c- n="">istringstream</c-><c- p="">{</c-><c- s="">"Hello world"</c-><c- p="">}</c-> <c- o="">&gt;&gt;</c-> <c- n="">word</c-><c- p="">;</c->
<c- c1="">// word == "Hello"</c->

<c- k="">auto</c-> <c- n="">r</c-> <c- o="">=</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">scan</c-><c- o="">&lt;</c-><c- n="">string</c-><c- o="">&gt;</c-><c- p="">(</c-><c- s="">"Hello world"</c-><c- p="">,</c-> <c- s="">"{:s}"</c-><c- p="">);</c->
<c- c1="">// r-&gt;value() == "Hello"</c->
</pre>
   </div>
   <p class="note" role="note"><span class="marker">Note:</span> The <code class="highlight"><c- n="">c</c-></code> specifier is consistent with <code class="highlight"><c- n="">scanf</c-></code>,
but is not supported for strings by <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">format</c-></code>.</p>
   <h4 class="heading settled" data-level="4.3.7" id="fmt-type-int"><span class="secno">4.3.7. </span><span class="content">Type specifiers: integers</span><a class="self-link" href="#fmt-type-int"></a></h4>
   <p>Integer values are scanned as if by using <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">from_chars</c-></code>, except:</p>
   <ul>
    <li data-md="">
     <p>A positive <code class="highlight"><c- o="">+</c-></code> sign and a base prefix are always allowed to be present.</p>
    </li><li data-md="">
     <p>Preceding whitespace is skipped.</p>
   </li></ul>
   <table>
    <tbody>
     <tr>
      <th>Type 
      </th><th>Meaning 
     </th></tr><tr>
      <td><code class="highlight"><c- n="">b</c-></code>, <code class="highlight"><c- n="">B</c-></code> 
      </td><td><code class="highlight"><c- n="">from_chars</c-></code> with base 2. The base prefix is <code class="highlight"><c- mi="">0</c-><c- n="">b</c-></code> or <code class="highlight"><c- mi="">0</c-><c- n="">B</c-></code>. 
     </td></tr><tr>
      <td><code class="highlight"><c- n="">o</c-></code> 
      </td><td><code class="highlight"><c- n="">from_chars</c-></code> with base 8. For non-zero values, the base prefix is <code class="highlight"><c- mi="">0</c-></code>. 
     </td></tr><tr>
      <td><code class="highlight"><c- n="">x</c-></code>, <code class="highlight"><c- n="">X</c-></code> 
      </td><td><code class="highlight"><c- n="">from_chars</c-></code> with base 16. The base prefix is <code class="highlight"><c- mi="">0</c-><c- n="">x</c-></code> or <code class="highlight"><c- mi="">0</c-><c- n="">X</c-></code>. 
     </td></tr><tr>
      <td><code class="highlight"><c- n="">d</c-></code> 
      </td><td><code class="highlight"><c- n="">from_chars</c-></code> with base 10. No base prefix. 
     </td></tr><tr>
      <td><code class="highlight"><c- n="">u</c-></code> 
      </td><td><code class="highlight"><c- n="">from_chars</c-></code> with base 10. No base prefix. No <code class="highlight"><c- o="">-</c-></code> sign allowed. 
     </td></tr><tr>
      <td><code class="highlight"><c- n="">i</c-></code> 
      </td><td>Detect base from a possible prefix, default to decimal. 
     </td></tr><tr>
      <td><code class="highlight"><c- n="">c</c-></code> 
      </td><td>Copies a character from the input. 
     </td></tr><tr>
      <td>none 
      </td><td>Same as <code class="highlight"><c- n="">d</c-></code> 
   </td></tr></tbody></table>
   <p class="note" role="note"><span class="marker">Note:</span> The flags <code class="highlight"><c- n="">u</c-></code> and <code class="highlight"><c- n="">i</c-></code> are not supported by <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">format</c-></code>.
These flags are consistent with <code class="highlight"><c- n="">scanf</c-></code>.</p>
   <h4 class="heading settled" data-level="4.3.8" id="fmt-type-char"><span class="secno">4.3.8. </span><span class="content">Type specifiers: <code class="highlight"><c- n="">CharT</c-></code></span><a class="self-link" href="#fmt-type-char"></a></h4>
   <table>
    <tbody>
     <tr>
      <th>Type 
      </th><th>Meaning 
     </th></tr><tr>
      <td>none, <code class="highlight"><c- n="">c</c-></code> 
      </td><td>Copies a character from the input. 
     </td></tr><tr>
      <td><code class="highlight"><c- n="">b</c-></code>, <code class="highlight"><c- n="">B</c-></code>, <code class="highlight"><c- n="">d</c-></code>, <code class="highlight"><c- n="">i</c-></code>, <code class="highlight"><c- n="">o</c-></code>, <code class="highlight"><c- n="">u</c-></code>, <code class="highlight"><c- n="">x</c-></code>, <code class="highlight"><c- n="">X</c-></code> 
      </td><td>Same as for integers. 
     </td></tr><tr>
      <td><code class="highlight"><c- o="">?</c-></code> 
      </td><td>Copies an escaped character from the input. 
   </td></tr></tbody></table>
   <div class="example" id="example-f7879d81">
    <a class="self-link" href="#example-f7879d81"></a> This is not encoding or Unicode-aware.
Reading a <code class="highlight"><c- n="">CharT</c-></code> with the <code class="highlight"><c- n="">c</c-></code> type specifier
will just read a single code unit of type <code class="highlight"><c- n="">CharT</c-></code>.
This can lead to invalid encoding in the scanned values. 
<pre class="language-c++ highlight"><c- c1="">// As proposed:</c->
<c- c1="">// U+12345 is 0xF0 0x92 0x8D 0x85 in UTF-8</c->
<c- k="">auto</c-> <c- n="">r</c-> <c- o="">=</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">scan</c-><c- o="">&lt;</c-><c- b="">char</c-><c- p="">,</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">string</c-><c- o="">&gt;</c-><c- p="">(</c-><c- s="">"\u{12345}"</c-><c- p="">,</c-> <c- s="">"{}{}"</c-><c- p="">);</c->
<c- k="">auto</c-><c- o="">&amp;</c-> <c- p="">[</c-><c- n="">ch</c-><c- p="">,</c-> <c- n="">str</c-><c- p="">]</c-> <c- o="">=</c-> <c- n="">r</c-><c- o="">-&gt;</c-><c- n="">values</c-><c- p="">();</c->
<c- c1="">// ch == '\xF0'</c->
<c- c1="">// str == "\x92\x8d\x85" (invalid utf-8)</c->

<c- c1="">// This is the same behavior as with iostreams today</c->
</pre>
   </div>
   <h4 class="heading settled" data-level="4.3.9" id="fmt-type-bool"><span class="secno">4.3.9. </span><span class="content">Type specifiers: <code class="highlight"><c- b="">bool</c-></code></span><a class="self-link" href="#fmt-type-bool"></a></h4>
   <table>
    <tbody>
     <tr>
      <th>Type 
      </th><th>Meaning 
     </th></tr><tr>
      <td><code class="highlight"><c- n="">s</c-></code> 
      </td><td>Allows for textual representation, i.e. <code class="highlight">true</code> or <code class="highlight">false</code> 
     </td></tr><tr>
      <td><code class="highlight"><c- n="">b</c-></code>, <code class="highlight"><c- n="">B</c-></code>, <code class="highlight"><c- n="">d</c-></code>, <code class="highlight"><c- n="">i</c-></code>, <code class="highlight"><c- n="">o</c-></code>, <code class="highlight"><c- n="">u</c-></code>, <code class="highlight"><c- n="">x</c-></code>, <code class="highlight"><c- n="">X</c-></code> 
      </td><td>Allows for integral representation, i.e. <code class="highlight"><c- mi="">0</c-></code> or <code class="highlight"><c- mi="">1</c-></code> 
     </td></tr><tr>
      <td>none 
      </td><td>Allows for both textual and integral representation: i.e. <code class="highlight">true</code>, <code class="highlight"><c- mi="">1</c-></code>, <code class="highlight">false</code>, or <code class="highlight"><c- mi="">0</c-></code>. 
   </td></tr></tbody></table>
   <h4 class="heading settled" data-level="4.3.10" id="fmt-type-float"><span class="secno">4.3.10. </span><span class="content">Type specifiers: floating-point types</span><a class="self-link" href="#fmt-type-float"></a></h4>
   <p>Similar to integer types,
floating-point values are scanned as if by using <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">from_chars</c-></code>, except:</p>
   <ul>
    <li data-md="">
     <p>A positive <code class="highlight"><c- o="">+</c-></code> sign is always allowed to be present.</p>
    </li><li data-md="">
     <p>Preceding whitespace is skipped.</p>
   </li></ul>
   <table>
    <tbody>
     <tr>
      <th>Type 
      </th><th>Meaning 
     </th></tr><tr>
      <td><code class="highlight"><c- n="">a</c-></code>, <code class="highlight"><c- n="">A</c-></code> 
      </td><td><code class="highlight"><c- n="">from_chars</c-></code> with <code class="highlight"><c- n="">chars_format</c-><c- o="">::</c-><c- n="">hex</c-></code>, with <code class="highlight"><c- mi="">0</c-><c- n="">x</c-></code>/<code class="highlight"><c- mi="">0</c-><c- n="">X</c-></code>-prefix allowed. 
     </td></tr><tr>
      <td><code class="highlight"><c- n="">e</c-></code>, <code class="highlight"><c- n="">E</c-></code> 
      </td><td><code class="highlight"><c- n="">from_chars</c-></code> with <code class="highlight"><c- n="">chars_format</c-><c- o="">::</c-><c- n="">scientific</c-></code>. 
     </td></tr><tr>
      <td><code class="highlight"><c- n="">f</c-></code>, <code class="highlight"><c- n="">F</c-></code> 
      </td><td><code class="highlight"><c- n="">from_chars</c-></code> with <code class="highlight"><c- n="">chars_format</c-><c- o="">::</c-><c- n="">fixed</c-></code>. 
     </td></tr><tr>
      <td><code class="highlight"><c- n="">g</c-></code>, <code class="highlight"><c- n="">G</c-></code> 
      </td><td><code class="highlight"><c- n="">from_chars</c-></code> with <code class="highlight"><c- n="">chars_format</c-><c- o="">::</c-><c- n="">general</c-></code>. 
     </td></tr><tr>
      <td>none 
      </td><td><code class="highlight"><c- n="">from_chars</c-></code> with <code class="highlight"><c- n="">chars_format</c-><c- o="">::</c-><c- n="">general</c-> <c- o="">|</c-> <c- n="">chars_format</c-><c- o="">::</c-><c- n="">hex</c-></code>, with <code class="highlight"><c- mi="">0</c-><c- n="">x</c-></code>/<code class="highlight"><c- mi="">0</c-><c- n="">X</c-></code>-prefix allowed. 
   </td></tr></tbody></table>
   <h3 class="heading settled" data-level="4.4" id="ranges"><span class="secno">4.4. </span><span class="content">Ranges</span><a class="self-link" href="#ranges"></a></h3>
   <p>We propose, that <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">scan</c-></code> would take a range as its input.
This range should satisfy the requirements of <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">ranges</c-><c- o="">::</c-><c- n="">forward_range</c-></code> to
enable look-ahead, which is necessary for parsing.</p>
<pre class="language-c++ highlight"><c- n="">template</c-> <c- o="">&lt;</c-><c- n="">class</c-> <c- n="">Range</c-><c- p="">,</c-> <c- n="">class</c-> <c- n="">CharT</c-><c- o="">&gt;</c->
<c- n="">concept</c-> <c- n="">scannable_range</c-> <c- o="">=</c->
  <c- n="">ranges</c-><c- o="">::</c-><c- n="">forward_range</c-><c- o="">&lt;</c-><c- n="">Range</c-><c- o="">&gt;</c-> <c- o="">&amp;&amp;</c-> <c- n="">same_as</c-><c- o="">&lt;</c-><c- n="">ranges</c-><c- o="">::</c-><c- n="">range_value_t</c-><c- o="">&lt;</c-><c- n="">Range</c-><c- o="">&gt;</c-><c- p="">,</c-> <c- n="">CharT</c-><c- o="">&gt;</c-><c- p="">;</c->
</pre>
   <p>For a range to be a <code class="highlight"><c- n="">scannable_range</c-></code>, its character type (range <code class="highlight"><c- n="">value_type</c-></code>, code unit type)
needs to also be correct, i.e. it needs to match the character type of the format string.
Mixing and matching character types between the input range and the format string is not supported.</p>
   <div class="example" id="example-f62b1496">
    <a class="self-link" href="#example-f62b1496"></a> 
<pre class="language-c++ highlight"><c- n="">scan</c-><c- o="">&lt;</c-><c- b="">int</c-><c- o="">&gt;</c-><c- p="">(</c-><c- s="">"42"</c-><c- p="">,</c-> <c- s="">"{}"</c-><c- p="">);</c->   <c- c1="">// OK</c->
<c- n="">scan</c-><c- o="">&lt;</c-><c- b="">int</c-><c- o="">&gt;</c-><c- p="">(</c->L<c- s="">"42"</c-><c- p="">,</c-> L<c- s="">"{}"</c-><c- p="">);</c-> <c- c1="">// OK</c->
<c- n="">scan</c-><c- o="">&lt;</c-><c- b="">int</c-><c- o="">&gt;</c-><c- p="">(</c->L<c- s="">"42"</c-><c- p="">,</c-> <c- s="">"{}"</c-><c- p="">);</c->  <c- c1="">// Error: wchar_t\[N] is not a scannable_range&lt;char&gt;</c->
</pre>
   </div>
   <p>It should be noted, that standard range facilities related to iostreams, namely <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">istreambuf_iterator</c-></code>, model <code class="highlight"><c- n="">input_iterator</c-></code>.
Thus, they can’t be used with <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">scan</c-></code>, and therefore, for example, <code class="highlight"><c- n="">stdin</c-></code>, can’t be read directly using <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">scan</c-></code>.
The reference implementation deals with this by providing a range type, that wraps a <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">basic_istreambuf</c-></code>, and provides a <code class="highlight"><c- n="">forward_range</c-></code>-compatible interface to it.
At this point, this is deemed out of scope for this proposal.</p>
   <p>As mentioned above, <code class="highlight"><c- n="">forward_range</c-></code>s are needed to support proper lookahead and rollback.
For example, when reading an <code class="highlight"><c- b="">int</c-></code> with the <code class="highlight"><c- n="">i</c-></code> format specifier (detect base from prefix),
whether a character is part of the <code class="highlight"><c- b="">int</c-></code> can’t be determined before reading past it.</p>
   <div class="example" id="example-c7bca27c">
    <a class="self-link" href="#example-c7bca27c"></a> 
<pre class="language-c++ highlight"><c- c1="">// Hex value "0xf"</c->
<c- k="">auto</c-> <c- n="">r1</c-> <c- o="">=</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">scan</c-><c- o="">&lt;</c-><c- b="">int</c-><c- o="">&gt;</c-><c- p="">(</c-><c- s="">"0xf"</c-><c- p="">,</c-> <c- s="">"{:i}"</c-><c- p="">);</c->
<c- c1="">// r1-&gt;value() == 0xf</c->
<c- c1="">// r1-&gt;range().empty() == true</c->

<c- c1="">// (Octal) value "0", with "xg" left over</c->
<c- k="">auto</c-> <c- n="">r2</c-> <c- o="">=</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">scan</c-><c- o="">&lt;</c-><c- b="">int</c-><c- o="">&gt;</c-><c- p="">(</c-><c- s="">"0xg"</c-><c- p="">,</c-> <c- s="">"{:i}"</c-><c- p="">);</c->
<c- c1="">// r2-&gt;value() == 0</c->
<c- c1="">// r2-&gt;range() == "xg"</c->
</pre>
   </div>
   <p>This behavior is different from <code class="highlight"><c- n="">scanf</c-></code>.</p>
   <p>The same behavior can be observed with floating-point values, when using exponents:
whether <code class="highlight"><c- mi="">1</c-><c- n="">e</c-><c- o="">+</c-><c- n="">X</c-></code> is parsed as a number, or as <code class="highlight"><c- mi="">1</c-></code> with the rest left over,
depends on whether <code class="highlight"><c- n="">X</c-></code> is a valid exponent.
For user-defined types, arbitrarily-long look-/rollback can be required.</p>
   <h3 class="heading settled" data-level="4.5" id="argument-passing"><span class="secno">4.5. </span><span class="content">Argument passing, and return type of <code class="highlight"><c- n="">scan</c-></code></span><a class="self-link" href="#argument-passing"></a></h3>
   <p>In an earlier revision of this paper, output parameters were used to return the scanned values
from <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">scan</c-></code>. In this revision, we propose returning the values instead, wrapped in an <code class="highlight"><c- n="">expected</c-></code>.</p>
<pre class="language-c++ highlight"><c- c1="">// R2 (current)</c->
<c- k="">auto</c-> <c- n="">result</c-> <c- o="">=</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">scan</c-><c- o="">&lt;</c-><c- b="">int</c-><c- o="">&gt;</c-><c- p="">(</c-><c- n="">input</c-><c- p="">,</c-> <c- s="">"{}"</c-><c- p="">);</c->
<c- k="">auto</c-> <c- p="">[</c-><c- n="">i</c-><c- p="">]</c-> <c- o="">=</c-> <c- n="">result</c-><c- o="">-&gt;</c-><c- n="">values</c-><c- p="">();</c->
<c- c1="">// or:</c->
<c- k="">auto</c-> <c- n="">i</c-> <c- o="">=</c-> <c- n="">result</c-><c- o="">-&gt;</c-><c- n="">value</c-><c- p="">();</c->

<c- c1="">// R1 (previous)</c->
<c- b="">int</c-> <c- n="">i</c-><c- p="">;</c->
<c- k="">auto</c-> <c- n="">result</c-> <c- o="">=</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">scan</c-><c- p="">(</c-><c- n="">input</c-><c- p="">,</c-> <c- s="">"{}"</c-><c- p="">,</c-> <c- n="">i</c-><c- p="">);</c->
</pre>
   <p>The rationale behind this change is as follows:</p>
   <ul>
    <li data-md="">
     <p>It was easy to accidentally use uninitialized values (as evident by the example above).
In this revision, the values can only be accessed when the operation is successful.</p>
    </li><li data-md="">
     <p>Modern C++ API design principles favor return values over output parameters.</p>
    </li><li data-md="">
     <p>The earlier design was conceived at a time, when C++17 support and usage wasn’t as prevalent as it is today.
Back then, the only way to use a return-value API was through <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">tie</c-></code>, which wasn’t ergonomic.</p>
    </li><li data-md="">
     <p>Previously, there were real performance implications when using complicated tuples,
both at compile-time and runtime. These concerns have since been alleviated, as compiler technology has improved.</p>
   </li></ul>
   <p>It should be noted, that not using output parameters removes a channel for user customization.
For example, <a data-link-type="biblio" href="#biblio-fmt" title="The fmt library">[FMT]</a> uses <code class="highlight"><c- n="">fmt</c-><c- o="">::</c-><c- n="">arg</c-></code> to specify named arguments. The same isn’t directly possible here.</p>
   <p>The return type of <code class="highlight"><c- n="">scan</c-></code>, <code class="highlight"><c- n="">scan_result</c-></code>, contains a <code class="highlight"><c- n="">subrange</c-></code> over the unparsed input.
With this, a new type alias is introduced, <code class="highlight"><c- n="">ranges</c-><c- o="">::</c-><c- n="">borrowed_tail_subrange_t</c-></code>, that is defined as follows:</p>
<pre class="highlight"><c- k="">template</c-> <c- o="">&lt;</c-><c- k="">typename</c-> <c- nc="">R</c-><c- o="">&gt;</c->
<c- k="">using</c-> <c- n="">borrowed_tail_subrange_t</c-> <c- o="">=</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">conditional_t</c-><c- o="">&lt;</c->
  <c- n="">ranges</c-><c- o="">::</c-><c- n="">borrowed_range</c-><c- o="">&lt;</c-><c- n="">R</c-><c- o="">&gt;</c-><c- p="">,</c->
  <c- n="">ranges</c-><c- o="">::</c-><c- n="">subrange</c-><c- o="">&lt;</c-><c- n="">ranges</c-><c- o="">::</c-><c- n="">iterator_t</c-><c- o="">&lt;</c-><c- n="">R</c-><c- o="">&gt;</c-><c- p="">,</c-> <c- n="">ranges</c-><c- o="">::</c-><c- n="">sentinel_t</c-><c- o="">&lt;</c-><c- n="">R</c-><c- o="">&gt;&gt;</c-><c- p="">,</c->
  <c- n="">ranges</c-><c- o="">::</c-><c- n="">dangling</c-><c- o="">&gt;</c-><c- p="">;</c->
</pre>
   <p>Compare this with <code class="highlight"><c- n="">borrowed_subrange_t</c-></code>, which is defined as <code class="highlight"><c- n="">ranges</c-><c- o="">::</c-><c- n="">subrange</c-><c- o="">&lt;</c-><c- n="">ranges</c-><c- o="">::</c-><c- n="">iterator_t</c-><c- o="">&lt;</c-><c- n="">R</c-><c- o="">&gt;</c-><c- p="">,</c-> <c- n="">ranges</c-><c- o="">::</c-><c- n="">iterator_t</c-><c- o="">&lt;</c-><c- n="">R</c-><c- o="">&gt;&gt;</c-></code>,
when the range models <code class="highlight"><c- n="">borrowed_range</c-></code>.</p>
   <p>This is novel in the ranges space: previously all algorithms have either returned an iterator,
or a subrange of two iterators. We believe that <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">scan</c-></code> warrants a diversion:
if (for <code class="highlight"><c- n="">I</c-> <c- o="">=</c-> <c- n="">ranges</c-><c- o="">::</c-><c- n="">iterator_t</c-><c- o="">&lt;</c-><c- n="">R</c-><c- o="">&gt;</c-></code> and <code class="highlight"><c- n="">S</c-> <c- o="">=</c-> <c- n="">ranges</c-><c- o="">::</c-><c- n="">sentinel_t</c-><c- o="">&lt;</c-><c- n="">R</c-><c- o="">&gt;</c-></code>) <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">random_access_iterator</c-><c- o="">&lt;</c-><c- n="">I</c-><c- o="">&gt;</c-> <c- o="">||</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">sized_sentinel_for</c-><c- o="">&lt;</c-><c- n="">I</c-><c- o="">&gt;</c-> <c- o="">||</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">assignable_from</c-><c- o="">&lt;</c-><c- n="">I</c-><c- o="">&amp;</c-><c- p="">,</c-> <c- n="">S</c-><c- o="">&gt;</c-></code> is <code class="highlight">false</code>, <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">scan</c-></code> will need to go through the rest of the input, in order to get the end iterator to return.
A superior alternative is to simply return the sentinel, since that’s always correct
(the leftover range always has the same end as the source range) and requires no additional computation.</p>
   <p>See this StackOverflow answer by Barry Revzin for more context: <a data-link-type="biblio" href="#biblio-barry-so-answer" title="Why the standard defines `borrowed_subrange_t` as `common_range`">[BARRY-SO-ANSWER]</a>.</p>
   <h4 class="heading settled" data-level="4.5.1" id="return-type-alternatives"><span class="secno">4.5.1. </span><span class="content">Design alternatives</span><a class="self-link" href="#return-type-alternatives"></a></h4>
   <p>As proposed, <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">scan</c-></code> returns an <code class="highlight"><c- n="">expected</c-></code>, containing either an iterator and a tuple, or a <code class="highlight"><c- n="">scan_error</c-></code>.</p>
   <p>An alternative could be returning a <code class="highlight"><c- n="">tuple</c-></code>, with a result object as its first (0th) element, and the parsed values occupying the rest.
This would enable neat usage of structured bindings:</p>
<pre class="language-c++ highlight"><c- c1="">// NOT PROPOSED, design alternative</c->
<c- k="">auto</c-> <c- p="">[</c-><c- n="">r</c-><c- p="">,</c-> <c- n="">i</c-><c- p="">]</c-> <c- o="">=</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">scan</c-><c- o="">&lt;</c-><c- b="">int</c-><c- o="">&gt;</c-><c- p="">(</c-><c- s="">"42"</c-><c- p="">,</c-> <c- s="">"{}"</c-><c- p="">);</c->
</pre>
   <p>However, there are two possible issues with this design:</p>
   <ol>
    <li data-md="">
     <p>It’s easy to accidentally skip checking whether the operation 
succeeded, and access the scanned values regardless.
This could be a potential security issue (even though the values would 
always be at least value-initialized, not default-initialized).
Returning an expected forces checking for success.</p>
    </li><li data-md="">
     <p>The numbering of the elements in the returned tuple would be off-by-one compared to the indexing used in format strings:</p>
<pre class="language-c++ highlight"><c- k="">auto</c-> <c- n="">r</c-> <c- o="">=</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">scan</c-><c- o="">&lt;</c-><c- b="">int</c-><c- o="">&gt;</c-><c- p="">(</c-><c- s="">"42"</c-><c- p="">,</c-> <c- s="">"{0}"</c-><c- p="">);</c->
<c- c1="">// std::get&lt;0&gt;(r) refers to the result object</c->
<c- c1="">// std::get&lt;1&gt;(r) refers to {0}</c->
</pre>
   </li></ol>
   <p>For the same reason as enumerated in 2. above, the <code class="highlight"><c- n="">scan_result</c-></code> type as proposed doesn’t follow the tuple protocol, so that structured bindings can’t be used with it:</p>
<pre class="language-c++ highlight"><c- c1="">// NOT PROPOSED</c->
<c- k="">auto</c-> <c- n="">result</c-> <c- o="">=</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">scan</c-><c- o="">&lt;</c-><c- b="">int</c-><c- o="">&gt;</c-><c- p="">(</c-><c- s="">"42"</c-><c- p="">,</c-> <c- s="">"{0}"</c-><c- p="">);</c->
<c- c1="">// std::get&lt;0&gt;(*result) would refer to the iterator</c->
<c- c1="">// std::get&lt;1&gt;(*result) would refer to {0}</c->
</pre>
   <h3 class="heading settled" data-level="4.6" id="error-handling"><span class="secno">4.6. </span><span class="content">Error handling</span><a class="self-link" href="#error-handling"></a></h3>
   <p>Contrasting with <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">format</c-></code>, this proposed library communicates errors with return values,
instead of throwing exceptions. This is because error conditions are expected to be much
more frequent when parsing user input, as opposed to text formatting.
With the introduction of <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">expected</c-></code>, error handling using return values is also more ergonomic than before,
and it provides a vocabulary type we can use here, instead of designing something novel.</p>
   <p><code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">scan_error</c-></code> holds an enumerated error code value, and a message string.
The message is used in the same way as the message in <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">exception</c-></code>:
it gives more details about the error, but its contents are unspecified.</p>
<pre class="language-c++ highlight"><c- c1="">// Not a specification, just exposition</c->
<c- n="">class</c-> <c- n="">scan_error</c-> <c- p="">{</c->
<c- n="">public</c-><c- o="">:</c->
  <c- k="">enum</c-> <c- n="">code_type</c-> <c- p="">{</c->
    <c- n="">good</c-><c- p="">,</c->

    <c- c1="">// EOF:</c->
    <c- c1="">// tried to read from an empty range,</c->
    <c- c1="">// or the input ended unexpectedly.</c->
    <c- c1="">// Naming alternative: end_of_input</c->
    <c- n="">end_of_range</c-><c- p="">,</c->

    <c- n="">invalid_format_string</c-><c- p="">,</c->

    <c- n="">invalid_scanned_value</c-><c- p="">,</c->

    <c- n="">value_out_of_range</c->
  <c- p="">};</c->

  <c- n="">constexpr</c-> <c- nf="">scan_error</c-><c- p="">()</c-> <c- o="">=</c-> <c- k="">default</c-><c- p="">;</c->
  <c- n="">constexpr</c-> <c- nf="">scan_error</c-><c- p="">(</c-><c- n="">code_type</c-><c- p="">,</c-> <c- k="">const</c-> <c- b="">char</c-><c- o="">*</c-><c- p="">);</c->

  <c- n="">constexpr</c-> <c- n="">explicit</c-> <c- n="">operator</c-> <c- b="">bool</c-><c- p="">()</c-> <c- k="">const</c-> <c- n="">noexcept</c-><c- p="">;</c->

  <c- n="">constexpr</c-> <c- n="">code_type</c-> <c- n="">code</c-><c- p="">()</c-> <c- k="">const</c-> <c- n="">noexcept</c-><c- p="">;</c->
  <c- n="">constexpr</c-> <c- k="">const</c-> <c- b="">char</c-><c- o="">*</c-> <c- n="">msg</c-><c- p="">()</c-> <c- k="">const</c-><c- p="">;</c->
<c- p="">};</c->
</pre>
   <h4 class="heading settled" data-level="4.6.1" id="error-handling-discussion-type"><span class="secno">4.6.1. </span><span class="content">Design discussion: Essence of <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">scan_error</c-></code></span><a class="self-link" href="#error-handling-discussion-type"></a></h4>
   <p>The reason why we propose adding the type <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">scan_error</c-></code> instead of just using <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">errc</c-></code> is,
that we want to avoid losing information. The enumerators of <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">errc</c-></code> are insufficient for
this use, as evident by the table below: there are no clear one-to-one mappings between <code class="highlight"><c- n="">scan_error</c-><c- o="">::</c-><c- n="">code_type</c-></code> and <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">errc</c-></code>, but <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">errc</c-><c- o="">::</c-><c- n="">invalid_argument</c-></code> would need to cover a lot of cases.</p>
   <p>The <code class="highlight"><c- k="">const</c-> <c- b="">char</c-><c- o="">*</c-></code> in <code class="highlight"><c- n="">scan_error</c-></code> is extremely useful for user code, for use in logging and debugging.
Even with the <code class="highlight"><c- n="">scan_error</c-><c- o="">::</c-><c- n="">code_type</c-></code> enumerators, more information is often needed, to isolate any possible problem.</p>
   <p>Possible mappings from <code class="highlight"><c- n="">scan_error</c-><c- o="">::</c-><c- n="">code_type</c-></code> to <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">errc</c-></code> could be:</p>
   <table>
    <thead>
     <tr>
      <th><code class="highlight"><c- n="">scan_error</c-><c- o="">::</c-><c- n="">code_type</c-></code> 
      </th><th><code class="highlight"><c- n="">errc</c-></code> 
    </th></tr></thead><tbody>
     <tr>
      <td><code class="highlight"><c- n="">scan_error</c-><c- o="">::</c-><c- n="">good</c-></code> 
      </td><td><code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">errc</c-><c- p="">{}</c-></code> 
     </td></tr><tr>
      <td><code class="highlight"><c- n="">scan_error</c-><c- o="">::</c-><c- n="">end_of_range</c-></code> 
      </td><td rowspan="3" style="vertical-align: middle"><code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">errc</c-><c- o="">::</c-><c- n="">invalid_argument</c-></code> 
     </td></tr><tr>
      <td><code class="highlight"><c- n="">scan_error</c-><c- o="">::</c-><c- n="">invalid_format_string</c-></code> 
     </td></tr><tr>
      <td><code class="highlight"><c- n="">scan_error</c-><c- o="">::</c-><c- n="">invalid_scanned_value</c-></code> 
     </td></tr><tr>
      <td><code class="highlight"><c- n="">scan_error</c-><c- o="">::</c-><c- n="">value_out_of_range</c-></code> 
      </td><td><code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">errc</c-><c- o="">::</c-><c- n="">result_out_of_range</c-></code> 
   </td></tr></tbody></table>
   <p>There are multiple dimensions of design decisions to be done here:</p>
   <ol>
    <li>
     <b>Should <code class="highlight"><c- n="">scan_error</c-></code> use a custom enumeration?</b> 
     <ol>
      <li data-md="">
       <p><b>Yes.</b> (currently proposed, our preference)</p>
      </li><li data-md="">
       <p><b>No, use <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">errc</c-></code>.</b> Loses precision in error codes</p>
     </li></ol>
    </li><li>
     <b>Should <code class="highlight"><c- n="">scan_error</c-></code> contain a message?</b> 
     <ol>
      <li data-md="">
       <p><b>Yes, a <code class="highlight"><c- k="">const</c-> <c- b="">char</c-><c- o="">*</c-></code></b>. (currently proposed, weak preference)</p>
      </li><li data-md="">
       <p><b>Yes, a <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">string</c-></code>.</b> Potentially more expensive.</p>
      </li><li data-md="">
       <p><b>No.</b> Worse user experience for loss of diagnostic information</p>
     </li></ol>
   </li></ol>
   <h4 class="heading settled" data-level="4.6.2" id="error-handling-discussion-detail"><span class="secno">4.6.2. </span><span class="content">Design discussion: Additional information</span><a class="self-link" href="#error-handling-discussion-detail"></a></h4>
   <p>Only having <code class="highlight"><c- n="">value_out_of_range</c-></code> does not give a way to differentiate
between different kinds of out-of-range errors, like overflowing
(absolute value too large, either positive or negative), or underflowing
(value not representable, between zero and the smallest subnormal).</p>
   <p>Both <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">istream</c-></code> (through <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">num_get</c-></code>), and
the <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">strto</c-><c- o="">*</c-></code> family of functions support differentiating between
differentiating between different kinds of overflow and underflow,
through the magnitude of the returned value. <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">from_chars</c-></code> currently does not (see <a data-link-type="biblio" href="#biblio-lwg3081" title="Floating point from_chars API does not distinguish between overflow and underflow">[LWG3081]</a>). <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">scanf</c-></code> does not, either.</p>
   <div class="example" id="example-3c33295d">
    <a class="self-link" href="#example-3c33295d"></a> 
<pre class="language-c++ highlight"><c- c1="">// larger than INT32_MAX</c->
<c- n="">std</c-><c- o="">::</c-><c- n="">string</c-> <c- n="">source</c-><c- p="">{</c-><c- s="">"999999999999999999999999999999"</c-><c- p="">};</c->

<c- p="">{</c->
  <c- n="">std</c-><c- o="">::</c-><c- n="">istringstream</c-> <c- n="">iss</c-><c- p="">{</c-><c- n="">source</c-><c- p="">};</c->
  <c- b="">int</c-> <c- n="">i</c-><c- p="">{};</c->
  <c- n="">iss</c-> <c- o="">&gt;&gt;</c-> <c- n="">i</c-><c- p="">;</c->
  <c- c1="">// iss.fail() == true</c->
  <c- c1="">// i == INT32_MAX</c->
<c- p="">}</c->

<c- p="">{</c->
  <c- c1="">// (assuming sizeof(long) == 4)</c->
  <c- k="">auto</c-> <c- n="">i</c-> <c- o="">=</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">strtol</c-><c- p="">(</c-><c- n="">source</c-><c- p="">.</c-><c- n="">c_str</c-><c- p="">(),</c-> <c- n="">nullptr</c-><c- p="">,</c-> <c- mi="">10</c-><c- p="">);</c->
  <c- c1="">// i == LONG_MAX</c->
  <c- c1="">// errno == ERANGE</c->
<c- p="">}</c->

<c- p="">{</c->
  <c- b="">int</c-> <c- n="">i</c-><c- p="">{};</c->
  <c- k="">auto</c-> <c- p="">[</c-><c- n="">ec</c-><c- p="">,</c-> <c- n="">ptr</c-><c- p="">]</c-> <c- o="">=</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">from_chars</c-><c- p="">(</c-><c- n="">source</c-><c- p="">.</c-><c- n="">data</c-><c- p="">(),</c-> <c- n="">source</c-><c- p="">.</c-><c- n="">data</c-><c- p="">()</c-> <c- o="">+</c-> <c- n="">source</c-><c- p="">.</c-><c- n="">size</c-><c- p="">(),</c-> <c- n="">i</c-><c- p="">);</c->
  <c- c1="">// ec == std::errc::result_out_of_range</c->
  <c- c1="">// i == 0 (!)</c->
<c- p="">}</c->

<c- p="">{</c->
  <c- b="">int</c-> <c- n="">i</c-><c- p="">{};</c->
  <c- k="">auto</c-> <c- n="">r</c-> <c- o="">=</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">sscanf</c-><c- p="">(</c-><c- n="">source</c-><c- p="">.</c-><c- n="">c_str</c-><c- p="">(),</c-> <c- s="">"%d"</c-><c- p="">,</c-> <c- o="">&amp;</c-><c- n="">i</c-><c- p="">);</c->
  <c- c1="">// r == 1  (?)</c->
  <c- c1="">// i == -1 (?)</c->
  <c- c1="">// errno == ERANGE</c->
<c- p="">}</c->
</pre>
   </div>
   <p>This is predicated on an issue with using <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">expected</c-></code>:
we can only ever either return an error, or a value.
Those aforementioned facilities can both return an error code,
while simultaneously communicating additional information
about possible errors through the scanned value.</p>
   <p>Nevertheless, there’s a simple reason for using <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">expected</c-></code>:
it prevents user errors. Because an <code class="highlight"><c- n="">expected</c-></code> can indeed
only hold either a value or an error, there’s never a situation
where an user accidentally forgets to check for an error,
and mistakenly uses the scanned value directly instead:</p>
   <div class="example" id="example-46ddcaef">
    <a class="self-link" href="#example-46ddcaef"></a> 
<pre class="language-c++ highlight"><c- b="">int</c-> <c- n="">i</c-><c- p="">{};</c->
<c- n="">std</c-><c- o="">::</c-><c- n="">cin</c-> <c- o="">&gt;&gt;</c-> <c- n="">i</c-><c- p="">;</c->
<c- c1="">// We would need to check std::cin.operator bool() first,</c->
<c- c1="">// to determine whether `i` was successfully read:</c->
<c- c1="">// that's very easy to forget</c->

<c- k="">auto</c-> <c- n="">r</c-> <c- o="">=</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">scan</c-><c- o="">&lt;</c-><c- b="">int</c-><c- o="">&gt;</c-><c- p="">(...,</c-> <c- s="">"{}"</c-><c- p="">);</c->
<c- b="">int</c-> <c- n="">i</c-> <c- o="">=</c-> <c- n="">r</c-><c- o="">-&gt;</c-><c- n="">value</c-><c- p="">();</c->
<c- c1="">//        ^</c->
<c- c1="">//      dereference</c->
<c- c1="">// does not allow for accidentally accessing the value if we had an error</c->
</pre>
   </div>
   <p>It’s a tradeoff.
Either we allow for an additional avenue for error reporting through the scanned value,
or we use <code class="highlight"><c- n="">expected</c-></code> to prevent reading the values during an error.
Currently, this paper propses doing the latter.</p>
   <h3 class="heading settled" data-level="4.7" id="binary-footprint"><span class="secno">4.7. </span><span class="content">Binary footprint and type erasure</span><a class="self-link" href="#binary-footprint"></a></h3>
   <p>We propose using a type erasure technique to reduce the per-call binary code size.
The scanning function that uses variadic templates can be implemented as a
small inline wrapper around its non-variadic counterpart:</p>
<pre class="highlight"><c- k="">template</c-><c- o="">&lt;</c-><c- n="">scannable_range</c-><c- o="">&lt;</c-><c- b="">char</c-><c- o="">&gt;</c-> <c- n="">Range</c-><c- o="">&gt;</c->
<c- k="">auto</c-> <c- n="">vscan</c-><c- p="">(</c-><c- n="">Range</c-><c- o="">&amp;&amp;</c-> <c- n="">range</c-><c- p="">,</c-> <c- n="">string_view</c-> <c- n="">fmt</c-><c- p="">,</c-> <c- n="">scan_args</c-> <c- n="">args</c-><c- p="">)</c->
  <c- o="">-&gt;</c-> <c- n="">expected</c-><c- o="">&lt;</c-><c- n="">ranges</c-><c- o="">::</c-><c- n="">borrowed_tail_subrange_t</c-><c- o="">&lt;</c-><c- n="">Range</c-><c- o="">&gt;</c-><c- p="">,</c-> <c- n="">scan_error</c-><c- o="">&gt;</c-><c- p="">;</c->

<c- k="">template</c-> <c- o="">&lt;</c-><c- k="">typename</c-><c- p="">...</c-> <c- n="">Args</c-><c- p="">,</c-> <c- n="">scannable_range</c-><c- o="">&lt;</c-><c- b="">char</c-><c- o="">&gt;</c-> <c- n="">SourceRange</c-><c- o="">&gt;</c->
<c- k="">auto</c-> <c- n="">scan</c-><c- p="">(</c-><c- n="">SourceRange</c-><c- o="">&amp;&amp;</c-> <c- n="">source</c-><c- p="">,</c-> <c- n="">scan_format_string</c-><c- o="">&lt;</c-><c- n="">Range</c-><c- p="">,</c-> <c- n="">Args</c-><c- p="">...</c-><c- o="">&gt;</c-> <c- n="">format</c-><c- p="">)</c->
    <c- o="">-&gt;</c-> <c- n="">expected</c-><c- o="">&lt;</c-><c- n="">scan_result</c-><c- o="">&lt;</c-><c- n="">ranges</c-><c- o="">::</c-><c- n="">borrowed_tail_subrange_t</c-><c- o="">&lt;</c-><c- n="">SourceRange</c-><c- o="">&gt;</c-><c- p="">,</c-> <c- n="">Args</c-><c- p="">...</c-><c- o="">&gt;</c-><c- p="">,</c-> <c- n="">scan_error</c-><c- o="">&gt;</c-> <c- p="">{</c->
  <c- k="">auto</c-> <c- n="">args</c-> <c- o="">=</c-> <c- n="">make_scan_args</c-><c- o="">&lt;</c-><c- n="">SourceRange</c-><c- p="">,</c-> <c- n="">Args</c-><c- p="">...</c-><c- o="">&gt;</c-><c- p="">();</c->
  <c- k="">auto</c-> <c- n="">result</c-> <c- o="">=</c-> <c- n="">vscan</c-><c- p="">(</c-><c- n="">std</c-><c- o="">::</c-><c- n="">forward</c-><c- o="">&lt;</c-><c- n="">SourceRange</c-><c- o="">&gt;</c-><c- p="">(</c-><c- n="">range</c-><c- p="">),</c-> <c- n="">format</c-><c- p="">,</c-> <c- n="">args</c-><c- p="">);</c->
  <c- k="">return</c-> <c- n="">make_scan_result</c-><c- p="">(</c-><c- n="">std</c-><c- o="">::</c-><c- n="">move</c-><c- p="">(</c-><c- n="">result</c-><c- p="">),</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">move</c-><c- p="">(</c-><c- n="">args</c-><c- p="">));</c->
<c- p="">}</c->
</pre>
   <p>As shown in <a data-link-type="biblio" href="#biblio-p0645" title="Text Formatting">[P0645]</a> this dramatically reduces binary code size, which will make <code class="highlight"><c- n="">scan</c-></code> comparable to <code class="highlight"><c- n="">scanf</c-></code> on this metric.</p>
   <p><code class="highlight"><c- n="">make_scan_args</c-></code> type erases the arguments that are to be scanned.
This is similar to <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">make_format_args</c-></code>, used with <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">format</c-></code>.</p>
   <p class="note" role="note"><span class="marker">Note:</span> This implementation of <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">scan</c-></code> is more complicated
compared to <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">format</c-></code>, which can be described as a one-liner calling <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">vformat</c-></code>.
This is because the <code class="highlight"><i><c- n="">scan</c-><c- o="">-</c-><c- n="">arg</c-><c- o="">-</c-><c- n="">store</c-></i></code> returned by <code class="highlight"><c- n="">make_scan_args</c-></code> needs to outlive the call to <code class="highlight"><c- n="">vscan</c-></code>, and then be converted to a <code class="highlight"><c- n="">tuple</c-></code> and returned from <code class="highlight"><c- n="">scan</c-></code>.
Whereas with <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">format</c-></code>, the <code class="highlight"><i><c- n="">format</c-><c- o="">-</c-><c- n="">arg</c-><c- o="">-</c-><c- n="">store</c-></i></code> returned by <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">make_format_args</c-></code> is immediately consumed by <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">vformat</c-></code>, and not used elsewhere.</p>
   <h3 class="heading settled" data-level="4.8" id="safety"><span class="secno">4.8. </span><span class="content">Safety</span><a class="self-link" href="#safety"></a></h3>
   <p><code class="highlight"><c- n="">scanf</c-></code> is arguably more unsafe than <code class="highlight"><c- n="">printf</c-></code> because <code class="highlight"><c- n="">__attribute__</c-><c- p="">((</c-><c- n="">format</c-><c- p="">(</c-><c- n="">scanf</c-><c- p="">,</c-> <c- p="">...)))</c-></code> (<a data-link-type="biblio" href="#biblio-attr" title="Common Function Attributes">[ATTR]</a>) implemented by GCC and Clang
doesn’t catch the whole class of buffer overflow bugs, e.g.</p>
<pre class="language-c++ highlight"><c- b="">char</c-> <c- n="">s</c-><c- p="">[</c-><c- mi="">10</c-><c- p="">];</c->
<c- n="">std</c-><c- o="">::</c-><c- n="">sscanf</c-><c- p="">(</c-><c- n="">input</c-><c- p="">,</c-> <c- s="">"%s"</c-><c- p="">,</c-> <c- n="">s</c-><c- p="">);</c-> <c- c1="">// s may overflow.</c->
</pre>
   <p>Specifying the maximum length in the format string above solves the issue but is
error-prone, especially since one has to account for the terminating null.</p>
   <p>Unlike <code class="highlight"><c- n="">scanf</c-></code>, the proposed facility relies on variadic templates instead of
the mechanism provided by <code class="highlight"><c- o="">&lt;</c-><c- n="">cstdarg</c-><c- o="">&gt;</c-></code>. The type information is captured
automatically and passed to scanners, guaranteeing type safety and making many of
the <code class="highlight"><c- n="">scanf</c-></code> specifiers redundant (see <a href="#format-strings">§ 4.2 Format strings</a>). Memory management is
automatic to prevent buffer overflow errors.</p>
   <h3 class="heading settled" data-level="4.9" id="extensibility"><span class="secno">4.9. </span><span class="content">Extensibility</span><a class="self-link" href="#extensibility"></a></h3>
   <p>We propose an extension API for user-defined types similar to <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">formatter</c-></code>,
used with <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">format</c-></code>. It separates format string processing and parsing, enabling
compile-time format string checks, and allows extending the format specification
language for user types. It enables scanning of user-defined types.</p>
<pre class="language-c++ highlight"><c- k="">auto</c-> <c- n="">r</c-> <c- o="">=</c-> <c- n="">scan</c-><c- o="">&lt;</c-><c- n="">tm</c-><c- o="">&gt;</c-><c- p="">(</c-><c- n="">input</c-><c- p="">,</c-> <c- s="">"Date: {0:%Y-%m-%d}"</c-><c- p="">);</c->
</pre>
   <p>This is done by providing a specialization of <code class="highlight"><c- n="">scanner</c-></code> for <code class="highlight"><c- n="">tm</c-></code>:</p>
<pre class="language-c++ highlight"><c- n="">template</c-> <c- o="">&lt;&gt;</c->
<c- k="">struct</c-> <c- nc="">scanner</c-><c- o="">&lt;</c-><c- n="">tm</c-><c- o="">&gt;</c-> <c- p="">{</c->
  <c- n="">constexpr</c-> <c- k="">auto</c-> <c- n="">parse</c-><c- p="">(</c-><c- n="">scan_parse_context</c-><c- o="">&amp;</c-> <c- n="">ctx</c-><c- p="">)</c->
    <c- o="">-&gt;</c-> <c- n="">expected</c-><c- o="">&lt;</c-><c- n="">scan_parse_context</c-><c- o="">::</c-><c- n="">iterator</c-><c- p="">,</c-> <c- n="">scan_error</c-><c- o="">&gt;</c-><c- p="">;</c->

  <c- n="">template</c-> <c- o="">&lt;</c-><c- n="">class</c-> <c- n="">ScanContext</c-><c- o="">&gt;</c->
  <c- k="">auto</c-> <c- n="">scan</c-><c- p="">(</c-><c- n="">tm</c-><c- o="">&amp;</c-> <c- n="">t</c-><c- p="">,</c-> <c- n="">ScanContext</c-><c- o="">&amp;</c-> <c- n="">ctx</c-><c- p="">)</c-> <c- k="">const</c->
    <c- o="">-&gt;</c-> <c- n="">expected</c-><c- o="">&lt;</c-><c- n="">typename</c-> <c- n="">ScanContext</c-><c- o="">::</c-><c- n="">iterator</c-><c- p="">,</c-> <c- n="">scan_error</c-><c- o="">&gt;</c-><c- p="">;</c->
<c- p="">};</c->
</pre>
   <p>The <code class="highlight"><c- n="">scanner</c-><c- o="">&lt;</c-><c- n="">tm</c-><c- o="">&gt;::</c-><c- n="">parse</c-></code> function parses the <code class="highlight"><c- n="">format</c-><c- o="">-</c-><c- n="">spec</c-></code> portion of the format
string corresponding to the current argument, and <code class="highlight"><c- n="">scanner</c-><c- o="">&lt;</c-><c- n="">tm</c-><c- o="">&gt;::</c-><c- n="">scan</c-></code> parses the
input range <code class="highlight"><c- n="">ctx</c-><c- p="">.</c-><c- n="">range</c-><c- p="">()</c-></code> and stores the result in <code class="highlight"><c- n="">t</c-></code>.</p>
   <p>An implementation of <code class="highlight"><c- n="">scanner</c-><c- o="">&lt;</c-><c- n="">T</c-><c- o="">&gt;::</c-><c- n="">scan</c-></code> can potentially use the istream extraction <code class="highlight"><c- k="">operator</c-><c- o="">&gt;&gt;</c-></code> for user-defined type <code class="highlight"><c- n="">T</c-></code>, if available.</p>
   <h3 class="heading settled" data-level="4.10" id="locales"><span class="secno">4.10. </span><span class="content">Locales</span><a class="self-link" href="#locales"></a></h3>
   <p>As pointed out in <a data-link-type="biblio" href="#biblio-n4412" title="N4412: Shortcomings of iostreams">[N4412]</a>:</p>
   <blockquote>
    <p>There are a number of communications protocol frameworks in use that employ
text-based representations of data, for example XML and JSON. The text is
machine-generated and machine-read and should not depend on or consider the
locales at either end.</p>
   </blockquote>
   <p>To address this, <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">format</c-></code> provided control over the use of locales. We propose
doing the same for the current facility by performing locale-independent parsing
by default and designating separate format specifiers for locale-specific ones.
In particular, locale-specific behavior can be opted into by using the <code class="highlight"><c- n="">L</c-></code> format specifier, and supplying a <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">locale</c-></code> object.</p>
   <div class="example" id="example-092ec9ed">
    <a class="self-link" href="#example-092ec9ed"></a> 
<pre class="language-c++ highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">locale</c-><c- o="">::</c-><c- n="">global</c-><c- p="">(</c-><c- n="">std</c-><c- o="">::</c-><c- n="">locale</c-><c- o="">::</c-><c- n="">classic</c-><c- p="">());</c->

<c- c1="">// {} uses no locale</c->
<c- c1="">// {:L} uses the global locale</c->
<c- k="">auto</c-> <c- n="">r0</c-> <c- o="">=</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">scan</c-><c- o="">&lt;</c-><c- b="">double</c-><c- p="">,</c-> <c- b="">double</c-><c- o="">&gt;</c-><c- p="">(</c-><c- s="">"1.23 4.56"</c-><c- p="">,</c-> <c- s="">"{} {:L}"</c-><c- p="">);</c->
<c- c1="">// r0-&gt;values(): (1.23, 4.56)</c->

<c- c1="">// {} uses no locale</c->
<c- c1="">// {:L} uses the supplied locale</c->
<c- k="">auto</c-> <c- n="">r1</c-> <c- o="">=</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">scan</c-><c- o="">&lt;</c-><c- b="">double</c-><c- p="">,</c-> <c- b="">double</c-><c- o="">&gt;</c-><c- p="">(</c-><c- n="">std</c-><c- o="">::</c-><c- n="">locale</c-><c- p="">{</c-><c- s="">"fi_FI"</c-><c- p="">},</c-> <c- s="">"1.23 4,56"</c-><c- p="">,</c-> <c- s="">"{} {:L}"</c-><c- p="">);</c->
<c- c1="">// r1-&gt;values(): (1.23, 4.56)</c->
</pre>
   </div>
   <h3 class="heading settled" data-level="4.11" id="encoding"><span class="secno">4.11. </span><span class="content">Encoding</span><a class="self-link" href="#encoding"></a></h3>
   <p>In a similar manner as with <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">format</c-></code>, input given to <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">scan</c-></code> is assumed
to be in the (ordinary/wide) literal encoding.</p>
   <p>If an error in encoding is encountered while reading a value of a string type
(<code class="highlight"><c- n="">basic_string</c-></code>, <code class="highlight"><c- n="">basic_string_view</c-></code>), an <code class="highlight"><c- n="">invalid_scanned_value</c-></code> error is returned.
For other types, the reading is stopped, as the parser can’t parse a numeric value from
something that isn’t digits.</p>
   <div class="example" id="example-047db6d3">
    <a class="self-link" href="#example-047db6d3"></a> 
<pre class="language-c++ highlight"><c- c1="">// Invalid UTF-8</c->
<c- k="">auto</c-> <c- n="">r</c-> <c- o="">=</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">scan</c-><c- o="">&lt;</c-><c- n="">std</c-><c- o="">::</c-><c- n="">string</c-><c- o="">&gt;</c-><c- p="">(</c-><c- s="">"a</c-><c- se="">\xc3</c-><c- s=""> "</c-><c- p="">,</c-> <c- s="">"{}"</c-><c- p="">);</c->
<c- c1="">// r == false</c->
<c- c1="">// r-&gt;error() == std::scan_error::invalid_scanner_value</c->

<c- k="">auto</c-> <c- n="">r2</c-> <c- o="">=</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">scan</c-><c- o="">&lt;</c-><c- b="">int</c-><c- o="">&gt;</c-><c- p="">(</c-><c- s="">"1</c-><c- se="">\xc3</c-><c- s=""> "</c-><c- p="">,</c-> <c- s="">"{}"</c-><c- p="">);</c->
<c- c1="">// r2 == true</c->
<c- c1="">// r2-&gt;value() == 1</c->
<c- c1="">// r2-&gt;range() == "\xc3 "</c->
</pre>
   </div>
   <p>Reading raw bytes (not in the literal encoding) into a <code class="highlight"><c- n="">string</c-></code> isn’t directly supported.
This can be achieved either with simpler range algorithms already in the standard,
or by using a custom type or scanner.</p>
   <h3 class="heading settled" data-level="4.12" id="performance"><span class="secno">4.12. </span><span class="content">Performance</span><a class="self-link" href="#performance"></a></h3>
   <p>The API allows efficient implementation that minimizes virtual function calls
and dynamic memory allocations, and avoids unnecessary copies. In particular,
since it doesn’t need to guarantee the lifetime of the input across multiple
function calls, <code class="highlight"><c- n="">scan</c-></code> can take <code class="highlight"><c- n="">string_view</c-></code> avoiding an extra string copy
compared to <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">istringstream</c-></code>. Since, in the default case, it also doesn’t
deal with locales, it can internally use something like <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">from_chars</c-></code>.</p>
   <p>We can also avoid unnecessary copies required by <code class="highlight"><c- n="">scanf</c-></code> when parsing strings,
e.g.</p>
<pre class="language-c++ highlight"><c- k="">auto</c-> <c- n="">r</c-> <c- o="">=</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">scan</c-><c- o="">&lt;</c-><c- n="">std</c-><c- o="">::</c-><c- n="">string_view</c-><c- p="">,</c-> <c- b="">int</c-><c- o="">&gt;</c-><c- p="">(</c-><c- s="">"answer = 42"</c-><c- p="">,</c-> <c- s="">"{} = {}"</c-><c- p="">);</c->
</pre>
   <p>Because the format strings are checked at compile time, while being aware
of the exact types to scan, and the source range type, it’s possible to check
at compile time, whether scanning a <code class="highlight"><c- n="">string_view</c-></code> would dangle, or if it’S
possible at all (reading from a non-<code class="highlight"><c- n="">contiguous_range</c-></code>).</p>
   <h3 class="heading settled" data-level="4.13" id="chrono"><span class="secno">4.13. </span><span class="content">Integration with chrono</span><a class="self-link" href="#chrono"></a></h3>
   <p>The proposed facility can be integrated with <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">chrono</c-><c- o="">::</c-><c- n="">parse</c-></code> (<a data-link-type="biblio" href="#biblio-p0355" title="Extending &lt;chrono&gt; to Calendars and Time Zones">[P0355]</a>)
via the extension mechanism, similarly to the integration between chrono and text
formatting proposed in <a data-link-type="biblio" href="#biblio-p1361" title="Integration of chrono with text formatting">[P1361]</a>. This will improve consistency between parsing
and formatting, make parsing multiple objects easier, and allow avoiding dynamic
memory allocations without resolving to the deprecated <code class="highlight"><c- n="">strstream</c-></code>.</p>
   <p>Before:</p>
<pre class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">istringstream</c-> <c- n="">is</c-><c- p="">(</c-><c- s="">"start = 10:30"</c-><c- p="">);</c->
<c- n="">std</c-><c- o="">::</c-><c- n="">string</c-> <c- n="">key</c-><c- p="">;</c->
<c- b="">char</c-> <c- n="">sep</c-><c- p="">;</c->
<c- n="">std</c-><c- o="">::</c-><c- n="">chrono</c-><c- o="">::</c-><c- n="">seconds</c-> <c- n="">time</c-><c- p="">;</c->
<c- n="">is</c-> <c- o="">&gt;&gt;</c-> <c- n="">key</c-> <c- o="">&gt;&gt;</c-> <c- n="">sep</c-> <c- o="">&gt;&gt;</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">chrono</c-><c- o="">::</c-><c- n="">parse</c-><c- p="">(</c-><c- s="">"%H:%M"</c-><c- p="">,</c-> <c- n="">time</c-><c- p="">);</c->
</pre>
   <p>After:</p>
<pre class="highlight"><c- k="">auto</c-> <c- n="">result</c-> <c- o="">=</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">scan</c-><c- o="">&lt;</c-><c- n="">std</c-><c- o="">::</c-><c- n="">string</c-><c- p="">,</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">chrono</c-><c- o="">::</c-><c- n="">seconds</c-><c- o="">&gt;</c-><c- p="">(</c-><c- s="">"start = 10:30"</c-><c- p="">,</c-> <c- s="">"{0} = {1:%H:%M}"</c-><c- p="">);</c->
<c- k="">const</c-> <c- k="">auto</c-><c- o="">&amp;</c-> <c- p="">[</c-><c- n="">key</c-><c- p="">,</c-> <c- n="">time</c-><c- p="">]</c-> <c- o="">=</c-> <c- n="">result</c-><c- o="">-&gt;</c-><c- n="">values</c-><c- p="">();</c->
</pre>
   <p>Note that the <code class="highlight"><c- n="">scan</c-></code> version additionally validates the separator.</p>
   <h3 class="heading settled" data-level="4.14" id="deep-impact"><span class="secno">4.14. </span><span class="content">Impact on existing code</span><a class="self-link" href="#deep-impact"></a></h3>
   <p>The proposed API is defined in a new header and should have no impact on
existing code.</p>
   <h2 class="heading settled" data-level="5" id="existing-work"><span class="secno">5. </span><span class="content">Existing work</span><a class="self-link" href="#existing-work"></a></h2>
   <p><a data-link-type="biblio" href="#biblio-scnlib" title="scnlib: scanf for modern C++">[SCNLIB]</a> is a C++ library that, among other things,
provides an interface similar to the one described in this paper.
As of the publication of this paper, the latest release (v2.0.0) of <a data-link-type="biblio" href="#biblio-scnlib" title="scnlib: scanf for modern C++">[SCNLIB]</a> is the reference implementation of this proposal.</p>
   <p><a data-link-type="biblio" href="#biblio-fmt" title="The fmt library">[FMT]</a> has a prototype implementation of an earlier version of the proposal.</p>
   <h2 class="heading settled" data-level="6" id="future"><span class="secno">6. </span><span class="content">Future extensions</span><a class="self-link" href="#future"></a></h2>
   <p>To keep the scope of this paper somewhat manageable,
we’ve chosen to only include functionality we consider fundamental.
This leaves the design space open for future extensions and other proposals.
However, we are not categorically against exploring this design space,
if it is deemed critical for v1.</p>
   <p>All of the possible future extensions described below are implemented in <a data-link-type="biblio" href="#biblio-scnlib" title="scnlib: scanf for modern C++">[SCNLIB]</a>.</p>
   <h3 class="heading settled" data-level="6.1" id="stdio-integration"><span class="secno">6.1. </span><span class="content">Integration with <code class="highlight"><c- n="">stdio</c-></code></span><a class="self-link" href="#stdio-integration"></a></h3>
   <p>In the SG9 meeting in Kona (11/2023), it was polled, that:</p>
   <blockquote>
     SG9 feels that it essential for std::scan to be useable with stdin and cin
(and the paper would be incomplete without this feature). 
    <table>
     <tbody>
      <tr>
       <th>SF
       </th><th>F
       </th><th>N
       </th><th>A
       </th><th>SA
      </th></tr><tr>
       <td>0
       </td><td>5
       </td><td>1
       </td><td>3
       </td><td>0
    </td></tr></tbody></table>
   </blockquote>
   <p>We’ve decided to follow the route of <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">format</c-></code> + <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">print</c-></code>,
i.e. to not complicate and bloat this paper further by involving I/O.
This is still an important avenue of future expansion,
and the library proposed in this paper is designed and specified in such a way
as to easily allow that expansion.</p>
   <p><a data-link-type="biblio" href="#biblio-scnlib" title="scnlib: scanf for modern C++">[SCNLIB]</a> implements this by providing a function, <code class="highlight"><c- n="">scn</c-><c- o="">::</c-><c- n="">input</c-></code>,
for interfacing with <code class="highlight"><c- n="">stdin</c-></code>, and by allowing passing in <code class="highlight"><c- b="">FILE</c-><c- o="">*</c-></code>s as input
to <code class="highlight"><c- n="">scn</c-><c- o="">::</c-><c- n="">scan</c-></code>, in addition to <code class="highlight"><c- n="">scannable_range</c-></code>s.</p>
   <h3 class="heading settled" data-level="6.2" id="char-set-match"><span class="secno">6.2. </span><span class="content"><code class="highlight"><c- n="">scanf</c-></code>-like <code class="highlight"><c- p="">[</c-><c- n="">character</c-> <c- n="">set</c-><c- p="">]</c-></code> matching</span><a class="self-link" href="#char-set-match"></a></h3>
   <p><code class="highlight"><c- n="">scanf</c-></code> supports the <code class="highlight"><c- p="">[</c-></code> format specifier, which allows for matching for a set of accepted
characters. Unfortunately, because some of the syntax for specifying that set is
implementation-defined, the utility of this functionality is hampered.
Properly specified, this could be useful.</p>
   <div class="example" id="example-5353faf4">
    <a class="self-link" href="#example-5353faf4"></a> 
<pre class="language-c++ highlight"><c- k="">auto</c-> <c- n="">r</c-> <c- o="">=</c-> <c- n="">scan</c-><c- o="">&lt;</c-><c- n="">string</c-><c- o="">&gt;</c-><c- p="">(</c-><c- s="">"abc123"</c-><c- p="">,</c-> <c- s="">"{:[a-zA-Z]}"</c-><c- p="">);</c-> <c- c1="">// r-&gt;value() == "abc", r-&gt;range() == "123"</c->
<c- c1="">// Compare with:</c->
<c- b="">char</c-> <c- n="">buf</c->\<c- p="">[</c-><c- n="">N</c-><c- p="">];</c->
<c- n="">sscanf</c-><c- p="">(</c-><c- s="">"abc123"</c-><c- p="">,</c-> <c- s="">"%[a-zA-Z]"</c-><c- p="">,</c-> <c- n="">buf</c-><c- p="">);</c->

<c- c1="">// ...</c->

<c- k="">auto</c-> <c- n="">_</c-> <c- o="">=</c-> <c- n="">scan</c-><c- o="">&lt;</c-><c- n="">string</c-><c- o="">&gt;</c-><c- p="">(...,</c-> <c- s="">"{:[^</c-><c- se="">\n</c-><c- s="">]}"</c-><c- p="">);</c-> <c- c1="">// match until newline</c->
</pre>
   </div>
   <p>It should be noted, that while the syntax is quite similar, this is not a regular expression.
This syntax is intentionally way more limited, as is meant for simple character matching.</p>
   <p><a data-link-type="biblio" href="#biblio-scnlib" title="scnlib: scanf for modern C++">[SCNLIB]</a> implements this syntax, providing support for matching single characters/code points
(<code class="highlight"><c- p="">{</c-><c- o="">:</c-><c- p="">[</c-><c- n="">abc</c-><c- p="">]}</c-></code>) and code point ranges (<code class="highlight"><c- p="">{</c-><c- o="">:</c-><c- p="">[</c-><c- n="">a</c-><c- o="">-</c-><c- n="">z</c-><c- p="">]}</c-></code>).
Full regex matching is also supported with <code class="highlight"><c- p="">{</c-><c- o="">:/</c-><c- p="">...</c-><c- o="">/</c-><c- p="">}</c-></code>.</p>
   <h3 class="heading settled" data-level="6.3" id="scan-code-point"><span class="secno">6.3. </span><span class="content">Reading code points (or even grapheme clusters?)</span><a class="self-link" href="#scan-code-point"></a></h3>
   <p><code class="highlight"><c- b="">char32_t</c-></code> in nowadays the type denoting a Unicode code point.
Reading individual code points, or even Unicode grapheme clusters, could be a useful feature.
Currently, this proposal only supports reading of individual code units (<code class="highlight"><c- b="">char</c-></code> or <code class="highlight"><c- b="">wchar_t</c-></code>).</p>
   <p><a data-link-type="biblio" href="#biblio-scnlib" title="scnlib: scanf for modern C++">[SCNLIB]</a> supports reading Unicode code points with <code class="highlight"><c- b="">char32_t</c-></code>.</p>
   <h3 class="heading settled" data-level="6.4" id="scan-transcode"><span class="secno">6.4. </span><span class="content">Reading strings and chars of different width</span><a class="self-link" href="#scan-transcode"></a></h3>
   <p>In C++, we have character types other than <code class="highlight"><c- b="">char</c-></code> and <code class="highlight"><c- b="">wchar_t</c-></code>, too:
namely <code class="highlight"><c- b="">char8_t</c-></code>, <code class="highlight"><c- b="">char16_t</c-></code>, and <code class="highlight"><c- b="">char32_t</c-></code>.
Currently, this proposal only supports reading strings with the same
character type as the input range, and reading <code class="highlight"><c- b="">wchar_t</c-></code> characters from
narrow <code class="highlight"><c- b="">char</c-></code>-oriented input ranges, as does <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">format</c-></code>. <code class="highlight"><c- n="">scanf</c-></code> somewhat supports this with the <code class="highlight"><c- n="">l</c-></code>-flag (and the absence of one in <code class="highlight"><c- n="">wscanf</c-></code>).
Providing support for reading differently-encoded strings could be useful.</p>
   <div class="example" id="example-0540dee3">
    <a class="self-link" href="#example-0540dee3"></a> 
<pre class="language-c++ highlight"><c- c1="">// Currently supported:</c->
<c- k="">auto</c-> <c- n="">r0</c-> <c- o="">=</c-> <c- n="">scan</c-><c- o="">&lt;</c-><c- b="">wchar_t</c-><c- o="">&gt;</c-><c- p="">(</c-><c- s="">"abc"</c-><c- p="">,</c-> <c- s="">"{}"</c-><c- p="">);</c->

<c- c1="">// Not supported:</c->
<c- k="">auto</c-> <c- n="">r1</c-> <c- o="">=</c-> <c- n="">scan</c-><c- o="">&lt;</c-><c- b="">char</c-><c- o="">&gt;</c-><c- p="">(</c->L<c- s="">"abc"</c-><c- p="">,</c-> L<c- s="">"{}"</c-><c- p="">);</c->
<c- k="">auto</c-> <c- n="">r2</c-> <c- o="">=</c->
  <c- n="">scan</c-><c- o="">&lt;</c-><c- n="">string</c-><c- p="">,</c-> <c- n="">wstring</c-><c- p="">,</c-> <c- n="">u8string</c-><c- p="">,</c-> <c- n="">u16string</c-><c- p="">,</c-> <c- n="">u32string</c-><c- o="">&gt;</c-><c- p="">(</c-><c- s="">"abc def ghi jkl mno"</c-><c- p="">,</c-> <c- s="">"{} {} {} {} {}"</c-><c- p="">);</c->
<c- k="">auto</c-> <c- n="">r3</c-> <c- o="">=</c->
  <c- n="">scan</c-><c- o="">&lt;</c-><c- n="">string</c-><c- p="">,</c-> <c- n="">wstring</c-><c- p="">,</c-> <c- n="">u8string</c-><c- p="">,</c-> <c- n="">u16string</c-><c- p="">,</c-> <c- n="">u32string</c-><c- o="">&gt;</c-><c- p="">(</c->L<c- s="">"abc def ghi jkl mno"</c-><c- p="">,</c-> L<c- s="">"{} {} {} {} {}"</c-><c- p="">);</c->
</pre>
   </div>
   <h3 class="heading settled" data-level="6.5" id="range-scanning"><span class="secno">6.5. </span><span class="content">Scanning of ranges</span><a class="self-link" href="#range-scanning"></a></h3>
   <p>Introduced in <a data-link-type="biblio" href="#biblio-p2286" title="Formatting Ranges">[P2286]</a> for <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">format</c-></code>, enabling the user to use <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">scan</c-></code> to scan ranges, could be useful.</p>
   <h3 class="heading settled" data-level="6.6" id="default-values"><span class="secno">6.6. </span><span class="content">Default values for scanned values</span><a class="self-link" href="#default-values"></a></h3>
   <p>Currently, the values returned by <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">scan</c-></code> are value-constructed,
and assigned over if a value is read successfully.
It may be useful to be able to provide an initial value different from a value-constructed
one, for example, for preallocating a <code class="highlight"><c- n="">string</c-></code>, and possibly reusing it:</p>
   <div class="example" id="example-cdfbeaa1">
    <a class="self-link" href="#example-cdfbeaa1"></a> 
<pre class="language-c++ highlight"><c- n="">string</c-> <c- n="">str</c-><c- p="">;</c->
<c- n="">str</c-><c- p="">.</c-><c- n="">reserve</c-><c- p="">(</c-><c- n="">n</c-><c- p="">);</c->
<c- k="">auto</c-> <c- n="">r0</c-> <c- o="">=</c-> <c- n="">scan</c-><c- o="">&lt;</c-><c- n="">string</c-><c- o="">&gt;</c-><c- p="">(...,</c-> <c- s="">"{}"</c-><c- p="">,</c-> <c- p="">{</c-><c- n="">std</c-><c- o="">::</c-><c- n="">move</c-><c- p="">(</c-><c- n="">str</c-><c- p="">)});</c->
<c- c1="">// ...</c->
<c- n="">r0</c-><c- o="">-&gt;</c-><c- n="">value</c-><c- p="">().</c-><c- n="">clear</c-><c- p="">();</c->
<c- k="">auto</c-> <c- n="">r1</c-> <c- o="">=</c-> <c- n="">scan</c-><c- o="">&lt;</c-><c- n="">string</c-><c- o="">&gt;</c-><c- p="">(...,</c-> <c- s="">"{}"</c-><c- p="">,</c-> <c- p="">{</c-><c- n="">std</c-><c- o="">::</c-><c- n="">move</c-><c- p="">(</c-><c- n="">r0</c-><c- o="">-&gt;</c-><c- n="">value</c-><c- p="">())});</c->
</pre>
   </div>
   <p>This same facility could be also used for additional user customization,
as pointed out in <a href="#argument-passing">§ 4.5 Argument passing, and return type of scan</a>.</p>
   <h3 class="heading settled" data-level="6.7" id="discard"><span class="secno">6.7. </span><span class="content">Assignment suppression / discarding values</span><a class="self-link" href="#discard"></a></h3>
   <p><code class="highlight"><c- n="">scanf</c-></code> supports discarding scanned values with the <code class="highlight"><c- o="">*</c-></code> specifier in the format string. <a data-link-type="biblio" href="#biblio-scnlib" title="scnlib: scanf for modern C++">[SCNLIB]</a> provides similar functionality through a special type, <code class="highlight"><c- n="">scn</c-><c- o="">::</c-><c- n="">discard</c-></code>:</p>
   <div class="example" id="example-beec30a1">
    <a class="self-link" href="#example-beec30a1"></a> 
<pre class="language-c++ highlight"><c- b="">int</c-> <c- n="">i</c-><c- p="">;</c->
<c- n="">scanf</c-><c- p="">(</c-><c- s="">"%*d"</c-><c- p="">,</c-> <c- o="">&amp;</c-><c- n="">i</c-><c- p="">);</c->

<c- k="">auto</c-> <c- n="">r</c-> <c- o="">=</c-> <c- n="">scn</c-><c- o="">::</c-><c- n="">scan</c-><c- o="">&lt;</c-><c- n="">scn</c-><c- o="">::</c-><c- n="">discard</c-><c- o="">&lt;</c-><c- b="">int</c-><c- o="">&gt;&gt;</c-><c- p="">(...,</c-> <c- s="">"{}"</c-><c- p="">);</c->
<c- k="">auto</c-> <c- p="">[</c-><c- n="">_</c-><c- p="">]</c-> <c- o="">=</c-> <c- n="">r</c-><c- o="">-&gt;</c-><c- n="">values</c-><c- p="">();</c->
</pre>
   </div>
   <h2 class="heading settled" data-level="7" id="spec"><span class="secno">7. </span><span class="content">Specification</span><a class="self-link" href="#spec"></a></h2>
   <p>At this point, only the synopses are provided.</p>
   <p>Note the similarity with <a data-link-type="biblio" href="#biblio-p0645" title="Text Formatting">[P0645]</a> (<code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">format</c-></code>) in some parts.</p>
   <p>The changes to the wording include additions to the header <code class="highlight"><c- o="">&lt;</c-><c- n="">ranges</c-><c- o="">&gt;</c-></code>, and a new header, <code class="highlight"><c- o="">&lt;</c-><c- n="">scan</c-><c- o="">&gt;</c-></code>.</p>
   <h3 class="heading settled" data-level="7.1" id="spec-ranges-syn"><span class="secno">7.1. </span><span class="content">Modify "Header <code class="highlight"><c- o="">&lt;</c-><c- n="">ranges</c-><c- o="">&gt;</c-></code> synopsis" [ranges.syn]</span><a class="self-link" href="#spec-ranges-syn"></a></h3>
<pre class="highlight"><c- cp="">#include</c-> &lt;compare&gt;
<c- cp="">#include</c-> &lt;initializer_list&gt;
<c- cp="">#include</c-> &lt;iterator&gt;

<c- k="">namespace</c-> <c- nn="">std</c-><c- o="">::</c-><c- nn="">ranges</c-> <c- p="">{</c->
  <c- c1="">// ...</c->

  <c- k="">template</c-><c- o="">&lt;</c-><c- n="">range</c-> <c- n="">R</c-><c- o="">&gt;</c->
    <c- k="">using</c-> <c- n="">borrowed_iterator_t</c-> <c- o="">=</c-> <i><c- n="">see</c-> <c- n="">below</c-></i><c- p="">;</c->   <c- c1="">// freestanding</c->

  <c- k="">template</c-><c- o="">&lt;</c-><c- n="">range</c-> <c- n="">R</c-><c- o="">&gt;</c->
    <c- k="">using</c-> <c- n="">borrowed_subrange_t</c-> <c- o="">=</c-> <i><c- n="">see</c-> <c- n="">below</c-></i><c- p="">;</c->   <c- c1="">// freestanding</c->
  
  <ins><c- k="">template</c-><c- o="">&lt;</c-><c- n="">range</c-> <c- n="">R</c-><c- o="">&gt;</c->
    <c- k="">using</c-> <c- n="">borrowed_tail_subrange_t</c-> <c- o="">=</c-> <i><c- n="">see</c-> <c- n="">below</c-></i><c- p="">;</c->  <c- c1="">// freestanding</c-></ins>

  <c- c1="">// ...</c->
<c- p="">}</c->
</pre>
   <h3 class="heading settled" data-level="7.2" id="spec-range-dangling"><span class="secno">7.2. </span><span class="content">Modify "Dangling iterator handling", paragraph 3 [range.dangling]</span><a class="self-link" href="#spec-range-dangling"></a></h3>
   <p>For a type <code class="highlight"><c- n="">R</c-></code> that models <code class="highlight"><c- n="">range</c-></code>:</p>
   <ul>
    <li>
     if <code class="highlight"><c- n="">R</c-></code> models <code class="highlight"><c- n="">borrowed_range</c-></code>, then <code class="highlight"><c- n="">borrowed_iterator_t</c-><c- o="">&lt;</c-><c- n="">R</c-><c- o="">&gt;</c-></code> denotes <code class="highlight"><c- n="">iterator_t</c-><c- o="">&lt;</c-><c- n="">R</c-><c- o="">&gt;</c-></code>, 
     <del>and <code class="highlight"><c- n="">borrowed_subrange_t</c-><c- o="">&lt;</c-><c- n="">R</c-><c- o="">&gt;</c-></code> denotes <code class="highlight"><c- n="">subrange</c-><c- o="">&lt;</c-><c- n="">iterator_t</c-><c- o="">&lt;</c-><c- n="">R</c-><c- o="">&gt;&gt;</c-></code>;</del>
     <ins><code class="highlight"><c- n="">borrowed_subrange_t</c-><c- o="">&lt;</c-><c- n="">R</c-><c- o="">&gt;</c-></code> denotes <code class="highlight"><c- n="">subrange</c-><c- o="">&lt;</c-><c- n="">iterator_t</c-><c- o="">&lt;</c-><c- n="">R</c-><c- o="">&gt;&gt;</c-></code>,
and <code class="highlight"><c- n="">borrowed_tail_subrange_t</c-><c- o="">&lt;</c-><c- n="">R</c-><c- o="">&gt;</c-></code> denotes <code class="highlight"><c- n="">subrange</c-><c- o="">&lt;</c-><c- n="">iterator_t</c-><c- o="">&lt;</c-><c- n="">R</c-><c- o="">&gt;</c-><c- p="">,</c-> <c- n="">sentinel_t</c-><c- o="">&lt;</c-><c- n="">R</c-><c- o="">&gt;&gt;</c-></code>;</ins>
    </li><li>
     otherwise, 
     <del>both <code class="highlight"><c- n="">borrowed_iterator_t</c-><c- o="">&lt;</c-><c- n="">R</c-><c- o="">&gt;</c-></code> and <code class="highlight"><c- n="">borrowed_subrange_t</c-><c- o="">&lt;</c-><c- n="">R</c-><c- o="">&gt;</c-></code> denote <code class="highlight"><c- n="">dangling</c-></code>.</del>
     <ins><code class="highlight"><c- n="">borrowed_iterator_t</c-><c- o="">&lt;</c-><c- n="">R</c-><c- o="">&gt;</c-></code>, <code class="highlight"><c- n="">borrowed_subrange_t</c-><c- o="">&lt;</c-><c- n="">R</c-><c- o="">&gt;</c-></code>, and <code class="highlight"><c- n="">borrowed_tail_subrange_t</c-><c- o="">&lt;</c-><c- n="">R</c-><c- o="">&gt;</c-></code> all denote <code class="highlight"><c- n="">dangling</c-></code>.</ins>
   </li></ul>
   <h3 class="heading settled" data-level="7.3" id="spec-header-synopsis"><span class="secno">7.3. </span><span class="content">Header <code class="highlight"><c- o="">&lt;</c-><c- n="">scan</c-><c- o="">&gt;</c-></code> synopsis</span><a class="self-link" href="#spec-header-synopsis"></a></h3>
<pre class="highlight"><c- k="">namespace</c-> <c- nn="">std</c-> <c- p="">{</c->
  <c- k="">template</c-><c- o="">&lt;</c-><c- k="">class</c-> <c- nc="">charT</c-><c- p="">,</c-> <c- k="">class</c-> <c- nc="">Range</c-><c- p="">,</c-> <c- k="">class</c-><c- p="">...</c-> <c- n="">Args</c-><c- o="">&gt;</c->
    <c- k="">struct</c-> <c- nc="">basic_scan_format_string</c-><c- p="">;</c->

  <c- k="">template</c-><c- o="">&lt;</c-><c- k="">class</c-> <c- nc="">Range</c-><c- p="">,</c-> <c- k="">class</c-><c- p="">...</c-> <c- n="">Args</c-><c- o="">&gt;</c->
    <c- k="">using</c-> <c- n="">scan_format_string</c-> <c- o="">=</c->
      <c- n="">basic_scan_format_string</c-><c- o="">&lt;</c-><c- b="">char</c-><c- p="">,</c->
                               <c- n="">type_identity_t</c-><c- o="">&lt;</c-><c- n="">Range</c-><c- o="">&gt;</c-><c- p="">,</c->
                               <c- n="">type_identity_t</c-><c- o="">&lt;</c-><c- n="">Args</c-><c- o="">&gt;</c-><c- p="">...</c-><c- o="">&gt;</c-><c- p="">;</c->
  <c- k="">template</c-><c- o="">&lt;</c-><c- k="">class</c-> <c- nc="">Range</c-><c- p="">,</c-> <c- k="">class</c-><c- p="">...</c-> <c- n="">Args</c-><c- o="">&gt;</c->
    <c- k="">using</c-> <c- n="">wscan_format_string</c-> <c- o="">=</c->
      <c- n="">basic_scan_format_string</c-><c- o="">&lt;</c-><c- b="">wchar_t</c-><c- p="">,</c->
                               <c- n="">type_identity_t</c-><c- o="">&lt;</c-><c- n="">Range</c-><c- o="">&gt;</c-><c- p="">,</c->
                               <c- n="">type_identity_t</c-><c- o="">&lt;</c-><c- n="">Args</c-><c- o="">&gt;</c-><c- p="">...</c-><c- o="">&gt;</c-><c- p="">;</c->

  <c- k="">class</c-> <c- nc="">scan_error</c-><c- p="">;</c->

  <c- k="">template</c-><c- o="">&lt;</c-><c- k="">class</c-> <c- nc="">Range</c-><c- p="">,</c-> <c- k="">class</c-><c- p="">...</c-> <c- n="">Args</c-><c- o="">&gt;</c->
    <c- k="">class</c-> <c- nc="">scan_result</c-><c- p="">;</c->

  <c- k="">template</c-><c- o="">&lt;</c-><c- k="">class</c-> <c- nc="">Range</c-><c- p="">,</c-> <c- k="">class</c-> <c- nc="">CharT</c-><c- o="">&gt;</c->
    <c- k="">concept</c-> <c- nc="">scannable_range</c-> <c- o="">=</c->
      <c- n="">ranges</c-><c- o="">::</c-><c- n="">forward_range</c-><c- o="">&lt;</c-><c- n="">Range</c-><c- o="">&gt;</c-> <c- o="">&amp;&amp;</c->
      <c- n="">same_as</c-><c- o="">&lt;</c-><c- n="">ranges</c-><c- o="">::</c-><c- n="">range_value_t</c-><c- o="">&lt;</c-><c- n="">Range</c-><c- o="">&gt;</c-><c- p="">,</c-> <c- n="">CharT</c-><c- o="">&gt;</c-><c- p="">;</c->

  <c- k="">template</c-><c- o="">&lt;</c-><c- k="">class</c-> <c- nc="">Range</c-><c- p="">,</c-> <c- k="">class</c-><c- p="">...</c-> <c- n="">Args</c-><c- o="">&gt;</c->
    <c- k="">using</c-> <i><c- n="">scan</c-><c- o="">-</c-><c- n="">result</c-><c- o="">-</c-><c- n="">type</c-></i> <c- o="">=</c-> <c- n="">expected</c-><c- o="">&lt;</c->
      <c- n="">scan_result</c-><c- o="">&lt;</c-><c- n="">ranges</c-><c- o="">::</c-><c- n="">borrowed_tail_subrange_t</c-><c- o="">&lt;</c-><c- n="">Range</c-><c- o="">&gt;</c-><c- p="">,</c-> <c- n="">Args</c-><c- p="">...</c-><c- o="">&gt;</c-><c- p="">,</c->
      <c- n="">scan_error</c-><c- o="">&gt;</c-><c- p="">;</c-> <c- c1="">// exposition only</c->

  <c- k="">template</c-><c- o="">&lt;</c-><c- k="">class</c-><c- p="">...</c-> <c- n="">Args</c-><c- p="">,</c-> <c- n="">scannable_range</c-><c- o="">&lt;</c-><c- b="">char</c-><c- o="">&gt;</c-> <c- n="">Range</c-><c- o="">&gt;</c->
    <i><c- n="">scan</c-><c- o="">-</c-><c- n="">result</c-><c- o="">-</c-><c- n="">type</c-></i><c- o="">&lt;</c-><c- n="">Range</c-><c- p="">,</c-> <c- n="">Args</c-><c- p="">...</c-><c- o="">&gt;</c-> <c- n="">scan</c-><c- p="">(</c-><c- n="">Range</c-><c- o="">&amp;&amp;</c-> <c- n="">range</c-><c- p="">,</c->
                                          <c- n="">scan_format_string</c-><c- o="">&lt;</c-><c- n="">Range</c-><c- p="">,</c-> <c- n="">Args</c-><c- p="">...</c-><c- o="">&gt;</c-> <c- n="">fmt</c-><c- p="">);</c->

  <c- k="">template</c-><c- o="">&lt;</c-><c- k="">class</c-><c- p="">...</c-> <c- n="">Args</c-><c- p="">,</c-> <c- n="">scannable_range</c-><c- o="">&lt;</c-><c- b="">wchar_t</c-><c- o="">&gt;</c-> <c- n="">Range</c-><c- o="">&gt;</c->
    <i><c- n="">scan</c-><c- o="">-</c-><c- n="">result</c-><c- o="">-</c-><c- n="">type</c-></i><c- o="">&lt;</c-><c- n="">Range</c-><c- p="">,</c-> <c- n="">Args</c-><c- p="">...</c-><c- o="">&gt;</c-> <c- n="">scan</c-><c- p="">(</c-><c- n="">Range</c-><c- o="">&amp;&amp;</c-> <c- n="">range</c-><c- p="">,</c->
                                          <c- n="">wscan_format_string</c-><c- o="">&lt;</c-><c- n="">Range</c-><c- p="">,</c-> <c- n="">Args</c-><c- p="">...</c-><c- o="">&gt;</c-> <c- n="">fmt</c-><c- p="">);</c->

  <c- k="">template</c-><c- o="">&lt;</c-><c- k="">class</c-><c- p="">...</c-> <c- n="">Args</c-><c- p="">,</c-> <c- n="">scannable_range</c-><c- o="">&lt;</c-><c- b="">char</c-><c- o="">&gt;</c-> <c- n="">Range</c-><c- o="">&gt;</c->
    <i><c- n="">scan</c-><c- o="">-</c-><c- n="">result</c-><c- o="">-</c-><c- n="">type</c-></i><c- o="">&lt;</c-><c- n="">Range</c-><c- p="">,</c-> <c- n="">Args</c-><c- p="">...</c-><c- o="">&gt;</c-> <c- n="">scan</c-><c- p="">(</c-><c- k="">const</c-> <c- n="">locale</c-><c- o="">&amp;</c-> <c- n="">loc</c-><c- p="">,</c-> <c- n="">Range</c-><c- o="">&amp;&amp;</c-> <c- n="">range</c-><c- p="">,</c->
                                          <c- n="">scan_format_string</c-><c- o="">&lt;</c-><c- n="">Range</c-><c- p="">,</c-> <c- n="">Args</c-><c- p="">...</c-><c- o="">&gt;</c-> <c- n="">fmt</c-><c- p="">);</c->

  <c- k="">template</c-> <c- o="">&lt;</c-><c- k="">class</c-><c- p="">...</c-> <c- n="">Args</c-><c- p="">,</c-> <c- n="">scannable_range</c-><c- o="">&lt;</c-><c- b="">wchar_t</c-><c- o="">&gt;</c-> <c- n="">Range</c-><c- o="">&gt;</c->
    <i><c- n="">scan</c-><c- o="">-</c-><c- n="">result</c-><c- o="">-</c-><c- n="">type</c-></i><c- o="">&lt;</c-><c- n="">Range</c-><c- p="">,</c-> <c- n="">Args</c-><c- p="">...</c-><c- o="">&gt;</c-> <c- n="">scan</c-><c- p="">(</c-><c- k="">const</c-> <c- n="">locale</c-><c- o="">&amp;</c-> <c- n="">loc</c-><c- p="">,</c-> <c- n="">Range</c-><c- o="">&amp;&amp;</c-> <c- n="">range</c-><c- p="">,</c->
                                          <c- n="">wscan_format_string</c-><c- o="">&lt;</c-><c- n="">Range</c-><c- p="">,</c-> <c- n="">Args</c-><c- p="">...</c-><c- o="">&gt;</c-> <c- n="">fmt</c-><c- p="">);</c->

  <c- k="">template</c-><c- o="">&lt;</c-><c- k="">class</c-> <c- nc="">Range</c-><c- p="">,</c-> <c- k="">class</c-> <c- nc="">charT</c-><c- o="">&gt;</c-> <c- k="">class</c-> <c- nc="">basic_scan_context</c-><c- p="">;</c->
  <c- k="">using</c-> <c- n="">scan_context</c-> <c- o="">=</c-> <c- n="">basic_scan_context</c-><c- o="">&lt;</c-><i><c- n="">unspecified</c-></i><c- p="">,</c-> <c- b="">char</c-><c- o="">&gt;</c-><c- p="">;</c->
  <c- k="">using</c-> <c- n="">wscan_context</c-> <c- o="">=</c-> <c- n="">basic_scan_context</c-><c- o="">&lt;</c-><i><c- n="">unspecified</c-></i><c- p="">,</c-> <c- b="">wchar_t</c-><c- o="">&gt;</c-><c- p="">;</c->
  
  <c- k="">template</c-><c- o="">&lt;</c-><c- k="">class</c-> <c- nc="">Context</c-><c- o="">&gt;</c-> <c- k="">class</c-> <c- nc="">basic_scan_args</c-><c- p="">;</c->
  <c- k="">using</c-> <c- n="">scan_args</c-> <c- o="">=</c-> <c- n="">basic_scan_args</c-><c- o="">&lt;</c-><c- n="">scan_context</c-><c- o="">&gt;</c-><c- p="">;</c->
  <c- k="">using</c-> <c- n="">wscan_args</c-> <c- o="">=</c-> <c- n="">basic_scan_args</c-><c- o="">&lt;</c-><c- n="">wscan_context</c-><c- o="">&gt;</c-><c- p="">;</c->

  <c- k="">template</c-><c- o="">&lt;</c-><c- k="">class</c-> <c- nc="">Range</c-><c- o="">&gt;</c->
    <c- k="">using</c-> <i><c- n="">vscan</c-><c- o="">-</c-><c- n="">result</c-><c- o="">-</c-><c- n="">type</c-></i> <c- o="">=</c-> <c- n="">expected</c-><c- o="">&lt;</c->
      <c- n="">ranges</c-><c- o="">::</c-><c- n="">borrowed_tail_subrange_t</c-><c- o="">&lt;</c-><c- n="">Range</c-><c- o="">&gt;</c-><c- p="">,</c->
      <c- n="">scan_error</c-><c- o="">&gt;</c-><c- p="">;</c-> <c- c1="">// exposition only</c->

  <c- k="">template</c-><c- o="">&lt;</c-><c- n="">scannable_range</c-><c- o="">&lt;</c-><c- b="">char</c-><c- o="">&gt;</c-> <c- n="">Range</c-><c- o="">&gt;</c->
    <i><c- n="">vscan</c-><c- o="">-</c-><c- n="">result</c-><c- o="">-</c-><c- n="">type</c-></i><c- o="">&lt;</c-><c- n="">Range</c-><c- o="">&gt;</c-> <c- n="">vscan</c-><c- p="">(</c-><c- n="">Range</c-><c- o="">&amp;&amp;</c-> <c- n="">range</c-><c- p="">,</c-> <c- n="">string_view</c-> <c- n="">fmt</c-><c- p="">,</c-> <c- n="">scan_args</c-> <c- n="">args</c-><c- p="">);</c->

  <c- k="">template</c-><c- o="">&lt;</c-><c- n="">scannable_range</c-><c- o="">&lt;</c-><c- b="">wchar_t</c-><c- o="">&gt;</c-> <c- n="">Range</c-><c- o="">&gt;</c->
    <i><c- n="">vscan</c-><c- o="">-</c-><c- n="">result</c-><c- o="">-</c-><c- n="">type</c-></i><c- o="">&lt;</c-><c- n="">Range</c-><c- o="">&gt;</c-> <c- n="">vscan</c-><c- p="">(</c-><c- n="">Range</c-><c- o="">&amp;&amp;</c-> <c- n="">range</c-><c- p="">,</c-> <c- n="">wstring_view</c-> <c- n="">fmt</c-><c- p="">,</c-> <c- n="">wscan_args</c-> <c- n="">args</c-><c- p="">);</c->

  <c- k="">template</c-><c- o="">&lt;</c-><c- n="">scannable_range</c-><c- o="">&lt;</c-><c- b="">char</c-><c- o="">&gt;</c-> <c- n="">Range</c-><c- o="">&gt;</c->
    <i><c- n="">vscan</c-><c- o="">-</c-><c- n="">result</c-><c- o="">-</c-><c- n="">type</c-></i><c- o="">&lt;</c-><c- n="">Range</c-><c- o="">&gt;</c-> <c- n="">vscan</c-><c- p="">(</c-><c- k="">const</c-> <c- n="">locale</c-><c- o="">&amp;</c-> <c- n="">loc</c-><c- p="">,</c->
                                   <c- n="">Range</c-><c- o="">&amp;&amp;</c-> <c- n="">range</c-><c- p="">,</c->
                                   <c- n="">string_view</c-> <c- n="">fmt</c-><c- p="">,</c->
                                   <c- n="">scan_args</c-> <c- n="">args</c-><c- p="">);</c->

  <c- k="">template</c-><c- o="">&lt;</c-><c- n="">scannable_range</c-><c- o="">&lt;</c-><c- b="">wchar_t</c-><c- o="">&gt;</c-> <c- n="">Range</c-><c- o="">&gt;</c->
    <i><c- n="">vscan</c-><c- o="">-</c-><c- n="">result</c-><c- o="">-</c-><c- n="">type</c-></i><c- o="">&lt;</c-><c- n="">Range</c-><c- o="">&gt;</c-> <c- n="">vscan</c-><c- p="">(</c-><c- k="">const</c-> <c- n="">locale</c-><c- o="">&amp;</c-> <c- n="">loc</c-><c- p="">,</c->
                                   <c- n="">Range</c-><c- o="">&amp;&amp;</c-> <c- n="">range</c-><c- p="">,</c->
                                   <c- n="">wstring_view</c-> <c- n="">fmt</c-><c- p="">,</c->
                                   <c- n="">wscan_args</c-> <c- n="">args</c-><c- p="">);</c->

  <c- k="">template</c-><c- o="">&lt;</c-><c- k="">class</c-> <c- nc="">T</c-><c- p="">,</c-> <c- k="">class</c-> <c- nc="">CharT</c-> <c- o="">=</c-> <c- b="">char</c-><c- o="">&gt;</c->
    <c- k="">struct</c-> <c- nc="">scanner</c-><c- p="">;</c->

  <c- k="">template</c-><c- o="">&lt;</c-><c- k="">class</c-> <c- nc="">T</c-><c- p="">,</c-> <c- k="">class</c-> <c- nc="">CharT</c-><c- o="">&gt;</c->
    <c- k="">concept</c-> <c- nc="">scannable</c-> <c- o="">=</c-> <i><c- n="">see</c-> <c- n="">below</c-></i><c- p="">;</c->
  
  <c- k="">template</c-><c- o="">&lt;</c-><c- k="">class</c-> <c- nc="">CharT</c-><c- o="">&gt;</c->
    <c- k="">using</c-> <c- n="">basic_scan_parse_context</c-> <c- o="">=</c-> <c- n="">basic_format_parse_context</c-><c- o="">&lt;</c-><c- n="">CharT</c-><c- o="">&gt;</c-><c- p="">;</c->
  
  <c- k="">using</c-> <c- n="">scan_parse_context</c-> <c- o="">=</c-> <c- n="">basic_scan_parse_context</c-><c- o="">&lt;</c-><c- b="">char</c-><c- o="">&gt;</c-><c- p="">;</c->
  <c- k="">using</c-> <c- n="">wscan_parse_context</c-> <c- o="">=</c-> <c- n="">basic_scan_parse_context</c-><c- o="">&lt;</c-><c- b="">wchar_t</c-><c- o="">&gt;</c-><c- p="">;</c->

  <c- k="">template</c-><c- o="">&lt;</c-><c- k="">class</c-> <c- nc="">Context</c-><c- o="">&gt;</c->
    <c- k="">class</c-> <c- nc="">basic_scan_arg</c-><c- p="">;</c->
  
  <c- k="">template</c-><c- o="">&lt;</c-><c- k="">class</c-> <c- nc="">Context</c-><c- p="">,</c-> <c- k="">class</c-><c- p="">...</c-> <c- n="">Args</c-><c- o="">&gt;</c->
    <c- k="">class</c-> <i><c- nc="">scan</c-><c- o="">-</c-><c- n="">arg</c-><c- o="">-</c-><c- n="">store</c-></i><c- p="">;</c-> <c- c1="">// exposition only</c->

  <c- k="">template</c-><c- o="">&lt;</c-><c- k="">class</c-> <c- nc="">Range</c-><c- p="">,</c-> <c- k="">class</c-><c- p="">...</c-> <c- n="">Args</c-><c- o="">&gt;</c->
    <c- k="">constexpr</c-> <i><c- n="">see</c-> <c- n="">below</c-></i> <c- n="">make_scan_args</c-><c- p="">();</c->

  <c- k="">template</c-><c- o="">&lt;</c-><c- k="">class</c-> <c- nc="">Range</c-><c- p="">,</c-> <c- k="">class</c-> <c- nc="">Context</c-><c- p="">,</c-> <c- k="">class</c-><c- p="">...</c-> <c- n="">Args</c-><c- o="">&gt;</c->
    <c- n="">expected</c-><c- o="">&lt;</c-><c- n="">scan_result</c-><c- o="">&lt;</c-><c- n="">Range</c-><c- p="">,</c-> <c- n="">Args</c-><c- p="">...</c-><c- o="">&gt;</c-><c- p="">,</c-> <c- n="">scan_error</c-><c- o="">&gt;</c->
      <c- n="">make_scan_result</c-><c- p="">(</c-><c- n="">expected</c-><c- o="">&lt;</c-><c- n="">Range</c-><c- p="">,</c-> <c- n="">scan_error</c-><c- o="">&gt;&amp;&amp;</c-> <c- n="">source</c-><c- p="">,</c->
                       <i><c- n="">scan</c-><c- o="">-</c-><c- n="">arg</c-><c- o="">-</c-><c- n="">store</c-></i><c- o="">&lt;</c-><c- n="">Context</c-><c- p="">,</c-> <c- n="">Args</c-><c- p="">...</c-><c- o="">&gt;&amp;&amp;</c-> <c- n="">args</c-><c- p="">);</c->
<c- p="">}</c->
</pre>
   <h3 class="heading settled" data-level="7.4" id="spec-scan-error-synopsis"><span class="secno">7.4. </span><span class="content">Class <code class="highlight"><c- n="">scan_error</c-></code> synopsis</span><a class="self-link" href="#spec-scan-error-synopsis"></a></h3>
<pre class="highlight"><c- k="">namespace</c-> <c- nn="">std</c-> <c- p="">{</c->
  <c- k="">class</c-> <c- nc="">scan_error</c-> <c- p="">{</c->
  <c- k="">public</c-><c- o="">:</c->
    <c- k="">enum</c-> <c- nc="">code_type</c-> <c- p="">{</c->
      <c- n="">good</c-><c- p="">,</c->
      <c- n="">end_of_range</c-><c- p="">,</c->
      <c- n="">invalid_format_string</c-><c- p="">,</c->
      <c- n="">invalid_scanned_value</c-><c- p="">,</c->
      <c- n="">value_out_of_range</c->
    <c- p="">};</c->

    <c- k="">constexpr</c-> <c- n="">scan_error</c-><c- p="">()</c-> <c- o="">=</c-> <c- k="">default</c-><c- p="">;</c->
    <c- k="">constexpr</c-> <c- n="">scan_error</c-><c- p="">(</c-><c- n="">code_type</c-> <c- n="">error_code</c-><c- p="">,</c-> <c- k="">const</c-> <c- b="">char</c-><c- o="">*</c-> <c- n="">message</c-><c- p="">);</c->

    <c- k="">constexpr</c-> <c- k="">explicit</c-> <c- k="">operator</c-> <c- b="">bool</c-><c- p="">()</c-> <c- k="">const</c-> <c- k="">noexcept</c-><c- p="">;</c->

    <c- k="">constexpr</c-> <c- n="">code_type</c-> <c- nf="">code</c-><c- p="">()</c-> <c- k="">const</c-> <c- k="">noexcept</c-><c- p="">;</c->
    <c- k="">constexpr</c-> <c- k="">const</c-> <c- b="">char</c-><c- o="">*</c-> <c- nf="">msg</c-><c- p="">()</c-> <c- k="">const</c-><c- p="">;</c->

  <c- k="">private</c-><c- o="">:</c->
    <c- n="">code_type</c-> <i><c- n="">code_</c-></i><c- p="">;</c->      <c- c1="">// exposition only</c->
    <c- k="">const</c-> <c- b="">char</c-><c- o="">*</c-> <i><c- n="">message_</c-></i><c- p="">;</c-> <c- c1="">// exposition only</c->
  <c- p="">};</c->
<c- p="">}</c->
</pre>
   <h3 class="heading settled" data-level="7.5" id="spec-scan-result-synopsis"><span class="secno">7.5. </span><span class="content">Class template <code class="highlight"><c- n="">scan_result</c-></code> synopsis</span><a class="self-link" href="#spec-scan-result-synopsis"></a></h3>
<pre class="highlight"><c- k="">namespace</c-> <c- nn="">std</c-> <c- p="">{</c->
  <c- k="">template</c-><c- o="">&lt;</c-><c- k="">class</c-> <c- nc="">Range</c-><c- p="">,</c-> <c- k="">class</c-><c- p="">...</c-> <c- n="">Args</c-><c- o="">&gt;</c->
  <c- k="">class</c-> <c- nc="">scan_result</c-> <c- p="">{</c->
  <c- k="">public</c-><c- o="">:</c->
    <c- k="">using</c-> <c- n="">range_type</c-> <c- o="">=</c-> <c- n="">Range</c-><c- p="">;</c->

    <c- k="">constexpr</c-> <c- n="">scan_result</c-><c- p="">()</c-> <c- o="">=</c-> <c- k="">default</c-><c- p="">;</c->
    <c- k="">constexpr</c-> <c- o="">~</c-><c- n="">scan_result</c-><c- p="">()</c-> <c- o="">=</c-> <c- k="">default</c-><c- p="">;</c->

    <c- k="">constexpr</c-> <c- n="">scan_result</c-><c- p="">(</c-><c- n="">range_type</c-> <c- n="">r</c-><c- p="">,</c-> <c- n="">tuple</c-><c- o="">&lt;</c-><c- n="">Args</c-><c- p="">...</c-><c- o="">&gt;&amp;&amp;</c-> <c- n="">values</c-><c- p="">);</c->
    
    <c- k="">template</c-><c- o="">&lt;</c-><c- k="">class</c-> <c- nc="">OtherR</c-><c- p="">,</c-> <c- k="">class</c-><c- p="">...</c-> <c- n="">OtherArgs</c-><c- o="">&gt;</c->
      <c- k="">constexpr</c-> <c- k="">explicit</c-><c- p="">(</c-><i><c- n="">see</c-> <c- n="">below</c-></i><c- p="">)</c-> <c- n="">scan_result</c-><c- p="">(</c-><c- n="">OtherR</c-><c- o="">&amp;&amp;</c-> <c- n="">it</c-><c- p="">,</c-> <c- n="">tuple</c-><c- o="">&lt;</c-><c- n="">OtherArgs</c-><c- p="">...</c-><c- o="">&gt;&amp;&amp;</c-> <c- n="">values</c-><c- p="">);</c->

    <c- k="">constexpr</c-> <c- n="">scan_result</c-><c- p="">(</c-><c- k="">const</c-> <c- n="">scan_result</c-><c- o="">&amp;</c-><c- p="">)</c-> <c- o="">=</c-> <c- k="">default</c-><c- p="">;</c->
    <c- k="">template</c-><c- o="">&lt;</c-><c- k="">class</c-> <c- nc="">OtherR</c-><c- p="">,</c-> <c- k="">class</c-><c- p="">...</c-> <c- n="">OtherArgs</c-><c- o="">&gt;</c->
      <c- k="">constexpr</c-> <c- k="">explicit</c-><c- p="">(</c-><i><c- n="">see</c-> <c- n="">below</c-></i><c- p="">)</c-> <c- n="">scan_result</c-><c- p="">(</c-><c- k="">const</c-> <c- n="">scan_result</c-><c- o="">&lt;</c-><c- n="">OtherR</c-><c- p="">,</c-> <c- n="">OtherArgs</c-><c- p="">...</c-><c- o="">&gt;&amp;</c-> <c- n="">other</c-><c- p="">);</c->

    <c- k="">constexpr</c-> <c- n="">scan_result</c-><c- p="">(</c-><c- n="">scan_result</c-><c- o="">&amp;&amp;</c-><c- p="">)</c-> <c- o="">=</c-> <c- k="">default</c-><c- p="">;</c->
    <c- k="">template</c-><c- o="">&lt;</c-><c- k="">class</c-> <c- nc="">OtherR</c-><c- p="">,</c-> <c- k="">class</c-><c- p="">...</c-> <c- n="">OtherArgs</c-><c- o="">&gt;</c->
      <c- k="">constexpr</c-> <c- k="">explicit</c-><c- p="">(</c-><i><c- n="">see</c-> <c- n="">below</c-></i><c- p="">)</c-> <c- n="">scan_result</c-><c- p="">(</c-><c- n="">scan_result</c-><c- o="">&lt;</c-><c- n="">OtherR</c-><c- p="">,</c-> <c- n="">OtherArgs</c-><c- p="">...</c-><c- o="">&gt;&amp;&amp;</c-> <c- n="">other</c-><c- p="">);</c->

    <c- k="">constexpr</c-> <c- n="">scan_result</c-><c- o="">&amp;</c-> <c- k="">operator</c-><c- o="">=</c-><c- p="">(</c-><c- k="">const</c-> <c- n="">scan_result</c-><c- o="">&amp;</c-><c- p="">)</c-> <c- o="">=</c-> <c- k="">default</c-><c- p="">;</c->
    <c- k="">template</c-><c- o="">&lt;</c-><c- k="">class</c-> <c- nc="">OtherR</c-><c- p="">,</c-> <c- k="">class</c-><c- p="">...</c-> <c- n="">OtherArgs</c-><c- o="">&gt;</c->
      <c- k="">constexpr</c-> <c- n="">scan_result</c-><c- o="">&amp;</c-> <c- k="">operator</c-><c- o="">=</c-><c- p="">(</c-><c- k="">const</c-> <c- n="">scan_result</c-><c- o="">&lt;</c-><c- n="">OtherR</c-><c- p="">,</c-> <c- n="">OtherArgs</c-><c- p="">...</c-><c- o="">&gt;&amp;</c-> <c- n="">other</c-><c- p="">);</c->

    <c- k="">constexpr</c-> <c- n="">scan_result</c-><c- o="">&amp;</c-> <c- k="">operator</c-><c- o="">=</c-><c- p="">(</c-><c- n="">scan_result</c-><c- o="">&amp;&amp;</c-><c- p="">)</c-> <c- o="">=</c-> <c- k="">default</c-><c- p="">;</c->
    <c- k="">template</c-><c- o="">&lt;</c-><c- k="">class</c-> <c- nc="">OtherR</c-><c- p="">,</c-> <c- k="">class</c-><c- p="">...</c-> <c- n="">OtherArgs</c-><c- o="">&gt;</c->
      <c- k="">constexpr</c-> <c- n="">scan_result</c-><c- o="">&amp;</c-> <c- k="">operator</c-><c- o="">=</c-><c- p="">(</c-><c- n="">scan_result</c-><c- o="">&lt;</c-><c- n="">OtherR</c-><c- p="">,</c-> <c- n="">OtherArgs</c-><c- p="">...</c-><c- o="">&gt;&amp;&amp;</c-> <c- n="">other</c-><c- p="">);</c->

    <c- k="">constexpr</c-> <c- n="">range_type</c-> <c- nf="">range</c-><c- p="">()</c-> <c- k="">const</c-><c- p="">;</c->

    <c- k="">constexpr</c-> <i><c- n="">see</c-> <c- n="">below</c-></i> <c- n="">begin</c-><c- p="">()</c-> <c- k="">const</c-><c- p="">;</c->
    <c- k="">constexpr</c-> <i><c- n="">see</c-> <c- n="">below</c-></i> <c- n="">end</c-><c- p="">()</c-> <c- k="">const</c-><c- p="">;</c->

    <c- k="">template</c-><c- o="">&lt;</c-><c- k="">class</c-> <c- nc="">Self</c-><c- o="">&gt;</c->
      <c- k="">constexpr</c-> <c- k="">auto</c-><c- o="">&amp;&amp;</c-> <c- n="">values</c-><c- p="">(</c-><c- k="">this</c-> <c- n="">Self</c-><c- o="">&amp;&amp;</c-><c- p="">);</c->

    <c- k="">template</c-><c- o="">&lt;</c-><c- k="">class</c-> <c- nc="">Self</c-><c- o="">&gt;</c->
      <c- k="">requires</c-> <c- k="">sizeof</c-><c- p="">...(</c-><c- n="">Args</c-><c- p="">)</c-> <c- o="">==</c-> <c- mi="">1</c->
      <c- k="">constexpr</c-> <c- k="">auto</c-><c- o="">&amp;&amp;</c-> <c- n="">value</c-><c- p="">(</c-><c- k="">this</c-> <c- n="">Self</c-><c- o="">&amp;&amp;</c-><c- p="">);</c->

  <c- k="">private</c-><c- o="">:</c->
    <c- n="">range_type</c-> <i><c- n="">range_</c-></i><c- p="">;</c->      <c- c1="">// exposition only</c->
    <c- n="">tuple</c-><c- o="">&lt;</c-><c- n="">Args</c-><c- p="">...</c-><c- o="">&gt;</c-> <i><c- n="">values_</c-></i><c- p="">;</c-> <c- c1="">// exposition only</c->
  <c- p="">};</c->
<c- p="">}</c->
</pre>
   <h3 class="heading settled" data-level="7.6" id="spec-scan-format-string-synopsis"><span class="secno">7.6. </span><span class="content">Class template <code class="highlight"><c- n="">basic_scan_format_string</c-></code> synopsis</span><a class="self-link" href="#spec-scan-format-string-synopsis"></a></h3>
<pre class="highlight"><c- k="">namespace</c-> <c- nn="">std</c-> <c- p="">{</c->
  <c- k="">template</c-><c- o="">&lt;</c-><c- k="">class</c-> <c- nc="">charT</c-><c- p="">,</c-> <c- k="">class</c-> <c- nc="">Range</c-><c- p="">,</c-> <c- k="">class</c-><c- p="">...</c-> <c- n="">Args</c-><c- o="">&gt;</c->
  <c- k="">struct</c-> <c- nc="">basic_scan_format_string</c-> <c- p="">{</c->
  <c- k="">private</c-><c- o="">:</c->
    <c- n="">basic_string_view</c-><c- o="">&lt;</c-><c- n="">charT</c-><c- o="">&gt;</c-> <i><c- n="">str</c-></i><c- p="">;</c->  <c- c1="">// exposition only</c->

  <c- k="">public</c-><c- o="">:</c->
    <c- k="">template</c-><c- o="">&lt;</c-><c- k="">class</c-> <c- nc="">T</c-><c- o="">&gt;</c-> <c- k="">consteval</c-> <c- n="">basic_scan_format_string</c-><c- p="">(</c-><c- k="">const</c-> <c- n="">T</c-><c- o="">&amp;</c-> <c- n="">s</c-><c- p="">);</c->

    <c- k="">constexpr</c-> <c- n="">basic_string_view</c-><c- o="">&lt;</c-><c- n="">charT</c-><c- o="">&gt;</c-> <c- n="">get</c-><c- p="">()</c-> <c- k="">const</c-> <c- k="">noexcept</c-> <c- p="">{</c-> <c- k="">return</c-> <i><c- n="">str</c-></i><c- p="">;</c-> <c- p="">}</c->
  <c- p="">};</c->
<c- p="">}</c->
</pre>
   <h3 class="heading settled" data-level="7.7" id="spec-scan-context-synopsis"><span class="secno">7.7. </span><span class="content">Class template <code class="highlight"><c- n="">basic_scan_context</c-></code> synopsis</span><a class="self-link" href="#spec-scan-context-synopsis"></a></h3>
<pre class="highlight"><c- k="">namespace</c-> <c- nn="">std</c-> <c- p="">{</c->
  <c- k="">template</c-><c- o="">&lt;</c-><c- k="">class</c-> <c- nc="">Range</c-><c- p="">,</c-> <c- k="">class</c-> <c- nc="">CharT</c-><c- o="">&gt;</c->
  <c- k="">class</c-> <c- nc="">basic_scan_context</c-> <c- p="">{</c->
  <c- k="">public</c-><c- o="">:</c->
    <c- k="">using</c-> <c- n="">char_type</c-> <c- o="">=</c-> <c- n="">CharT</c-><c- p="">;</c->
    <c- k="">using</c-> <c- n="">range_type</c-> <c- o="">=</c-> <c- n="">Range</c-><c- p="">;</c->
    <c- k="">using</c-> <c- n="">iterator</c-> <c- o="">=</c-> <c- n="">ranges</c-><c- o="">::</c-><c- n="">iterator_t</c-><c- o="">&lt;</c-><c- n="">range_type</c-><c- o="">&gt;</c-><c- p="">;</c->
    <c- k="">using</c-> <c- n="">sentinel</c-> <c- o="">=</c-> <c- n="">ranges</c-><c- o="">::</c-><c- n="">sentinel_t</c-><c- o="">&lt;</c-><c- n="">range_type</c-><c- o="">&gt;</c-><c- p="">;</c->
    <c- k="">template</c-><c- o="">&lt;</c-><c- k="">class</c-> <c- nc="">T</c-><c- o="">&gt;</c-> <c- k="">using</c-> <c- n="">scanner_type</c-> <c- o="">=</c-> <c- n="">scanner</c-><c- o="">&lt;</c-><c- n="">T</c-><c- p="">,</c-> <c- n="">char_type</c-><c- o="">&gt;</c-><c- p="">;</c->

    <c- k="">constexpr</c-> <c- n="">basic_scan_arg</c-><c- o="">&lt;</c-><c- n="">basic_scan_context</c-><c- o="">&gt;</c-> <c- n="">arg</c-><c- p="">(</c-><c- b="">size_t</c-> <c- n="">id</c-><c- p="">)</c-> <c- k="">const</c-> <c- k="">noexcept</c-><c- p="">;</c->
    <c- n="">std</c-><c- o="">::</c-><c- n="">locale</c-> <c- nf="">locale</c-><c- p="">();</c->

    <c- k="">constexpr</c-> <c- n="">iterator</c-> <c- nf="">begin</c-><c- p="">()</c-> <c- k="">const</c-><c- p="">;</c->
    <c- k="">constexpr</c-> <c- n="">sentinel</c-> <c- nf="">end</c-><c- p="">()</c-> <c- k="">const</c-><c- p="">;</c->
    <c- k="">constexpr</c-> <c- n="">range_type</c-> <c- nf="">range</c-><c- p="">()</c-> <c- k="">const</c-><c- p="">;</c->
    <c- k="">constexpr</c-> <c- b="">void</c-> <c- nf="">advance_to</c-><c- p="">(</c-><c- n="">iterator</c-> <c- n="">it</c-><c- p="">);</c->

  <c- k="">private</c-><c- o="">:</c->
    <c- n="">iterator</c-> <i><c- n="">current_</c-></i><c- p="">;</c->                         <c- c1="">// exposition only</c->
    <c- n="">sentinel</c-> <i><c- n="">end_</c-></i><c- p="">;</c->                             <c- c1="">// exposition only</c->
    <c- n="">std</c-><c- o="">::</c-><c- n="">locale</c-> <i><c- n="">locale_</c-></i><c- p="">;</c->                       <c- c1="">// exposition only</c->
    <c- n="">basic_scan_args</c-><c- o="">&lt;</c-><c- n="">basic_scan_context</c-><c- o="">&gt;</c-> <i><c- n="">args_</c-></i><c- p="">;</c-> <c- c1="">// exposition only</c->
  <c- p="">};</c->
<c- p="">}</c->
</pre>
   <h3 class="heading settled" data-level="7.8" id="spec-scan-args-synopsis"><span class="secno">7.8. </span><span class="content">Class template <code class="highlight"><c- n="">basic_scan_args</c-></code> synopsis</span><a class="self-link" href="#spec-scan-args-synopsis"></a></h3>
<pre class="highlight"><c- k="">namespace</c-> <c- nn="">std</c-> <c- p="">{</c->
  <c- k="">template</c-><c- o="">&lt;</c-><c- k="">class</c-> <c- nc="">Context</c-><c- o="">&gt;</c->
  <c- k="">class</c-> <c- nc="">basic_scan_args</c-> <c- p="">{</c->
    <c- b="">size_t</c-> <i><c- n="">size_</c-></i><c- p="">;</c->                   <c- c1="">// exposition only</c->
    <c- n="">basic_scan_arg</c-><c- o="">&lt;</c-><c- n="">Context</c-><c- o="">&gt;*</c-> <i><c- n="">data_</c-></i><c- p="">;</c-> <c- c1="">// exposition only</c->

  <c- k="">public</c-><c- o="">:</c->
    <c- n="">basic_scan_args</c-><c- p="">()</c-> <c- k="">noexcept</c-><c- p="">;</c->

    <c- k="">template</c-><c- o="">&lt;</c-><c- k="">class</c-><c- p="">...</c-> <c- n="">Args</c-><c- o="">&gt;</c->
      <c- n="">basic_scan_args</c-><c- p="">(</c-><i><c- n="">scan</c-><c- o="">-</c-><c- n="">arg</c-><c- o="">-</c-><c- n="">store</c-></i><c- o="">&lt;</c-><c- n="">Context</c-><c- p="">,</c-> <c- n="">Args</c-><c- p="">...</c-><c- o="">&gt;&amp;</c-> <c- n="">store</c-><c- p="">)</c-> <c- k="">noexcept</c-><c- p="">;</c->

    <c- n="">basic_scan_arg</c-><c- o="">&lt;</c-><c- n="">Context</c-><c- o="">&gt;</c-> <c- n="">get</c-><c- p="">(</c-><c- b="">size_t</c-> <c- n="">i</c-><c- p="">)</c-> <c- k="">noexcept</c-><c- p="">;</c->
  <c- p="">};</c->

  <c- k="">template</c-><c- o="">&lt;</c-><c- k="">class</c-> <c- nc="">Context</c-><c- p="">,</c-> <c- k="">class</c-><c- p="">...</c-> <c- n="">Args</c-><c- o="">&gt;</c->
    <c- n="">basic_scan_args</c-><c- p="">(</c-><i><c- n="">scan</c-><c- o="">-</c-><c- n="">arg</c-><c- o="">-</c-><c- n="">store</c-></i><c- o="">&lt;</c-><c- n="">Context</c-><c- p="">,</c-> <c- n="">Args</c-><c- p="">...</c-><c- o="">&gt;</c-><c- p="">)</c-> <c- o="">-&gt;</c-> <c- n="">basic_scan_args</c-><c- o="">&lt;</c-><c- n="">Context</c-><c- o="">&gt;</c-><c- p="">;</c->
<c- p="">}</c->
</pre>
   <h3 class="heading settled" data-level="7.9" id="spec-scannable"><span class="secno">7.9. </span><span class="content">Concept <code class="highlight"><c- n="">scannable</c-></code></span><a class="self-link" href="#spec-scannable"></a></h3>
<pre class="highlight"><c- k="">namespace</c-> <c- nn="">std</c-> <c- p="">{</c->
  <c- k="">template</c-><c- o="">&lt;</c-><c- k="">class</c-> <c- nc="">T</c-><c- p="">,</c-> <c- k="">class</c-> <c- nc="">Context</c-><c- p="">,</c->
           <c- k="">class</c-> <c- nc="">Scanner</c-> <c- o="">=</c-> <c- k="">typename</c-> <c- nc="">Context</c-><c- o="">::</c-><c- k="">template</c-> <c- n="">scanner_type</c-><c- o="">&lt;</c-><c- n="">remove_const_t</c-><c- o="">&lt;</c-><c- n="">T</c-><c- o="">&gt;&gt;&gt;</c->
    <c- k="">concept</c-> <i><c- nc="">scannable</c-><c- o="">-</c-><c- n="">with</c-></i> <c- o="">=</c->            <c- c1="">// exposition only</c->
      <c- n="">semiregular</c-><c- o="">&lt;</c-><c- n="">Scanner</c-><c- o="">&gt;</c-> <c- o="">&amp;&amp;</c->
      <c- k="">requires</c-><c- p="">(</c-><c- n="">Scanner</c-><c- o="">&amp;</c-> <c- n="">s</c-><c- p="">,</c-> <c- k="">const</c-> <c- n="">Scanner</c-><c- o="">&amp;</c-> <c- n="">cs</c-><c- p="">,</c-> <c- n="">T</c-><c- o="">&amp;</c-> <c- n="">t</c-><c- p="">,</c-> <c- n="">Context</c-><c- o="">&amp;</c-> <c- n="">ctx</c-><c- p="">,</c->
               <c- n="">basic_scan_parse_context</c-><c- o="">&lt;</c-><c- k="">typename</c-> <c- nc="">Context</c-><c- o="">::</c-><c- n="">char_type</c-><c- o="">&gt;&amp;</c-> <c- n="">pctx</c-><c- p="">)</c->
      <c- p="">{</c->
        <c- p="">{</c-> <c- n="">s</c-><c- p="">.</c-><c- n="">parse</c-><c- p="">(</c-><c- n="">pctx</c-><c- p="">)</c-> <c- p="">}</c-> <c- o="">-&gt;</c-> <c- n="">same_as</c-><c- o="">&lt;</c-><c- n="">expected</c-><c- o="">&lt;</c-><c- k="">typename</c-> <c- nc="">decltype</c-><c- p="">(</c-><c- n="">pctx</c-><c- p="">)</c-><c- o="">::</c-><c- n="">iterator</c-><c- p="">,</c-> <c- n="">scan_error</c-><c- o="">&gt;&gt;</c-><c- p="">;</c->
        <c- p="">{</c-> <c- n="">cs</c-><c- p="">.</c-><c- n="">scan</c-><c- p="">(</c-><c- n="">t</c-><c- p="">,</c-> <c- n="">ctx</c-><c- p="">)</c-> <c- p="">}</c-> <c- o="">-&gt;</c-> <c- n="">same_as</c-><c- o="">&lt;</c-><c- n="">expected</c-><c- o="">&lt;</c-><c- k="">typename</c-> <c- nc="">Context</c-><c- o="">::</c-><c- n="">iterator</c-><c- p="">,</c-> <c- n="">scan_error</c-><c- o="">&gt;&gt;</c-><c- p="">;</c->
      <c- p="">};</c->

  <c- k="">template</c-><c- o="">&lt;</c-><c- k="">class</c-> <c- nc="">T</c-><c- p="">,</c-> <c- k="">class</c-> <c- nc="">CharT</c-><c- o="">&gt;</c->
    <c- k="">concept</c-> <c- nc="">scannable</c-> <c- o="">=</c->
      <i><c- n="">scannable</c-><c- o="">-</c-><c- n="">with</c-></i><c- o="">&lt;</c-><c- n="">remove_reference_t</c-><c- o="">&lt;</c-><c- n="">T</c-><c- o="">&gt;</c-><c- p="">,</c-> <c- n="">basic_scan_context</c-><c- o="">&lt;</c-><i><c- n="">unspecified</c-></i><c- p="">,</c-> <c- n="">CharT</c-><c- o="">&gt;&gt;</c-><c- p="">;</c->
<c- p="">}</c->
</pre>
   <h3 class="heading settled" data-level="7.10" id="spec-scan-arg-synopsis"><span class="secno">7.10. </span><span class="content">Class template <code class="highlight"><c- n="">basic_scan_arg</c-></code> synopsis</span><a class="self-link" href="#spec-scan-arg-synopsis"></a></h3>
<pre class="highlight"><c- k="">namespace</c-> <c- nn="">std</c-> <c- p="">{</c->
  <c- k="">template</c-><c- o="">&lt;</c-><c- k="">class</c-> <c- nc="">Context</c-><c- o="">&gt;</c->
  <c- k="">class</c-> <c- nc="">basic_scan_arg</c-> <c- p="">{</c->
  <c- k="">public</c-><c- o="">:</c->
    <c- k="">class</c-> <c- nc="">handle</c-><c- p="">;</c->

  <c- k="">private</c-><c- o="">:</c->
    <c- k="">using</c-> <c- n="">char_type</c-> <c- o="">=</c-> <c- k="">typename</c-> <c- nc="">Context</c-><c- o="">::</c-><c- n="">char_type</c-><c- p="">;</c->            <c- c1="">// exposition only</c->

    <c- n="">variant</c-><c- o="">&lt;</c->
      <c- n="">monostate</c-><c- p="">,</c->
      <c- b="">signed</c-> <c- b="">char</c-><c- o="">*</c-><c- p="">,</c-> <c- b="">short</c-><c- o="">*</c-><c- p="">,</c-> <c- b="">int</c-><c- o="">*</c-><c- p="">,</c-> <c- b="">long</c-><c- o="">*</c-><c- p="">,</c-> <c- b="">long</c-> <c- b="">long</c-><c- o="">*</c-><c- p="">,</c->
      <c- b="">unsigned</c-> <c- b="">char</c-><c- o="">*</c-><c- p="">,</c-> <c- b="">unsigned</c-> <c- b="">short</c-><c- o="">*</c-><c- p="">,</c-> <c- b="">unsigned</c-> <c- b="">int</c-><c- o="">*</c-><c- p="">,</c-> <c- b="">unsigned</c-> <c- b="">long</c-><c- o="">*</c-><c- p="">,</c-> <c- b="">unsigned</c-> <c- b="">long</c-> <c- b="">long</c-><c- o="">*</c-><c- p="">,</c->
      <c- b="">bool</c-><c- o="">*</c-><c- p="">,</c-> <c- n="">char_type</c-><c- o="">*</c-><c- p="">,</c-> <c- b="">void</c-><c- o="">**</c-><c- p="">,</c->
      <c- b="">float</c-><c- o="">*</c-><c- p="">,</c-> <c- b="">double</c-><c- o="">*</c-><c- p="">,</c-> <c- b="">long</c-> <c- b="">double</c-><c- o="">*</c-><c- p="">,</c->
      <c- n="">basic_string</c-><c- o="">&lt;</c-><c- n="">char_type</c-><c- o="">&gt;*</c-><c- p="">,</c-> <c- n="">basic_string_view</c-><c- o="">&lt;</c-><c- n="">char_type</c-><c- o="">&gt;*</c-><c- p="">,</c->
      <c- n="">handle</c-><c- o="">&gt;</c-> <c- n="">value</c-><c- p="">;</c->                                          <c- c1="">// exposition only</c->

    <c- k="">template</c-><c- o="">&lt;</c-><c- k="">class</c-> <c- nc="">T</c-><c- o="">&gt;</c-> <c- k="">explicit</c-> <c- n="">basic_scan_arg</c-><c- p="">(</c-><c- n="">T</c-><c- o="">&amp;</c-> <c- n="">v</c-><c- p="">)</c-> <c- k="">noexcept</c-><c- p="">;</c-> <c- c1="">// exposition only</c->

  <c- k="">public</c-><c- o="">:</c->
    <c- n="">basic_scan_arg</c-><c- p="">()</c-> <c- k="">noexcept</c-><c- p="">;</c->

    <c- k="">explicit</c-> <c- k="">operator</c-> <c- b="">bool</c-><c- p="">()</c-> <c- k="">const</c-> <c- k="">noexcept</c-><c- p="">;</c->
  <c- p="">};</c->
<c- p="">}</c->
</pre>
   <h3 class="heading settled" data-level="7.11" id="spec-scan-arg-store"><span class="secno">7.11. </span><span class="content">Exposition-only class template <code class="highlight"><i><c- n="">scan</c-><c- o="">-</c-><c- n="">arg</c-><c- o="">-</c-><c- n="">store</c-></i></code> synopsis</span><a class="self-link" href="#spec-scan-arg-store"></a></h3>
<pre class="highlight"><c- k="">namespace</c-> <c- nn="">std</c-> <c- p="">{</c->
  <c- k="">template</c-><c- o="">&lt;</c-><c- k="">class</c-> <c- nc="">Context</c-><c- p="">,</c-> <c- k="">class</c-><c- p="">...</c-> <c- n="">Args</c-><c- o="">&gt;</c->
  <c- k="">class</c-> <i><c- nc="">scan</c-><c- o="">-</c-><c- n="">arg</c-><c- o="">-</c-><c- n="">store</c-></i> <c- p="">{</c->                                  <c- c1="">// exposition only</c->
    <c- n="">tuple</c-><c- o="">&lt;</c-><c- n="">Args</c-><c- p="">...</c-><c- o="">&gt;</c-> <i><c- n="">args</c-></i><c- p="">;</c->                                  <c- c1="">// exposition only</c->
    <c- n="">array</c-><c- o="">&lt;</c-><c- n="">basic_scan_arg</c-><c- o="">&lt;</c-><c- n="">Context</c-><c- o="">&gt;</c-><c- p="">,</c-> <c- k="">sizeof</c-><c- p="">...(</c-><c- n="">Args</c-><c- p="">)</c-><c- o="">&gt;</c-> <i><c- n="">data</c-></i><c- p="">;</c-> <c- c1="">// exposition only</c->
  <c- p="">};</c->
<c- p="">}</c->
</pre>
  </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-attr">[ATTR]
   </dt><dd><a href="https://gcc.gnu.org/onlinedocs/gcc-8.2.0/gcc/Common-Function-Attributes.html"><cite>Common Function Attributes</cite></a>. URL: <a href="https://gcc.gnu.org/onlinedocs/gcc-8.2.0/gcc/Common-Function-Attributes.html">https://gcc.gnu.org/onlinedocs/gcc-8.2.0/gcc/Common-Function-Attributes.html</a>
   </dd><dt id="biblio-barry-so-answer">[BARRY-SO-ANSWER]
   </dt><dd><a href="https://stackoverflow.com/a/66819929"><cite>Why the standard defines `borrowed_subrange_t` as `common_range`</cite></a>. URL: <a href="https://stackoverflow.com/a/66819929">https://stackoverflow.com/a/66819929</a>
   </dd><dt id="biblio-codesearch">[CODESEARCH]
   </dt><dd>Andrew Tomazos. <a href="https://codesearch.isocpp.org/"><cite>Code search engine website</cite></a>. URL: <a href="https://codesearch.isocpp.org/">https://codesearch.isocpp.org</a>
   </dd><dt id="biblio-fmt">[FMT]
   </dt><dd>Victor Zverovich et al. <a href="https://github.com/fmtlib/fmt"><cite>The fmt library</cite></a>. URL: <a href="https://github.com/fmtlib/fmt">https://github.com/fmtlib/fmt</a>
   </dd><dt id="biblio-lwg3081">[LWG3081]
   </dt><dd>Greg Falcon. <a href="https://wg21.link/lwg3081"><cite>Floating point from_chars API does not distinguish between overflow and underflow</cite></a>. Open. URL: <a href="https://wg21.link/lwg3081">https://wg21.link/lwg3081</a>
   </dd><dt id="biblio-n4412">[N4412]
   </dt><dd>Jens Maurer. <a href="http://open-std.org/JTC1/SC22/WG21/docs/papers/2015/n4412.html"><cite>N4412: Shortcomings of iostreams</cite></a>. URL: <a href="http://open-std.org/JTC1/SC22/WG21/docs/papers/2015/n4412.html">http://open-std.org/JTC1/SC22/WG21/docs/papers/2015/n4412.html</a>
   </dd><dt id="biblio-p0355">[P0355]
   </dt><dd>Howard E. Hinnant; Tomasz Kamiński. <a href="https://wg21.link/p0355"><cite>Extending &lt;chrono&gt; to Calendars and Time Zones</cite></a>. URL: <a href="https://wg21.link/p0355">https://wg21.link/p0355</a>
   </dd><dt id="biblio-p0645">[P0645]
   </dt><dd>Victor Zverovich. <a href="https://wg21.link/p0645"><cite>Text Formatting</cite></a>. URL: <a href="https://wg21.link/p0645">https://wg21.link/p0645</a>
   </dd><dt id="biblio-p1361">[P1361]
   </dt><dd>Victor Zverovich; Daniela Engert; Howard E. Hinnant. <a href="https://wg21.link/p1361"><cite>Integration of chrono with text formatting</cite></a>. URL: <a href="https://wg21.link/p1361">https://wg21.link/p1361</a>
   </dd><dt id="biblio-p2286">[P2286]
   </dt><dd>Barry Revzin. <a href="https://wg21.link/p2286"><cite>Formatting Ranges</cite></a>. URL: <a href="https://wg21.link/p2286">https://wg21.link/p2286</a>
   </dd><dt id="biblio-p2561">[P2561]
   </dt><dd>Barry Revzin. <a href="https://wg21.link/p2561"><cite>A control flow operator</cite></a>. URL: <a href="https://wg21.link/p2561">https://wg21.link/p2561</a>
   </dd><dt id="biblio-p2637">[P2637]
   </dt><dd>Barry Revzin. <a href="https://wg21.link/p2637"><cite>Member `visit`</cite></a>. URL: <a href="https://wg21.link/p2637">https://wg21.link/p2637</a>
   </dd><dt id="biblio-parse">[PARSE]
   </dt><dd><a href="https://pypi.org/project/parse/"><cite>Python `parse` package</cite></a>. URL: <a href="https://pypi.org/project/parse/">https://pypi.org/project/parse/</a>
   </dd><dt id="biblio-scnlib">[SCNLIB]
   </dt><dd>Elias Kosunen. <a href="https://github.com/eliaskosunen/scnlib"><cite>scnlib: scanf for modern C++</cite></a>. URL: <a href="https://github.com/eliaskosunen/scnlib">https://github.com/eliaskosunen/scnlib</a>
  </dd></dl></body></html>