<!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>P1803R0: packexpr(args, I) -- compile-time friendly pack inspection</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
 *
 * 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)
 *   - .assertion  for assertions                    (div, p, span)
 *   - .advisement for loud normative statements     (div, p, strong)
 *   - .annoying-warning for spec obsoletion notices (div, aside, details)
 *
 * 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
 *
 * 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)
 *
 ******************************************************************************/

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

	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;

		/* Colors */
		color: black;
		background: white 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-width: .65rem .7rem .6rem;
		border-radius: .4rem;
		background: #1a5e9a;
		color: white;
		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;
		border-color: #c00;
	}

	/* 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: 2;
			bottom: 0; left: 0;
			margin: 0;
			min-width: 1.33em;
			border-top-right-radius: 2rem;
			box-shadow: 0 0 2px;
			font-size: 1.5em;
			color: black;
		}
		#toc-nav > a {
			display: block;
			white-space: nowrap;

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

			background: white;
			box-shadow: 0 0 2px;
			border: none;
			border-top-right-radius: 1.33em;
			background: white;
		}
		#toc-nav > #toc-jump {
			padding-bottom: 2em;
			margin-bottom: -1.9em;
		}

		#toc-nav > a:hover,
		#toc-nav > a:focus {
			background: #f8f8f8;
		}
		#toc-nav > a:not(:hover):not(:focus) {
			color: #707070;
		}

		/* 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-toggle-inline {
			vertical-align: 0.05em;
			font-size: 80%;
			color: gray;
			color: hsla(203,20%,40%,.7);
			border-style: none;
			background: transparent;
			position: relative;
		}
		#toc-toggle-inline:hover:not(:active),
		#toc-toggle-inline:focus:not(:active) {
			text-shadow: 1px 1px silver;
			top: -1px;
			left: -1px;
		}

		#toc-nav :active {
			color: #C00;
		}
	}

/** 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);
			background: inherit;
			background-color: #f7f8f9;
			z-index: 1;
			box-shadow: -.1em 0 .25em rgba(0,0,0,.1) 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);
		}
		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);
			background: inherit;
			background-color: #f7f8f9;
			z-index: 1;
			box-shadow: -.1em 0 .25em rgba(0,0,0,.1) 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);
		}

		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;
		background: transparent;
	}

	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,
	#subtitle {
		/* #subtitle 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) > hr {
		font-size: 1.5em;
		text-align: center;
		margin: 1em auto;
		height: auto;
		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;
	}

	/* Put nice boxes around each algorithm. */
	[data-algorithm]:not(.heading) {
	  padding: .5em;
	  border: thin solid #ddd; 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: medium;
	}
	dfn var {
		font-style: normal;
	}

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

	del { color: red;  text-decoration: line-through; }
	ins { color: #080; text-decoration: underline;    }

/** 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;
		page-break-inside: avoid;
		hyphens: none;
		text-transform: none;
	}
	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;
		text-decoration: none;
		border-bottom: 1px solid #707070;
		/* Need a bit of extending for it to look okay */
		padding: 0 1px 0;
		margin: 0 -1px 0;
	}
	a:visited {
		border-bottom-color: #BBB;
	}

	/* Use distinguishing colors when user is interacting with the link */
	a[href]:focus,
	a[href]:hover {
		background: #f8f8f8;
		background: rgba(75%, 75%, 75%, .25);
		border-bottom-width: 3px;
		margin-bottom: -2px;
	}
	a[href]:active {
		color: #C00;
		border-color: #C00;
	}

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

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

	img {
		border-style: none;
	}

	/* 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;
	}
	.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 {
		padding: .5em;
		border: .5em;
		border-left-style: solid;
		page-break-inside: avoid;
	}
	span.issue, span.note {
		padding: .1em .5em .15em;
		border-right-style: solid;
	}

	.issue,
	.note,
	.example,
	.advisement,
	.assertion,
	blockquote {
		margin: 1em auto;
	}
	.note  > p:first-child,
	.issue > p:first-child,
	blockquote > :first-child {
		margin-top: 0;
	}
	blockquote > :last-child {
		margin-bottom: 0;
	}

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

	blockquote {
		border-color: silver;
	}

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

	.issue {
		border-color: #E05252;
		background: #FBE9E9;
		counter-increment: issue;
		overflow: auto;
	}
	.issue::before, .issue > .marker {
		text-transform: uppercase;
		color: #AE1E1E;
		padding-right: 1em;
		text-transform: uppercase;
	}
	/* 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;
		background: #FCFAEE;
		counter-increment: example;
		overflow: auto;
		clear: both;
	}
	.example::before, .example > .marker {
		text-transform: uppercase;
		color: #827017;
		min-width: 7.5em;
		display: block;
	}
	/* 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;
		background: #E9FBE9;
		overflow: auto;
	}

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

	details.note > summary {
		display: block;
		color: hsl(120, 70%, 30%);
	}
	details.note[open] > summary {
		border-bottom: 1px silver solid;
	}

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

	.assertion {
		border-color: #AAA;
		background: #EEE;
	}

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

	.advisement {
		border-color: orange;
		border-style: none solid;
		background: #FFEECC;
	}
	strong.advisement {
		display: block;
		text-align: center;
	}
	.advisement > .marker {
		color: #B35F00;
	}

/** 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: #fdd;
		color: red;
		font-weight: bold;
		padding: .75em 1em;
		border: thick red;
		border-style: solid;
		border-radius: 1em;
	}
	.annoying-warning :last-child {
		margin-bottom: 0;
	}

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

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

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

	.def {
		padding: .5em 1em;
		background: #DEF;
		margin: 1.2em 0;
		border-left: 0.5em solid #8CCBF2;
	}

/******************************************************************************/
/*                                    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;
	}

	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-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;
		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;
		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-top: 0.1rem;
		/* Larger, more consistently-sized click target */
		display: block;
		/* Reverse color scheme */
		color: black;
		border-color: #3980B5;
		border-bottom-width: 3px !important;
		margin-bottom: 0px !important;
	}
	.toc a:visited {
		border-color: #054572;
	}
	.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;
		line-height: 1.1rem; /* consistent spacing */
	}

	/* 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 .secno { font-size: 85%; }
	.toc > li li li li li { font-size:   85%;    }
	.toc > li li li li li .secno { font-size: 100%; }

	/* @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 {
			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; }
		}
	/* } */

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


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

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

/** 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]) {
		background: #f7f8f9;
	}

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

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

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

/******************************************************************************/
/*                                    Legacy                                  */
/******************************************************************************/

	/* This rule is inherited from past style sheets. No idea what it's for. */
	.hide { display: none }



/******************************************************************************/
/*                             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 > table {
		/* limit preferred width of table */
		max-width: 50em;
		margin-left: auto;
		margin-right: auto;
	}

	@media (min-width: 55em) {
		.overlarge {
			margin-left: calc(13px + 26.5rem - 50vw);
			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-left: calc(40em - 50vw) !important;
			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-left: 0 !important;
			margin-right: calc(84.5em - 100vw) !important;
		}
	}

	@media not print {
		.overlarge {
			overflow-x: auto;
			/* See Lea Verou's explanation background-attachment:
			 * http://lea.verou.me/2012/04/background-attachment-local/
			 *
			background: top left  / 4em 100% linear-gradient(to right,  #ffffff, rgba(255, 255, 255, 0)) local,
			            top right / 4em 100% linear-gradient(to left, #ffffff, rgba(255, 255, 255, 0)) local,
			            top left  / 1em 100% linear-gradient(to right,  #c3c3c5, rgba(195, 195, 197, 0)) scroll,
			            top right / 1em 100% linear-gradient(to left, #c3c3c5, rgba(195, 195, 197, 0)) scroll,
			            white;
			background-repeat: no-repeat;
			*/
		}
	}
</style>
<style type="text/css">
    table, th, td {
      border: 1px solid black;
      border-collapse: collapse;
      vertical-align: top;
    }
    th, td {
      border-left: none;
      border-right: none;
      padding: 0px 10px;
    }
    th {
      text-align: center;
    }
  </style>
  <meta content="Bikeshed version 1cff2db4ee2c3bba7a4077d3007528ec73b0485d" name="generator">
  <link href="https://isocpp.org/favicon.ico" rel="icon">
  <meta content="4842efd88c07ef26735ddae2f63b61ac77b8c6b4" name="document-revision">
<style>
pre {
  margin-top: 0px;
  margin-bottom: 0px;
}
.ins, ins, ins *, span.ins, span.ins * {
  background-color: rgb(200, 250, 200);
  color: rgb(0, 136, 0);
  text-decoration: underline;
}
.del, del, del *, span.del, span.del * {
  background-color: rgb(250, 200, 200);
  color: rgb(255, 0, 0);
  text-decoration: line-through;
  text-decoration-color: rgb(255, 0, 0);
}
math, span.math {
  font-family: serif;
  font-style: italic;
}
ul {
  list-style-type: "— ";
}
blockquote {
  counter-reset: paragraph;
}
div.numbered, div.newnumbered {
  margin-left: 2em;
  margin-top: 1em;
  margin-bottom: 1em;
}
div.numbered:before, div.newnumbered:before {
  position: absolute;
  margin-left: -2em;
  display-style: block;
}
div.numbered:before {
  content: counter(paragraph);
  counter-increment: paragraph;
}
div.newnumbered:before {
  content: "�";
}
div.numbered ul, div.newnumbered ul {
  counter-reset: list_item;
}
div.numbered li, div.newnumbered li {
  margin-left: 3em;
}
div.numbered li:before, div.newnumbered li:before {
  position: absolute;
  margin-left: -4.8em;
  display-style: block;
}
div.numbered li:before {
  content: "(" counter(paragraph) "." counter(list_item) ")";
  counter-increment: list_item;
}
div.newnumbered li:before {
  content: "(�." counter(list_item) ")";
  counter-increment: list_item;
}
</style>
<style>/* style-md-lists */

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

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

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

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

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

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

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

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

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

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

[data-link-type=biblio] {
    white-space: pre;
}</style>
 <body class="h-entry">
  <div class="head">
   <p data-fill-with="logo"></p>
   <h1 class="p-name no-ref" id="title">P1803R0<br>packexpr(args, I) -- compile-time friendly pack inspection</h1>
   <h2 class="no-num no-toc no-ref heading settled" id="subtitle"><span class="content">Published Proposal, <time class="dt-updated" datetime="2019-01-21">2019-01-21</time></span></h2>
   <div data-fill-with="spec-metadata">
    <dl>
     <dt>Author:
     <dd>
      <dd class="editor p-author h-card vcard"><a class="p-name fn u-email email" href="mailto:phdofthehouse@gmail.com">JeanHeyd Meneide</a>
     <dt>Audience:
     <dd>SG17
     <dt>Project:
     <dd>ISO/IEC JTC1/SC22/WG21 14882: Programming Language — C++
     <dt>Target:
     <dd>C++23
     <dt>Latest:
     <dd><a href="https://thephd.github.io/vendor/future_cxx/papers/d1803.html">https://thephd.github.io/vendor/future_cxx/papers/d1803.html</a>
    </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>A proposal to refer to a single argument from a variadic pack, piggybacking from the nomenclature and feature set of the Expansion Statements (P1306) paper.</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="#changelog"><span class="secno">1</span> <span class="content">Revision History</span></a>
     <ol class="toc">
      <li><a href="#changelog-r1"><span class="secno">1.1</span> <span class="content">Revision 0 - August 5th, 2019</span></a>
     </ol>
    <li>
     <a href="#motivation"><span class="secno">2</span> <span class="content">Motivation</span></a>
     <ol class="toc">
      <li><a href="#motivation-algorithmic"><span class="secno">2.1</span> <span class="content">Motivation: Algorithms</span></a>
      <li><a href="#motivation-history"><span class="secno">2.2</span> <span class="content">Motivation: a History</span></a>
     </ol>
    <li>
     <a href="#design"><span class="secno">3</span> <span class="content">Design</span></a>
     <ol class="toc">
      <li><a href="#design-tuple_get"><span class="secno">3.1</span> <span class="content">Why not std::get?</span></a>
      <li>
       <a href="#design-syntax"><span class="secno">3.2</span> <span class="content">Syntax</span></a>
       <ol class="toc">
        <li><a href="#design-syntax-keyword"><span class="secno">3.2.1</span> <span class="content">Syntax 0: Keyword Syntax</span></a>
        <li><a href="#design-syntax-sugar"><span class="secno">3.2.2</span> <span class="content">Syntax 1: Unambiguous Syntax Sugar</span></a>
        <li><a href="#design-syntax-lockouts"><span class="secno">3.2.3</span> <span class="content">Picking a Syntax: Lockouts?</span></a>
       </ol>
     </ol>
    <li><a href="#acknowledgements"><span class="secno">4</span> <span class="content">Acknowledgements</span></a>
    <li>
     <a href="#references"><span class="secno"></span> <span class="content">References</span></a>
     <ol class="toc">
      <li><a href="#informative"><span class="secno"></span> <span class="content">Informative References</span></a>
     </ol>
   </ol>
  </nav>
  <main>
   <h2 class="heading settled" data-level="1" id="changelog"><span class="secno">1. </span><span class="content">Revision History</span><a class="self-link" href="#changelog"></a></h2>
   <h3 class="heading settled" data-level="1.1" id="changelog-r1"><span class="secno">1.1. </span><span class="content">Revision 0 - August 5th, 2019</span><a class="self-link" href="#changelog-r1"></a></h3>
   <ul>
    <li data-md>
     <p>Initial release.</p>
   </ul>
   <h2 class="heading settled" data-level="2" id="motivation"><span class="secno">2. </span><span class="content">Motivation</span><a class="self-link" href="#motivation"></a></h2>
   <p>Initially, p1306 "Expansion Statements" were slated to go into C++20. With some problems spotted with the syntax and their retargeting to C++23, it has become clear that the syntactic and parsing ambiguities of <code class="highlight"><c- k>for</c-> <c- p>...</c-></code> were a bit hairy and convoluted. Still, there is one part of the proposal which calls back to an older paper written by Sean Middleditch and reviewed in 2013, hidden with <a data-link-type="biblio" href="#biblio-p1306r1">[p1306r1]</a>'s specification details:</p>
   <blockquote>
    <p>For unexpanded packs, and destructurable objects, the expansion can be trivially implemented in terms of a simple integer index.</p>
   </blockquote>
   <p>In particular, consider the following from <a data-link-type="biblio" href="#biblio-p1306r1">[p1306r1]</a>:</p>
   <blockquote>
<pre class="highlight"><c- k>template</c-><c- o>&lt;</c-><c- k>typename</c-><c- p>...</c-> <c- n>Ts</c-><c- o>></c->
<c- b>void</c-> <c- n>f</c-><c- p>(</c-><c- n>Ts</c-><c- o>&amp;&amp;</c-><c- p>...</c-> <c- n>args</c-><c- p>)</c-> <c- p>{</c->
	<c- k>for</c-><c- p>...</c-> <c- p>(</c-><c- k>const</c-> <c- k>auto</c-><c- o>&amp;</c-> <c- nl>x</c-> <c- p>:</c-> <c- n>args</c-><c- p>)</c->
		<c- n>cout</c-> <c- o>&lt;&lt;</c-> <c- n>x</c-> <c- o>&lt;&lt;</c-> ‘\<c- n>n</c->’<c- p>;</c->
<c- p>}</c->

<c- b>void</c-> <c- n>foo</c-><c- p>()</c-> <c- p>{</c->
	<c- n>f</c-><c- p>(</c-><c- mi>0</c-><c- p>,</c-> ‘<c- n>a</c->’<c- p>);</c->
<c- p>}</c->
</pre>
    The instantiation of  f  generated from  foo  will have the expansion: 
<pre class="highlight"><c- p>{</c->
	<c- p>{</c->
		<c- k>const</c-> <c- k>auto</c-><c- o>&amp;</c-> <c- n>x</c-> <c- o>=</c-> <c- d>/*  first element args  */</c-><c- p>;</c->
		<c- n>cout</c-> <c- o>&lt;&lt;</c-> <c- n>x</c-> <c- o>&lt;&lt;</c-> ‘\<c- n>n</c->’<c- p>;</c->
	<c- p>}</c->
	<c- p>{</c->
		<c- k>const</c-> <c- k>auto</c-><c- o>&amp;</c-> <c- n>x</c-> <c- o>=</c-> <c- d>/*  second element in args  */</c-><c- p>;</c->
		<c- n>cout</c-> <c- o>&lt;&lt;</c-> <c- n>x</c-> <c- o>&lt;&lt;</c-> ‘\<c- n>n</c->’<c- p>;</c->
	<c- p>}</c->
<c- p>}</c->
</pre>
   </blockquote>
   <p>Note specifically, the following expression in the paper:</p>
<pre class="highlight"><c- k>const</c-> <c- k>auto</c-><c- o>&amp;</c-> <c- n>x</c-> <c- o>=</c-> <c- d>/*  first element args  */</c-><c- p>;</c->
</pre>
   <p>This proposal is for the thing that goes in the comment here that the paper hand-waves as "<i><code class="highlight"><c- n>get</c->­<c- o>-</c-><c- n>expr</c-><c- p>(</c-><c- n>I</c-><c- p>)</c-></code></i>", where <code class="highlight"><c- n>I</c-></code> is the <em>I</em> <sup>th</sup> element of the pack. As this functionality already needs to be generated by a feature that everyone agrees they want (modulo changes during the C++23 design phase), it seems timely that we standardize a feature that was previously proposed and told to come back with a (non-polled but noted in the minutes) strong consensus for a language feature.</p>
   <h3 class="heading settled" data-level="2.1" id="motivation-algorithmic"><span class="secno">2.1. </span><span class="content">Motivation: Algorithms</span><a class="self-link" href="#motivation-algorithmic"></a></h3>
   <p>The largest and most striking problem of packs is the inability to match patterns of input or conduct efficient order-dependent linear processing on the contents of said pack without resorting to recursive operations or worse.</p>
   <p>Consider, for example, a function template which is used to process 2 elements at a time from its variadic parameter expressions:</p>
<pre class="highlight"><c- b>void</c-> <c- nf>two_at_a_time</c-><c- p>()</c-> <c- p>{</c->
	<c- c1>// base case</c->
<c- p>}</c->

<c- k>template</c-> <c- o>&lt;</c-><c- k>typename</c-> <c- n>Arg0</c-><c- p>,</c-> <c- k>typename</c-> <c- n>Arg1</c-><c- p>,</c-> <c- k>typename</c-><c- p>...</c-> <c- n>Args</c-><c- o>></c->
<c- b>void</c-> <c- n>two_at_a_time</c-> <c- p>(</c-><c- n>Arg0</c-><c- o>&amp;&amp;</c-><c- p>...</c-> <c- n>arg0</c-><c- p>,</c-> <c- n>Arg1</c-><c- o>&amp;&amp;</c-><c- p>...</c-> <c- n>arg1</c-><c- p>,</c-> <c- n>Args</c-><c- o>&amp;&amp;</c-><c- p>...</c-> <c- n>args</c-><c- p>)</c-> <c- p>{</c->
	<c- c1>// process arg0, arg1</c->
	<c- n>two_at_a_time</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>Args</c-><c- o>></c-><c- p>(</c-><c- n>args</c-><c- p>)...);</c->
<c- p>}</c->
</pre>
   <p>Unfortunately, <code class="highlight"><c- k>template</c-> <c- k>for</c-></code> can only offer one-way, one-at-a-time, linear processing of its elements. There is no way to get out 2 elements at a time from a parameter pack with the proposed language feature:</p>
<pre class="highlight"><c- k>template</c-> <c- o>&lt;</c-><c- k>typename</c-><c- p>...</c-> <c- n>Args</c-><c- o>></c->
<c- b>void</c-> <c- n>two_at_a_time</c-> <c- p>(</c-><c- n>Args</c-><c- o>&amp;&amp;</c-><c- p>...</c-> <c- n>args</c-><c- p>)</c-> <c- p>{</c->
	<c- k>template</c-> <c- k>for</c-> <c- p>(</c-><c- k>auto</c-><c- o>&amp;</c-> <c- nl>arg</c-> <c- p>:</c-> <c- n>args</c-><c- p>)</c-> <c- p>{</c->
		<c- c1>// Uhhh...</c->
	<c- p>}</c->
<c- p>}</c->
</pre>
   <p>Yet still, a <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>initializer_list</c-></code> of a <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>pair</c-></code> of types does not work because the list contains heterogenous types that cannot be fixed before-time. Or worse, one would need to instantiate a tuple, and then use <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>index_sequence</c-></code> tricks to index into the tuple in a custom manner. <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>tuple</c-></code> might actually be the worst of the problem here: it is its own Russian Doll of template instantiations that does not work well with the compiler’s execution time or memory consumption at all. Most flagrant of the implementation’s abuses here is the VC++ Standard Library’s implementation of <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>tuple</c-></code>, which is a recursively-self-deriving structure which bites off one element of the type list and then delegates all further elements down to its bases, until it reaches the empty tuple.</p>
   <h3 class="heading settled" data-level="2.2" id="motivation-history"><span class="secno">2.2. </span><span class="content">Motivation: a History</span><a class="self-link" href="#motivation-history"></a></h3>
   <p>Previously, Sean Middleditch wrote <a data-link-type="biblio" href="#biblio-n3761">[N3761]</a> back in 2013. It was a library extension to do much the same as is going to be proposed in this paper. The feature was discussed extensively during the Chicago, Illinois 2013 C++ Standards Meeting to standardize exactly this functionality, except as 2 library-based functions. The feedback he was given at the time was that there was strong encouragement to release this not as a library feature, but as a language feature for various reasons.</p>
   <ul>
    <li data-md>
     <p>Compile-time complexity problems with a library feature;</p>
    <li data-md>
     <p>function template instantiation costs even with the use of a built-in or intrinsic internally inside of the library function;</p>
    <li data-md>
     <p>and, compiler memory consumption is <em>enormous</em>.</p>
   </ul>
   <p>It was perhaps thought that a variadic pack of e.g. <code class="highlight"><c- n>Args</c-><c- p>...</c-> <c- n>args</c-></code> could be given the random-access pack indexing of <code class="highlight"><c- n>args</c-><c- p>...[</c-><c- n>I</c-><c- p>]</c-></code>, where <code class="highlight"><c- n>I</c-></code> is a constant evaluated integer value. The problem is that this conflicts with an <a href="https://godbolt.org/z/Zqhkl-">existing declaration that is entirely valid code</a> (Clang accepts, GCC and VC++ reject, but Clang’s interpretation seems valid as per the C++ grammar).</p>
   <p>The paper was not pursued, mostly because the original author has not had the time to do so. Further papers from Bill Seymour and Stephan T. Lavavej -- <a data-link-type="biblio" href="#biblio-n4144">[N4144]</a> -- as well as Daveed Vandevoorde -- <a data-link-type="biblio" href="#biblio-n4235">[N4235]</a> -- were presented a year later. Both were heavily encouraged for future work towards a language direction and to bring additional examples. Both <a data-link-type="biblio" href="#biblio-n3761">[N3761]</a>'s discussion and <a data-link-type="biblio" href="#biblio-n4144">[N4144]</a>'s discussion came to the same conclusion: template metaprogramming proposals "ultimately compensate for shortcomings of the core language".</p>
   <p>Daveed Vandevoorde’s <a data-link-type="biblio" href="#biblio-n4235">[N4235]</a> is the language variant of all of the above. In it, he avoids the earlier syntactic ambiguities present with <code class="highlight"><c- n>args</c-><c- p>...[</c-><c- n>I</c-><c- p>]</c-></code>, and instead chose the syntax <code class="highlight"><c- n>args</c-><c- p>.[</c-><c- n>I</c-><c- p>]</c-></code>. This was both unambiguous and rather unique, and could be applied without breakage for both types and values. Evolution Working Group polls at the time were largely supportive of this effort:</p>
   <blockquote>
    <p>Proceed with proposed syntax (<code class="highlight"><c- n>args</c-><c- p>.[</c-><c- n>index</c-><c- p>]</c-></code>)?</p>
   </blockquote>
<pre class="highlight"><c- n>SF</c->  <c- n>F</c-> <c- n>N</c->  <c- n>A</c-> <c- n>SA</c->
 <c- mi>5</c-> <c- mi>11</c-> <c- mi>8</c->  <c- mi>3</c->  <c- mi>0</c->
</pre>
   <blockquote>
    <p>Choose some other syntax (those who are OK with syntax should vote No/Against)?</p>
   </blockquote>
<pre class="highlight"><c- n>SF</c-> <c- n>F</c->  <c- n>N</c->  <c- n>A</c-> <c- n>SA</c->
 <c- mi>3</c-> <c- mi>1</c-> <c- mi>16</c->  <c- mi>2</c->  <c- mi>1</c-> 
</pre>
   <p>Unfortunately, this is where the trail goes absolutely cold. It is unclearly whether early Reflection discussion dominated the arena or whether refocused efforts left the papers largely untouched. As has become a modus-operandi of this paper’s author, this paper is being picked up due to widespread indication that something to access packs directly has been requested by developers from multiple software engineering-influenced disciplines. The author has also encountered the need for this <a href="https://thephd.github.io/sol3-compile-times-binary-sizes">when combating compile time issues and code bloat</a> in a heavily templated library, as have many others. <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>tuple</c-></code> is one of the greatest offenders of compile-time, alongside <a href="https://github.com/boostorg/hana/commit/540f665e5132d75bbf6eda704638622727c0c01c">common functions such as std::move and std::forward</a>. While we cannot solve all of the compile-time issues in generic libraries, this proposal represents a useful opportunity to prevent additional compile time bloat as well as make it easier to express simple algorithms.</p>
   <h2 class="heading settled" data-level="3" id="design"><span class="secno">3. </span><span class="content">Design</span><a class="self-link" href="#design"></a></h2>
   <p>The feature is designed as a language feature, rather than a library feature. Working with the Schrödinger-like entity that are variadic packs in the C++ language is a tedious and computationally expensive (at compile-time) chore. They can contain one (or more) values or types, and cannot be inspected unless something is instantiated over those values or types, templated or not. This means that generic code has often had to perform recursive function template and class template instantiation to process types and values, or worse. Therefore, this feature focuses on providing random-access, constant evaluated integral expressions as the means of accessing pack values and pack types.</p>
   <h3 class="heading settled" data-level="3.1" id="design-tuple_get"><span class="secno">3.1. </span><span class="content">Why not std::get?</span><a class="self-link" href="#design-tuple_get"></a></h3>
   <p><code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>get</c-></code> can be ambiguous and dangerous to overload for this purpose. Consider the following:</p>
<pre class="highlight"><c- k>template</c-> <c- o>&lt;</c-><c- k>typename</c-><c- p>...</c-> <c- n>Args</c-><c- o>></c->
<c- b>void</c-> <c- n>f</c-> <c- p>(</c-><c- n>Args</c-><c- o>&amp;&amp;</c-> <c- p>...</c-> <c- n>args</c-> <c- p>)</c-> <c- p>{</c->
     <c- k>decltype</c-><c- p>(</c-><c- k>auto</c-><c- p>)</c-> <c- n>expr0</c-> <c- o>=</c-> <c- n>std</c-><c- o>::</c-><c- n>get</c-><c- o>&lt;</c-><c- mi>0</c-><c- o>></c-><c- p>(</c-><c- n>args</c-><c- p>...);</c->
<c- p>}</c->

<c- b>int</c-> <c- n>main</c-> <c- p>()</c-> <c- p>{</c->
     <c- n>std</c-><c- o>::</c-><c- n>tuple</c-><c- o>&lt;</c-><c- b>int</c-><c- o>></c-> <c- n>thing0</c-><c- p>{</c-><c- mi>0</c-><c- p>};</c->
     <c- n>foo</c-><c- p>(</c-><c- n>thing0</c-><c- p>);</c->
<c- p>}</c->
</pre>
   <p>Here, <code class="highlight"><c- n>expr0</c-></code> is not <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>tuple</c-><c- o>&lt;</c-><c- b>int</c-><c- o>></c-></code> -- it is <code class="highlight"><c- b>int</c-></code>, due to the previous overloads to retrieve a value out of a single tuple. This makes is very important to separate what this low-level pack access tool means from any generic tuple-unwrapping facility proposed and in the standard to date, lest we risk severe collisions in the domain space.</p>
   <h3 class="heading settled" data-level="3.2" id="design-syntax"><span class="secno">3.2. </span><span class="content">Syntax</span><a class="self-link" href="#design-syntax"></a></h3>
   <p>There are two potential syntaxes for this feature, a keyword and built-in grammar sugar.</p>
   <h4 class="heading settled" data-level="3.2.1" id="design-syntax-keyword"><span class="secno">3.2.1. </span><span class="content">Syntax 0: Keyword Syntax</span><a class="self-link" href="#design-syntax-keyword"></a></h4>
   <p>This first syntax uses a new keyword to retrieve the value of a pack, at the specified index. It is used as follows:</p>
<pre class="highlight"><c- k>template</c-> <c- o>&lt;</c-><c- k>typename</c-><c- p>...</c-> <c- n>Args</c-><c- o>></c->
<c- b>void</c-> <c- n>foo</c-><c- p>(</c-><c- n>Args</c-><c- o>&amp;&amp;</c-><c- p>...</c-> <c- n>args</c-><c- p>)</c-> <c- p>{</c->
	<c- k>decltype</c-><c- p>(</c-><c- k>auto</c-><c- p>)</c-> <c- n>x</c-> <c- o>=</c-> <c- n>packexpr</c-><c- p>(</c-><c- n>args</c-><c- p>,</c-> <c- mi>1</c-><c- p>);</c->
<c- p>}</c->
</pre>
   <p>It results in an error if the index is greater than <code class="highlight"><c- k>sizeof</c-><c- p>...(</c-><c- n>Args</c-><c- p>)</c-></code>:</p>
<pre class="highlight"><c- k>template</c-> <c- o>&lt;</c-><c- k>typename</c-><c- p>...</c-> <c- n>Args</c-><c- o>></c->
<c- b>void</c-> <c- n>foo</c-><c- p>(</c-><c- n>Args</c-><c- o>&amp;&amp;</c-><c- p>...</c-> <c- n>args</c-><c- p>)</c-> <c- p>{</c->
	<c- k>decltype</c-><c- p>(</c-><c- k>auto</c-><c- p>)</c-> <c- n>x</c-> <c- o>=</c-> <c- n>packexpr</c-><c- p>(</c-><c- n>args</c-><c- p>,</c-> <c- mi>1</c-><c- p>);</c->
<c- p>}</c->

<c- b>int</c-> <c- n>main</c-> <c- p>()</c-> <c- p>{</c->
	<c- n>foo</c-><c- p>(</c-><c- s>"hi"</c-><c- p>);</c-> <c- c1>// produces error from within above function</c->
	<c- k>return</c-> <c- mi>0</c-><c- p>;</c->
<c- p>}</c->
</pre>
   <p>There is no direct expression for retrieving the type out of a pack, because that can be done by just using <code class="highlight"><c- k>decltype</c-><c- p>()</c-></code> around <code class="highlight"><c- n>packexpr</c-><c- p>(</c-><c- n>args</c-><c- p>,</c-> <c- n>index</c-><c- p>)</c-></code>.</p>
   <p>The potential names for the language keyword could be as follows:</p>
   <ul>
    <li data-md>
     <p>pack_expr, packexpr (~200 unique hits in preliminary code searches)</p>
    <li data-md>
     <p>get_pack_expr, getpackexpr (0 unique hits in preliminary code searches)</p>
    <li data-md>
     <p>pack_get_expr, packgetexpr (0 unique hits in preliminary code searches)</p>
    <li data-md>
     <p>static_pack_get (0 unique hits in preliminary code searches)</p>
    <li data-md>
     <p>pack_get (~2500+ unique hits in preliminary code searches, including usages with Boost.HOF)</p>
   </ul>
   <p>This proposal, despite the collisions, prefers <code class="highlight"><c- n>packexpr</c-></code> for being one of the best words to describe this functionality so far. However, there is pre-existing code that takes the names <code class="highlight"><c- n>packexpr</c-></code> and <code class="highlight"><c- n>pack_expr</c-></code>. The author would not consider it a large breakage, but a breakage nonetheless: further name bikeshedding should be done to find a name that is still just as cromulent and descriptive that falls in line with <code class="highlight"><c- k>decltype</c-><c- p>()</c-></code> and friends.</p>
   <h4 class="heading settled" data-level="3.2.2" id="design-syntax-sugar"><span class="secno">3.2.2. </span><span class="content">Syntax 1: Unambiguous Syntax Sugar</span><a class="self-link" href="#design-syntax-sugar"></a></h4>
   <p>This is the second syntax option. It was the one previously proposed and voted heavily in favor of in Evolution Working Group, as demonstrated in the <a href="#motivation-history">polls above</a>.</p>
   <p>The functionality is exactly the same as <a href="#design-syntax-keyword">Syntax 0</a>, just that it comes with the form <code class="highlight"><c- n>args</c-><c- p>.</c-><c- n>T</c-><c- p>[</c-><c- n>index</c-><c- p>]</c-></code> instead. The paper originally proposing this feature wanted to do pack selection and separation as well, allowing arbitrary packs and type names to be reconstituted from the original pack using a syntax somewhat similar to <code class="highlight"><c- n>args</c-><c- p>.</c-><c- o>&lt;</c-><c- n>index0</c-><c- p>,</c-> <c- n>index1</c-><c- p>,</c-> <c- p>...,</c-> <c- n>indexN</c-><c- o>></c-></code>. We do not propose this syntax at this time, wanting to focus on just the core viable use case that can reduce compilation times for users.</p>
<pre class="highlight"><c- k>template</c-> <c- o>&lt;</c-><c- k>typename</c-><c- p>...</c-> <c- n>Args</c-><c- o>></c->
<c- b>void</c-> <c- n>foo</c-><c- p>(</c-><c- n>Args</c-><c- o>&amp;&amp;</c-><c- p>...</c-> <c- n>args</c-><c- p>)</c-> <c- p>{</c->
	<c- k>decltype</c-><c- p>(</c-><c- k>auto</c-><c- p>)</c-> <c- n>x</c-> <c- o>=</c-> <c- n>args</c-><c- p>.[</c-><c- mi>1</c-><c- p>];</c->
<c- p>}</c->
</pre>
   <p>It results in an error if the index is greater than <code class="highlight"><c- k>sizeof</c-><c- p>...(</c-><c- n>Args</c-><c- p>)</c-></code>:</p>
<pre class="highlight"><c- k>template</c-> <c- o>&lt;</c-><c- k>typename</c-><c- p>...</c-> <c- n>Args</c-><c- o>></c->
<c- b>void</c-> <c- n>foo</c-><c- p>(</c-><c- n>Args</c-><c- o>&amp;&amp;</c-><c- p>...</c-> <c- n>args</c-><c- p>)</c-> <c- p>{</c->
	<c- k>decltype</c-><c- p>(</c-><c- k>auto</c-><c- p>)</c-> <c- n>x</c-> <c- o>=</c-> <c- n>args</c-><c- p>.[</c-><c- mi>1</c-><c- p>];</c->
<c- p>}</c->

<c- b>int</c-> <c- n>main</c-> <c- p>()</c-> <c- p>{</c->
	<c- n>foo</c-><c- p>(</c-><c- s>"hi"</c-><c- p>);</c-> <c- c1>// produces error from within above function</c->
	<c- k>return</c-> <c- mi>0</c-><c- p>;</c->
<c- p>}</c->
</pre>
   <h4 class="heading settled" data-level="3.2.3" id="design-syntax-lockouts"><span class="secno">3.2.3. </span><span class="content">Picking a Syntax: Lockouts?</span><a class="self-link" href="#design-syntax-lockouts"></a></h4>
   <p>Neither syntax prevents future developing of the idea in either keyword form or syntax sugar form. Slices can still be developed for both of these.</p>
   <h2 class="heading settled" data-level="4" id="acknowledgements"><span class="secno">4. </span><span class="content">Acknowledgements</span><a class="self-link" href="#acknowledgements"></a></h2>
   <p>Thanks to Sean Middleditch for the original proposal and helping me track down the history of it and informing me of its fate. Thanks to Richard Smith for helping show me why the <code class="highlight"><c- n>args</c-><c- p>...[</c-><c- n>index</c-><c- p>]</c-></code> syntax was ambiguous. A special mention to Barry Revzin, who was able to help track down the rest of this paper’s history.</p>
  </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-n3761">[N3761]
   <dd>Sean Middleditch. <a href="https://wg21.link/n3761">Proposing type_at&lt;></a>. 29 August 2013. URL: <a href="https://wg21.link/n3761">https://wg21.link/n3761</a>
   <dt id="biblio-n4144">[N4144]
   <dd>B. Seymour, S. Lavavej. <a href="https://wg21.link/n4144">Searching and Manipulation of Parameter Packs</a>. 11 September 2014. URL: <a href="https://wg21.link/n4144">https://wg21.link/n4144</a>
   <dt id="biblio-n4235">[N4235]
   <dd>Daveed Vandevoorde. <a href="https://wg21.link/n4235">Selecting from Parameter Packs</a>. 10 October 2014. URL: <a href="https://wg21.link/n4235">https://wg21.link/n4235</a>
   <dt id="biblio-p1306r1">[P1306R1]
   <dd>Andrew Sutton, Sam Goodrick, Daveed Vandevoorde. <a href="https://wg21.link/p1306r1">Expansion statements</a>. 21 January 2019. URL: <a href="https://wg21.link/p1306r1">https://wg21.link/p1306r1</a>
  </dl>