<!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>P1729R2: 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 5fcd28d6d, updated Tue May 30 13:12:11 2023 -0700" name="generator">
  <link href="http://wg21.link/P1729R2" rel="canonical">
  <link href="https://isocpp.org/favicon.ico" rel="icon">
  <meta content="bae0db863b7c985f57eb91e98c30a0d2cb45a824" name="document-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>
 <body class="h-entry">
  <div class="head">
   <p data-fill-with="logo"></p>
   <h1 class="p-name no-ref" id="title">P1729R2<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="2023-07-08">2023-07-08</time></span></h2>
   <div data-fill-with="spec-metadata">
    <dl>
     <dt>This version:
     <dd><a class="u-url" href="http://wg21.link/P1729R2">http://wg21.link/P1729R2</a>
     <dt class="editor">Authors:
     <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 class="editor p-author h-card vcard"><a class="p-name fn u-email email" href="mailto:victor.zverovich@gmail.com">Victor Zverovich</a>
     <dt>Audience:
     <dd>LEWG, SG9, SG16
     <dt>Project:
     <dd>ISO/IEC JTC1/SC22/WG21 14882: Programming Language — C++
    </dl>
   </div>
   <div data-fill-with="warning"></div>
   <hr title="Separator for header">
  </div>
  <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-r1"><span class="secno">1.1</span> <span class="content">Changes since R1</span></a>
     </ol>
    <li><a href="#introduction"><span class="secno">2</span> <span class="content">Introduction</span></a>
    <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><a href="#example-multiple"><span class="secno">3.2</span> <span class="content">Reading multiple values at once</span></a>
      <li><a href="#example-range"><span class="secno">3.3</span> <span class="content">Reading from an arbitrary range</span></a>
      <li><a href="#example-loop"><span class="secno">3.4</span> <span class="content">Reading multiple values in a loop</span></a>
      <li><a href="#example-alt-error"><span class="secno">3.5</span> <span class="content">Alternative error handling</span></a>
      <li><a href="#example-userdef"><span class="secno">3.6</span> <span class="content">Scanning an user-defined type</span></a>
     </ol>
    <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><a href="#format-strings"><span class="secno">4.2</span> <span class="content">Format strings</span></a>
      <li><a href="#format-string-specifiers"><span class="secno">4.3</span> <span class="content">Format string specifiers</span></a>
      <li><a href="#ranges"><span class="secno">4.4</span> <span class="content">Ranges</span></a>
      <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><a href="#error-handling"><span class="secno">4.6</span> <span class="content">Error handling</span></a>
      <li><a href="#binary-footprint"><span class="secno">4.7</span> <span class="content">Binary footprint and type erasure</span></a>
      <li><a href="#safety"><span class="secno">4.8</span> <span class="content">Safety</span></a>
      <li><a href="#extensibility"><span class="secno">4.9</span> <span class="content">Extensibility</span></a>
      <li><a href="#locales"><span class="secno">4.10</span> <span class="content">Locales</span></a>
      <li><a href="#performance"><span class="secno">4.11</span> <span class="content">Performance</span></a>
      <li><a href="#chrono"><span class="secno">4.12</span> <span class="content">Integration with chrono</span></a>
      <li><a href="#deep-impact"><span class="secno">4.13</span> <span class="content">Impact on existing code</span></a>
     </ol>
    <li><a href="#existing-work"><span class="secno">5</span> <span class="content">Existing work</span></a>
    <li>
     <a href="#future"><span class="secno">6</span> <span class="content">Future extensions</span></a>
     <ol class="toc">
      <li><a href="#istream-integration"><span class="secno">6.1</span> <span class="content">Integration with <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>istream</c-></code>s</span></a>
      <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><a href="#scan-transcode"><span class="secno">6.3</span> <span class="content">Reading strings and chars of different width</span></a>
      <li><a href="#range-scanning"><span class="secno">6.4</span> <span class="content">Scanning of ranges</span></a>
      <li><a href="#default-values"><span class="secno">6.5</span> <span class="content">Default values for scanned values</span></a>
      <li><a href="#discard"><span class="secno">6.6</span> <span class="content">Assignment suppression / discarding values</span></a>
     </ol>
    <li>
     <a href="#spec"><span class="secno">7</span> <span class="content">Specification</span></a>
     <ol class="toc">
      <li><a href="#spec-header-synopsis"><span class="secno">7.1</span> <span class="content">Header <code class="highlight"><c- o>&lt;</c-><c- n>scan</c-><c- o>></c-></code> synopsis</span></a>
      <li><a href="#spec-scan-error-synopsis"><span class="secno">7.2</span> <span class="content">Class <code class="highlight"><c- n>scan_error</c-></code> synopsis</span></a>
      <li><a href="#spec-scan-result-synopsis"><span class="secno">7.3</span> <span class="content">Class template <code class="highlight"><c- n>scan_result</c-></code> synopsis</span></a>
      <li><a href="#spec-scan-context-synopsis"><span class="secno">7.4</span> <span class="content">Class template <code class="highlight"><c- n>basic_scan_context</c-></code> synopsis</span></a>
      <li><a href="#spec-scan-args-synopsis"><span class="secno">7.5</span> <span class="content">Class template <code class="highlight"><c- n>basic_scan_args</c-></code> synopsis</span></a>
      <li><a href="#spec-scannable"><span class="secno">7.6</span> <span class="content">Concept <code class="highlight"><c- n>scannable</c-></code></span></a>
      <li><a href="#spec-scan-arg-synopsis"><span class="secno">7.7</span> <span class="content">Class template <code class="highlight"><c- n>basic_scan_arg</c-></code> synopsis</span></a>
      <li><a href="#spec-scan-arg-store"><span class="secno">7.8</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>
     </ol>
    <li>
     <a href="#references"><span class="secno"></span> <span class="content">References</span></a>
     <ol class="toc">
      <li><a href="#informative"><span class="secno"></span> <span class="content">Informative References</span></a>
     </ol>
   </ol>
  </nav>
  <main>
   <h2 class="heading settled" data-level="1" id="history"><span class="secno">1. </span><span class="content">Revision history</span><a class="self-link" href="#history"></a></h2>
   <h3 class="heading settled" data-level="1.1" id="history-since-r1"><span class="secno">1.1. </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 data-md>
     <p>Add examples</p>
    <li data-md>
     <p>Add specification (synopses only)</p>
    <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 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 data-md>
       <p>Remove support for partial successes</p>
     </ul>
   </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 explores the possibility of adding a symmetric parsing facility,
to complement the <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>format</c-></code> family, called <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>scan</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>
   <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>></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>-></c-><c- n>values</c-><c- p>();</c->
  <c- c1>//           ~~~~~~~~~~</c->
  <c- c1>//            scanned</c->
  <c- c1>//            values</c->

  <c- c1>// result == true</c->
  <c- c1>// result.begin() points to the end of the given input (the null terminator)</c->
  <c- c1>// key == "answer"</c->
  <c- c1>// value == 42</c->
<c- p>}</c-> <c- k>else</c-> <c- p>{</c->
  <c- c1>// We’ll end up here if we had an error</c->
  <c- c1>// Inspect the returned scan_error with result.error()</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>></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-> 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>-></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 an arbitrary 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>></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 inspected with result->value()</c->
  <c- c1>// result->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>></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>it</c-> <c- o>=</c-> <c- n>range</c-><c- p>.</c-><c- n>begin</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>></c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>ranges</c-><c- o>::</c-><c- n>subrange</c-><c- p>{</c-><c- n>it</c-><c- p>,</c-> <c- n>range</c-><c- p>.</c-><c- n>end</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>-></c-><c- n>value</c-><c- p>());</c->
  <c- n>it</c-> <c- o>=</c-> <c- n>result</c-><c- o>-></c-><c- n>begin</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>></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>auto</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- k>auto</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>></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 an 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- n>template</c-> <c- o>&lt;></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- p>,</c-> <c- b>char</c-><c- o>></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- p>,</c-> <c- b>char</c-><c- o>></c-> <c- p>{</c->
  <c- n>template</c-> <c- o>&lt;</c-><c- n>typename</c-> <c- n>Context</c-><c- o>></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>-></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>></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>></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>></c-><c- p>(</c-><c- s>"[123, 456]"</c-><c- p>,</c-> <c- s>"{}"</c-><c- p>);</c->
<c- c1>// result->value().a == 123</c->
<c- c1>// result->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>></c-> <c- n>Range</c-><c- o>></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>format_string</c-><c- o>&lt;</c-><c- n>Args</c-><c- p>...</c-><c- o>></c-> <c- n>fmt</c-><c- p>)</c->
  <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_iterator_t</c-><c- o>&lt;</c-><c- n>Range</c-><c- o>></c-><c- p>,</c-> <c- n>Args</c-><c- p>...</c-><c- o>></c-><c- p>,</c-> <c- n>scan_error</c-><c- o>></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>></c-> <c- n>Range</c-><c- o>></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>wformat_string</c-><c- o>&lt;</c-><c- n>Args</c-><c- p>...</c-><c- o>></c-> <c- n>fmt</c-><c- p>)</c->
  <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_iterator_t</c-><c- o>&lt;</c-><c- n>Range</c-><c- o>></c-><c- p>,</c-> <c- n>Args</c-><c- p>...</c-><c- o>></c-><c- p>,</c-> <c- n>scan_error</c-><c- o>></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 an iterator, which points to the beginning of 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 data-md>
     <p>There is no standard way to extend the syntax for user-defined types.</p>
    <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>
   </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 data-md>
     <p>Extensibility for user-defined types</p>
    <li data-md>
     <p>Positional arguments</p>
    <li data-md>
     <p>Support for both locale-specific and locale-independent parsing (see <a href="#locales">§ 4.10 Locales</a>)</p>
    <li data-md>
     <p>Consistency with <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>format</c-></code>.</p>
   </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 characters in the format string,
an identical character is consumed from the input range. For whitespace characters,
all available whitespace characters are consumed. Whether a character is a whitespace character
is determined as if by calling <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>isspace</c-></code> with the locale given to <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>scan</c-></code>.
If no locale is provided for <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>scan</c-></code>, the behavior is locale-independent (as if by using <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>locale</c-><c- o>::</c-><c- n>classic</c-><c- p>()</c-></code>).</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>></c-><c- p>(</c-><c- s>"abcd"</c-><c- p>,</c-> <c- s>"ab{}d"</c-><c- p>);</c-> <c- c1>// r0->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>></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>-></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><code class="highlight"><c- n>format</c-></code> replacement field syntax
    <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- n>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- n>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- n>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>'>'</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>
<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- n>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- n>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- n>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>'>'</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>
   </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.
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>></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>-></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- n>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- n>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>'>'</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-7f6a037e">
    <a class="self-link" href="#example-7f6a037e"></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>></c-><c- p>(</c-><c- s>"   42"</c-><c- p>,</c-> <c- s>"{}"</c-><c- p>);</c-> <c- c1>// r0->value() == 42, r0->begin() == ""</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>></c-><c- p>(</c-><c- s>"   x"</c-><c- p>,</c-> <c- s>"{}"</c-><c- p>);</c-> <c- c1>// r1->value() == ' ', r1->begin() == "  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>></c-><c- p>(</c-><c- s>"x   "</c-><c- p>,</c-> <c- s>"{}"</c-><c- p>);</c-> <c- c1>// r2->value() == 'x', r2->begin() == "   "</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>></c-><c- p>(</c-><c- s>"    42"</c-><c- p>,</c-> <c- s>"{:6}"</c-><c- p>);</c->  <c- c1>// r3->value() == 42, r3->begin() == ""</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>></c-><c- p>(</c-><c- s>"x     "</c-><c- p>,</c-> <c- s>"{:6}"</c-><c- p>);</c-> <c- c1>// r4->value() == 'x', r4->begin() == ""</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>></c-><c- p>(</c-><c- s>"***42"</c-><c- p>,</c-> <c- s>"{:*>}"</c-><c- p>);</c->  <c- c1>// r5->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>></c-><c- p>(</c-><c- s>"***42"</c-><c- p>,</c-> <c- s>"{:*>5}"</c-><c- p>);</c-> <c- c1>// r6->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>></c-><c- p>(</c-><c- s>"***42"</c-><c- p>,</c-> <c- s>"{:*>4}"</c-><c- p>);</c-> <c- c1>// r7->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>></c-><c- p>(</c-><c- s>"42"</c-><c- p>,</c-> <c- s>"{:*>}"</c-><c- p>);</c->     <c- c1>// r8->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>></c-><c- p>(</c-><c- s>"42"</c-><c- p>,</c-> <c- s>"{:*>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>></c-><c- p>(</c-><c- s>"42***"</c-><c- p>,</c-> <c- s>"{:*&lt;}"</c-><c- p>);</c->  <c- c1>// rA->value() == 42, rA->begin() == ""</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>></c-><c- p>(</c-><c- s>"42***"</c-><c- p>,</c-> <c- s>"{:*&lt;5}"</c-><c- p>);</c-> <c- c1>// rB->value() == 42, rB->begin() == ""</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>></c-><c- p>(</c-><c- s>"42***"</c-><c- p>,</c-> <c- s>"{:*&lt;4}"</c-><c- p>);</c-> <c- c1>// rC->value() == 42, rC->begin() == "*"</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>></c-><c- p>(</c-><c- s>"42"</c-><c- p>,</c-> <c- s>"{:*&lt;}"</c-><c- p>);</c->     <c- c1>// rD->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>></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>></c-><c- p>(</c-><c- s>"42"</c-><c- p>,</c-> <c- s>"{:*^}"</c-><c- p>);</c->    <c- c1>// rF->value() == 42, rF->begin() == ""</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>></c-><c- p>(</c-><c- s>"*42*"</c-><c- p>,</c-> <c- s>"{:*^}"</c-><c- p>);</c->  <c- c1>// rG->value() == 42, rG->begin() == ""</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>></c-><c- p>(</c-><c- s>"*42**"</c-><c- p>,</c-> <c- s>"{:*^}"</c-><c- p>);</c-> <c- c1>// rH->value() == 42, rH->begin() == "*"</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>></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>></c-><c- p>(</c-><c- s>"**42**"</c-><c- p>,</c-> <c- s>"{:*^6}"</c-><c- p>);</c-> <c- c1>// rJ->value() == 42, rJ->begin() == ""</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>></c-><c- p>(</c-><c- s>"*42**"</c-><c- p>,</c-> <c- s>"{:*^5}"</c-><c- p>);</c->  <c- c1>// rK->value() == 42, rK->begin() == ""</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 somewhat 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>
   <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 data-md>
      <p>U+4dc0 – U+4dff (Yijing Hexagram Symbols)</p>
     <li data-md>
      <p>U+1f300 – U+1f5ff (Miscellaneous Symbols and Pictographs)</p>
     <li data-md>
      <p>U+1f900 – U+1f9ff (Supplemental Symbols and Pictographs)</p>
    </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>
   <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 data-md>
      <p>Unicode code points</p>
     <li data-md>
      <p>Unicode (extended) grapheme clusters</p>
     <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 data-md>
      <p>Exclusively using UAX #11 (East Asian Width) widths</p>
    </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 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 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>
   </ul>
   <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>Meaning 
     <tr>
      <td>none, <code class="highlight"><c- n>s</c-></code> 
      <td>Copies from the input until a whitespace character is encountered. 
     <tr>
      <td><code class="highlight"><c- o>?</c-></code> 
      <td>Copies an escaped string from the input. 
     <tr>
      <td><code class="highlight"><c- n>c</c-></code> 
      <td>Copies from the input until the field width is exhausted.
Does not skip preceding whitespace.
Errors, if no field width is provided. 
   </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>>></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>></c-><c- p>(</c-><c- s>"Hello world"</c-><c- p>,</c-> <c- s>"{:s}"</c-><c- p>);</c->
<c- c1>// r->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 data-md>
     <p>Preceding whitespace is skipped.</p>
   </ul>
   <table>
    <tbody>
     <tr>
      <th>Type 
      <th>Meaning 
     <tr>
      <td><code class="highlight"><c- n>b</c-></code>, <code class="highlight"><c- n>B</c-></code> 
      <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>. 
     <tr>
      <td><code class="highlight"><c- n>o</c-></code> 
      <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>. 
     <tr>
      <td><code class="highlight"><c- n>x</c-></code>, <code class="highlight"><c- n>X</c-></code> 
      <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>. 
     <tr>
      <td><code class="highlight"><c- n>d</c-></code> 
      <td><code class="highlight"><c- n>from_chars</c-></code> with base 10. No base prefix. 
     <tr>
      <td><code class="highlight"><c- n>u</c-></code> 
      <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. 
     <tr>
      <td><code class="highlight"><c- n>i</c-></code> 
      <td>Detect base from a possible prefix, default to decimal. 
     <tr>
      <td><code class="highlight"><c- n>c</c-></code> 
      <td>Copies a character from the input. 
     <tr>
      <td>none 
      <td>Same as <code class="highlight"><c- n>d</c-></code> 
   </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>Meaning 
     <tr>
      <td>none, <code class="highlight"><c- n>c</c-></code> 
      <td>Copies a character from the input. 
     <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>Same as for integers. 
     <tr>
      <td><code class="highlight"><c- o>?</c-></code> 
      <td>Copies an escaped character from the input. 
   </table>
   <p class="note" role="note"><span class="marker">Note:</span> 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>.</p>
   <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>Meaning 
     <tr>
      <td><code class="highlight"><c- n>s</c-></code> 
      <td>Allows for textual representation, i.e. <code class="highlight">true</code> or <code class="highlight">false</code> 
     <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>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>Allows for integral representation, i.e. <code class="highlight"><c- mi>0</c-></code> or <code class="highlight"><c- mi>1</c-></code> 
     <tr>
      <td>none 
      <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>. 
   </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 data-md>
     <p>Preceding whitespace is skipped.</p>
   </ul>
   <table>
    <tbody>
     <tr>
      <th>Type 
      <th>Meaning 
     <tr>
      <td><code class="highlight"><c- n>a</c-></code>, <code class="highlight"><c- n>A</c-></code> 
      <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. 
     <tr>
      <td><code class="highlight"><c- n>e</c-></code>, <code class="highlight"><c- n>E</c-></code> 
      <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>. 
     <tr>
      <td><code class="highlight"><c- n>f</c-></code>, <code class="highlight"><c- n>F</c-></code> 
      <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>. 
     <tr>
      <td><code class="highlight"><c- n>g</c-></code>, <code class="highlight"><c- n>G</c-></code> 
      <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>. 
     <tr>
      <td>none 
      <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. 
   </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>></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>></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>></c-><c- p>,</c-> <c- n>CharT</c-><c- o>></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-c3c92fab">
    <a class="self-link" href="#example-c3c92fab"></a> 
<pre class="language-c++ highlight"><c- n>scan</c-><c- o>&lt;</c-><c- b>int</c-><c- o>></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>></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>></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></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>To prevent excessive code bloat, implementations are encouraged to type-erase the range
provided to <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>scan</c-></code>, in a similar fashion as inside <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>format_to</c-></code>.
This can be achieved with something similar to <code class="highlight"><c- n>any_view</c-></code> from Range-v3.
The reference implementation does something similar to this, inside the implementation of <code class="highlight"><c- n>vscan</c-></code>,
where ranges that are both contiguous and sized are internally passed along as <code class="highlight"><c- n>string_view</c-></code>s,
and as type-erased <code class="highlight"><c- n>forward_range</c-></code>s otherwise.</p>
   <p>It should be noted, that if the range is not type-erased, the library internals need to be exposed
to the user (in a header), and be instantiated for every different kind of range type the user uses.</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>></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>-></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>-></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 data-md>
     <p>Modern C++ API design principles favor return values over output parameters.</p>
    <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 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>
   </ul>
   <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>></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 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>></c-><c- p>(</c-><c- s>"42"</c-><c- p>,</c-> <c- s>"{0}"</c-><c- p>);</c->
<c- c1>// std::get&lt;0>(r) refers to the result object</c->
<c- c1>// std::get&lt;1>(r) refers to {0}</c->
</pre>
   </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>></c-><c- p>(</c-><c- s>"42"</c-><c- p>,</c-> <c- s>"{0}"</c-><c- p>);</c->
<c- c1>// std::get&lt;0>(*result) would refer to the iterator</c->
<c- c1>// std::get&lt;1>(*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"><span class="secno">4.6.1. </span><span class="content">Design discussion</span><a class="self-link" href="#error-handling-discussion"></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><code class="highlight"><c- n>errc</c-></code> 
    <tbody>
     <tr>
      <td><code class="highlight"><c- n>scan_error</c-><c- o>::</c-><c- n>good</c-></code> 
      <td><code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>errc</c-><c- p>{}</c-></code> 
     <tr>
      <td><code class="highlight"><c- n>scan_error</c-><c- o>::</c-><c- n>end_of_range</c-></code> 
      <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> 
     <tr>
      <td><code class="highlight"><c- n>scan_error</c-><c- o>::</c-><c- n>invalid_format_string</c-></code> 
     <tr>
      <td><code class="highlight"><c- n>scan_error</c-><c- o>::</c-><c- n>invalid_scanned_value</c-></code> 
     <tr>
      <td><code class="highlight"><c- n>scan_error</c-><c- o>::</c-><c- n>value_out_of_range</c-></code> 
      <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> 
   </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 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>
     </ol>
    <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 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 data-md>
       <p><b>No.</b> Worse user experience for loss of diagnostic information</p>
     </ol>
   </ol>
   <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>></c-> <c- n>Range</c-><c- o>></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_for</c-><c- o>&lt;</c-><c- n>Range</c-><c- o>></c-> <c- n>args</c-><c- p>)</c->
  <c- o>-></c-> <c- n>expected</c-><c- o>&lt;</c-><c- n>ranges</c-><c- o>::</c-><c- n>borrowed_iterator_t</c-><c- o>&lt;</c-><c- n>Range</c-><c- o>></c-><c- p>,</c-> <c- n>scan_error</c-><c- o>></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>></c-> <c- n>SourceRange</c-><c- o>></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>format_string</c-><c- o>&lt;</c-><c- n>Args</c-><c- p>...</c-><c- o>></c-> <c- n>format</c-><c- p>)</c->
    <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_iterator_t</c-><c- o>&lt;</c-><c- n>SourceRange</c-><c- o>></c-><c- p>,</c-> <c- n>Args</c-><c- p>...</c-><c- o>></c-><c- p>,</c-> <c- n>scan_error</c-><c- o>></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>Source</c-><c- p>,</c-> <c- n>Args</c-><c- p>...</c-><c- o>></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>Source</c-><c- o>></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>></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>></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;></c->
<c- k>struct</c-> <c- nc>scanner</c-><c- o>&lt;</c-><c- n>tm</c-><c- p>,</c-> <c- b>char</c-><c- o>></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>-></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>></c-><c- p>;</c->

  <c- n>template</c-> <c- o>&lt;</c-><c- n>class</c-> <c- n>ScanContext</c-><c- o>></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>-></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>></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>>::</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>>::</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>>::</c-><c- n>scan</c-></code> can potentially use the istream extraction <code class="highlight"><c- k>operator</c-><c- o>>></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>
   <h3 class="heading settled" data-level="4.11" id="performance"><span class="secno">4.11. </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>></c-><c- p>(</c-><c- s>"answer = 42"</c-><c- p>,</c-> <c- s>"{} = {}"</c-><c- p>);</c->
</pre>
   <p>This has lifetime implications similar to returning match objects in <a data-link-type="biblio" href="#biblio-p1433" title="Compile Time Regular Expressions">[P1433]</a> and iterators or subranges in the ranges library and can be mitigated in the same
way.</p>
   <p>It should be noted, that as proposed, this library does not support
checking at compile-time, whether scanning a <code class="highlight"><c- n>string_view</c-></code> would dangle, or
if it’s possible at all (it’s not possible to read a <code class="highlight"><c- n>string_view</c-></code> from a non-<code class="highlight"><c- n>contiguous_range</c-></code>).
This is the case, because the concept <code class="highlight"><c- n>scannable</c-></code> is defined in terms of the scanned type <code class="highlight"><c- n>T</c-></code> and the input range character type <code class="highlight"><c- n>CharT</c-></code>, not the type of the input range itself.</p>
   <h3 class="heading settled" data-level="4.12" id="chrono"><span class="secno">4.12. </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 <chrono> 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>>></c-> <c- n>key</c-> <c- o>>></c-> <c- n>sep</c-> <c- o>>></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>></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>-></c-><c- n>valus</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.13" id="deep-impact"><span class="secno">4.13. </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 <code class="highlight"><c- n>dev</c-></code>-branch of <a data-link-type="biblio" href="#biblio-scnlib" title="scnlib: scanf for modern C++">[SCNLIB]</a> contains the reference implementation for this proposal.</p>
   <p><a data-link-type="biblio" href="#biblio-fmt" title="The fmt library">[FMT]</a> has a prototype implementation 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="istream-integration"><span class="secno">6.1. </span><span class="content">Integration with <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>istream</c-></code>s</span><a class="self-link" href="#istream-integration"></a></h3>
   <p>Today, in C++, standard I/O is largely done with iostreams, and not with ranges.
The library proposed in this paper doesn’t support that use case well.
The proposed concept of <code class="highlight"><c- n>scannable_range</c-></code> requires <code class="highlight"><c- n>forward_range</c-></code>,
so facilities like <code class="highlight"><c- n>istreambuf_iterator</c-></code>, which only models <code class="highlight"><c- n>input_iterator</c-></code>,
can’t be used.</p>
   <p>Integration with iostreams is needed to enable working with files and <code class="highlight"><c- n>stdin</c-></code>.
This can be worked around with something like <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>getline</c-></code>,
and using its result with <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>scan</c-></code>, but error recovery with that gets very tricky very fast.</p>
   <p>A possible solution would be a more robust <code class="highlight"><c- n>istream_view</c-></code>, that models at least <code class="highlight"><c- n>forward_range</c-></code>,
either through caching the read characters in the view itself, or by utilizing the stream buffer. <a data-link-type="biblio" href="#biblio-scnlib" title="scnlib: scanf for modern C++">[SCNLIB]</a> implements this by providing a generic <code class="highlight"><c- n>caching_view</c-></code>, which wraps an <code class="highlight"><c- n>input_range</c-></code> and a buffer, and provides an interface that models <code class="highlight"><c- n>bidirectional_range</c-></code>.</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-8bcced7c">
    <a class="self-link" href="#example-8bcced7c"></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>></c-><c- p>(</c-><c- s>"abc123"</c-><c- p>,</c-> <c- s>"{:[a-zA-Z]}"</c-><c- p>);</c-> <c- c1>// r->value() == "abc", r->begin() == "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>></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>), 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>), and regex-like wildcards (<code class="highlight"><c- p>{</c-><c- o>:</c-><c- p>[</c-><c- o>:</c-><c- n>alpha</c-><c- o>:</c-><c- p>]}</c-></code> or <code class="highlight"><c- p>{</c-><c- o>:</c-><c- p>[</c->\\<c- n>w</c-><c- p>]})</c-></code>.</p>
   <h3 class="heading settled" data-level="6.3" id="scan-transcode"><span class="secno">6.3. </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>></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>></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>></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>></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.4" id="range-scanning"><span class="secno">6.4. </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.5" id="default-values"><span class="secno">6.5. </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>
<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>></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>-></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>></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>-></c-><c- n>value</c-><c- p>())});</c->
</pre>
   <h3 class="heading settled" data-level="6.6" id="discard"><span class="secno">6.6. </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>>></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>-></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>Add a new header, <code class="highlight"><c- o>&lt;</c-><c- n>scan</c-><c- o>></c-></code>.</p>
   <h3 class="heading settled" data-level="7.1" id="spec-header-synopsis"><span class="secno">7.1. </span><span class="content">Header <code class="highlight"><c- o>&lt;</c-><c- n>scan</c-><c- o>></c-></code> synopsis</span><a class="self-link" href="#spec-header-synopsis"></a></h3>
<pre class="highlight"><c- cp>#include</c-> &lt;expected>
<c- cp>#include</c-> &lt;format>
<c- cp>#include</c-> &lt;ranges>

<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>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Iterator</c-><c- p>,</c-> <c- k>class</c-><c- p>...</c-> <c- n>Args</c-><c- o>></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>></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>></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>></c-><c- p>,</c-> <c- n>CharT</c-><c- o>></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>></c->
    <c- k>using</c-> <c- n>scan_result_type</c-> <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_iterator_t</c-><c- o>&lt;</c-><c- n>Range</c-><c- o>></c-><c- p>,</c-> <c- n>Args</c-><c- p>...</c-><c- o>></c-><c- p>,</c->
      <c- n>scan_error</c-><c- o>></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>></c-> <c- n>Range</c-><c- o>></c->
    <c- n>scan_result_type</c-><c- o>&lt;</c-><c- n>Range</c-><c- p>,</c-> <c- n>Args</c-><c- p>...</c-><c- o>></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>format_string</c-><c- o>&lt;</c-><c- n>Args</c-><c- p>...</c-><c- o>></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>></c-> <c- n>Range</c-><c- o>></c->
    <c- n>scan_result_type</c-><c- o>&lt;</c-><c- n>Range</c-><c- p>,</c-> <c- n>Args</c-><c- p>...</c-><c- o>></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>wformat_string</c-><c- o>&lt;</c-><c- n>Args</c-><c- p>...</c-><c- o>></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>></c-> <c- n>Range</c-><c- o>></c->
    <c- n>scan_result_type</c-><c- o>&lt;</c-><c- n>Range</c-><c- p>,</c-> <c- n>Args</c-><c- p>...</c-><c- o>></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>format_string</c-><c- o>&lt;</c-><c- n>Args</c-><c- p>...</c-><c- o>></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>></c-> <c- n>Range</c-><c- o>></c->
    <c- n>scan_result_type</c-><c- o>&lt;</c-><c- n>Range</c-><c- p>,</c-> <c- n>Args</c-><c- p>...</c-><c- o>></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>wformat_string</c-><c- o>&lt;</c-><c- n>Args</c-><c- p>...</c-><c- o>></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>></c->
    <c- k>class</c-> <c- nc>basic_scan_context</c-><c- p>;</c->
  
  <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Context</c-><c- o>></c->
    <c- k>class</c-> <c- nc>basic_scan_args</c-><c- p>;</c->

  <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Range</c-><c- o>></c->
    <c- k>using</c-> <c- n>scan_args_for</c-> <c- o>=</c-> <c- n>basic_scan_args</c-><c- o>&lt;</c-><c- n>basic_scan_context</c-><c- o>&lt;</c->
      <i><c- n>unspecified</c-></i><c- p>,</c->
      <c- n>ranges</c-><c- o>::</c-><c- n>range_value_t</c-><c- o>&lt;</c-><c- n>Range</c-><c- o>>>></c-><c- p>;</c->

  <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Range</c-><c- o>></c->
  <c- k>using</c-> <c- n>vscan_result_type</c-> <c- o>=</c-> <c- n>expected</c-><c- o>&lt;</c-><c- n>ranges</c-><c- o>::</c-><c- n>borrowed_iterator_t</c-><c- o>&lt;</c-><c- n>Range</c-><c- o>></c-><c- p>,</c-> <c- n>scan_error</c-><c- o>></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>></c-> <c- n>Range</c-><c- o>></c->
  <c- n>vscan_result_type</c-><c- o>&lt;</c-><c- n>Range</c-><c- o>></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_for</c-><c- o>&lt;</c-><c- n>Range</c-><c- o>></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>></c-> <c- n>Range</c-><c- o>></c->
  <c- n>vscan_result_type</c-><c- o>&lt;</c-><c- n>Range</c-><c- o>></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>scan_args_for</c-><c- o>&lt;</c-><c- n>Range</c-><c- o>></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>></c-> <c- n>Range</c-><c- o>></c->
  <c- n>vscan_result_type</c-><c- o>&lt;</c-><c- n>Range</c-><c- o>></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_for</c-><c- o>&lt;</c-><c- n>Range</c-><c- o>></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>></c-> <c- n>Range</c-><c- o>></c->
  <c- n>vscan_result_type</c-><c- o>&lt;</c-><c- n>Range</c-><c- o>></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>scan_args_for</c-><c- o>&lt;</c-><c- n>Range</c-><c- o>></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- 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>></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>></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>></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>></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>></c-><c- p>;</c->

  <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Context</c-><c- o>></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>Visitor</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Context</c-><c- o>></c->
    <c- k>decltype</c-><c- p>(</c-><c- k>auto</c-><c- p>)</c-> <c- n>visit_scan_arg</c-><c- p>(</c-><c- n>Visitor</c-><c- o>&amp;&amp;</c-> <c- n>vis</c-><c- p>,</c-> <c- n>basic_scan_arg</c-><c- o>&lt;</c-><c- n>Context</c-><c- o>></c-> <c- n>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>></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>></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>Iterator</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>></c->
    <c- n>expected</c-><c- o>&lt;</c-><c- n>scan_result</c-><c- o>&lt;</c-><c- n>Iterator</c-><c- p>,</c-> <c- n>Args</c-><c- p>...</c-><c- o>></c-><c- p>,</c-> <c- n>scan_error</c-><c- o>></c->
      <c- n>make_scan_result</c-><c- p>(</c-><c- n>expected</c-><c- o>&lt;</c-><c- n>Iterator</c-><c- p>,</c-> <c- n>scan_error</c-><c- o>>&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>>&amp;&amp;</c-> <c- n>args</c-><c- p>);</c->
<c- p>}</c->
</pre>
   <h3 class="heading settled" data-level="7.2" id="spec-scan-error-synopsis"><span class="secno">7.2. </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.3" id="spec-scan-result-synopsis"><span class="secno">7.3. </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>Iterator</c-><c- p>,</c-> <c- k>class</c-><c- p>...</c-> <c- n>Args</c-><c- o>></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>iterator</c-> <c- o>=</c-> <c- n>Iterator</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>iterator</c-> <c- n>it</c-><c- p>,</c-> <c- n>tuple</c-><c- o>&lt;</c-><c- n>Args</c-><c- p>...</c-><c- o>>&amp;&amp;</c-> <c- n>values</c-><c- p>);</c->
    <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>OtherIt</c-><c- p>,</c-> <c- k>class</c-><c- p>...</c-> <c- n>OtherArgs</c-><c- o>></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>OtherIt</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>>&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>OtherIt</c-><c- p>,</c-> <c- k>class</c-><c- p>...</c-> <c- n>OtherArgs</c-><c- o>></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>OtherIt</c-><c- p>,</c-> <c- n>OtherArgs</c-><c- p>...</c-><c- o>>&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>OtherIt</c-><c- p>,</c-> <c- k>class</c-><c- p>...</c-> <c- n>OtherArgs</c-><c- o>></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>OtherIt</c-><c- p>,</c-> <c- n>OtherArgs</c-><c- p>...</c-><c- o>>&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>OtherIt</c-><c- p>,</c-> <c- k>class</c-><c- p>...</c-> <c- n>OtherArgs</c-><c- o>></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>OtherIt</c-><c- p>,</c-> <c- n>OtherArgs</c-><c- p>...</c-><c- o>>&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>OtherIt</c-><c- p>,</c-> <c- k>class</c-><c- p>...</c-> <c- n>OtherArgs</c-><c- o>></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>OtherIt</c-><c- p>,</c-> <c- n>OtherArgs</c-><c- p>...</c-><c- o>>&amp;&amp;</c-> <c- n>other</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>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Self</c-><c- o>></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>></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>iterator</c-> <i><c- n>begin_</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>></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.4" id="spec-scan-context-synopsis"><span class="secno">7.4. </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>></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>></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>></c-><c- p>;</c->
    <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>T</c-><c- o>></c-> <c- k>using</c-> <c- n>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>></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>></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>current</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>></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.5" id="spec-scan-args-synopsis"><span class="secno">7.5. </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>></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>>*</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>></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>>&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>></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>></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>></c-><c- p>)</c-> <c- o>-></c-> <c- n>basic_scan_args</c-><c- o>&lt;</c-><c- n>Context</c-><c- o>></c-><c- p>;</c->
<c- p>}</c->
</pre>
   <h3 class="heading settled" data-level="7.6" id="spec-scannable"><span class="secno">7.6. </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>>>></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>></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_format_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>>&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>-></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>>></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>-></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>>></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>></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>></c-><c- p>,</c-> <c- n>basic_scan_context</c-><c- o>&lt;</c-><i><c- n>unspecified</c-></i><c- o>>></c-><c- p>;</c->
<c- p>}</c->
</pre>
   <h3 class="heading settled" data-level="7.7" id="spec-scan-arg-synopsis"><span class="secno">7.7. </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>></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>>*</c-><c- p>,</c-> <c- n>basic_string_view</c-><c- o>&lt;</c-><c- n>char_type</c-><c- o>>*</c-><c- p>,</c->
      <c- n>handle</c-><c- o>></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>></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.8" id="spec-scan-arg-store"><span class="secno">7.8. </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>></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>></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>></c-><c- p>,</c-> <c- k>sizeof</c-><c- p>...(</c-><c- n>Args</c-><c- p>)</c-><c- o>></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]
   <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>
   <dt id="biblio-codesearch">[CODESEARCH]
   <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>
   <dt id="biblio-fmt">[FMT]
   <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>
   <dt id="biblio-n4412">[N4412]
   <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>
   <dt id="biblio-p0355">[P0355]
   <dd>Howard E. Hinnant; Tomasz Kamiński. <a href="https://wg21.link/p0355"><cite>Extending &lt;chrono> to Calendars and Time Zones</cite></a>. URL: <a href="https://wg21.link/p0355">https://wg21.link/p0355</a>
   <dt id="biblio-p0645">[P0645]
   <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>
   <dt id="biblio-p1361">[P1361]
   <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>
   <dt id="biblio-p1433">[P1433]
   <dd>Hana Dusíková. <a href="https://wg21.link/p1433"><cite>Compile Time Regular Expressions</cite></a>. URL: <a href="https://wg21.link/p1433">https://wg21.link/p1433</a>
   <dt id="biblio-p2286">[P2286]
   <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>
   <dt id="biblio-p2561">[P2561]
   <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>
   <dt id="biblio-parse">[PARSE]
   <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>
   <dt id="biblio-scnlib">[SCNLIB]
   <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>
  </dl>