<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang xml:lang>
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="mpark/wg21" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <meta name="dcterms.date" content="2019-10-06" />
  <title>Generalized pack declaration and usage</title>
  <style>
      code{white-space: pre-wrap;}
      span.smallcaps{font-variant: small-caps;}
      span.underline{text-decoration: underline;}
      div.column{display: inline-block; vertical-align: top; width: 50%;}
  </style>
  <style>
code.sourceCode > span { display: inline-block; line-height: 1.25; }
code.sourceCode > span { color: inherit; text-decoration: inherit; }
code.sourceCode > span:empty { height: 1.2em; }
.sourceCode { overflow: visible; }
code.sourceCode { white-space: pre; position: relative; }
div.sourceCode { margin: 1em 0; }
pre.sourceCode { margin: 0; }
@media screen {
div.sourceCode { overflow: auto; }
}
@media print {
code.sourceCode { white-space: pre-wrap; }
code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
}
pre.numberSource code
  { counter-reset: source-line 0; }
pre.numberSource code > span
  { position: relative; left: -4em; counter-increment: source-line; }
pre.numberSource code > span > a:first-child::before
  { content: counter(source-line);
    position: relative; left: -1em; text-align: right; vertical-align: baseline;
    border: none; display: inline-block;
    -webkit-touch-callout: none; -webkit-user-select: none;
    -khtml-user-select: none; -moz-user-select: none;
    -ms-user-select: none; user-select: none;
    padding: 0 4px; width: 4em;
    color: #aaaaaa;
  }
pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa;  padding-left: 4px; }
div.sourceCode
  {  background-color: #f6f8fa; }
@media screen {
code.sourceCode > span > a:first-child::before { text-decoration: underline; }
}
code span. { } /* Normal */
code span.al { color: #ff0000; } /* Alert */
code span.an { } /* Annotation */
code span.at { } /* Attribute */
code span.bn { color: #9f6807; } /* BaseN */
code span.bu { color: #9f6807; } /* BuiltIn */
code span.cf { color: #00607c; } /* ControlFlow */
code span.ch { color: #9f6807; } /* Char */
code span.cn { } /* Constant */
code span.co { color: #008000; font-style: italic; } /* Comment */
code span.cv { color: #008000; font-style: italic; } /* CommentVar */
code span.do { color: #008000; } /* Documentation */
code span.dt { color: #00607c; } /* DataType */
code span.dv { color: #9f6807; } /* DecVal */
code span.er { color: #ff0000; font-weight: bold; } /* Error */
code span.ex { } /* Extension */
code span.fl { color: #9f6807; } /* Float */
code span.fu { } /* Function */
code span.im { } /* Import */
code span.in { color: #008000; } /* Information */
code span.kw { color: #00607c; } /* Keyword */
code span.op { color: #af1915; } /* Operator */
code span.ot { } /* Other */
code span.pp { color: #6f4e37; } /* Preprocessor */
code span.re { } /* RegionMarker */
code span.sc { color: #9f6807; } /* SpecialChar */
code span.ss { color: #9f6807; } /* SpecialString */
code span.st { color: #9f6807; } /* String */
code span.va { } /* Variable */
code span.vs { color: #9f6807; } /* VerbatimString */
code span.wa { color: #008000; font-weight: bold; } /* Warning */
code.diff {color: #898887}
code.diff span.va {color: #006e28}
code.diff span.st {color: #bf0303}
  </style>
  <style type="text/css">
body {
margin: 5em;
font-family: serif;

hyphens: auto;
line-height: 1.35;
}
div.wrapper {
max-width: 60em;
margin: auto;
}
ul {
list-style-type: none;
padding-left: 2em;
margin-top: -0.2em;
margin-bottom: -0.2em;
}
a {
text-decoration: none;
color: #4183C4;
}
a.hidden_link {
text-decoration: none;
color: inherit;
}
li {
margin-top: 0.6em;
margin-bottom: 0.6em;
}
h1, h2, h3, h4 {
position: relative;
line-height: 1;
}
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;
font-family: sans-serif;
font-weight: normal;
font-size: 83%;
}
a.self-link:hover { opacity: 1; }
a.self-link::before { content: "§"; }
ul > li:before {
content: "\2014";
position: absolute;
margin-left: -1.5em;
}
:target { background-color: #C9FBC9; }
:target .codeblock { background-color: #C9FBC9; }
:target ul { background-color: #C9FBC9; }
.abbr_ref { float: right; }
.folded_abbr_ref { float: right; }
:target .folded_abbr_ref { display: none; }
:target .unfolded_abbr_ref { float: right; display: inherit; }
.unfolded_abbr_ref { display: none; }
.secnum { display: inline-block; min-width: 35pt; }
.header-section-number { display: inline-block; min-width: 35pt; }
.annexnum { display: block; }
div.sourceLinkParent {
float: right;
}
a.sourceLink {
position: absolute;
opacity: 0;
margin-left: 10pt;
}
a.sourceLink:hover {
opacity: 1;
}
a.itemDeclLink {
position: absolute;
font-size: 75%;
text-align: right;
width: 5em;
opacity: 0;
}
a.itemDeclLink:hover { opacity: 1; }
span.marginalizedparent {
position: relative;
left: -5em;
}
li span.marginalizedparent { left: -7em; }
li ul > li span.marginalizedparent { left: -9em; }
li ul > li ul > li span.marginalizedparent { left: -11em; }
li ul > li ul > li ul > li span.marginalizedparent { left: -13em; }
div.footnoteNumberParent {
position: relative;
left: -4.7em;
}
a.marginalized {
position: absolute;
font-size: 75%;
text-align: right;
width: 5em;
}
a.enumerated_item_num {
position: relative;
left: -3.5em;
display: inline-block;
margin-right: -3em;
text-align: right;
width: 3em;
}
div.para { margin-bottom: 0.6em; margin-top: 0.6em; text-align: justify; }
div.section { text-align: justify; }
div.sentence { display: inline; }
span.indexparent {
display: inline;
position: relative;
float: right;
right: -1em;
}
a.index {
position: absolute;
display: none;
}
a.index:before { content: "⟵"; }

a.index:target {
display: inline;
}
.indexitems {
margin-left: 2em;
text-indent: -2em;
}
div.itemdescr {
margin-left: 3em;
}
.bnf {
font-family: serif;
margin-left: 40pt;
margin-top: 0.5em;
margin-bottom: 0.5em;
}
.ncbnf {
font-family: serif;
margin-top: 0.5em;
margin-bottom: 0.5em;
margin-left: 40pt;
}
.ncsimplebnf {
font-family: serif;
font-style: italic;
margin-top: 0.5em;
margin-bottom: 0.5em;
margin-left: 40pt;
background: inherit; 
}
span.textnormal {
font-style: normal;
font-family: serif;
white-space: normal;
display: inline-block;
}
span.rlap {
display: inline-block;
width: 0px;
}
span.descr { font-style: normal; font-family: serif; }
span.grammarterm { font-style: italic; }
span.term { font-style: italic; }
span.terminal { font-family: monospace; font-style: normal; }
span.nonterminal { font-style: italic; }
span.tcode { font-family: monospace; font-style: normal; }
span.textbf { font-weight: bold; }
span.textsc { font-variant: small-caps; }
a.nontermdef { font-style: italic; font-family: serif; }
span.emph { font-style: italic; }
span.techterm { font-style: italic; }
span.mathit { font-style: italic; }
span.mathsf { font-family: sans-serif; }
span.mathrm { font-family: serif; font-style: normal; }
span.textrm { font-family: serif; }
span.textsl { font-style: italic; }
span.mathtt { font-family: monospace; font-style: normal; }
span.mbox { font-family: serif; font-style: normal; }
span.ungap { display: inline-block; width: 2pt; }
span.textit { font-style: italic; }
span.texttt { font-family: monospace; }
span.tcode_in_codeblock { font-family: monospace; font-style: normal; }
span.phantom { color: white; }

span.math { font-style: normal; }
span.mathblock {
display: block;
margin-left: auto;
margin-right: auto;
margin-top: 1.2em;
margin-bottom: 1.2em;
text-align: center;
}
span.mathalpha {
font-style: italic;
}
span.synopsis {
font-weight: bold;
margin-top: 0.5em;
display: block;
}
span.definition {
font-weight: bold;
display: block;
}
.codeblock {
margin-left: 1.2em;
line-height: 127%;
}
.outputblock {
margin-left: 1.2em;
line-height: 127%;
}
div.itemdecl {
margin-top: 2ex;
}
code.itemdeclcode {
white-space: pre;
display: block;
}
span.textsuperscript {
vertical-align: super;
font-size: smaller;
line-height: 0;
}
.footnotenum { vertical-align: super; font-size: smaller; line-height: 0; }
.footnote {
font-size: small;
margin-left: 2em;
margin-right: 2em;
margin-top: 0.6em;
margin-bottom: 0.6em;
}
div.minipage {
display: inline-block;
margin-right: 3em;
}
div.numberedTable {
text-align: center;
margin: 2em;
}
div.figure {
text-align: center;
margin: 2em;
}
table {
border: 1px solid black;
border-collapse: collapse;
margin-left: auto;
margin-right: auto;
margin-top: 0.8em;
text-align: left;
hyphens: none; 
}
td, th {
padding-left: 1em;
padding-right: 1em;
vertical-align: top;
}
td.empty {
padding: 0px;
padding-left: 1px;
}
td.left {
text-align: left;
}
td.right {
text-align: right;
}
td.center {
text-align: center;
}
td.justify {
text-align: justify;
}
td.border {
border-left: 1px solid black;
}
tr.rowsep, td.cline {
border-top: 1px solid black;
}
tr.even, tr.odd {
border-bottom: 1px solid black;
}
tr.capsep {
border-top: 3px solid black;
border-top-style: double;
}
tr.header {
border-bottom: 3px solid black;
border-bottom-style: double;
}
th {
border-bottom: 1px solid black;
}
span.centry {
font-weight: bold;
}
div.table {
display: block;
margin-left: auto;
margin-right: auto;
text-align: center;
width: 90%;
}
span.indented {
display: block;
margin-left: 2em;
margin-bottom: 1em;
margin-top: 1em;
}
ol.enumeratea { list-style-type: none; background: inherit; }
ol.enumerate { list-style-type: none; background: inherit; }

code.sourceCode > span { display: inline; }

div#refs p { padding-left: 32px; text-indent: -32px; }
</style>
  <style type="text/css">a {
color : #4183C4;
text-decoration: underline;
}
a.marginalized {
text-decoration: none;
}
a.self-link {
text-decoration: none;
}
h1#toctitle {
border-bottom: 1px solid #cccccc;
}
#TOC li {
margin-top: 1px;
margin-bottom: 1px;
}
#TOC ul>li:before { display: none; }
h3.subtitle { margin-top: -15px; }
h1:target { background-color: transparent; }
h2:target { background-color: transparent; }
h3:target { background-color: transparent; }
h4:target { background-color: transparent; }
h5:target { background-color: transparent; }
h6:target { background-color: transparent; }
code span.co { font-family: monospace; }
table tr {
background-color: white;
}
table tr:nth-child(2n) {
background-color: #f6f8fa;
}
#title-block-header > table tr:nth-child(2n) {
background-color: white;
}
td > div.sourceCode {
background-color: inherit;
}
table {
border-collapse: collapse;
}
table td, table th {
border: 1px solid #cccccc;
}
table th {
border-bottom: 1px solid black;
text-align: center;
}
table tr:first-child th {
border-top: 0;
}
table tr:last-child td {
border-bottom: 0;
}
table tr td:first-child,
table tr th:first-child {
border-left: 0;
}
table tr td:last-child,
table tr th:last-child {
border-right: 0;
}
table tbody tr:first-child td {
border-top: 1px solid black;
}
#title-block-header td { border: 0; }
@media all {
body {
margin: 2em;
}
}
@media screen and (min-width: 480px) {
body {
margin: 5em;
}
}
#refs code{padding-left: 0px; text-indent: 0px;}
:root {
--diff-ins: #e6ffed;
--diff-strongins: #acf2bd;
--diff-del: #ffdddd;
--diff-strongdel: #ff8888;
}
span.diffins {
background-color: var(--diff-strongins);
}
span.diffdel {
background-color: var(--diff-strongdel);
}
div.rm { text-decoration: line-through; }
div.rm code.sourceCode { text-decoration: line-through; }
div.addu, span.addu {
color: #006e28;
background-color: var(--diff-ins);
}

div.rm pre, div.add pre { background-color: #f6f8fa; }
div.addu pre { background-color: var(--diff-ins); }
div.add, div.add pre { background-color: var(--diff-ins); }
div.addu blockquote {
border-left: 4px solid #00a000;
padding: 0 15px;
color: #006e28;
text-decoration: none;
}
div.addu blockquote code.sourceCode { text-decoration: none; }
div.addu blockquote pre { text-decoration: none; }
div.addu blockquote pre code { text-decoration: none; }
code.diff span.va { color: #000000; background-color: var(--diff-ins); }
code.diff span.st { color: #000000; background-color: var(--diff-del); }
</style>
  <link href="data:image/vnd.microsoft.icon;base64,AAABAAIAEBAAAAEAIABoBAAAJgAAACAgAAABACAAqBAAAI4EAAAoAAAAEAAAACAAAAABACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////AIJEAACCRAAAgkQAAIJEAACCRAAAgkQAVoJEAN6CRADegkQAWIJEAACCRAAAgkQAAIJEAACCRAAA////AP///wCCRAAAgkQAAIJEAACCRAAsgkQAvoJEAP+CRAD/gkQA/4JEAP+CRADAgkQALoJEAACCRAAAgkQAAP///wD///8AgkQAAIJEABSCRACSgkQA/IJEAP99PQD/dzMA/3czAP99PQD/gkQA/4JEAPyCRACUgkQAFIJEAAD///8A////AHw+AFiBQwDqgkQA/4BBAP9/PxP/uZd6/9rJtf/bybX/upd7/39AFP+AQQD/gkQA/4FDAOqAQgBc////AP///wDKklv4jlEa/3o7AP+PWC//8+3o///////////////////////z7un/kFox/35AAP+GRwD/mVYA+v///wD///8A0Zpk+NmibP+0d0T/8evj///////+/fv/1sKz/9bCs//9/fr//////+/m2/+NRwL/nloA/5xYAPj///8A////ANKaZPjRmGH/5cKh////////////k149/3UwAP91MQD/lmQ//86rhv+USg3/m1YA/5hSAP+bVgD4////AP///wDSmmT4zpJY/+/bx///////8+TV/8mLT/+TVx//gkIA/5lVAP+VTAD/x6B//7aEVv/JpH7/s39J+P///wD///8A0ppk+M6SWP/u2sf///////Pj1f/Nj1T/2KFs/8mOUv+eWhD/lEsA/8aee/+0glT/x6F7/7J8Rvj///8A////ANKaZPjRmGH/48Cf///////+/v7/2qt//82PVP/OkFX/37KJ/86siv+USg7/mVQA/5hRAP+bVgD4////AP///wDSmmT40ppk/9CVXP/69O////////7+/v/x4M//8d/P//7+/f//////9u7n/6tnJf+XUgD/nFgA+P///wD///8A0ppk+NKaZP/RmWL/1qNy//r07///////////////////////+vXw/9akdP/Wnmn/y5FY/6JfFvj///8A////ANKaZFTSmmTo0ppk/9GYYv/Ql1//5cWm//Hg0P/x4ND/5cWm/9GXYP/RmGH/0ppk/9KaZOjVnmpY////AP///wDSmmQA0ppkEtKaZI7SmmT60ppk/9CWX//OkVb/zpFW/9CWX//SmmT/0ppk/NKaZJDSmmQS0ppkAP///wD///8A0ppkANKaZADSmmQA0ppkKtKaZLrSmmT/0ppk/9KaZP/SmmT/0ppkvNKaZCrSmmQA0ppkANKaZAD///8A////ANKaZADSmmQA0ppkANKaZADSmmQA0ppkUtKaZNzSmmTc0ppkVNKaZADSmmQA0ppkANKaZADSmmQA////AP5/AAD4HwAA4AcAAMADAACAAQAAgAEAAIABAACAAQAAgAEAAIABAACAAQAAgAEAAMADAADgBwAA+B8AAP5/AAAoAAAAIAAAAEAAAAABACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////AP///wCCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAAyCRACMgkQA6oJEAOqCRACQgkQAEIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAA////AP///wD///8A////AIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRABigkQA5oJEAP+CRAD/gkQA/4JEAP+CRADqgkQAZoJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAAD///8A////AP///wD///8AgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAA4gkQAwoJEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQAxIJEADyCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAP///wD///8A////AP///wCCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAWgkQAmIJEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAJyCRAAYgkQAAIJEAACCRAAAgkQAAIJEAACCRAAA////AP///wD///8A////AIJEAACCRAAAgkQAAIJEAACCRAAAgkQAdIJEAPCCRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAPSCRAB4gkQAAIJEAACCRAAAgkQAAIJEAAD///8A////AP///wD///8AgkQAAIJEAACCRAAAgkQASoJEANKCRAD/gkQA/4JEAP+CRAD/g0YA/39AAP9zLgD/bSQA/2shAP9rIQD/bSQA/3MuAP9/PwD/g0YA/4JEAP+CRAD/gkQA/4JEAP+CRADUgkQAToJEAACCRAAAgkQAAP///wD///8A////AP///wB+PwAAgkUAIoJEAKiCRAD/gkQA/4JEAP+CRAD/hEcA/4BBAP9sIwD/dTAA/5RfKv+viF7/vp56/76ee/+wiF7/lWAr/3YxAP9sIwD/f0AA/4RHAP+CRAD/gkQA/4JEAP+CRAD/gkQArIJEACaBQwAA////AP///wD///8A////AIBCAEBzNAD6f0EA/4NFAP+CRAD/gkQA/4VIAP92MwD/bSUA/6N1Tv/ezsL/////////////////////////////////38/D/6V3Uv9uJgD/dTEA/4VJAP+CRAD/gkQA/4JEAP+BQwD/fUAA/4FDAEj///8A////AP///wD///8AzJRd5qBlKf91NgD/dDUA/4JEAP+FSQD/cy4A/3YyAP/PuKP//////////////////////////////////////////////////////9K7qP94NQD/ciwA/4VJAP+CRAD/fkEA/35BAP+LSwD/mlYA6v///wD///8A////AP///wDdpnL/4qx3/8KJUv+PUhf/cTMA/3AsAP90LgD/4dK+/////////////////////////////////////////////////////////////////+TYxf91MAD/dTIA/31CAP+GRwD/llQA/6FcAP+gWwD8////AP///wD///8A////ANGZY/LSm2X/4ap3/92mcP+wdT3/byQA/8mwj////////////////////////////////////////////////////////////////////////////+LYxv9zLgP/jUoA/59bAP+hXAD/nFgA/5xYAPL///8A////AP///wD///8A0ppk8tKaZP/RmWL/1p9q/9ubXv/XqXj////////////////////////////7+fD/vZyG/6BxS/+gcUr/vJuE//r37f//////////////////////3MOr/5dQBf+dVQD/nVkA/5xYAP+cWAD/nFgA8v///wD///8A////AP///wDSmmTy0ppk/9KaZP/SmWP/yohJ//jo2P//////////////////////4NTG/4JDFf9lGAD/bSQA/20kAP9kGAD/fz8S/+Xb0f//////5NG9/6txN/+LOgD/m1QA/51aAP+cWAD/m1cA/5xYAP+cWADy////AP///wD///8A////ANKaZPLSmmT/0ppk/8+TWf/Unmv//v37//////////////////////+TWRr/VwsA/35AAP+ERgD/g0UA/4JGAP9lHgD/kFga/8KXX/+TRwD/jT4A/49CAP+VTQD/n10A/5xYAP+OQQD/lk4A/55cAPL///8A////AP///wD///8A0ppk8tKaZP/SmmT/y4tO/92yiP//////////////////////8NnE/8eCQP+rcTT/ez0A/3IyAP98PgD/gEMA/5FSAP+USwD/jj8A/5lUAP+JNwD/yqV2/694Mf+HNQD/jkAA/82rf/+laBj/jT4A8v///wD///8A////AP///wDSmmTy0ppk/9KaZP/LiUr/4byY///////////////////////gupX/0I5P/+Wuev/Lklz/l1sj/308AP+QSwD/ol0A/59aAP+aVQD/k0oA/8yoh///////+fXv/6pwO//Lp3v///////Pr4f+oay7y////AP///wD///8A////ANKaZPLSmmT/0ppk/8uJSv/hvJj//////////////////////+G7l//Jhkb/0ppk/96nc//fqXX/x4xO/6dkFP+QSQD/llEA/5xXAP+USgD/yaOA///////38uv/qG05/8ijdv//////8efb/6ZpLPL///8A////AP///wD///8A0ppk8tKaZP/SmmT/zIxO/9yxh///////////////////////7dbA/8iEQf/Sm2X/0Zlj/9ScZv/eqHf/2KJv/7yAQf+XTgD/iToA/5lSAP+JNgD/yKFv/611LP+HNQD/jT8A/8qmeP+kZRT/jT4A8v///wD///8A////AP///wDSmmTy0ppk/9KaZP/Pk1n/1J5q//78+//////////////////+/fv/1aFv/8iEQv/Tm2b/0ppl/9GZY//Wn2z/1pZc/9eldf/Bl2b/kUcA/4w9AP+OQAD/lUwA/59eAP+cWQD/jT8A/5ZOAP+eXADy////AP///wD///8A////ANKaZPLSmmT/0ppk/9KZY//KiEn/8d/P///////////////////////47+f/05tm/8iCP//KiEj/yohJ/8eCP//RmGH//vfy///////n1sP/rXQ7/4k4AP+TTAD/nVoA/5xYAP+cVwD/nFgA/5xYAPL///8A////AP///wD///8A0ppk8tKaZP/SmmT/0ptl/8uLTf/aq37////////////////////////////+/fz/6c2y/961jv/etY7/6Myx//78+v//////////////////////3MWv/5xXD/+ORAD/mFQA/51ZAP+cWAD/nFgA8v///wD///8A////AP///wDSmmTy0ppk/9KaZP/SmmT/0ppk/8mFRP/s1b//////////////////////////////////////////////////////////////////////////////+PD/0JFU/7NzMv+WUQD/kUsA/5tXAP+dWQDy////AP///wD///8A////ANKaZP/SmmT/0ppk/9KaZP/Sm2X/z5NZ/8yMT//z5NX/////////////////////////////////////////////////////////////////9Ofa/8yNUP/UmGH/36p5/8yTWv+qaSD/kksA/5ROAPz///8A////AP///wD///8A0ppk5NKaZP/SmmT/0ppk/9KaZP/TnGf/zY9T/82OUv/t1sD//////////////////////////////////////////////////////+7Yw//OkFX/zI5R/9OcZ//SmmP/26V0/9ymdf/BhUf/ol8R6P///wD///8A////AP///wDSmmQ80ppk9tKaZP/SmmT/0ppk/9KaZP/TnGj/zpFW/8qJSv/dson/8uHS//////////////////////////////////Lj0//etIv/y4lL/86QVf/TnGj/0ppk/9KaZP/RmWP/05xn/9ymdfjUnWdC////AP///wD///8A////ANKaZADSmmQc0ppkotKaZP/SmmT/0ppk/9KaZP/Tm2b/0Zli/8qJSf/NjlH/16Z3/+G8mP/myKr/5siq/+G8mP/Xp3f/zY5S/8qISf/RmGH/05tm/9KaZP/SmmT/0ppk/9KaZP/SmmSm0pljINWdaQD///8A////AP///wD///8A0ppkANKaZADSmmQA0ppkQtKaZMrSmmT/0ppk/9KaZP/SmmT/0ptl/9GYYf/Nj1P/y4lL/8qISP/KiEj/y4lK/82PU//RmGH/0ptl/9KaZP/SmmT/0ppk/9KaZP/SmmTO0ppkRtKaZADSmmQA0ppkAP///wD///8A////AP///wDSmmQA0ppkANKaZADSmmQA0ppkANKaZGzSmmTu0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmTw0ppkcNKaZADSmmQA0ppkANKaZADSmmQA////AP///wD///8A////ANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZBLSmmSQ0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppklNKaZBTSmmQA0ppkANKaZADSmmQA0ppkANKaZAD///8A////AP///wD///8A0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQy0ppkutKaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppkvtKaZDbSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkAP///wD///8A////AP///wDSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkXNKaZODSmmT/0ppk/9KaZP/SmmT/0ppk5NKaZGDSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA////AP///wD///8A////ANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkBtKaZIbSmmTo0ppk6tKaZIrSmmQK0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZAD///8A////AP/8P///+B///+AH//+AAf//AAD//AAAP/AAAA/gAAAHwAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA+AAAAfwAAAP/AAAP/8AAP//gAH//+AH///4H////D//" rel="icon" />
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
  
</head>
<body>
<div class="wrapper">
<header id="title-block-header">
<h1 class="title" style="text-align:center">Generalized pack declaration and usage</h1>

<table style="border:none;float:right">
  <tr>
    <td>Document #: </td>
    <td>P1858R0</td>
  </tr>
  <tr>
    <td>Date: </td>
    <td>2019-10-06</td>
  </tr>
  <tr>
    <td style="vertical-align:top">Project: </td>
    <td>Programming Language C++<br>
      EWG<br>
    </td>
  </tr>
  <tr>
    <td style="vertical-align:top">Reply-to: </td>
    <td>
      Barry Revzin<br>&lt;<a href="mailto:barry.revzin@gmail.com" class="email">barry.revzin@gmail.com</a>&gt;<br>
    </td>
  </tr>
</table>

</header>
<div style="clear:both">
<h1 id="introduction-and-motivation" style="border-bottom:1px solid #cccccc"><span class="header-section-number">1</span> Introduction and Motivation<a href="#introduction-and-motivation" class="self-link"></a></h1>
<p>C++11 introduced variadic templates, one of the truly transformational language features introduced that standard. Despite pretty tight restrictions on where packs could be declared and how they could be used, this feature has proven incredibly successful. Three standards later, there hasn’t even been much change. C++17 added a couple new ways to use packs (fold expressions <span class="citation" data-cites="N4191">[<a href="#ref-N4191" role="doc-biblioref">N4191</a>]</span> and using-declarations <span class="citation" data-cites="P0195R2">[<a href="#ref-P0195R2" role="doc-biblioref">P0195R2</a>]</span>), and C++20 will add a new way to introduce them (in lambda capture <span class="citation" data-cites="P0780R2">[<a href="#ref-P0780R2" role="doc-biblioref">P0780R2</a>]</span>). A proposal to iterate over them (expansion statements <span class="citation" data-cites="P1306R1">[<a href="#ref-P1306R1" role="doc-biblioref">P1306R1</a>]</span>) didn’t quite make it. That’s it.</p>
<p>There have been many papers in the interlude about trying to enhance pack functionality: a language typelist <span class="citation" data-cites="N3728">[<a href="#ref-N3728" role="doc-biblioref">N3728</a>]</span>, fixed size and homogeneous packs <span class="citation" data-cites="N4072">[<a href="#ref-N4072" role="doc-biblioref">N4072</a>]</span> (and later <span class="citation" data-cites="P1219R1">[<a href="#ref-P1219R1" role="doc-biblioref">P1219R1</a>]</span>), indexing and slicing into packs <span class="citation" data-cites="N4235">[<a href="#ref-N4235" role="doc-biblioref">N4235</a>]</span> and <span class="citation" data-cites="P0535R0">[<a href="#ref-P0535R0" role="doc-biblioref">P0535R0</a>]</span>, being able to declare packs in more places <span class="citation" data-cites="P0341R0">[<a href="#ref-P0341R0" role="doc-biblioref">P0341R0</a>]</span> and other places <span class="citation" data-cites="P1061R0">[<a href="#ref-P1061R0" role="doc-biblioref">P1061R0</a>]</span>.</p>
<p>In short, there’s been work in this space, although not all of these papers have been discussed by Evolution. Although, many of these have been received favorably and then never followed up on.</p>
<p>Yet the features that keep getting hinted at and requested again and again are still missing from our feature set:</p>
<ol type="1">
<li>the ability to declare a variable pack at class, namespace, or local scope</li>
<li>the ability to index into a pack</li>
<li>the ability to unpack a tuple, or tuple-like type, inline</li>
</ol>
<p>All efficiently, from a compile time perspective. Instead, for (1) we have to use <code class="sourceCode cpp">std<span class="op">::</span>tuple</code>, for (2) we have to use <code class="sourceCode cpp">std<span class="op">::</span>get</code>, <code class="sourceCode cpp">std<span class="op">::</span>tuple_element</code>, or, if we’re only dealing with types, something like <code class="sourceCode cpp">mp_at_c</code> <span class="citation" data-cites="Boost.Mp11">[<a href="#ref-Boost.Mp11" role="doc-biblioref">Boost.Mp11</a>]</span>, for (3) we have to use <code class="sourceCode cpp">std<span class="op">::</span>apply<span class="op">()</span></code>, which necessarily introduces a new scope. <code class="sourceCode cpp">std<span class="op">::</span>apply<span class="op">()</span></code> is actually worse than that, since it doesn’t play well with callables that aren’t objects and even worse if you want to use additional arguments on top of that:</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb1-1"><a href="#cb1-1"></a>std<span class="op">::</span>tuple args<span class="op">(</span><span class="dv">1</span>, <span class="dv">2</span>, <span class="dv">3</span><span class="op">)</span>;</span>
<span id="cb1-2"><a href="#cb1-2"></a></span>
<span id="cb1-3"><a href="#cb1-3"></a><span class="co">// I want to call f with args... and then 4</span></span>
<span id="cb1-4"><a href="#cb1-4"></a>std<span class="op">::</span>apply<span class="op">([&amp;](</span><span class="kw">auto</span><span class="op">...</span> vs<span class="op">){</span> <span class="cf">return</span> f<span class="op">(</span>vs<span class="op">...</span>, <span class="dv">4</span><span class="op">)</span>; <span class="op">}</span>, args<span class="op">)</span>;</span></code></pre></div>
<p>Matt Calabrese is working on a library facility to help address the shortcomings here <span class="citation" data-cites="Calabrese.Argot">[<a href="#ref-Calabrese.Argot" role="doc-biblioref">Calabrese.Argot</a>]</span>.</p>
<p>This paper attempts to provide a solution to these problems, building on the work of prior paper authors. The goal of this paper is to provide a better implementation for a library <code class="sourceCode cpp">tuple</code>, one that ends up being much easier to implement, more compiler friendly, and more ergonomic. The paper will piecewise introduce the necessary langauge features, increasing in complexity as it goes.</p>
<h1 id="the-tuple-example" style="border-bottom:1px solid #cccccc"><span class="header-section-number">2</span> The Tuple Example<a href="#the-tuple-example" class="self-link"></a></h1>
<p>This paper proposes the ability to declare a variable pack wherever we can declare a variable today:</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb2-1"><a href="#cb2-1"></a><span class="kw">namespace</span> xstd <span class="op">{</span></span>
<span id="cb2-2"><a href="#cb2-2"></a>    <span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span><span class="op">...</span> Ts<span class="op">&gt;</span></span>
<span id="cb2-3"><a href="#cb2-3"></a>    <span class="kw">struct</span> tuple <span class="op">{</span></span>
<span id="cb2-4"><a href="#cb2-4"></a>        Ts<span class="op">...</span> elems;</span>
<span id="cb2-5"><a href="#cb2-5"></a>    <span class="op">}</span>;</span>
<span id="cb2-6"><a href="#cb2-6"></a><span class="op">}</span></span></code></pre></div>
<p>That gives us all the members that we need, using a syntax that arguably has obvious meaning to any reader familiar with C++ packs. All the usual rules follow directly from there. That class template is an aggregate, so we can use aggregate initialization:</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb3-1"><a href="#cb3-1"></a>xstd<span class="op">::</span>tuple<span class="op">&lt;</span><span class="dt">int</span>, <span class="dt">int</span>, <span class="dt">int</span><span class="op">&gt;</span> x<span class="op">{</span><span class="dv">1</span>, <span class="dv">2</span>, <span class="dv">3</span><span class="op">}</span>;</span></code></pre></div>
<p>Or, in C++20:</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb4-1"><a href="#cb4-1"></a>xstd<span class="op">::</span>tuple y<span class="op">{</span><span class="dv">1</span>, <span class="dv">2</span>, <span class="dv">3</span><span class="op">}</span>;</span></code></pre></div>
<h2 id="empty-variable-pack"><span class="header-section-number">2.1</span> Empty variable pack<a href="#empty-variable-pack" class="self-link"></a></h2>
<p>One question right off the back: what does <code class="sourceCode cpp">xstd<span class="op">::</span>tuple<span class="op">&lt;&gt;</span> t;</code> mean? The same way that an empty function parameter pack means a function taking no arguments, an empty member variable pack means no member variables. <code class="sourceCode cpp">xstd<span class="op">::</span>tuple<span class="op">&lt;&gt;</span></code> is an empty type.</p>
<h2 id="constructors"><span class="header-section-number">2.2</span> Constructors<a href="#constructors" class="self-link"></a></h2>
<p>But <code class="sourceCode cpp">tuple</code> has constructors. <code class="sourceCode cpp">tuple</code> has <em>lots</em> of constructors. We’re not going to go through all of them in this paper, just the interesting ones. But let’s at least start with the easy ones:</p>
<div class="sourceCode" id="cb5"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb5-1"><a href="#cb5-1"></a><span class="kw">namespace</span> xstd <span class="op">{</span></span>
<span id="cb5-2"><a href="#cb5-2"></a>    <span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span><span class="op">...</span> Ts<span class="op">&gt;</span></span>
<span id="cb5-3"><a href="#cb5-3"></a>    <span class="kw">class</span> tuple <span class="op">{</span></span>
<span id="cb5-4"><a href="#cb5-4"></a>    <span class="kw">public</span><span class="op">:</span></span>
<span id="cb5-5"><a href="#cb5-5"></a>        <span class="kw">constexpr</span> tuple<span class="op">()</span> <span class="kw">requires</span> <span class="op">(</span>std<span class="op">::</span>default_constructible<span class="op">&lt;</span>Ts<span class="op">&gt;</span> <span class="op">&amp;&amp;</span> <span class="op">...)</span></span>
<span id="cb5-6"><a href="#cb5-6"></a>            <span class="op">:</span> elems<span class="op">()...</span></span>
<span id="cb5-7"><a href="#cb5-7"></a>        <span class="op">{</span> <span class="op">}</span></span>
<span id="cb5-8"><a href="#cb5-8"></a>        </span>
<span id="cb5-9"><a href="#cb5-9"></a>        <span class="kw">constexpr</span> tuple<span class="op">(</span>Ts <span class="kw">const</span><span class="op">&amp;...</span> args<span class="op">)</span></span>
<span id="cb5-10"><a href="#cb5-10"></a>                <span class="kw">requires</span> <span class="op">(</span>std<span class="op">::</span>copy_constructible<span class="op">&lt;</span>Ts<span class="op">&gt;</span> <span class="op">&amp;&amp;</span> <span class="op">...)</span></span>
<span id="cb5-11"><a href="#cb5-11"></a>            <span class="op">:</span> elems<span class="op">(</span>args<span class="op">)...</span></span>
<span id="cb5-12"><a href="#cb5-12"></a>        <span class="op">{</span> <span class="op">}</span></span>
<span id="cb5-13"><a href="#cb5-13"></a></span>
<span id="cb5-14"><a href="#cb5-14"></a>    <span class="kw">private</span><span class="op">:</span></span>
<span id="cb5-15"><a href="#cb5-15"></a>        Ts<span class="op">...</span> elems;</span>
<span id="cb5-16"><a href="#cb5-16"></a>    <span class="op">}</span>;</span>
<span id="cb5-17"><a href="#cb5-17"></a><span class="op">}</span></span></code></pre></div>
<p>Note the new pack expansion in the <em>mem-initializer</em>. This is a new ability this paper is proposing. It wouldn’t have made sense to have if you could not declare a member variable pack.</p>
<p>Let’s pick a more complex constructor. A <code class="sourceCode cpp">std<span class="op">::</span>tuple<span class="op">&lt;</span>Ts<span class="op">...&gt;</span></code> can be constructed from a <code class="sourceCode cpp">std<span class="op">::</span>pair<span class="op">&lt;</span>T, U<span class="op">&gt;</span></code> if <code class="sourceCode cpp"><span class="kw">sizeof</span><span class="op">...(</span>Ts<span class="op">)</span> <span class="op">==</span> <span class="dv">2</span></code> and the two corresponding types are convertible. How would we implement that? To do that check, we need to get the corresponding types. How do we get the first and second types from <code class="sourceCode cpp">Ts</code>?</p>
<h2 id="pack-indexing"><span class="header-section-number">2.3</span> Pack Indexing<a href="#pack-indexing" class="self-link"></a></h2>
<p>This paper proposes a “simple selection” facility similar to the one initially introduced in <span class="citation" data-cites="N4235">[<a href="#ref-N4235" role="doc-biblioref">N4235</a>]</span> (and favorably received in Urbana 2014): <code class="sourceCode cpp">T<span class="op">...[</span>I<span class="op">]</span></code> is the <code class="sourceCode cpp">I</code>th element of the pack <code class="sourceCode cpp">T</code>, which is a type or value or template based on what kind of pack <code class="sourceCode cpp">T</code> is. <a href="#disambiguating-packs-of-tuples">Later sections</a> of this paper will discuss why this paper diverges from that original proposal in choice of syntax.</p>
<p>Such indexing allows for implementing the pair converting constructor:</p>
<div class="sourceCode" id="cb6"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb6-1"><a href="#cb6-1"></a><span class="kw">namespace</span> xstd <span class="op">{</span></span>
<span id="cb6-2"><a href="#cb6-2"></a>    <span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span><span class="op">...</span> Ts<span class="op">&gt;</span></span>
<span id="cb6-3"><a href="#cb6-3"></a>    <span class="kw">class</span> tuple <span class="op">{</span></span>
<span id="cb6-4"><a href="#cb6-4"></a>    <span class="kw">public</span><span class="op">:</span></span>
<span id="cb6-5"><a href="#cb6-5"></a>        <span class="kw">template</span> <span class="op">&lt;</span>std<span class="op">::</span>convertible_to<span class="op">&lt;</span>Ts<span class="op">...[</span><span class="dv">0</span><span class="op">]&gt;</span> T,</span>
<span id="cb6-6"><a href="#cb6-6"></a>                  std<span class="op">::</span>convertible_to<span class="op">&lt;</span>Ts<span class="op">...[</span><span class="dv">1</span><span class="op">]&gt;</span> U<span class="op">&gt;</span></span>
<span id="cb6-7"><a href="#cb6-7"></a>            <span class="kw">requires</span> <span class="kw">sizeof</span><span class="op">...(</span>Ts<span class="op">)</span> <span class="op">==</span> <span class="dv">2</span></span>
<span id="cb6-8"><a href="#cb6-8"></a>        <span class="kw">constexpr</span> tuple<span class="op">(</span>std<span class="op">::</span>pair<span class="op">&lt;</span>T, U<span class="op">&gt;</span> <span class="kw">const</span><span class="op">&amp;</span> p<span class="op">)</span></span>
<span id="cb6-9"><a href="#cb6-9"></a>            <span class="op">:</span> elems<span class="op">...[</span><span class="dv">0</span><span class="op">](</span>p<span class="op">.</span>first<span class="op">)</span></span>
<span id="cb6-10"><a href="#cb6-10"></a>            , elems<span class="op">...[</span><span class="dv">1</span><span class="op">](</span>p<span class="op">.</span>second<span class="op">)</span></span>
<span id="cb6-11"><a href="#cb6-11"></a>        <span class="op">{</span> <span class="op">}</span></span>
<span id="cb6-12"><a href="#cb6-12"></a>    <span class="kw">private</span><span class="op">:</span></span>
<span id="cb6-13"><a href="#cb6-13"></a>        Ts<span class="op">...</span> elems;</span>
<span id="cb6-14"><a href="#cb6-14"></a>    <span class="op">}</span>;</span>
<span id="cb6-15"><a href="#cb6-15"></a><span class="op">}</span></span></code></pre></div>
<p>A properly constrained converting constructor from a pack:</p>
<div class="sourceCode" id="cb7"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb7-1"><a href="#cb7-1"></a><span class="kw">namespace</span> xstd <span class="op">{</span></span>
<span id="cb7-2"><a href="#cb7-2"></a>    <span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span><span class="op">...</span> Ts<span class="op">&gt;</span></span>
<span id="cb7-3"><a href="#cb7-3"></a>    <span class="kw">class</span> tuple <span class="op">{</span></span>
<span id="cb7-4"><a href="#cb7-4"></a>    <span class="kw">public</span><span class="op">:</span></span>
<span id="cb7-5"><a href="#cb7-5"></a>        <span class="kw">template</span> <span class="op">&lt;</span>std<span class="op">::</span>constructible<span class="op">&lt;</span>Ts<span class="op">&gt;...</span> Us<span class="op">&gt;</span>   <span class="co">// everything is convertible</span></span>
<span id="cb7-6"><a href="#cb7-6"></a>            <span class="kw">requires</span> <span class="op">(</span><span class="kw">sizeof</span><span class="op">...(</span>Us<span class="op">)</span> <span class="op">&gt;</span> <span class="dv">1</span> <span class="op">||</span>        <span class="co">// exclude the copy ctor match</span></span>
<span id="cb7-7"><a href="#cb7-7"></a>                    <span class="op">!</span>std<span class="op">::</span>derived_from<span class="op">&lt;</span>std<span class="op">::</span>remove_cvref_t<span class="op">&lt;</span>Us<span class="op">...[</span><span class="dv">0</span><span class="op">]&gt;</span>, tuple<span class="op">&gt;)</span></span>
<span id="cb7-8"><a href="#cb7-8"></a>        <span class="kw">constexpr</span> tuple<span class="op">(</span>Us<span class="op">&amp;&amp;...</span> us<span class="op">)</span></span>
<span id="cb7-9"><a href="#cb7-9"></a>            <span class="op">:</span> elems<span class="op">(</span>std<span class="op">::</span>forward<span class="op">&lt;</span>Us<span class="op">&gt;(</span>us<span class="op">))...</span></span>
<span id="cb7-10"><a href="#cb7-10"></a>        <span class="op">{</span> <span class="op">}</span></span>
<span id="cb7-11"><a href="#cb7-11"></a>    <span class="kw">private</span><span class="op">:</span></span>
<span id="cb7-12"><a href="#cb7-12"></a>        Ts<span class="op">...</span> elems;</span>
<span id="cb7-13"><a href="#cb7-13"></a>    <span class="op">}</span>;</span>
<span id="cb7-14"><a href="#cb7-14"></a><span class="op">}</span></span></code></pre></div>
<p>As well as implementing <code class="sourceCode cpp">tuple_element</code>:</p>
<div class="sourceCode" id="cb8"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb8-1"><a href="#cb8-1"></a><span class="kw">namespace</span> xstd <span class="op">{</span></span>
<span id="cb8-2"><a href="#cb8-2"></a>    <span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span><span class="op">...</span> <span class="op">&gt;</span> <span class="kw">class</span> tuple;</span>
<span id="cb8-3"><a href="#cb8-3"></a>    </span>
<span id="cb8-4"><a href="#cb8-4"></a>    <span class="kw">template</span> <span class="op">&lt;</span><span class="dt">size_t</span> I, <span class="kw">typename</span><span class="op">&gt;</span></span>
<span id="cb8-5"><a href="#cb8-5"></a>    <span class="kw">struct</span> tuple_element;</span>
<span id="cb8-6"><a href="#cb8-6"></a>    <span class="kw">template</span> <span class="op">&lt;</span><span class="dt">size_t</span> I, <span class="kw">typename</span><span class="op">...</span> Ts<span class="op">&gt;</span></span>
<span id="cb8-7"><a href="#cb8-7"></a>    <span class="kw">struct</span> tuple_element<span class="op">&lt;</span>I, tuple<span class="op">&lt;</span>Ts<span class="op">...&gt;&gt;</span> <span class="kw">requires</span> <span class="op">(</span>I <span class="op">&lt;</span> <span class="kw">sizeof</span><span class="op">...(</span>Ts<span class="op">))</span></span>
<span id="cb8-8"><a href="#cb8-8"></a>    <span class="op">{</span></span>
<span id="cb8-9"><a href="#cb8-9"></a>        <span class="kw">using</span> type <span class="op">=</span> Ts<span class="op">...[</span>I<span class="op">]</span>;</span>
<span id="cb8-10"><a href="#cb8-10"></a>    <span class="op">}</span>;</span>
<span id="cb8-11"><a href="#cb8-11"></a><span class="op">}</span></span></code></pre></div>
<p>This is nicer than status quo, but I think we can do better in this regard with a little bit more help.</p>
<h2 id="pack-aliases-and-generalized-indexing"><span class="header-section-number">2.4</span> Pack aliases and generalized indexing<a href="#pack-aliases-and-generalized-indexing" class="self-link"></a></h2>
<p>The previous section defines the syntax <code class="sourceCode cpp">T<span class="op">...[</span>I<span class="op">]</span></code> to be indexing into a pack, <code class="sourceCode cpp">T</code>. Let’s immediately generalize this. Let’s also say that a <em>type</em> can be pack-indexed into if the type provides an alias named <code class="sourceCode cpp"><span class="op">...</span></code></p>
<p>That is:</p>
<div class="sourceCode" id="cb9"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb9-1"><a href="#cb9-1"></a><span class="kw">namespace</span> xstd <span class="op">{</span></span>
<span id="cb9-2"><a href="#cb9-2"></a>    <span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span><span class="op">...</span> Ts<span class="op">&gt;</span></span>
<span id="cb9-3"><a href="#cb9-3"></a>    <span class="kw">class</span> tuple <span class="op">{</span></span>
<span id="cb9-4"><a href="#cb9-4"></a>    <span class="kw">public</span><span class="op">:</span></span>
<span id="cb9-5"><a href="#cb9-5"></a>        <span class="kw">using</span> <span class="op">...</span> <span class="op">=</span> Ts; <span class="co">// declares that tuple&lt;Ts...&gt; can be indexed just like Ts...</span></span>
<span id="cb9-6"><a href="#cb9-6"></a>                        <span class="co">// note that the Ts on the right-hand-side is not expanded</span></span>
<span id="cb9-7"><a href="#cb9-7"></a>    <span class="op">}</span>;</span>
<span id="cb9-8"><a href="#cb9-8"></a>    </span>
<span id="cb9-9"><a href="#cb9-9"></a>    <span class="kw">template</span> <span class="op">&lt;</span><span class="dt">size_t</span> I, <span class="kw">typename</span> Tuple<span class="op">&gt;</span></span>
<span id="cb9-10"><a href="#cb9-10"></a>    <span class="kw">struct</span> tuple_element <span class="op">{</span></span>
<span id="cb9-11"><a href="#cb9-11"></a>        <span class="kw">using</span> type <span class="op">=</span> Tuple<span class="op">.[</span>I<span class="op">]</span>; <span class="co">// indexes via the pack Tuple::...</span></span>
<span id="cb9-12"><a href="#cb9-12"></a>    <span class="op">}</span>;</span>
<span id="cb9-13"><a href="#cb9-13"></a><span class="op">}</span></span></code></pre></div>
<p>The above is not a typo: while we index into a <em>pack</em> by way of <code class="sourceCode cpp">x<span class="op">...[</span>I<span class="op">]</span></code>, we index into a specific type or object via <code class="sourceCode cpp">x<span class="op">.[</span>I<span class="op">]</span></code>. A proper discussion of the motivation for the differing syntax will follow.</p>
<p>This isn’t quite right though, since we want to constrain <code class="sourceCode cpp">tuple_element</code> here. We have the operator <code class="sourceCode cpp"><span class="kw">sizeof</span><span class="op">...</span></code>, which takes a pack. We just need a way of passing the pack itself. To do that, this paper proposes the syntax <code class="sourceCode cpp">T<span class="op">.[:]</span></code>. You can think of this as the “add a layer of packness” operator:</p>
<div class="sourceCode" id="cb10"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb10-1"><a href="#cb10-1"></a><span class="kw">namespace</span> xstd <span class="op">{</span></span>
<span id="cb10-2"><a href="#cb10-2"></a>    <span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span><span class="op">...</span> Ts<span class="op">&gt;</span></span>
<span id="cb10-3"><a href="#cb10-3"></a>    <span class="kw">class</span> tuple <span class="op">{</span></span>
<span id="cb10-4"><a href="#cb10-4"></a>    <span class="kw">public</span><span class="op">:</span></span>
<span id="cb10-5"><a href="#cb10-5"></a>        <span class="kw">using</span> <span class="op">...</span> <span class="op">=</span> Ts;</span>
<span id="cb10-6"><a href="#cb10-6"></a>    <span class="op">}</span>;</span>
<span id="cb10-7"><a href="#cb10-7"></a>    </span>
<span id="cb10-8"><a href="#cb10-8"></a>    <span class="kw">template</span> <span class="op">&lt;</span><span class="dt">size_t</span> I, <span class="kw">typename</span> Tuple<span class="op">&gt;</span></span>
<span id="cb10-9"><a href="#cb10-9"></a>    <span class="kw">struct</span> tuple_element;</span>
<span id="cb10-10"><a href="#cb10-10"></a></span>
<span id="cb10-11"><a href="#cb10-11"></a>    <span class="kw">template</span> <span class="op">&lt;</span><span class="dt">size_t</span> I, <span class="kw">typename</span> Tuple<span class="op">&gt;</span></span>
<span id="cb10-12"><a href="#cb10-12"></a>        <span class="kw">requires</span> <span class="op">(</span>I <span class="op">&lt;</span> <span class="kw">sizeof</span><span class="op">...(</span>Tuple<span class="op">.[:]))</span></span>
<span id="cb10-13"><a href="#cb10-13"></a>    <span class="kw">struct</span> tuple_element<span class="op">&lt;</span>I, Tuple<span class="op">&gt;</span></span>
<span id="cb10-14"><a href="#cb10-14"></a>    <span class="op">{</span></span>
<span id="cb10-15"><a href="#cb10-15"></a>        <span class="kw">using</span> type <span class="op">=</span> Tuple<span class="op">.[</span>I<span class="op">]</span>;</span>
<span id="cb10-16"><a href="#cb10-16"></a>    <span class="op">}</span>;</span>
<span id="cb10-17"><a href="#cb10-17"></a><span class="op">}</span></span></code></pre></div>
<p>In the wild, we could use <code class="sourceCode cpp">Tuple<span class="op">.[</span>I<span class="op">]</span></code> directly. It is SFINAE-friendly (simply discard the overload if the type either does not provide a pack template or the <em>constant-expression</em> <code class="sourceCode cpp">I</code> is out of bounds for the size of the pack).</p>
<h2 id="named-pack-aliases"><span class="header-section-number">2.5</span> Named pack aliases<a href="#named-pack-aliases" class="self-link"></a></h2>
<p>Pack aliases can be named as well, it’s just that the unnamed pack alias gets special treatment as far as the language is concerned:</p>
<div class="sourceCode" id="cb11"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb11-1"><a href="#cb11-1"></a><span class="kw">namespace</span> xstd <span class="op">{</span></span>
<span id="cb11-2"><a href="#cb11-2"></a>    <span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span><span class="op">...</span> Ts<span class="op">&gt;</span></span>
<span id="cb11-3"><a href="#cb11-3"></a>    <span class="kw">class</span> tuple <span class="op">{</span></span>
<span id="cb11-4"><a href="#cb11-4"></a>    <span class="kw">public</span><span class="op">:</span></span>
<span id="cb11-5"><a href="#cb11-5"></a>        <span class="kw">using</span> <span class="op">...</span> <span class="op">=</span> Ts;</span>
<span id="cb11-6"><a href="#cb11-6"></a>        <span class="kw">using</span> <span class="op">...</span>refs <span class="op">=</span> Ts<span class="op">&amp;</span>;</span>
<span id="cb11-7"><a href="#cb11-7"></a>    <span class="op">}</span>;</span>
<span id="cb11-8"><a href="#cb11-8"></a>    </span>
<span id="cb11-9"><a href="#cb11-9"></a>    <span class="kw">using</span> Record <span class="op">=</span> tuple<span class="op">&lt;</span><span class="dt">int</span>, <span class="dt">double</span>, std<span class="op">::</span>string<span class="op">&gt;</span>;</span>
<span id="cb11-10"><a href="#cb11-10"></a>    <span class="kw">static_assert</span><span class="op">(</span>std<span class="op">::</span>is_same_v<span class="op">&lt;</span>Record<span class="op">.[</span><span class="dv">0</span><span class="op">]</span>, <span class="dt">int</span><span class="op">&gt;)</span>;</span>
<span id="cb11-11"><a href="#cb11-11"></a>    <span class="kw">static_assert</span><span class="op">(</span>std<span class="op">::</span>is_same_v<span class="op">&lt;</span>Record<span class="op">::</span>refs<span class="op">...[</span><span class="dv">1</span><span class="op">]</span>, <span class="dt">double</span><span class="op">&amp;&gt;)</span>;</span>
<span id="cb11-12"><a href="#cb11-12"></a><span class="op">}</span></span></code></pre></div>
<p>Note the differing access syntax: <code class="sourceCode cpp">Record</code> is a type that we’re treating as a pack, whereas <code class="sourceCode cpp">Record<span class="op">::</span>refs</code> is a pack.</p>
<h2 id="unpacking"><span class="header-section-number">2.6</span> Unpacking<a href="#unpacking" class="self-link"></a></h2>
<p>Let’s go back to our initial sketch, where <code class="sourceCode cpp">xstd<span class="op">::</span>tuple</code> was an aggregate:</p>
<div class="sourceCode" id="cb12"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb12-1"><a href="#cb12-1"></a><span class="kw">namespace</span> xstd <span class="op">{</span></span>
<span id="cb12-2"><a href="#cb12-2"></a>    <span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span><span class="op">...</span> Ts<span class="op">&gt;</span></span>
<span id="cb12-3"><a href="#cb12-3"></a>    <span class="kw">struct</span> tuple <span class="op">{</span></span>
<span id="cb12-4"><a href="#cb12-4"></a>        Ts<span class="op">...</span> elems;</span>
<span id="cb12-5"><a href="#cb12-5"></a>    <span class="op">}</span>;</span>
<span id="cb12-6"><a href="#cb12-6"></a><span class="op">}</span></span></code></pre></div>
<p>Since we know <code class="sourceCode cpp">elems</code> is a pack, we can directly access and unpack it into a function:</p>
<div class="sourceCode" id="cb13"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb13-1"><a href="#cb13-1"></a><span class="dt">int</span> sum<span class="op">(</span><span class="dt">int</span> x, <span class="dt">int</span> y, <span class="dt">int</span> z<span class="op">)</span> <span class="op">{</span> <span class="cf">return</span> x <span class="op">+</span> y <span class="op">+</span> z; <span class="op">}</span></span>
<span id="cb13-2"><a href="#cb13-2"></a></span>
<span id="cb13-3"><a href="#cb13-3"></a>xstd<span class="op">::</span>tuple<span class="op">&lt;</span><span class="dt">int</span>, <span class="dt">int</span>, <span class="dt">int</span><span class="op">&gt;</span> point<span class="op">{</span><span class="dv">1</span>, <span class="dv">2</span>, <span class="dv">3</span><span class="op">}</span>;</span>
<span id="cb13-4"><a href="#cb13-4"></a><span class="dt">int</span> s <span class="op">=</span> sum<span class="op">(</span>point<span class="op">.</span>elems<span class="op">...)</span>; <span class="co">// ok, 6</span></span></code></pre></div>
<p>This can work since the compiler knows that <code class="sourceCode cpp">point<span class="op">.</span>elems</code> is a pack, and unpacking that is reasonable following the rules of the language.</p>
<p>However, we quickly run into a problem as soon as we add more templates into the mix:</p>
<div class="sourceCode" id="cb14"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb14-1"><a href="#cb14-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> Tuple<span class="op">&gt;</span></span>
<span id="cb14-2"><a href="#cb14-2"></a><span class="dt">int</span> tuple_sum<span class="op">(</span>Tuple t<span class="op">)</span> <span class="op">{</span></span>
<span id="cb14-3"><a href="#cb14-3"></a>    <span class="cf">return</span> sum<span class="op">(</span>t<span class="op">.</span>elems<span class="op">...)</span>; <span class="co">// ??</span></span>
<span id="cb14-4"><a href="#cb14-4"></a><span class="op">}</span></span></code></pre></div>
<p>This isn’t going to work. From <span class="citation" data-cites="Smith.Pack">[<a href="#ref-Smith.Pack" role="doc-biblioref">Smith.Pack</a>]</span>:</p>
<blockquote>
<div class="sourceCode" id="cb15"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb15-1"><a href="#cb15-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">typename</span> T<span class="op">&gt;</span> <span class="dt">void</span> call_f<span class="op">(</span>T t<span class="op">)</span> <span class="op">{</span></span>
<span id="cb15-2"><a href="#cb15-2"></a>  f<span class="op">(</span>t<span class="op">.</span>x <span class="op">...)</span></span>
<span id="cb15-3"><a href="#cb15-3"></a><span class="op">}</span></span></code></pre></div>
<p>Right now, this is ill-formed (no diagnostic required) because “t.x” does not contain an unexpanded parameter pack. But if we allow class members to be pack expansions, this code could be valid – we’d lose any syntactic mechanism to determine whether an expression contains an unexpanded pack. This is fatal to at least one implementation strategy for variadic templates. It also admits the possibility of pack expansions occurring outside templates, which current implementations are not well-suited to handle.</p>
</blockquote>
<p>As well as introducing ambiguities:</p>
<div class="sourceCode" id="cb16"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb16-1"><a href="#cb16-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> T, <span class="kw">typename</span><span class="op">...</span> U<span class="op">&gt;</span></span>
<span id="cb16-2"><a href="#cb16-2"></a><span class="dt">void</span> call_f<span class="op">(</span>T t, U<span class="op">...</span> us<span class="op">)</span></span>
<span id="cb16-3"><a href="#cb16-3"></a><span class="op">{</span></span>
<span id="cb16-4"><a href="#cb16-4"></a>    <span class="co">// Is this intended to add &#39;t&#39; to each element in &#39;us&#39;</span></span>
<span id="cb16-5"><a href="#cb16-5"></a>    <span class="co">// or is intended to pairwise sum the tuple &#39;t&#39; and</span></span>
<span id="cb16-6"><a href="#cb16-6"></a>    <span class="co">// the pack &#39;us&#39;?</span></span>
<span id="cb16-7"><a href="#cb16-7"></a>    f<span class="op">((</span>t <span class="op">+</span> us<span class="op">)...)</span>;</span>
<span id="cb16-8"><a href="#cb16-8"></a><span class="op">}</span></span></code></pre></div>
<p>We can’t have <em>no</em> syntactic mechanism (and note that this paper very much is introducing the possibility of pack expansions occurring outside templates). In order to make the dependent <code class="sourceCode cpp">tuple_sum</code> case work, we need one. One such could be a context-sensitive keyword like <code class="sourceCode cpp">pack</code>:</p>
<div class="sourceCode" id="cb17"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb17-1"><a href="#cb17-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> Tuple<span class="op">&gt;</span></span>
<span id="cb17-2"><a href="#cb17-2"></a><span class="dt">int</span> tuple_sum<span class="op">(</span>Tuple t<span class="op">)</span> <span class="op">{</span></span>
<span id="cb17-3"><a href="#cb17-3"></a>    <span class="cf">return</span> sum<span class="op">(</span>t<span class="op">.</span>pack elems<span class="op">...)</span>;</span>
<span id="cb17-4"><a href="#cb17-4"></a><span class="op">}</span></span></code></pre></div>
<p>However, having a context-sensitive keyword isn’t going to cut it… because of the possibility of writing code like this:</p>
<div class="sourceCode" id="cb18"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb18-1"><a href="#cb18-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">typename</span> <span class="op">...</span>Ts<span class="op">&gt;</span> <span class="kw">struct</span> X <span class="op">{</span> <span class="kw">using</span> <span class="op">...</span>types <span class="op">=</span> Ts; <span class="op">}</span>;</span>
<span id="cb18-2"><a href="#cb18-2"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">typename</span> MyX<span class="op">&gt;</span> <span class="dt">void</span> f<span class="op">()</span> <span class="op">{</span></span>
<span id="cb18-3"><a href="#cb18-3"></a>  <span class="kw">using</span> Fn <span class="op">=</span> <span class="dt">void</span><span class="op">(</span><span class="kw">typename</span> MyX<span class="op">::</span>pack types <span class="op">...)</span>;</span>
<span id="cb18-4"><a href="#cb18-4"></a><span class="op">}</span></span></code></pre></div>
<p>Today that’s declaring a function type that takes one argument of type <code class="sourceCode cpp"><span class="kw">typename</span> MyX<span class="op">::</span>pack</code> named <code class="sourceCode cpp">types</code> and then varargs with the comma elided. If we make the comma mandatory (as <span class="citation" data-cites="P1219R1">[<a href="#ref-P1219R1" role="doc-biblioref">P1219R1</a>]</span> proposes to do), then that would open up our ability to use a context-sensitive <code class="sourceCode cpp">pack</code> here.</p>
<p>Otherwise, we would need a new keyword to make this happen, and <code class="sourceCode cpp">pack</code> seems entirely too pretty to make this work. As a placeholder, this paper suggests using <em>preceding</em> ellipses (which still need to be separated by a space). That is:</p>
<div class="sourceCode" id="cb19"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb19-1"><a href="#cb19-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> Tuple<span class="op">&gt;</span></span>
<span id="cb19-2"><a href="#cb19-2"></a><span class="dt">int</span> tuple_sum<span class="op">(</span>Tuple t<span class="op">)</span> <span class="op">{</span></span>
<span id="cb19-3"><a href="#cb19-3"></a>    <span class="cf">return</span> sum<span class="op">(</span>t<span class="op">.</span> <span class="op">...</span>elems<span class="op">...)</span>;</span>
<span id="cb19-4"><a href="#cb19-4"></a><span class="op">}</span></span></code></pre></div>
<p>Class access wouldn’t need a leading dot (e.g. <code class="sourceCode cpp">Tuple<span class="op">::...</span>elems</code>), but either way that’s a lot of dots. Don’t worry too much about the above syntax, it’s not intended to be the commonly used approach - simply something that would be necessary to have. And such a marker would necessarily be an incomplete solution anyway. With the earlier examples of implementing <code class="sourceCode cpp">tuple</code> having constructors, <code class="sourceCode cpp">elems</code> was private. How would we access it?</p>
<h2 id="generalized-unpacking-and-operator..."><span class="header-section-number">2.7</span> Generalized unpacking and <code class="sourceCode cpp"><span class="kw">operator</span><span class="op">...</span></code><a href="#generalized-unpacking-and-operator..." class="self-link"></a></h2>
<p>In the same way that we let <code class="sourceCode cpp">xstd<span class="op">::</span>tuple<span class="op">&lt;</span>Ts<span class="op">...&gt;</span></code> be directly indexed into, we can also let it be directly unpacked. We do that with the help of <code class="sourceCode cpp"><span class="kw">operator</span><span class="op">...()</span></code>:</p>
<div class="sourceCode" id="cb20"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb20-1"><a href="#cb20-1"></a><span class="kw">namespace</span> xstd <span class="op">{</span></span>
<span id="cb20-2"><a href="#cb20-2"></a>    <span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span><span class="op">...</span> Ts<span class="op">&gt;</span></span>
<span id="cb20-3"><a href="#cb20-3"></a>    <span class="kw">class</span> tuple <span class="op">{</span></span>
<span id="cb20-4"><a href="#cb20-4"></a>    <span class="kw">public</span><span class="op">:</span></span>
<span id="cb20-5"><a href="#cb20-5"></a>        Ts<span class="op">&amp;</span>        <span class="kw">operator</span> <span class="op">...()</span> <span class="op">&amp;</span>       <span class="op">{</span> <span class="cf">return</span> elems; <span class="op">}</span></span>
<span id="cb20-6"><a href="#cb20-6"></a>        Ts <span class="kw">const</span><span class="op">&amp;</span>  <span class="kw">operator</span> <span class="op">...()</span> <span class="kw">const</span><span class="op">&amp;</span>  <span class="op">{</span> <span class="cf">return</span> elems; <span class="op">}</span></span>
<span id="cb20-7"><a href="#cb20-7"></a>        Ts<span class="op">&amp;&amp;</span>       <span class="kw">operator</span> <span class="op">...()</span> <span class="op">&amp;&amp;</span>      <span class="op">{</span> <span class="cf">return</span> std<span class="op">::</span>move<span class="op">(*</span><span class="kw">this</span><span class="op">).</span>elems; <span class="op">}</span></span>
<span id="cb20-8"><a href="#cb20-8"></a>        Ts <span class="kw">const</span><span class="op">&amp;&amp;</span> <span class="kw">operator</span> <span class="op">...()</span> <span class="kw">const</span><span class="op">&amp;&amp;</span> <span class="op">{</span> <span class="cf">return</span> std<span class="op">::</span>move<span class="op">(*</span><span class="kw">this</span><span class="op">).</span>elems; <span class="op">}</span></span>
<span id="cb20-9"><a href="#cb20-9"></a>    <span class="kw">private</span><span class="op">:</span></span>
<span id="cb20-10"><a href="#cb20-10"></a>        Ts<span class="op">...</span> elems;</span>
<span id="cb20-11"><a href="#cb20-11"></a>    <span class="op">}</span>;</span>
<span id="cb20-12"><a href="#cb20-12"></a><span class="op">}</span></span></code></pre></div>
<p>We do not need to dismabiguate <code class="sourceCode cpp">elems</code> here because we know <code class="sourceCode cpp">elems</code> is a pack, it’s declared as such. Were we to retrieve <code class="sourceCode cpp">elems</code> from a dependent base class though, we would need some form of disambiguation as described above (i.e. <code class="sourceCode cpp"><span class="kw">this</span><span class="op">-&gt;...</span>elems</code>).</p>
<p>Note that this form of the declaration uses an unexpanded pack on the left (the <code class="sourceCode cpp"><span class="op">...</span></code> does not expand the <code class="sourceCode cpp">Ts <span class="kw">const</span><span class="op">&amp;</span></code>, not really anyway) and in the body. Later sections in the paper will show other forms.</p>
<p>Also, from here on out, this paper will only use the <code class="sourceCode cpp"><span class="kw">const</span><span class="op">&amp;</span></code> overloads of relevant functions for general sanity (see also <span class="citation" data-cites="P0847R2">[<a href="#ref-P0847R2" role="doc-biblioref">P0847R2</a>]</span>).</p>
<p>The above declarations allow for:</p>
<div class="sourceCode" id="cb21"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb21-1"><a href="#cb21-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> Tuple<span class="op">&gt;</span></span>
<span id="cb21-2"><a href="#cb21-2"></a><span class="kw">constexpr</span> <span class="kw">auto</span> tuple_sum<span class="op">(</span>Tuple <span class="kw">const</span><span class="op">&amp;</span> tuple<span class="op">)</span> <span class="op">{</span></span>
<span id="cb21-3"><a href="#cb21-3"></a>    <span class="cf">return</span> <span class="op">(</span>tuple<span class="op">.[:]</span> <span class="op">+</span> <span class="op">...)</span>;</span>
<span id="cb21-4"><a href="#cb21-4"></a><span class="op">}</span></span>
<span id="cb21-5"><a href="#cb21-5"></a></span>
<span id="cb21-6"><a href="#cb21-6"></a><span class="kw">static_assert</span><span class="op">(</span>tuple_sum<span class="op">(</span>xstd<span class="op">::</span>tuple<span class="op">(</span><span class="dv">1</span>, <span class="dv">2</span>, <span class="dv">3</span><span class="op">))</span> <span class="op">==</span> <span class="dv">6</span><span class="op">)</span>;</span></code></pre></div>
<p><code class="sourceCode cpp">tuple<span class="op">.[:]</span></code> works by adding a layer of packness on top of <code class="sourceCode cpp">tuple</code> - it does this by creating a pack by way of <code class="sourceCode cpp"><span class="kw">operator</span><span class="op">...()</span></code> and using that pack as an unexpanded pack expression. That unexpanded pack is then expanded with the <em>fold-expression</em> as if it were a normal pack.</p>
<p>Or more generally:</p>
<div class="sourceCode" id="cb22"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb22-1"><a href="#cb22-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> F, <span class="kw">typename</span> Tuple<span class="op">&gt;</span></span>
<span id="cb22-2"><a href="#cb22-2"></a><span class="kw">constexpr</span> <span class="kw">decltype</span><span class="op">(</span><span class="kw">auto</span><span class="op">)</span> apply<span class="op">(</span>F<span class="op">&amp;&amp;</span> f, Tuple<span class="op">&amp;&amp;</span> tuple<span class="op">)</span> <span class="op">{</span></span>
<span id="cb22-3"><a href="#cb22-3"></a>    <span class="cf">return</span> std<span class="op">::</span>invoke<span class="op">(</span>std<span class="op">::</span>forward<span class="op">&lt;</span>F<span class="op">&gt;(</span>f<span class="op">)</span>, std<span class="op">::</span>forward<span class="op">&lt;</span>Tuple<span class="op">&gt;(</span>tuple<span class="op">).[:]...)</span>;</span>
<span id="cb22-4"><a href="#cb22-4"></a><span class="op">}</span></span></code></pre></div>
<p>As well as writing our <code class="sourceCode cpp">get</code> function template:</p>
<div class="sourceCode" id="cb23"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb23-1"><a href="#cb23-1"></a><span class="kw">namespace</span> xstd <span class="op">{</span></span>
<span id="cb23-2"><a href="#cb23-2"></a>    <span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span><span class="op">...</span> Ts<span class="op">&gt;</span></span>
<span id="cb23-3"><a href="#cb23-3"></a>    <span class="kw">class</span> tuple <span class="op">{</span></span>
<span id="cb23-4"><a href="#cb23-4"></a>    <span class="kw">public</span><span class="op">:</span></span>
<span id="cb23-5"><a href="#cb23-5"></a>        <span class="kw">using</span> <span class="op">...</span> <span class="op">=</span> Ts;</span>
<span id="cb23-6"><a href="#cb23-6"></a>        Ts <span class="kw">const</span><span class="op">&amp;</span> <span class="kw">operator</span> <span class="op">...()</span> <span class="kw">const</span><span class="op">&amp;</span> <span class="op">{</span> <span class="cf">return</span> elems; <span class="op">}</span></span>
<span id="cb23-7"><a href="#cb23-7"></a>    <span class="kw">private</span><span class="op">:</span></span>
<span id="cb23-8"><a href="#cb23-8"></a>        Ts<span class="op">...</span> elems;</span>
<span id="cb23-9"><a href="#cb23-9"></a>    <span class="op">}</span>;</span>
<span id="cb23-10"><a href="#cb23-10"></a>    </span>
<span id="cb23-11"><a href="#cb23-11"></a>    <span class="kw">template</span> <span class="op">&lt;</span><span class="dt">size_t</span> I, <span class="kw">typename</span><span class="op">...</span> Ts<span class="op">&gt;</span></span>
<span id="cb23-12"><a href="#cb23-12"></a>    <span class="kw">constexpr</span> <span class="kw">auto</span> <span class="kw">const</span><span class="op">&amp;</span> get<span class="op">(</span>tuple<span class="op">&lt;</span>Ts<span class="op">...&gt;</span> <span class="kw">const</span><span class="op">&amp;</span> v<span class="op">)</span> <span class="kw">noexcept</span> <span class="op">{</span></span>
<span id="cb23-13"><a href="#cb23-13"></a>        <span class="cf">return</span> v<span class="op">.[</span>I<span class="op">]</span>;</span>
<span id="cb23-14"><a href="#cb23-14"></a>    <span class="op">}</span></span>
<span id="cb23-15"><a href="#cb23-15"></a><span class="op">}</span></span></code></pre></div>
<p>Although since the syntax directly allows for <code class="sourceCode cpp">v<span class="op">.[</span><span class="dv">0</span><span class="op">]</span></code>, why would anyone write <code class="sourceCode cpp">xstd<span class="op">::</span>get<span class="op">&lt;</span><span class="dv">0</span><span class="op">&gt;(</span>v<span class="op">)</span></code>? And if you could write <code class="sourceCode cpp">f<span class="op">(</span>t<span class="op">.[:]...)</span></code>, why would anyone call <code class="sourceCode cpp">std<span class="op">::</span>apply<span class="op">()</span></code>?</p>
<h2 id="syntax-free-unpacking"><span class="header-section-number">2.8</span> Syntax-free unpacking?<a href="#syntax-free-unpacking" class="self-link"></a></h2>
<p>The above allows us to write:</p>
<div class="sourceCode" id="cb24"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb24-1"><a href="#cb24-1"></a>xstd<span class="op">::</span>tuple x<span class="op">{</span><span class="dv">1</span>, <span class="dv">2</span>, <span class="dv">3</span><span class="op">}</span>;</span>
<span id="cb24-2"><a href="#cb24-2"></a>foo<span class="op">(</span>x<span class="op">.[:]...)</span>; <span class="co">// calls foo(1, 2, 3)</span></span></code></pre></div>
<p>But do we explicitly need to add a layer of packness to <code class="sourceCode cpp">x</code> when we already know that <code class="sourceCode cpp">x</code> is a <code class="sourceCode cpp">tuple</code> and nothing is dependent? Could we simply allow:</p>
<div class="sourceCode" id="cb25"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb25-1"><a href="#cb25-1"></a>foo<span class="op">(</span>x<span class="op">...)</span>; <span class="co">// implicitly add packness to x and unpack it</span></span></code></pre></div>
<p>I’m not sure it’s worth it to pursue.</p>
<h2 id="disambiguating-packs-of-tuples"><span class="header-section-number">2.9</span> Disambiguating packs of tuples<a href="#disambiguating-packs-of-tuples" class="self-link"></a></h2>
<p>The previous section showed how to write <code class="sourceCode cpp">apply</code> taking a single function and a single tuple. What if we generalized it to taking multiple tuples? How do we handle a pack of tuples?</p>
<p>It’s at this point that it’s worth taking a step back and talking about disambiguation and why this paper makes the syntax choices that it makes. We need to be able to differentiate between packs and tuples. The two concepts are very similar, and this paper seeks to make them much more similar, but we still need to differentiate between them. It’s the pack of tuples case that really brings the ambiguity to light.</p>
<p>The rules this paper proposes, which have all been introduced at this point, are:</p>
<ul>
<li><p><code class="sourceCode cpp">e<span class="op">.[:]</span></code> takes a <a href="#pack-like-type"><em>pack-like type</em></a> (or object of such) and adds a layer of packness to it, by way of either <code class="sourceCode cpp"><span class="kw">operator</span><span class="op">...()</span></code> or <code class="sourceCode cpp"><span class="kw">using</span> <span class="op">...</span></code>. It never is applied to an existing pack, and it is never used to disambiguate dependent member access.</p></li>
<li><p><code class="sourceCode cpp">e<span class="op">.[</span>I<span class="op">]</span></code> never removes a layer of packness. It is picking the <code class="sourceCode cpp">I</code>th element of a pack-like type.</p></li>
<li><p><code class="sourceCode cpp">e<span class="op">...[</span>I<span class="op">]</span></code> always removes a layer of packness. It is picking the <code class="sourceCode cpp">I</code>th element of a pack.</p></li>
<li><p><code class="sourceCode cpp">e<span class="op">.</span> <span class="op">...</span>f</code> disambiguates dependent member access and identifies <code class="sourceCode cpp">f</code> as a pack The space between the <code class="sourceCode cpp"><span class="op">.</span></code> and <code class="sourceCode cpp"><span class="op">...</span></code> is required.</p></li>
</ul>
<p>That is, <code class="sourceCode cpp">pack<span class="op">...[</span>I<span class="op">]</span></code> and <code class="sourceCode cpp">tuple<span class="op">.[</span>I<span class="op">]</span></code> are valid, <code class="sourceCode cpp">tuple<span class="op">...[</span>I<span class="op">]</span></code> is an error, and <code class="sourceCode cpp">pack<span class="op">.[</span>I<span class="op">]</span></code> would be applying <code class="sourceCode cpp"><span class="op">.[</span>I<span class="op">]</span></code> to each element of the pack (and is itself still an unexpanded pack expression). Rule of thumb: you need <code class="sourceCode cpp"><span class="op">...</span></code>s if and only if you have a pack.</p>
<p><code class="sourceCode cpp">e<span class="op">.[</span>I<span class="op">]</span></code> is an equivalent shorthand for <code class="sourceCode cpp">e<span class="op">.[:]...[</span>I<span class="op">]</span></code>.</p>
<p>This leads to clear meanings of each of the following. If we have a function template taking an argument <code class="sourceCode cpp">e</code> which has a member <code class="sourceCode cpp">f</code>, where the kind of <code class="sourceCode cpp">e</code> is specified by the columns of this table and the kind of <code class="sourceCode cpp">f</code> is specified by the rows:</p>
<table>
<tr>
<td></td>
<th>
<code class="sourceCode cpp">e</code> is a Pack
</th>
<th>
<code class="sourceCode cpp">e</code> is a Pack-like type
</th>
<th>
<code class="sourceCode cpp">e</code> is not expanded
</th>
</tr>
<tr>
<th>
<code class="sourceCode cpp">f</code> is a Pack
</th>
<td>
<code class="sourceCode cpp">foo<span class="op">(</span>e<span class="op">.</span> <span class="op">...</span>f<span class="op">...</span> <span class="op">...)</span>;</code>
</td>
<td>
<code class="sourceCode cpp">foo<span class="op">(</span>e<span class="op">.[:].</span> <span class="op">...</span>f<span class="op">...</span> <span class="op">...)</span>;</code>
</td>
<td>
<code class="sourceCode cpp">foo<span class="op">(</span>e<span class="op">.</span> <span class="op">...</span>f<span class="op">...)</span>;</code>
</td>
</tr>
<tr>
<th>
<code class="sourceCode cpp">f</code> is a Pack-like type
</th>
<td>
<code class="sourceCode cpp">foo<span class="op">(</span>e<span class="op">.</span>f<span class="op">.[:]...</span> <span class="op">...)</span>;</code>
</td>
<td>
<code class="sourceCode cpp">foo<span class="op">(</span>e<span class="op">.[:].</span>f<span class="op">.[:]...</span> <span class="op">...)</span>;</code>
</td>
<td>
<code class="sourceCode cpp">foo<span class="op">(</span>e<span class="op">.</span>f<span class="op">.[:]...)</span>;</code>
</td>
</tr>
<tr>
<th>
<code class="sourceCode cpp">f</code> is not expanded
</th>
<td>
<code class="sourceCode cpp">foo<span class="op">(</span>e<span class="op">.</span>f<span class="op">...)</span>;</code>
</td>
<td>
<code class="sourceCode cpp">foo<span class="op">(</span>e<span class="op">.[:].</span>f<span class="op">...)</span>;</code>
</td>
<td>
<code class="sourceCode cpp">foo<span class="op">(</span>e<span class="op">.</span>f<span class="op">)</span>;</code>
</td>
</table>
<p>The only two valid cells in that table in C++20 are the bottom-left and bottom-right ones. Note that every cell has different syntax, by design.</p>
<h2 id="nested-pack-expansions"><span class="header-section-number">2.10</span> Nested pack expansions<a href="#nested-pack-expansions" class="self-link"></a></h2>
<p>In order for the above table to work at all, we also need a new kind of pack expansion. When C++11 introduced pack expansion, the rules were very simple: The expression in <code class="sourceCode cpp">expr<span class="op">...</span></code> must contain at least one unexpanded pack expression and every unexpanded pack expression must have the same length.</p>
<p>But with the concepts introduced in this proposal, we have the ability to introduce new things that behave like unexpanded pack expressions within an unexpanded pack expression and we need to define rules for that. Consider:</p>
<div class="sourceCode" id="cb26"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb26-1"><a href="#cb26-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span><span class="op">...</span> Ts<span class="op">&gt;</span></span>
<span id="cb26-2"><a href="#cb26-2"></a><span class="dt">void</span> foo<span class="op">(</span>Ts<span class="op">...</span> e<span class="op">)</span> <span class="op">{</span></span>
<span id="cb26-3"><a href="#cb26-3"></a>    bar<span class="op">(</span>e<span class="op">.[:]...</span> <span class="op">...)</span>;</span>
<span id="cb26-4"><a href="#cb26-4"></a><span class="op">}</span></span>
<span id="cb26-5"><a href="#cb26-5"></a></span>
<span id="cb26-6"><a href="#cb26-6"></a><span class="co">// what does this do?</span></span>
<span id="cb26-7"><a href="#cb26-7"></a>foo<span class="op">(</span>xstd<span class="op">::</span>tuple<span class="op">{</span><span class="dv">1</span><span class="op">}</span>, xstd<span class="op">::</span>tuple<span class="op">{</span><span class="dv">2</span>, <span class="dv">3</span><span class="op">})</span>;</span></code></pre></div>
<p>Following the rules presented above, <code class="sourceCode cpp">e<span class="op">.[:]</span></code> adds a layer of packness to each element in the pack (which is fine because <code class="sourceCode cpp">xstd<span class="op">::</span>tuple</code>s are pack-like types which define an <code class="sourceCode cpp"><span class="kw">operator</span><span class="op">...()</span></code>). But what then do the <code class="sourceCode cpp"><span class="op">...</span></code>s refer to?</p>
<p>We say that adding layer of packness in the middle of an existing unexpanded pack expression will hang a new, nested unexpanded pack expression onto that.</p>
<p>In the above example, <code class="sourceCode cpp">e</code> is an unexpanded pack expression. <code class="sourceCode cpp">e<span class="op">.[:]</span></code> is a nested unexpanded pack expression underneath <code class="sourceCode cpp">e</code>.</p>
<p>When we encounter the the first <code class="sourceCode cpp"><span class="op">...</span></code>, we say that it expands the most nested unexpanded pack expression that of the expression that it refers to. The most nested unexpanded pack expression here is <code class="sourceCode cpp">e<span class="op">.[:]</span></code>, which transforms the expression into:</p>
<div class="sourceCode" id="cb27"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb27-1"><a href="#cb27-1"></a>bar<span class="op">((</span>e<span class="op">.[</span><span class="dv">0</span><span class="op">]</span>, e<span class="op">.[</span><span class="dv">1</span><span class="op">]</span>, e<span class="op">.[</span><span class="dv">2</span><span class="op">]</span>, <span class="co">/* etc. */</span>, e<span class="op">.[</span>M<span class="op">-</span><span class="dv">1</span><span class="op">])...)</span>;</span></code></pre></div>
<p>This isn’t really valid C++ code (or, worse, it actually is valid but would use the comma operator rather than having <code class="sourceCode cpp">M</code> arguments). But the idea is we now have one more <code class="sourceCode cpp"><span class="op">...</span></code> which now has a single unexpanded pack expression to be expanded, which is the unexpanded pack expression that expands each element in a pack-like type.</p>
<p>A different way of looking at is the outer-most <code class="sourceCode cpp"><span class="op">...</span></code> expands the outer-most unexpanded pack expression, keeping the inner ones in tact. If we only touch the outer-most <code class="sourceCode cpp"><span class="op">...</span></code>, we end up with the following transformation:</p>
<div class="sourceCode" id="cb28"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb28-1"><a href="#cb28-1"></a>bar<span class="op">(</span>e<sub>0</sub><span class="op">.[:]...</span>, e<sub>1</sub><span class="op">.[:]...</span>, <span class="co">/* etc. */</span>, e<sub>N-1</sub><span class="op">.[:]...)</span>;</span></code></pre></div>
<p>The two interpretations are isomorphic, though the latter is likely easier to understand.</p>
<p>Either way, the full answer to what does <code class="sourceCode cpp">foo<span class="op">(</span>xstd<span class="op">::</span>tuple<span class="op">{</span><span class="dv">1</span><span class="op">}</span>, xstd<span class="op">::</span>tuple<span class="op">{</span><span class="dv">2</span>, <span class="dv">3</span><span class="op">})</span></code> do in this example is that it calls <code class="sourceCode cpp">bar<span class="op">(</span><span class="dv">1</span>, <span class="dv">2</span>, <span class="dv">3</span><span class="op">)</span></code>.</p>
<p>For more concrete examples, here is a generalized <code class="sourceCode cpp">apply<span class="op">()</span></code> which can take many tuples and expand them in order:</p>
<div class="sourceCode" id="cb29"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb29-1"><a href="#cb29-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> F, <span class="kw">typename</span><span class="op">...</span> Tuples<span class="op">&gt;</span></span>
<span id="cb29-2"><a href="#cb29-2"></a><span class="kw">constexpr</span> <span class="kw">decltype</span><span class="op">(</span><span class="kw">auto</span><span class="op">)</span> apply<span class="op">(</span>F<span class="op">&amp;&amp;</span> f, Tuples<span class="op">&amp;&amp;...</span> tuples<span class="op">)</span> <span class="op">{</span></span>
<span id="cb29-3"><a href="#cb29-3"></a>    <span class="cf">return</span> std<span class="op">::</span>invoke<span class="op">(</span></span>
<span id="cb29-4"><a href="#cb29-4"></a>        std<span class="op">::</span>forward<span class="op">&lt;</span>F<span class="op">&gt;(</span>f<span class="op">)</span>,</span>
<span id="cb29-5"><a href="#cb29-5"></a>        std<span class="op">::</span>forward<span class="op">&lt;</span>Tuples<span class="op">&gt;(</span>tuples<span class="op">).[:]...</span> <span class="op">...)</span>;</span>
<span id="cb29-6"><a href="#cb29-6"></a><span class="op">}</span></span></code></pre></div>
<p>which, again more concretely, expands into something like:</p>
<div class="sourceCode" id="cb30"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb30-1"><a href="#cb30-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> F, <span class="kw">typename</span> T<sub>0</sub>, <span class="kw">typename</span> T<sub>1</sub>, <span class="op">...</span>, <span class="kw">typename</span> T<sub>N-1</sub><span class="op">&gt;</span></span>
<span id="cb30-2"><a href="#cb30-2"></a><span class="kw">constexpr</span> <span class="kw">decltype</span><span class="op">(</span><span class="kw">auto</span><span class="op">)</span> apply<span class="op">(</span>F<span class="op">&amp;&amp;</span> f, T<sub>0</sub> t<sub>0</sub>, T<sub>1</sub> t<sub>1</sub>, <span class="op">...</span>, T<sub>N-1</sub> t<sub>N-1</sub><span class="op">)</span> <span class="op">{</span></span>
<span id="cb30-3"><a href="#cb30-3"></a>    <span class="cf">return</span> std<span class="op">::</span>invoke<span class="op">(</span>std<span class="op">::</span>forward<span class="op">&lt;</span>F<span class="op">&gt;(</span>f<span class="op">)</span>,</span>
<span id="cb30-4"><a href="#cb30-4"></a>        std<span class="op">::</span>forward<span class="op">&lt;</span>T<sub>0</sub><span class="op">&gt;(</span>t<sub>0</sub><span class="op">).[:]...</span>,</span>
<span id="cb30-5"><a href="#cb30-5"></a>        std<span class="op">::</span>forward<span class="op">&lt;</span>T<sub>1</sub><span class="op">&gt;(</span>t<sub>1</sub><span class="op">).[:]...</span>,</span>
<span id="cb30-6"><a href="#cb30-6"></a>        <span class="op">...</span></span>
<span id="cb30-7"><a href="#cb30-7"></a>        std<span class="op">::</span>forward<span class="op">&lt;</span>T<sub>N-1</sub><span class="op">&gt;(</span>t<sub>N-1</sub><span class="op">).[:]...)</span>;</span>
<span id="cb30-8"><a href="#cb30-8"></a><span class="op">}</span></span></code></pre></div>
<p>And then we unpack each of these <code class="sourceCode cpp"><span class="op">...</span></code>s through the appropriate <code class="sourceCode cpp"><span class="kw">operator</span><span class="op">...</span></code>s.</p>
<p>Similarly, <code class="sourceCode cpp">tuple_cat</code> would be:</p>
<div class="sourceCode" id="cb31"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb31-1"><a href="#cb31-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span><span class="op">...</span> Tuples<span class="op">&gt;</span></span>
<span id="cb31-2"><a href="#cb31-2"></a><span class="kw">constexpr</span> std<span class="op">::</span>tuple<span class="op">&lt;</span>Tuples<span class="op">.[:]...</span> <span class="op">...&gt;</span> tuple_cat<span class="op">(</span>Tuples<span class="op">&amp;&amp;...</span> tuples<span class="op">)</span> <span class="op">{</span></span>
<span id="cb31-3"><a href="#cb31-3"></a>    <span class="cf">return</span> <span class="op">{</span>std<span class="op">::</span>forward<span class="op">&lt;</span>Tuples<span class="op">&gt;(</span>tuples<span class="op">).[:]...</span> <span class="op">...}</span>;</span>
<span id="cb31-4"><a href="#cb31-4"></a><span class="op">}</span></span></code></pre></div>
<p>And itself leads to a different implementation of generalized <code class="sourceCode cpp">apply</code>:</p>
<div class="sourceCode" id="cb32"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb32-1"><a href="#cb32-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> F, <span class="kw">typename</span><span class="op">...</span> Tuples<span class="op">&gt;</span></span>
<span id="cb32-2"><a href="#cb32-2"></a><span class="kw">constexpr</span> <span class="kw">decltype</span><span class="op">(</span><span class="kw">auto</span><span class="op">)</span> apply<span class="op">(</span>F<span class="op">&amp;&amp;</span> f, Tuples<span class="op">&amp;&amp;...</span> tuples<span class="op">)</span> <span class="op">{</span></span>
<span id="cb32-3"><a href="#cb32-3"></a>    <span class="cf">return</span> std<span class="op">::</span>invoke<span class="op">(</span></span>
<span id="cb32-4"><a href="#cb32-4"></a>        std<span class="op">::</span>forward<span class="op">&lt;</span>F<span class="op">&gt;(</span>f<span class="op">)</span>,</span>
<span id="cb32-5"><a href="#cb32-5"></a>        tuple_cat<span class="op">(</span>std<span class="op">::</span>forward<span class="op">&lt;</span>Tuples<span class="op">&gt;(</span>tuples<span class="op">)...).[:]...</span></span>
<span id="cb32-6"><a href="#cb32-6"></a><span class="op">}</span></span></code></pre></div>
<p>Admitedly, six <code class="sourceCode cpp"><span class="op">.</span></code>s is a little cryptic. But is it any worse than the current implementation?</p>
<h2 id="structured-bindings-for-pack-expandable-types"><span class="header-section-number">2.11</span> Structured bindings for pack-expandable types<a href="#structured-bindings-for-pack-expandable-types" class="self-link"></a></h2>
<p>Structured bindings <span class="citation" data-cites="P0144R2">[<a href="#ref-P0144R2" role="doc-biblioref">P0144R2</a>]</span> were a great usability feature introduced in C++17, but it’s quite cumbersome to opt-in to the customization mechanism: you need to specialize <code class="sourceCode cpp">std<span class="op">::</span>tuple_size</code>, <code class="sourceCode cpp">std<span class="op">::</span>tuple_element</code>, and provide a <code class="sourceCode cpp">get<span class="op">()</span></code> of some sort. There was a proposal to reduce the customization mechanism by dropping <code class="sourceCode cpp">std<span class="op">::</span>tuple_element</code> <span class="citation" data-cites="P1096R0">[<a href="#ref-P1096R0" role="doc-biblioref">P1096R0</a>]</span>, which was… close. 13-7 in San Diego.</p>
<p>But the mechanisms presented in this paper provide a better customization point for structured bindings: <code class="sourceCode cpp"><span class="kw">operator</span><span class="op">...</span></code>! This is a single function that the language can examine to determine the arity, the types, and the values. All without even having to include <code class="sourceCode cpp"><span class="op">&lt;</span>tuple<span class="op">&gt;</span></code>:</p>
<div class="sourceCode" id="cb33"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb33-1"><a href="#cb33-1"></a><span class="kw">namespace</span> xstd <span class="op">{</span></span>
<span id="cb33-2"><a href="#cb33-2"></a>    <span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span><span class="op">...</span> Ts<span class="op">&gt;</span></span>
<span id="cb33-3"><a href="#cb33-3"></a>    <span class="kw">class</span> tuple <span class="op">{</span></span>
<span id="cb33-4"><a href="#cb33-4"></a>    <span class="kw">public</span><span class="op">:</span></span>
<span id="cb33-5"><a href="#cb33-5"></a><span class="pp">#ifdef ADD_ALIAS</span></span>
<span id="cb33-6"><a href="#cb33-6"></a>        <span class="kw">using</span> <span class="op">...</span> <span class="op">=</span> Ts;</span>
<span id="cb33-7"><a href="#cb33-7"></a><span class="pp">#endif</span></span>
<span id="cb33-8"><a href="#cb33-8"></a>        Ts<span class="op">&amp;</span> <span class="kw">operator</span> <span class="op">...()</span> <span class="op">&amp;</span> <span class="op">{</span> <span class="cf">return</span> elems; <span class="op">}</span></span>
<span id="cb33-9"><a href="#cb33-9"></a>    <span class="kw">private</span><span class="op">:</span></span>
<span id="cb33-10"><a href="#cb33-10"></a>        Ts<span class="op">...</span> elems;</span>
<span id="cb33-11"><a href="#cb33-11"></a>    <span class="op">}</span>;</span>
<span id="cb33-12"><a href="#cb33-12"></a><span class="op">}</span></span>
<span id="cb33-13"><a href="#cb33-13"></a></span>
<span id="cb33-14"><a href="#cb33-14"></a><span class="dt">int</span> n <span class="op">=</span> <span class="dv">0</span>;</span>
<span id="cb33-15"><a href="#cb33-15"></a></span>
<span id="cb33-16"><a href="#cb33-16"></a>xstd<span class="op">::</span>tuple<span class="op">&lt;</span><span class="dt">int</span>, <span class="dt">int</span><span class="op">&amp;&gt;</span> tref<span class="op">{</span>n, n<span class="op">}</span>;</span>
<span id="cb33-17"><a href="#cb33-17"></a><span class="kw">auto</span><span class="op">&amp;</span> <span class="op">[</span>i, iref<span class="op">]</span> <span class="op">=</span> tref;</span></code></pre></div>
<p>This paper proposes that the above is well-formed, with or without <code class="sourceCode cpp">ADD_ALIAS</code> defined. And either way, <code class="sourceCode cpp"><span class="kw">decltype</span><span class="op">(</span>i<span class="op">)</span></code> is <code class="sourceCode cpp"><span class="dt">int</span></code>. If there is no pack alias declared, then the type will be determined from the <code class="sourceCode cpp"><span class="kw">operator</span><span class="op">...</span></code> result (similar to what <span class="citation" data-cites="P1096R0">[<a href="#ref-P1096R0" role="doc-biblioref">P1096R0</a>]</span> proposed). If there is a pack alias declared, then the type will be determined from that pack alias. That is, <code class="sourceCode cpp"><span class="kw">decltype</span><span class="op">(</span>iref<span class="op">)</span></code> is <code class="sourceCode cpp"><span class="dt">int</span><span class="op">&amp;</span></code> if <code class="sourceCode cpp">ADD_ALIAS</code> is defined and <code class="sourceCode cpp"><span class="dt">int</span></code> otherwise.</p>
<p>More specifically, the type of the <code class="sourceCode cpp">i</code>th binding is <code class="sourceCode cpp">E<span class="op">.[</span>I<span class="op">]</span></code> if that is a valid expression (i.e. if <code class="sourceCode cpp"><span class="kw">using</span> <span class="op">...</span></code> is declared), otherwise <code class="sourceCode cpp">std<span class="op">::</span>remove_reference_t<span class="op">&lt;</span><span class="kw">decltype</span><span class="op">(</span>e<span class="op">.[</span>I<span class="op">])&gt;</span></code>.</p>
<h2 id="language-arrays-and-types-with-all-public-members"><span class="header-section-number">2.12</span> Language arrays and types with all-public members<a href="#language-arrays-and-types-with-all-public-members" class="self-link"></a></h2>
<p>Structured bindings works by default with language arrays and types with all- public members. This paper proposes that such types also have an implicitly-defaulted pack alias and pack operator. This allows for the same kind seamless unpacking this paper demonstrates for <code class="sourceCode cpp">xstd<span class="op">::</span>tuple</code>:</p>
<div class="sourceCode" id="cb34"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb34-1"><a href="#cb34-1"></a><span class="dt">void</span> bar<span class="op">(</span><span class="dt">int</span>, <span class="dt">int</span><span class="op">)</span>;</span>
<span id="cb34-2"><a href="#cb34-2"></a></span>
<span id="cb34-3"><a href="#cb34-3"></a><span class="dt">int</span> values<span class="op">[]</span> <span class="op">=</span> <span class="op">{</span><span class="dv">42</span>, <span class="dv">17</span><span class="op">}</span>;</span>
<span id="cb34-4"><a href="#cb34-4"></a>bar<span class="op">(</span>values<span class="op">.[:]...)</span>; <span class="co">// equivalent to bar(42, 17)</span></span></code></pre></div>
<p>And likewise for those other types that we can already use with structured bindings:</p>
<div class="sourceCode" id="cb35"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb35-1"><a href="#cb35-1"></a><span class="kw">struct</span> X <span class="op">{</span> <span class="dt">int</span> i, j; <span class="op">}</span>;</span>
<span id="cb35-2"><a href="#cb35-2"></a><span class="kw">struct</span> Y <span class="op">{</span> <span class="dt">int</span> k, m; <span class="op">}</span>;</span>
<span id="cb35-3"><a href="#cb35-3"></a></span>
<span id="cb35-4"><a href="#cb35-4"></a><span class="dt">int</span> sum<span class="op">(</span>X x, Y y<span class="op">)</span> <span class="op">{</span></span>
<span id="cb35-5"><a href="#cb35-5"></a>    <span class="co">// equivalent to: return x.i + x.j + y.k * y.k + y.m * y.m</span></span>
<span id="cb35-6"><a href="#cb35-6"></a>    <span class="cf">return</span> <span class="op">(</span>x<span class="op">.[:]</span> <span class="op">+</span> <span class="op">...)</span> <span class="op">+</span> <span class="op">((</span>y<span class="op">.[:]</span> <span class="op">*</span> y<span class="op">.[:])</span> <span class="op">+</span> <span class="op">...)</span>;</span>
<span id="cb35-7"><a href="#cb35-7"></a><span class="op">}</span></span></code></pre></div>
<p>But also provides a direct solution to the fixed-size pack problem <span class="citation" data-cites="N4072">[<a href="#ref-N4072" role="doc-biblioref">N4072</a>]</span>:</p>
<div class="sourceCode" id="cb36"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb36-1"><a href="#cb36-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> T, <span class="dt">int</span> N<span class="op">&gt;</span></span>
<span id="cb36-2"><a href="#cb36-2"></a><span class="kw">class</span> Vector <span class="op">{</span></span>
<span id="cb36-3"><a href="#cb36-3"></a><span class="kw">public</span><span class="op">:</span></span>
<span id="cb36-4"><a href="#cb36-4"></a>    <span class="co">// I want this to be constructible from exactly N T&#39;s. The type T[N]</span></span>
<span id="cb36-5"><a href="#cb36-5"></a>    <span class="co">// expands directly into that</span></span>
<span id="cb36-6"><a href="#cb36-6"></a>    Vector<span class="op">(</span>T<span class="op">[</span>N<span class="op">].[:]...</span> vals<span class="op">)</span>;</span>
<span id="cb36-7"><a href="#cb36-7"></a>    </span>
<span id="cb36-8"><a href="#cb36-8"></a>    <span class="co">// ... which possibly reads better if you take an alias first</span></span>
<span id="cb36-9"><a href="#cb36-9"></a>    <span class="kw">using</span> D <span class="op">=</span> T<span class="op">[</span>N<span class="op">]</span>;</span>
<span id="cb36-10"><a href="#cb36-10"></a>    Vector<span class="op">(</span>D<span class="op">.[:]...</span> vals<span class="op">)</span>;</span>
<span id="cb36-11"><a href="#cb36-11"></a><span class="op">}</span>;</span></code></pre></div>
<p>Note that this behaves differently from the homogenous variadic function packs paper <span class="citation" data-cites="P1219R1">[<a href="#ref-P1219R1" role="doc-biblioref">P1219R1</a>]</span>:</p>
<div class="sourceCode" id="cb37"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb37-1"><a href="#cb37-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> T, <span class="dt">int</span> N<span class="op">&gt;</span></span>
<span id="cb37-2"><a href="#cb37-2"></a><span class="kw">class</span> Vector2 <span class="op">{</span></span>
<span id="cb37-3"><a href="#cb37-3"></a><span class="kw">public</span><span class="op">:</span></span>
<span id="cb37-4"><a href="#cb37-4"></a>    <span class="co">// independently deduces each ts and requires that</span></span>
<span id="cb37-5"><a href="#cb37-5"></a>    <span class="co">// they all deduce to T. As opposed to the previous</span></span>
<span id="cb37-6"><a href="#cb37-6"></a>    <span class="co">// implementation which behaves as if the constructor</span></span>
<span id="cb37-7"><a href="#cb37-7"></a>    <span class="co">// were not a template, just that it took N T&#39;s.</span></span>
<span id="cb37-8"><a href="#cb37-8"></a>    Vector2<span class="op">(</span>T<span class="op">...</span> ts<span class="op">)</span> <span class="kw">requires</span> <span class="op">(</span><span class="kw">sizeof</span><span class="op">...(</span>ts<span class="op">)</span> <span class="op">==</span> N<span class="op">)</span>;</span>
<span id="cb37-9"><a href="#cb37-9"></a><span class="op">}</span>;</span></code></pre></div>
<p>For instance:</p>
<div class="sourceCode" id="cb38"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb38-1"><a href="#cb38-1"></a>Vector<span class="op">&lt;</span><span class="dt">int</span>, <span class="dv">2</span><span class="op">&gt;</span>  x<span class="op">(</span><span class="ch">&#39;a&#39;</span>, <span class="dv">2</span><span class="op">)</span>; <span class="co">// ok</span></span>
<span id="cb38-2"><a href="#cb38-2"></a>Vector2<span class="op">&lt;</span><span class="dt">int</span>, <span class="dv">2</span><span class="op">&gt;</span> y<span class="op">(</span><span class="ch">&#39;a&#39;</span>, <span class="dv">2</span><span class="op">)</span>; <span class="co">// ill-formed, deduction failure</span></span></code></pre></div>
<h2 id="declaring-packs-in-other-contexts"><span class="header-section-number">2.13</span> Declaring packs in other contexts<a href="#declaring-packs-in-other-contexts" class="self-link"></a></h2>
<p><span class="citation" data-cites="P0780R2">[<a href="#ref-P0780R2" role="doc-biblioref">P0780R2</a>]</span> allowed pack expansion in lambda init-capture:</p>
<div class="sourceCode" id="cb39"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb39-1"><a href="#cb39-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span><span class="op">...</span> T<span class="op">&gt;</span></span>
<span id="cb39-2"><a href="#cb39-2"></a><span class="dt">void</span> f<span class="op">(</span>T<span class="op">...</span> t<span class="op">)</span></span>
<span id="cb39-3"><a href="#cb39-3"></a><span class="op">{</span></span>
<span id="cb39-4"><a href="#cb39-4"></a>    <span class="op">[...</span>u<span class="op">=</span>t<span class="op">]{}</span>;</span>
<span id="cb39-5"><a href="#cb39-5"></a><span class="op">}</span></span></code></pre></div>
<p>If you think of lambda init-capture as basically a variable declaration with implicit <code class="sourceCode cpp"><span class="kw">auto</span></code>, then expanding out that capture gets us to a variable declaration pack:</p>
<div class="sourceCode" id="cb40"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb40-1"><a href="#cb40-1"></a><span class="kw">auto</span> <span class="op">...</span>u <span class="op">=</span> t;</span></code></pre></div>
<p>This paper proposes actually allowing that declaration form.</p>
<p>That is, a variable pack declaration takes as its initializer an unexpanded pack. Which could be a normal pack, or it could be a pack-like type with packness added to it:</p>
<div class="sourceCode" id="cb41"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb41-1"><a href="#cb41-1"></a>xstd<span class="op">::</span>tuple x<span class="op">{</span><span class="dv">1</span>, <span class="dv">2</span>, <span class="dv">3</span><span class="op">}</span>;</span>
<span id="cb41-2"><a href="#cb41-2"></a></span>
<span id="cb41-3"><a href="#cb41-3"></a><span class="co">// ill-formed, x is not an unexpanded pack</span></span>
<span id="cb41-4"><a href="#cb41-4"></a><span class="kw">auto</span> <span class="op">...</span>bad <span class="op">=</span> x;</span>
<span id="cb41-5"><a href="#cb41-5"></a></span>
<span id="cb41-6"><a href="#cb41-6"></a><span class="co">// proposed ok</span></span>
<span id="cb41-7"><a href="#cb41-7"></a><span class="kw">auto</span> <span class="op">...</span>good <span class="op">=</span> x<span class="op">.[:]</span>; <span class="co">// a pack of {1, 2, 3}</span></span>
<span id="cb41-8"><a href="#cb41-8"></a></span>
<span id="cb41-9"><a href="#cb41-9"></a><span class="co">// proposed ok</span></span>
<span id="cb41-10"><a href="#cb41-10"></a><span class="kw">auto</span> <span class="op">...</span>doubles <span class="op">=</span> x<span class="op">.[:]</span> <span class="op">*</span> <span class="dv">2</span>; <span class="co">// a pack of {2, 4, 6}</span></span></code></pre></div>
<p>The same idea can be used for declaring a pack alias (as was already shown earlier in this paper):</p>
<div class="sourceCode" id="cb42"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb42-1"><a href="#cb42-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span><span class="op">...</span> T<span class="op">&gt;</span></span>
<span id="cb42-2"><a href="#cb42-2"></a><span class="kw">struct</span> X <span class="op">{</span></span>
<span id="cb42-3"><a href="#cb42-3"></a>    <span class="co">// proposed ok</span></span>
<span id="cb42-4"><a href="#cb42-4"></a>    <span class="kw">using</span> <span class="op">...</span>pointers <span class="op">=</span> T<span class="op">*</span>;</span>
<span id="cb42-5"><a href="#cb42-5"></a><span class="op">}</span>;</span>
<span id="cb42-6"><a href="#cb42-6"></a></span>
<span id="cb42-7"><a href="#cb42-7"></a><span class="co">// ill-formed, not an unexpanded pack</span></span>
<span id="cb42-8"><a href="#cb42-8"></a><span class="kw">using</span> <span class="op">...</span>bad <span class="op">=</span> xstd<span class="op">::</span>tuple<span class="op">&lt;</span><span class="dt">int</span>, <span class="dt">double</span><span class="op">&gt;</span>;</span>
<span id="cb42-9"><a href="#cb42-9"></a></span>
<span id="cb42-10"><a href="#cb42-10"></a><span class="co">// proposed ok</span></span>
<span id="cb42-11"><a href="#cb42-11"></a><span class="kw">using</span> <span class="op">...</span>good <span class="op">=</span> xstd<span class="op">::</span>tuple<span class="op">&lt;</span><span class="dt">int</span>, <span class="dt">double</span><span class="op">&gt;.[:]</span>; <span class="co">// a pack of {int, double}</span></span></code></pre></div>
<h2 id="declaring-packs-from-a-braced-init-list"><span class="header-section-number">2.14</span> Declaring packs from a <em>braced-init-list</em><a href="#declaring-packs-from-a-braced-init-list" class="self-link"></a></h2>
<p>It may be worth generalizing even further and allowing declarations not just from unexpanded pack expressions but also from a <em>braced-init-list</em>. <span class="citation" data-cites="P0341R0">[<a href="#ref-P0341R0" role="doc-biblioref">P0341R0</a>]</span> presented something like this idea for variables, but instead used angle brackets for types. This paper proposed a <em>braced-init-list</em> for both cases, but with a slightly different formulation:</p>
<div class="sourceCode" id="cb43"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb43-1"><a href="#cb43-1"></a><span class="dt">int</span> <span class="op">...</span>squares <span class="op">=</span> <span class="op">{</span><span class="dv">1</span>, <span class="dv">4</span>, <span class="dv">9</span><span class="op">}</span>;</span>
<span id="cb43-2"><a href="#cb43-2"></a><span class="kw">using</span> <span class="op">...</span>types <span class="op">=</span> <span class="op">{</span><span class="dt">int</span>, <span class="dt">char</span>, <span class="dt">double</span><span class="op">}</span>;</span></code></pre></div>
<p>gcc already uses this notation in its compile errors:</p>
<div class="sourceCode" id="cb44"><pre class="sourceCode default"><code class="sourceCode default"><span id="cb44-1"><a href="#cb44-1"></a>In instantiation of &#39;void foo(T ...) [with T = {int, int, int}]&#39;:</span></code></pre></div>
<p>Such declarations would lead to the ability to provide default arguments for template parameter packs:</p>
<div class="sourceCode" id="cb45"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb45-1"><a href="#cb45-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span><span class="op">...</span> Ts <span class="op">=</span> <span class="op">{</span><span class="dt">int</span><span class="op">}&gt;</span></span>
<span id="cb45-2"><a href="#cb45-2"></a><span class="dt">void</span> f<span class="op">()</span>;</span>
<span id="cb45-3"><a href="#cb45-3"></a></span>
<span id="cb45-4"><a href="#cb45-4"></a>f<span class="op">()</span>; <span class="co">// calls f&lt;int&gt;</span></span></code></pre></div>
<p>And provides a direction for disambiguating expansion statements <span class="citation" data-cites="P1306R1">[<a href="#ref-P1306R1" role="doc-biblioref">P1306R1</a>]</span> over a pack:</p>
<div class="sourceCode" id="cb46"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb46-1"><a href="#cb46-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span><span class="op">...</span> Ts<span class="op">&gt;</span></span>
<span id="cb46-2"><a href="#cb46-2"></a><span class="dt">void</span> f<span class="op">(</span>Ts<span class="op">...</span> ts<span class="op">)</span></span>
<span id="cb46-3"><a href="#cb46-3"></a><span class="op">{</span></span>
<span id="cb46-4"><a href="#cb46-4"></a>    <span class="cf">for</span> <span class="op">...</span> <span class="op">(</span><span class="kw">auto</span> x <span class="op">:</span> <span class="op">{</span>ts<span class="op">...})</span></span>
<span id="cb46-5"><a href="#cb46-5"></a>    <span class="op">{</span></span>
<span id="cb46-6"><a href="#cb46-6"></a>    <span class="op">}</span></span>
<span id="cb46-7"><a href="#cb46-7"></a><span class="op">}</span></span></code></pre></div>
<p>The latter has some added wrinkles since you can already have a range-based for statement over a <em>braced-init-list</em> if it can be deduced to some <code class="sourceCode cpp">std<span class="op">::</span>initializer_list<span class="op">&lt;</span>T<span class="op">&gt;</span></code>, and we’d need a different declaration for the range (<code class="sourceCode cpp"><span class="kw">auto</span> <span class="op">...</span> range <span class="op">=</span> <span class="op">{</span>ts<span class="op">...}</span>;</code> vs <code class="sourceCode cpp"><span class="kw">auto</span> range <span class="op">=</span> <span class="op">{</span>ts<span class="op">...}</span>;</code>), but we <em>already</em> have a different declaration for the range in the <code class="sourceCode cpp"><span class="kw">constexpr</span></code> case, so what’s a third special case, really?</p>
<p>This does introduce some more added subtletly with initialization:</p>
<div class="sourceCode" id="cb47"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb47-1"><a href="#cb47-1"></a><span class="kw">auto</span>    a <span class="op">=</span> <span class="op">{</span><span class="dv">1</span>, <span class="dv">2</span>, <span class="dv">3</span><span class="op">}</span>; <span class="co">// a is a std::initializer_list&lt;int&gt;</span></span>
<span id="cb47-2"><a href="#cb47-2"></a><span class="kw">auto</span><span class="op">...</span> b <span class="op">=</span> <span class="op">{</span><span class="dv">1</span>, <span class="dv">2</span>, <span class="dv">3</span><span class="op">}</span>; <span class="co">// b is a pack of int&#39;s</span></span></code></pre></div>
<p>Those two declarations are very different. But also, they look very different - one has <code class="sourceCode cpp"><span class="op">...</span></code> and the other does not. One looks like it is declaring an object and the other looks like it is declaring a pack. This doesn’t seem inherently problematic.</p>
<h2 id="generalized-slicing-and-a-simplified-boost.mp11"><span class="header-section-number">2.15</span> Generalized Slicing and a simplified Boost.Mp11<a href="#generalized-slicing-and-a-simplified-boost.mp11" class="self-link"></a></h2>
<p>This paper proposes <code class="sourceCode cpp">T<span class="op">.[:]</span></code> to be a sigil to add packness. This also allows for more fine-grained control over which part of the pack is referenced.</p>
<p>Similar to Python’s syntax for slicing, this paper proposes to provide indexes on one side or the other of the <code class="sourceCode cpp"><span class="op">:</span></code> to take just parts of the pack. For instance, <code class="sourceCode cpp">T<span class="op">.[</span><span class="dv">1</span><span class="op">:]</span></code> is all but the first element of the pack. <code class="sourceCode cpp">T<span class="op">.[:-</span><span class="dv">1</span><span class="op">]</span></code> is all but the last element of the pack. <code class="sourceCode cpp">T<span class="op">.[</span><span class="dv">2</span><span class="op">:</span><span class="dv">3</span><span class="op">]</span></code> is a pack consisting only of the third element.</p>
<p>Such a feature would provide an easy way to write a <code class="sourceCode cpp">std<span class="op">::</span>visit</code> that takes the variants first and the function last:</p>
<div class="sourceCode" id="cb48"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb48-1"><a href="#cb48-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span><span class="op">...</span> Args<span class="op">&gt;</span></span>
<span id="cb48-2"><a href="#cb48-2"></a><span class="kw">constexpr</span> <span class="kw">decltype</span><span class="op">(</span><span class="kw">auto</span><span class="op">)</span> better_visit<span class="op">(</span>Args<span class="op">&amp;&amp;...</span> args<span class="op">)</span> <span class="op">{</span></span>
<span id="cb48-3"><a href="#cb48-3"></a>    <span class="cf">return</span> std<span class="op">::</span>visit<span class="op">(</span></span>
<span id="cb48-4"><a href="#cb48-4"></a>        <span class="co">// the function first</span></span>
<span id="cb48-5"><a href="#cb48-5"></a>        std<span class="op">::</span>forward<span class="op">&lt;</span>Args<span class="op">...[-</span><span class="dv">1</span><span class="op">]&gt;(</span>args<span class="op">...[-</span><span class="dv">1</span><span class="op">])</span>,</span>
<span id="cb48-6"><a href="#cb48-6"></a>        <span class="co">// all the variants next</span></span>
<span id="cb48-7"><a href="#cb48-7"></a>        <span class="co">// note that both slices on both Args and args are necessary, otherwise</span></span>
<span id="cb48-8"><a href="#cb48-8"></a>        <span class="co">// we end up with two packs of different sizes that need to get expanded</span></span>
<span id="cb48-9"><a href="#cb48-9"></a>        std<span class="op">::</span>forward<span class="op">&lt;</span>Args<span class="op">...[:-</span><span class="dv">1</span><span class="op">]&gt;(</span>args<span class="op">...[:-</span><span class="dv">1</span><span class="op">])...)</span>;</span>
<span id="cb48-10"><a href="#cb48-10"></a><span class="op">}</span></span></code></pre></div>
<p>Recall that since <code class="sourceCode cpp">Args</code> is a pack already, we index into it with <code class="sourceCode cpp">Args<span class="op">...[</span>I<span class="op">]</span></code> rather than <code class="sourceCode cpp">Args<span class="op">.[</span>I<span class="op">]</span></code> (which would index into each pack-like type of <code class="sourceCode cpp">Args</code>).</p>
<p>It would also allow for a single-overload variadic fold:</p>
<div class="sourceCode" id="cb49"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb49-1"><a href="#cb49-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> F, <span class="kw">typename</span> Z, <span class="kw">typename</span><span class="op">...</span> Ts<span class="op">&gt;</span></span>
<span id="cb49-2"><a href="#cb49-2"></a><span class="kw">constexpr</span> Z fold<span class="op">(</span>F f, Z z, Ts<span class="op">...</span> rest<span class="op">)</span></span>
<span id="cb49-3"><a href="#cb49-3"></a><span class="op">{</span></span>
<span id="cb49-4"><a href="#cb49-4"></a>    <span class="cf">if</span> <span class="kw">constexpr</span> <span class="op">(</span><span class="kw">sizeof</span><span class="op">...(</span>rest<span class="op">)</span> <span class="op">==</span> <span class="dv">0</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb49-5"><a href="#cb49-5"></a>        <span class="cf">return</span> z;</span>
<span id="cb49-6"><a href="#cb49-6"></a>    <span class="op">}</span> <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb49-7"><a href="#cb49-7"></a>        <span class="co">// we need to invoke f on z and the first elem in rest...</span></span>
<span id="cb49-8"><a href="#cb49-8"></a>        <span class="co">// and recurse, passing the rest of rest...</span></span>
<span id="cb49-9"><a href="#cb49-9"></a>        <span class="cf">return</span> fold<span class="op">(</span>f,</span>
<span id="cb49-10"><a href="#cb49-10"></a>            f<span class="op">(</span>z, rest<span class="op">...[</span><span class="dv">0</span><span class="op">])</span>,</span>
<span id="cb49-11"><a href="#cb49-11"></a>            rest<span class="op">...[</span><span class="dv">1</span><span class="op">:]...)</span>;</span>
<span id="cb49-12"><a href="#cb49-12"></a></span>
<span id="cb49-13"><a href="#cb49-13"></a>        <span class="co">// alternate formulation</span></span>
<span id="cb49-14"><a href="#cb49-14"></a>        <span class="kw">auto</span> head <span class="op">=</span> rest<span class="op">...[</span><span class="dv">0</span><span class="op">]</span>;</span>
<span id="cb49-15"><a href="#cb49-15"></a>        <span class="kw">auto</span> <span class="op">...</span>tail <span class="op">=</span> rest<span class="op">...[</span><span class="dv">1</span><span class="op">:]</span>;</span>
<span id="cb49-16"><a href="#cb49-16"></a>        <span class="cf">return</span> fold<span class="op">(</span>f, f<span class="op">(</span>z, head<span class="op">)</span>, tail<span class="op">...)</span>;</span>
<span id="cb49-17"><a href="#cb49-17"></a>    <span class="op">}</span></span>
<span id="cb49-18"><a href="#cb49-18"></a><span class="op">}</span></span></code></pre></div>
<h3 id="min"><span class="header-section-number">2.15.1</span> Min<a href="#min" class="self-link"></a></h3>
<p>Andrew Sutton in a CppCon 2019 talk <span class="citation" data-cites="Sutton">[<a href="#ref-Sutton" role="doc-biblioref">Sutton</a>]</span> showed an example using an expansion statement to find the mininum of a pack. This paper allows for a more direct implementation:</p>
<table>
<thead>
<tr class="header">
<th><div style="text-align:center">
<strong>Sutton</strong>
</div></th>
<th><div style="text-align:center">
<strong>This proposal</strong>
</div></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><div class="sourceCode" id="cb50"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb50-1"><a href="#cb50-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span><span class="op">...</span> Ts<span class="op">&gt;</span></span>
<span id="cb50-2"><a href="#cb50-2"></a><span class="kw">auto</span> min_arg<span class="op">(</span>Ts<span class="op">...</span> args<span class="op">)</span> <span class="op">{</span></span>
<span id="cb50-3"><a href="#cb50-3"></a>    <span class="kw">auto</span> min <span class="op">=</span> head<span class="op">(</span>args<span class="op">...)</span>;</span>
<span id="cb50-4"><a href="#cb50-4"></a>    <span class="kw">template</span> <span class="cf">for</span> <span class="op">(</span><span class="kw">auto</span> x <span class="op">:</span> tail<span class="op">(</span>args<span class="op">...))</span> <span class="op">{</span></span>
<span id="cb50-5"><a href="#cb50-5"></a>        <span class="cf">if</span> <span class="op">(</span>x <span class="op">&lt;</span> min<span class="op">)</span> <span class="op">{</span></span>
<span id="cb50-6"><a href="#cb50-6"></a>            min <span class="op">=</span> x;</span>
<span id="cb50-7"><a href="#cb50-7"></a>        <span class="op">}</span></span>
<span id="cb50-8"><a href="#cb50-8"></a>    <span class="op">}</span></span>
<span id="cb50-9"><a href="#cb50-9"></a>    <span class="cf">return</span> min;</span>
<span id="cb50-10"><a href="#cb50-10"></a><span class="op">}</span></span></code></pre></div></td>
<td><div class="sourceCode" id="cb51"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb51-1"><a href="#cb51-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span><span class="op">...</span> Ts<span class="op">&gt;</span></span>
<span id="cb51-2"><a href="#cb51-2"></a><span class="kw">auto</span> min_arg<span class="op">(</span>Ts<span class="op">...</span> args<span class="op">)</span> <span class="op">{</span></span>
<span id="cb51-3"><a href="#cb51-3"></a>    <span class="kw">auto</span> min <span class="op">=</span> args<span class="op">...[</span><span class="dv">0</span><span class="op">]</span>;</span>
<span id="cb51-4"><a href="#cb51-4"></a>    <span class="kw">template</span> <span class="cf">for</span> <span class="op">(</span><span class="kw">auto</span> x <span class="op">:</span> <span class="op">{</span>args<span class="op">.[</span><span class="dv">1</span><span class="op">:]...})</span> <span class="op">{</span></span>
<span id="cb51-5"><a href="#cb51-5"></a>        <span class="cf">if</span> <span class="op">(</span>x <span class="op">&lt;</span> min<span class="op">)</span> <span class="op">{</span></span>
<span id="cb51-6"><a href="#cb51-6"></a>            min <span class="op">=</span> x;</span>
<span id="cb51-7"><a href="#cb51-7"></a>        <span class="op">}</span></span>
<span id="cb51-8"><a href="#cb51-8"></a>    <span class="op">}</span></span>
<span id="cb51-9"><a href="#cb51-9"></a>    <span class="cf">return</span> min;</span>
<span id="cb51-10"><a href="#cb51-10"></a><span class="op">}</span></span></code></pre></div></td>
</tr>
</tbody>
</table>
<p>Looks basically the same. It’s just that there are no added <code class="sourceCode cpp">head</code> and <code class="sourceCode cpp">tail</code> function templates to instantiate, the latter of which has to return some kind of <code class="sourceCode cpp">tuple</code>.</p>
<h3 id="boost.mp11"><span class="header-section-number">2.15.2</span> Boost.Mp11<a href="#boost.mp11" class="self-link"></a></h3>
<p>Boost.Mp11 works by treating any variadic class template as a type list and providing operations that just work. A common pattern in the implementation of many of the metafunctions is to indirect to a class template specialization to do the pattern matching on the pack. This paper provides a more direct way to implement many of the facilities.</p>
<p>We just need one helper that we will reuse every time (as opposed to each metafunction needing its own helper):</p>
<div class="sourceCode" id="cb52"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb52-1"><a href="#cb52-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> L<span class="op">&gt;</span> <span class="kw">struct</span> pack_impl;</span>
<span id="cb52-2"><a href="#cb52-2"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span><span class="op">...&gt;</span> <span class="kw">class</span> L, <span class="kw">class</span><span class="op">...</span> Ts<span class="op">&gt;</span></span>
<span id="cb52-3"><a href="#cb52-3"></a><span class="kw">struct</span> pack_impl<span class="op">&lt;</span>L<span class="op">&lt;</span>Ts<span class="op">...&gt;&gt;</span> <span class="op">{</span></span>
<span id="cb52-4"><a href="#cb52-4"></a>    <span class="co">// a pack alias for the template arguments</span></span>
<span id="cb52-5"><a href="#cb52-5"></a>    <span class="kw">using</span> <span class="op">...</span> <span class="op">=</span> Ts;</span>
<span id="cb52-6"><a href="#cb52-6"></a>    </span>
<span id="cb52-7"><a href="#cb52-7"></a>    <span class="co">// an alias template for the class template itself</span></span>
<span id="cb52-8"><a href="#cb52-8"></a>    <span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span><span class="op">...</span> Us<span class="op">&gt;</span> <span class="kw">using</span> apply <span class="op">=</span> L<span class="op">&lt;</span>Us<span class="op">...&gt;</span>;</span>
<span id="cb52-9"><a href="#cb52-9"></a><span class="op">}</span>;</span>
<span id="cb52-10"><a href="#cb52-10"></a></span>
<span id="cb52-11"><a href="#cb52-11"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> L, <span class="kw">class</span><span class="op">...</span> Us<span class="op">&gt;</span></span>
<span id="cb52-12"><a href="#cb52-12"></a><span class="kw">using</span> apply_pack_impl <span class="op">=</span> <span class="kw">typename</span> pack_impl<span class="op">&lt;</span>L<span class="op">&gt;::</span><span class="kw">template</span> apply<span class="op">&lt;</span>Us<span class="op">...&gt;</span>;</span></code></pre></div>
<table>
<thead>
<tr class="header">
<th><div style="text-align:center">
<strong>Boost.Mp11</strong>
</div></th>
<th><div style="text-align:center">
<strong>This proposal</strong>
</div></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><div class="sourceCode" id="cb53"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb53-1"><a href="#cb53-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> L<span class="op">&gt;</span> <span class="kw">struct</span> mp_front_impl;</span>
<span id="cb53-2"><a href="#cb53-2"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span><span class="op">...&gt;</span> <span class="kw">class</span> L, <span class="kw">class</span> T, <span class="kw">class</span><span class="op">...</span> Ts<span class="op">&gt;</span></span>
<span id="cb53-3"><a href="#cb53-3"></a><span class="kw">struct</span> mp_front_impl<span class="op">&lt;</span>L<span class="op">&lt;</span>T, Ts<span class="op">...&gt;&gt;</span> <span class="op">{</span></span>
<span id="cb53-4"><a href="#cb53-4"></a>    <span class="kw">using</span> type <span class="op">=</span> T;</span>
<span id="cb53-5"><a href="#cb53-5"></a><span class="op">}</span>;</span>
<span id="cb53-6"><a href="#cb53-6"></a></span>
<span id="cb53-7"><a href="#cb53-7"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> L<span class="op">&gt;</span></span>
<span id="cb53-8"><a href="#cb53-8"></a><span class="kw">using</span> mp_front <span class="op">=</span> <span class="kw">typename</span> mp_front_impl<span class="op">&lt;</span>L<span class="op">&gt;::</span>type;</span></code></pre></div></td>
<td><div class="sourceCode" id="cb54"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb54-1"><a href="#cb54-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> L<span class="op">&gt;</span></span>
<span id="cb54-2"><a href="#cb54-2"></a><span class="kw">using</span> mp_front <span class="op">=</span> pack_impl<span class="op">&lt;</span>L<span class="op">&gt;.[</span><span class="dv">0</span><span class="op">]</span>;</span></code></pre></div></td>
</tr>
<tr class="even">
<td><div class="sourceCode" id="cb55"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb55-1"><a href="#cb55-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> L<span class="op">&gt;</span> <span class="kw">struct</span> mp_pop_front_impl;</span>
<span id="cb55-2"><a href="#cb55-2"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span><span class="op">...&gt;</span> <span class="kw">class</span> L, <span class="kw">class</span> T, <span class="kw">class</span><span class="op">...</span> Ts<span class="op">&gt;</span></span>
<span id="cb55-3"><a href="#cb55-3"></a><span class="kw">struct</span> mp_pop_front_impl<span class="op">&lt;</span>L<span class="op">&lt;</span>T, Ts<span class="op">...&gt;&gt;</span> <span class="op">{</span></span>
<span id="cb55-4"><a href="#cb55-4"></a>    <span class="kw">using</span> type <span class="op">=</span> T;</span>
<span id="cb55-5"><a href="#cb55-5"></a><span class="op">}</span>;</span>
<span id="cb55-6"><a href="#cb55-6"></a></span>
<span id="cb55-7"><a href="#cb55-7"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> L<span class="op">&gt;</span></span>
<span id="cb55-8"><a href="#cb55-8"></a><span class="kw">using</span> mp_pop_front <span class="op">=</span> <span class="kw">typename</span> mp_pop_front_impl<span class="op">&lt;</span>L<span class="op">&gt;::</span>type;</span></code></pre></div></td>
<td><div class="sourceCode" id="cb56"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb56-1"><a href="#cb56-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> L<span class="op">&gt;</span></span>
<span id="cb56-2"><a href="#cb56-2"></a><span class="kw">using</span> mp_pop_front <span class="op">=</span> apply_pack_impl<span class="op">&lt;</span></span>
<span id="cb56-3"><a href="#cb56-3"></a>    L, pack_impl<span class="op">&lt;</span>L<span class="op">&gt;.[</span><span class="dv">1</span><span class="op">:]...&gt;</span>;</span></code></pre></div></td>
</tr>
<tr class="odd">
<td><div class="sourceCode" id="cb57"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb57-1"><a href="#cb57-1"></a><span class="co">// you get the idea</span></span>
<span id="cb57-2"><a href="#cb57-2"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> L<span class="op">&gt;</span></span>
<span id="cb57-3"><a href="#cb57-3"></a><span class="kw">using</span> mp_second <span class="op">=</span> <span class="co">/* ... */</span>;</span>
<span id="cb57-4"><a href="#cb57-4"></a></span>
<span id="cb57-5"><a href="#cb57-5"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> L<span class="op">&gt;</span></span>
<span id="cb57-6"><a href="#cb57-6"></a><span class="kw">using</span> mp_third <span class="op">=</span> <span class="co">/* ... */</span>;</span>
<span id="cb57-7"><a href="#cb57-7"></a></span>
<span id="cb57-8"><a href="#cb57-8"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> L, <span class="kw">class</span><span class="op">...</span> Ts<span class="op">&gt;</span></span>
<span id="cb57-9"><a href="#cb57-9"></a><span class="kw">using</span> mp_push_front <span class="op">=</span> <span class="co">/* ... */</span>;</span>
<span id="cb57-10"><a href="#cb57-10"></a></span>
<span id="cb57-11"><a href="#cb57-11"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> L, <span class="kw">class</span><span class="op">...</span> Ts<span class="op">&gt;</span></span>
<span id="cb57-12"><a href="#cb57-12"></a><span class="kw">using</span> mp_push_back <span class="op">=</span> <span class="co">/* ... */</span>;</span>
<span id="cb57-13"><a href="#cb57-13"></a></span>
<span id="cb57-14"><a href="#cb57-14"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> L, <span class="kw">class</span> T<span class="op">&gt;</span></span>
<span id="cb57-15"><a href="#cb57-15"></a><span class="kw">using</span> mp_replace_front <span class="op">=</span> <span class="co">/* ... */</span>;</span>
<span id="cb57-16"><a href="#cb57-16"></a></span>
<span id="cb57-17"><a href="#cb57-17"></a><span class="co">// ...</span></span></code></pre></div></td>
<td><div class="sourceCode" id="cb58"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb58-1"><a href="#cb58-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> L<span class="op">&gt;</span></span>
<span id="cb58-2"><a href="#cb58-2"></a><span class="kw">using</span> mp_second <span class="op">=</span> pack_impl<span class="op">&lt;</span>L<span class="op">&gt;.[</span><span class="dv">1</span><span class="op">]</span>;</span>
<span id="cb58-3"><a href="#cb58-3"></a></span>
<span id="cb58-4"><a href="#cb58-4"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> L<span class="op">&gt;</span></span>
<span id="cb58-5"><a href="#cb58-5"></a><span class="kw">using</span> mp_third <span class="op">=</span> pack_impl<span class="op">&lt;</span>L<span class="op">&gt;.[</span><span class="dv">2</span><span class="op">]</span>;</span>
<span id="cb58-6"><a href="#cb58-6"></a></span>
<span id="cb58-7"><a href="#cb58-7"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> L, <span class="kw">class</span><span class="op">...</span> Ts<span class="op">&gt;</span></span>
<span id="cb58-8"><a href="#cb58-8"></a><span class="kw">using</span> mp_push_front <span class="op">=</span> apply_pack_impl<span class="op">&lt;</span></span>
<span id="cb58-9"><a href="#cb58-9"></a>    L, Ts<span class="op">...</span>, pack_impl<span class="op">&lt;</span>L<span class="op">&gt;.[:]...&gt;</span>;</span>
<span id="cb58-10"><a href="#cb58-10"></a></span>
<span id="cb58-11"><a href="#cb58-11"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> L, <span class="kw">class</span><span class="op">...</span> Ts<span class="op">&gt;</span></span>
<span id="cb58-12"><a href="#cb58-12"></a><span class="kw">using</span> mp_push_back <span class="op">=</span> apply_pack_impl<span class="op">&lt;</span></span>
<span id="cb58-13"><a href="#cb58-13"></a>    L, pack_impl<span class="op">&lt;</span>L<span class="op">&gt;.[:]...</span>, Ts<span class="op">...&gt;</span>;</span>
<span id="cb58-14"><a href="#cb58-14"></a></span>
<span id="cb58-15"><a href="#cb58-15"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> L, <span class="kw">class</span> T<span class="op">&gt;</span></span>
<span id="cb58-16"><a href="#cb58-16"></a><span class="kw">using</span> mp_replace_front <span class="op">=</span> apply_pack_impl<span class="op">&lt;</span></span>
<span id="cb58-17"><a href="#cb58-17"></a>    L, T, pack_impl<span class="op">&lt;</span>L<span class="op">&gt;.[</span><span class="dv">1</span><span class="op">:]...&gt;</span>;</span></code></pre></div></td>
</tr>
</tbody>
</table>
<h2 id="implementing-variant"><span class="header-section-number">2.16</span> Implementing variant<a href="#implementing-variant" class="self-link"></a></h2>
<p>While most of this paper has dealt specifically with making a better <code class="sourceCode cpp">tuple</code>, the features proposed in this paper would also make it much easier to implement <code class="sourceCode cpp">variant</code> as well. One of the difficulties with <code class="sourceCode cpp">variant</code> implementions is that you need to have a <code class="sourceCode cpp"><span class="kw">union</span></code>. With this proposal, we can declare a variant pack too.</p>
<p>Here are some parts of a variant implementation, to demonstrate what that might look like. Still need <em>some</em> metaprogramming facilities, but it’s certainly a a lot easier.</p>
<div class="sourceCode" id="cb59"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb59-1"><a href="#cb59-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span><span class="op">...</span> Ts<span class="op">&gt;</span></span>
<span id="cb59-2"><a href="#cb59-2"></a><span class="kw">class</span> variant <span class="op">{</span></span>
<span id="cb59-3"><a href="#cb59-3"></a>    <span class="dt">int</span> index_;</span>
<span id="cb59-4"><a href="#cb59-4"></a>    <span class="kw">union</span> <span class="op">{</span></span>
<span id="cb59-5"><a href="#cb59-5"></a>        Ts<span class="op">...</span> alts_;</span>
<span id="cb59-6"><a href="#cb59-6"></a>    <span class="op">}</span>;</span>
<span id="cb59-7"><a href="#cb59-7"></a><span class="kw">public</span><span class="op">:</span></span>
<span id="cb59-8"><a href="#cb59-8"></a>    <span class="kw">constexpr</span> variant<span class="op">()</span> <span class="kw">requires</span> std<span class="op">::</span>default_constructible<span class="op">&lt;</span>Ts<span class="op">...[</span><span class="dv">0</span><span class="op">]&gt;</span></span>
<span id="cb59-9"><a href="#cb59-9"></a>      <span class="op">:</span> index_<span class="op">(</span><span class="dv">0</span><span class="op">)</span></span>
<span id="cb59-10"><a href="#cb59-10"></a>      , alts_<span class="op">...[</span><span class="dv">0</span><span class="op">]()</span></span>
<span id="cb59-11"><a href="#cb59-11"></a>    <span class="op">{</span> <span class="op">}</span></span>
<span id="cb59-12"><a href="#cb59-12"></a></span>
<span id="cb59-13"><a href="#cb59-13"></a>    <span class="op">~</span>variant<span class="op">()</span> <span class="kw">requires</span> <span class="op">(</span>std<span class="op">::</span>is_trivially_destructible<span class="op">&lt;</span>Ts<span class="op">&gt;</span> <span class="op">&amp;&amp;</span> <span class="op">...)</span> <span class="op">=</span> <span class="cf">default</span>;</span>
<span id="cb59-14"><a href="#cb59-14"></a>    <span class="op">~</span>variant<span class="op">()</span> <span class="op">{</span></span>
<span id="cb59-15"><a href="#cb59-15"></a>        mp_with_index<span class="op">&lt;</span><span class="kw">sizeof</span><span class="op">...(</span>Ts<span class="op">)&gt;(</span>index_,</span>
<span id="cb59-16"><a href="#cb59-16"></a>            <span class="op">[](</span><span class="kw">auto</span> I<span class="op">){</span> destroy_at<span class="op">(&amp;</span>alts_<span class="op">...[</span>I<span class="op">])</span>; <span class="op">})</span>;</span>
<span id="cb59-17"><a href="#cb59-17"></a>    <span class="op">}</span></span>
<span id="cb59-18"><a href="#cb59-18"></a><span class="op">}</span>;</span>
<span id="cb59-19"><a href="#cb59-19"></a></span>
<span id="cb59-20"><a href="#cb59-20"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="dt">size_t</span> I, <span class="kw">typename</span> T<span class="op">&gt;</span></span>
<span id="cb59-21"><a href="#cb59-21"></a><span class="kw">struct</span> variant_alternative;</span>
<span id="cb59-22"><a href="#cb59-22"></a></span>
<span id="cb59-23"><a href="#cb59-23"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="dt">size_t</span> I, <span class="kw">typename</span><span class="op">...</span> Ts<span class="op">&gt;</span></span>
<span id="cb59-24"><a href="#cb59-24"></a>    <span class="kw">requires</span> <span class="op">(</span>I <span class="op">&lt;</span> <span class="kw">sizeof</span><span class="op">...(</span>Ts<span class="op">))</span></span>
<span id="cb59-25"><a href="#cb59-25"></a><span class="kw">struct</span> variant_alternative<span class="op">&lt;</span>I, variant<span class="op">&lt;</span>Ts<span class="op">...&gt;&gt;</span> <span class="op">{</span></span>
<span id="cb59-26"><a href="#cb59-26"></a>    <span class="kw">using</span> type <span class="op">=</span> Ts<span class="op">...[</span>I<span class="op">]</span>;</span>
<span id="cb59-27"><a href="#cb59-27"></a><span class="op">}</span>;</span>
<span id="cb59-28"><a href="#cb59-28"></a></span>
<span id="cb59-29"><a href="#cb59-29"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="dt">size_t</span> I, <span class="kw">typename</span><span class="op">...</span> Types<span class="op">&gt;</span></span>
<span id="cb59-30"><a href="#cb59-30"></a><span class="kw">constexpr</span> variant_alternative_t<span class="op">&lt;</span>I, variant<span class="op">&lt;</span>Types<span class="op">...&gt;&gt;*</span></span>
<span id="cb59-31"><a href="#cb59-31"></a>get_if<span class="op">(</span>variant<span class="op">&lt;</span>Types<span class="op">...&gt;*</span> v<span class="op">)</span> <span class="kw">noexcept</span> <span class="op">{</span></span>
<span id="cb59-32"><a href="#cb59-32"></a>    <span class="cf">if</span> <span class="op">(</span>v<span class="op">.</span>index_ <span class="op">==</span> I<span class="op">)</span> <span class="op">{</span></span>
<span id="cb59-33"><a href="#cb59-33"></a>        <span class="cf">return</span> <span class="op">&amp;</span>v<span class="op">.</span>alts_<span class="op">...[</span>I<span class="op">]</span>;</span>
<span id="cb59-34"><a href="#cb59-34"></a>    <span class="op">}</span> <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb59-35"><a href="#cb59-35"></a>        <span class="cf">return</span> <span class="kw">nullptr</span>;</span>
<span id="cb59-36"><a href="#cb59-36"></a>    <span class="op">}</span></span>
<span id="cb59-37"><a href="#cb59-37"></a><span class="op">}</span></span></code></pre></div>
<p>Directly indexing into the union variant members makes the implementation much easier to write and read. Not needing a recursive union template is a nice bonus.</p>
<h2 id="enumerating-over-a-pack"><span class="header-section-number">2.17</span> Enumerating over a pack<a href="#enumerating-over-a-pack" class="self-link"></a></h2>
<p>As another example, let’s say we want to take a parameter pack and print its contents along with an index. Here are some ways we could do that with this proposal (assuming expansion statements):</p>
<div class="sourceCode" id="cb60"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb60-1"><a href="#cb60-1"></a><span class="co">// iterate over the indices, and index into the pack</span></span>
<span id="cb60-2"><a href="#cb60-2"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span><span class="op">...</span> Ts<span class="op">&gt;</span></span>
<span id="cb60-3"><a href="#cb60-3"></a><span class="dt">void</span> enumerate1<span class="op">(</span>Ts<span class="op">...</span> ts<span class="op">)</span></span>
<span id="cb60-4"><a href="#cb60-4"></a><span class="op">{</span></span>
<span id="cb60-5"><a href="#cb60-5"></a>    <span class="cf">for</span> <span class="op">...</span> <span class="op">(</span><span class="kw">constexpr</span> <span class="kw">auto</span> I <span class="op">:</span> view<span class="op">::</span>iota<span class="op">(</span><span class="dv">0</span><span class="bu">u</span>, <span class="kw">sizeof</span><span class="op">...(</span>Ts<span class="op">)))</span> <span class="op">{</span></span>
<span id="cb60-6"><a href="#cb60-6"></a>        cout <span class="op">&lt;&lt;</span> I <span class="op">&lt;&lt;</span> <span class="ch">&#39; &#39;</span> <span class="op">&lt;&lt;</span> ts<span class="op">...[</span>I<span class="op">]</span> <span class="op">&lt;&lt;</span> <span class="ch">&#39;</span><span class="sc">\n</span><span class="ch">&#39;</span>;</span>
<span id="cb60-7"><a href="#cb60-7"></a>    <span class="op">}</span></span>
<span id="cb60-8"><a href="#cb60-8"></a><span class="op">}</span></span>
<span id="cb60-9"><a href="#cb60-9"></a></span>
<span id="cb60-10"><a href="#cb60-10"></a><span class="co">// construct a new pack of tuples</span></span>
<span id="cb60-11"><a href="#cb60-11"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span><span class="op">...</span> Ts<span class="op">&gt;</span></span>
<span id="cb60-12"><a href="#cb60-12"></a><span class="dt">void</span> enumerate2<span class="op">(</span>Ts<span class="op">...</span> ts<span class="op">)</span></span>
<span id="cb60-13"><a href="#cb60-13"></a><span class="op">{</span></span>
<span id="cb60-14"><a href="#cb60-14"></a>    <span class="kw">constexpr</span> <span class="kw">auto</span> indices <span class="op">=</span> view<span class="op">::</span>iota<span class="op">(</span><span class="dv">0</span><span class="bu">u</span>, <span class="kw">sizeof</span><span class="op">...(</span>Ts<span class="op">))</span>;</span>
<span id="cb60-15"><a href="#cb60-15"></a>    <span class="kw">auto</span> enumerated <span class="op">=</span> tuple<span class="op">{</span>tuple<span class="op">{</span>indices<span class="op">.[:]</span>, ts<span class="op">}...}</span>;</span>
<span id="cb60-16"><a href="#cb60-16"></a>    <span class="cf">for</span> <span class="op">...</span> <span class="op">(</span><span class="kw">auto</span> <span class="op">[</span>i, t<span class="op">]</span> <span class="op">:</span> enumerated<span class="op">)</span> <span class="op">{</span></span>
<span id="cb60-17"><a href="#cb60-17"></a>        cout <span class="op">&lt;&lt;</span> i <span class="op">&lt;&lt;</span> <span class="ch">&#39; &#39;</span> <span class="op">&lt;&lt;</span> t <span class="op">&lt;&lt;</span> <span class="ch">&#39;</span><span class="sc">\n</span><span class="ch">&#39;</span>;</span>
<span id="cb60-18"><a href="#cb60-18"></a>    <span class="op">}</span></span>
<span id="cb60-19"><a href="#cb60-19"></a><span class="op">}</span></span></code></pre></div>
<h2 id="what-about-reflection"><span class="header-section-number">2.18</span> What about Reflection?<a href="#what-about-reflection" class="self-link"></a></h2>
<p>Two recent reflection papers (<span class="citation" data-cites="P1240R0">[<a href="#ref-P1240R0" role="doc-biblioref">P1240R0</a>]</span> and <span class="citation" data-cites="P1717R0">[<a href="#ref-P1717R0" role="doc-biblioref">P1717R0</a>]</span>) provide solutions for some of the problems this paper is attempting to solve. What follows is my best attempt to compare the reflection solutions to the generalized pack solutions presented here. I am not entirely sure about the examples on the left, but hopefully they are at least close enough to correct to be able to evaluate the differences.</p>
<table>
<thead>
<tr class="header">
<th><div style="text-align:center">
<strong>Reflection</strong>
</div></th>
<th><div style="text-align:center">
<strong>This proposal</strong>
</div></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><div class="sourceCode" id="cb61"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb61-1"><a href="#cb61-1"></a><span class="co">// member pack declaration (P1717)</span></span>
<span id="cb61-2"><a href="#cb61-2"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span><span class="op">...</span> Types<span class="op">&gt;</span></span>
<span id="cb61-3"><a href="#cb61-3"></a><span class="kw">class</span> tuple <span class="op">{</span></span>
<span id="cb61-4"><a href="#cb61-4"></a>  <span class="kw">consteval</span> <span class="op">{</span></span>
<span id="cb61-5"><a href="#cb61-5"></a>    <span class="dt">int</span> counter <span class="op">=</span> <span class="dv">0</span>;</span>
<span id="cb61-6"><a href="#cb61-6"></a>    <span class="cf">for</span><span class="op">...</span> <span class="op">(</span>meta<span class="op">::</span>info type <span class="op">:</span> <span class="kw">reflexpr</span><span class="op">(</span>Types<span class="op">))</span> <span class="op">{</span></span>
<span id="cb61-7"><a href="#cb61-7"></a>      <span class="kw">auto</span> fragment <span class="op">=</span> __fragment <span class="kw">struct</span> <span class="op">{</span></span>
<span id="cb61-8"><a href="#cb61-8"></a>        <span class="kw">typename</span><span class="op">(</span>type<span class="op">)</span> unqualid<span class="op">(</span><span class="st">&quot;element_&quot;</span>, counter<span class="op">)</span>;</span>
<span id="cb61-9"><a href="#cb61-9"></a>      <span class="op">}</span>;</span>
<span id="cb61-10"><a href="#cb61-10"></a>      <span class="op">-&gt;</span> fragment;</span>
<span id="cb61-11"><a href="#cb61-11"></a>      <span class="op">++</span>counter;</span>
<span id="cb61-12"><a href="#cb61-12"></a>    <span class="op">}</span></span>
<span id="cb61-13"><a href="#cb61-13"></a>  <span class="op">}</span></span>
<span id="cb61-14"><a href="#cb61-14"></a><span class="op">}</span>;</span></code></pre></div></td>
<td><div class="sourceCode" id="cb62"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb62-1"><a href="#cb62-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span><span class="op">...</span> Types<span class="op">&gt;</span></span>
<span id="cb62-2"><a href="#cb62-2"></a><span class="kw">class</span> tuple <span class="op">{</span></span>
<span id="cb62-3"><a href="#cb62-3"></a>  Types<span class="op">...</span> element;</span>
<span id="cb62-4"><a href="#cb62-4"></a><span class="op">}</span>;</span></code></pre></div></td>
</tr>
<tr class="even">
<td><div class="sourceCode" id="cb63"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb63-1"><a href="#cb63-1"></a><span class="co">// pack indexing (P1240)</span></span>
<span id="cb63-2"><a href="#cb63-2"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="dt">size_t</span> I, <span class="kw">typename</span><span class="op">...</span> Ts<span class="op">&gt;</span></span>
<span id="cb63-3"><a href="#cb63-3"></a><span class="kw">using</span> at <span class="op">=</span> <span class="kw">typename</span><span class="op">(</span>std<span class="op">::</span>vector<span class="op">{</span><span class="kw">reflexpr</span><span class="op">(</span>Ts<span class="op">)...}[</span>I<span class="op">])</span>;</span></code></pre></div></td>
<td><div class="sourceCode" id="cb64"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb64-1"><a href="#cb64-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="dt">size_t</span> I, <span class="kw">typename</span><span class="op">...</span> Ts<span class="op">&gt;</span></span>
<span id="cb64-2"><a href="#cb64-2"></a><span class="kw">using</span> at <span class="op">=</span> Ts<span class="op">...[</span>I<span class="op">]</span>;</span></code></pre></div></td>
</tr>
<tr class="odd">
<td><div class="sourceCode" id="cb65"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb65-1"><a href="#cb65-1"></a><span class="co">// generalized pack indexing (P1240)</span></span>
<span id="cb65-2"><a href="#cb65-2"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span><span class="op">...</span> Types<span class="op">&gt;</span></span>
<span id="cb65-3"><a href="#cb65-3"></a><span class="kw">struct</span> tuple <span class="op">{</span></span>
<span id="cb65-4"><a href="#cb65-4"></a>  <span class="kw">consteval</span> <span class="kw">static</span> <span class="kw">auto</span> types<span class="op">()</span> <span class="op">{</span></span>
<span id="cb65-5"><a href="#cb65-5"></a>    <span class="cf">return</span> std<span class="op">::</span>vector<span class="op">{</span><span class="kw">reflexpr</span><span class="op">(</span>Types<span class="op">)...}</span>;</span>
<span id="cb65-6"><a href="#cb65-6"></a>  <span class="op">}</span></span>
<span id="cb65-7"><a href="#cb65-7"></a><span class="op">}</span>;</span>
<span id="cb65-8"><a href="#cb65-8"></a></span>
<span id="cb65-9"><a href="#cb65-9"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="dt">size_t</span> I, <span class="kw">typename</span> T<span class="op">&gt;</span></span>
<span id="cb65-10"><a href="#cb65-10"></a><span class="kw">using</span> tuple_element_t <span class="op">=</span> <span class="kw">typename</span><span class="op">(</span>T<span class="op">::</span>types<span class="op">()[</span>I<span class="op">])</span>;</span></code></pre></div></td>
<td><div class="sourceCode" id="cb66"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb66-1"><a href="#cb66-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span><span class="op">...</span> Types<span class="op">&gt;</span></span>
<span id="cb66-2"><a href="#cb66-2"></a><span class="kw">struct</span> tuple <span class="op">{</span></span>
<span id="cb66-3"><a href="#cb66-3"></a>    <span class="kw">using</span> <span class="op">...</span> <span class="op">=</span> Types;</span>
<span id="cb66-4"><a href="#cb66-4"></a><span class="op">}</span>;</span>
<span id="cb66-5"><a href="#cb66-5"></a></span>
<span id="cb66-6"><a href="#cb66-6"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="dt">size_t</span> I, <span class="kw">typename</span> T<span class="op">&gt;</span></span>
<span id="cb66-7"><a href="#cb66-7"></a><span class="kw">using</span> tuple_element_t <span class="op">=</span> T<span class="op">.[</span>I<span class="op">]</span>;</span></code></pre></div></td>
</tr>
<tr class="even">
<td><div class="sourceCode" id="cb67"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb67-1"><a href="#cb67-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span><span class="op">...</span> Types<span class="op">&gt;</span></span>
<span id="cb67-2"><a href="#cb67-2"></a><span class="kw">struct</span> tuple <span class="op">{</span></span>
<span id="cb67-3"><a href="#cb67-3"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> members<span class="op">()</span> <span class="kw">const</span> <span class="op">{</span></span>
<span id="cb67-4"><a href="#cb67-4"></a>    <span class="co">// return some range of vector&lt;meta::info&gt;</span></span>
<span id="cb67-5"><a href="#cb67-5"></a>    <span class="co">// here that represents the data members.</span></span>
<span id="cb67-6"><a href="#cb67-6"></a>    <span class="co">// I am not sure how to implement that</span></span>
<span id="cb67-7"><a href="#cb67-7"></a>  <span class="op">}</span></span>
<span id="cb67-8"><a href="#cb67-8"></a><span class="op">}</span>;</span>
<span id="cb67-9"><a href="#cb67-9"></a></span>
<span id="cb67-10"><a href="#cb67-10"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> Tuple<span class="op">&gt;</span></span>
<span id="cb67-11"><a href="#cb67-11"></a><span class="dt">void</span> call_f<span class="op">(</span>Tuple <span class="kw">const</span><span class="op">&amp;</span> t<span class="op">)</span> <span class="op">{</span></span>
<span id="cb67-12"><a href="#cb67-12"></a>  f<span class="op">(</span>t<span class="op">.</span><span class="kw">unreflexpr</span><span class="op">(</span>t<span class="op">.</span>members<span class="op">())...)</span>;</span>
<span id="cb67-13"><a href="#cb67-13"></a><span class="op">}</span></span></code></pre></div></td>
<td><div class="sourceCode" id="cb68"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb68-1"><a href="#cb68-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span><span class="op">...</span> Types<span class="op">&gt;</span></span>
<span id="cb68-2"><a href="#cb68-2"></a><span class="kw">struct</span> tuple <span class="op">{</span></span>
<span id="cb68-3"><a href="#cb68-3"></a>  <span class="kw">operator</span> Types <span class="kw">const</span><span class="op">&amp;...()</span> <span class="kw">const</span><span class="op">&amp;</span> <span class="op">{</span> <span class="cf">return</span> elems; <span class="op">}</span></span>
<span id="cb68-4"><a href="#cb68-4"></a>  </span>
<span id="cb68-5"><a href="#cb68-5"></a>  Types<span class="op">...</span> elems;</span>
<span id="cb68-6"><a href="#cb68-6"></a><span class="op">}</span>;</span>
<span id="cb68-7"><a href="#cb68-7"></a></span>
<span id="cb68-8"><a href="#cb68-8"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> Tuple<span class="op">&gt;</span></span>
<span id="cb68-9"><a href="#cb68-9"></a><span class="dt">void</span> call_f<span class="op">(</span>Tuple <span class="kw">const</span><span class="op">&amp;</span> t<span class="op">)</span> <span class="op">{</span></span>
<span id="cb68-10"><a href="#cb68-10"></a>  <span class="cf">return</span> f<span class="op">(</span>t<span class="op">.[:]...)</span>;</span>
<span id="cb68-11"><a href="#cb68-11"></a><span class="op">}</span></span></code></pre></div></td>
</tr>
</tbody>
</table>
<p>It’s not that I think that the reflection direction is bad, or isn’t useful. Far from. Indeed, this paper will build on it shortly. It’s just that dealing with <code class="sourceCode cpp">tuple</code> is, in no small part, and ergonomics problem and I don’t think any reflection proposal that I’ve seen so far can adequately address that. This is fine - sometimes we need a specific language feature for a specific use-case.</p>
<h1 id="the-pair-example-and-others" style="border-bottom:1px solid #cccccc"><span class="header-section-number">3</span> The Pair Example and others<a href="#the-pair-example-and-others" class="self-link"></a></h1>
<p>As shocking as it might be to hear, there are in fact other types in the standard library that are not <code class="sourceCode cpp">std<span class="op">::</span>tuple<span class="op">&lt;</span>Ts<span class="op">...&gt;</span></code>. We should probably consider how to fit those other types into this new world.</p>
<h2 id="stdpair"><span class="header-section-number">3.1</span> <code class="sourceCode cpp">std<span class="op">::</span>pair</code><a href="#stdpair" class="self-link"></a></h2>
<p>It might seem strange, in a paper proposing language features to make it easier to manipulate packs, to start with <code class="sourceCode cpp">tuple</code> (the quintessential pack example) and then transition to <code class="sourceCode cpp">pair</code> (a type that has no packs). But <code class="sourceCode cpp">pair</code> is in many ways just another <code class="sourceCode cpp">tuple</code>, so it should be usable in the same ways. If we will be able to inline unpack a tuple and call a function with its arguments, it would be somewhat jarring if we couldn’t do the same thing with a <code class="sourceCode cpp">pair</code>. So how do we?</p>
<p>In the previous section, this paper laid out proposals to declare a variable pack, to provide for an alias pack and <code class="sourceCode cpp"><span class="kw">operator</span><span class="op">...</span></code>, to index into each, and connect all of this into structured bindings. How would this work if we do <em>not</em> have a pack anywhere?</p>
<div class="sourceCode" id="cb69"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb69-1"><a href="#cb69-1"></a><span class="kw">namespace</span> xstd <span class="op">{</span></span>
<span id="cb69-2"><a href="#cb69-2"></a>    <span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> T, <span class="kw">typename</span> U<span class="op">&gt;</span></span>
<span id="cb69-3"><a href="#cb69-3"></a>    <span class="kw">struct</span> pair <span class="op">{</span></span>
<span id="cb69-4"><a href="#cb69-4"></a>        T first;</span>
<span id="cb69-5"><a href="#cb69-5"></a>        U second;</span>
<span id="cb69-6"><a href="#cb69-6"></a>        </span>
<span id="cb69-7"><a href="#cb69-7"></a>        <span class="kw">using</span> <span class="op">...</span> <span class="op">=</span> <span class="op">???</span>;</span>
<span id="cb69-8"><a href="#cb69-8"></a>        <span class="kw">operator</span> <span class="op">???</span> <span class="op">...</span> <span class="op">()</span> <span class="op">{</span> <span class="cf">return</span> <span class="op">???</span>; <span class="op">}</span></span>
<span id="cb69-9"><a href="#cb69-9"></a>    <span class="op">}</span>;</span>
<span id="cb69-10"><a href="#cb69-10"></a><span class="op">}</span></span></code></pre></div>
<p>The direction this paper proposes is a recursive one. I’m taking two ideas that are already present in the language and merging them:</p>
<ul>
<li><code class="sourceCode cpp"><span class="kw">operator</span><span class="op">-&gt;()</span></code> recurses down until it finds a pointer</li>
<li>Expansion statements <span class="citation" data-cites="P1306R1">[<a href="#ref-P1306R1" role="doc-biblioref">P1306R1</a>]</span> can take either an unexpanded pack, a type that adheres to the structured bindings protocol, or a constexpr range .</li>
</ul>
<p>In the same vein, this paper proposes that both the pack operator and pack aliases can be defined in terms of an unexpanded pack or a type that defines one of these aliases:</p>
<div class="sourceCode" id="cb70"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb70-1"><a href="#cb70-1"></a><span class="kw">namespace</span> xstd <span class="op">{</span></span>
<span id="cb70-2"><a href="#cb70-2"></a>    <span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> T, <span class="kw">typename</span> U<span class="op">&gt;</span></span>
<span id="cb70-3"><a href="#cb70-3"></a>    <span class="kw">struct</span> pair <span class="op">{</span></span>
<span id="cb70-4"><a href="#cb70-4"></a>        T first;</span>
<span id="cb70-5"><a href="#cb70-5"></a>        U second;</span>
<span id="cb70-6"><a href="#cb70-6"></a>        </span>
<span id="cb70-7"><a href="#cb70-7"></a>        <span class="kw">using</span> <span class="op">...</span> <span class="op">=</span> tuple<span class="op">&lt;</span>T, U<span class="op">&gt;</span>;</span>
<span id="cb70-8"><a href="#cb70-8"></a>        tuple<span class="op">&lt;</span>T<span class="op">&amp;</span>, U<span class="op">&amp;&gt;</span> <span class="kw">operator</span> <span class="op">...</span> <span class="op">()</span> <span class="op">&amp;</span> <span class="op">{</span> <span class="cf">return</span> <span class="op">{</span>first, second<span class="op">}</span>; <span class="op">}</span></span>
<span id="cb70-9"><a href="#cb70-9"></a>    <span class="op">}</span>;</span>
<span id="cb70-10"><a href="#cb70-10"></a><span class="op">}</span></span></code></pre></div>
<p>With the definition of <code class="sourceCode cpp">xstd<span class="op">::</span>tuple</code> presented in this paper, this is now a light type to instantiate (or at least, as light as possible), so the extra overhead might not be a concern.</p>
<p>In the following example:</p>
<div class="sourceCode" id="cb71"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb71-1"><a href="#cb71-1"></a><span class="dt">void</span> f<span class="op">(</span><span class="dt">int</span><span class="op">&amp;</span>, <span class="dt">char</span><span class="op">&amp;)</span>;</span>
<span id="cb71-2"><a href="#cb71-2"></a>xstd<span class="op">::</span>pair<span class="op">&lt;</span><span class="dt">int</span>, <span class="dt">char</span><span class="op">&gt;</span> p<span class="op">{</span><span class="dv">1</span>, <span class="ch">&#39;x&#39;</span><span class="op">}</span>;</span>
<span id="cb71-3"><a href="#cb71-3"></a>f<span class="op">(</span>p<span class="op">.[:]..)</span>;</span></code></pre></div>
<p><code class="sourceCode cpp">p<span class="op">.[:]...</span></code> will invoke <code class="sourceCode cpp">p<span class="op">.</span><span class="kw">operator</span><span class="op">...()</span></code>, which gives a <code class="sourceCode cpp">tuple<span class="op">&lt;</span><span class="dt">int</span><span class="op">&amp;</span>, <span class="dt">char</span><span class="op">&amp;&gt;</span></code>. That is not a pack, so we invoke its <code class="sourceCode cpp"><span class="kw">operator</span><span class="op">...()</span></code>, which gives us a pack of <code class="sourceCode cpp"><span class="dt">int</span><span class="op">&amp;</span></code> and <code class="sourceCode cpp"><span class="dt">char</span><span class="op">&amp;</span></code>.</p>
<p>A different, non-recursive approach would be to use the reflection facilities introduced in <span class="citation" data-cites="P1240R0">[<a href="#ref-P1240R0" role="doc-biblioref">P1240R0</a>]</span> and allow the returning of a consteval range:</p>
<div class="sourceCode" id="cb72"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb72-1"><a href="#cb72-1"></a>namepsace xstd <span class="op">{</span></span>
<span id="cb72-2"><a href="#cb72-2"></a>    <span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> T, <span class="kw">typename</span> U<span class="op">&gt;</span></span>
<span id="cb72-3"><a href="#cb72-3"></a>    <span class="kw">struct</span> pair <span class="op">{</span></span>
<span id="cb72-4"><a href="#cb72-4"></a>        T first;</span>
<span id="cb72-5"><a href="#cb72-5"></a>        U second;</span>
<span id="cb72-6"><a href="#cb72-6"></a>        </span>
<span id="cb72-7"><a href="#cb72-7"></a>        <span class="kw">using</span> <span class="op">...</span> <span class="op">=</span> <span class="kw">typename</span><span class="op">(</span>std<span class="op">::</span>vector<span class="op">{</span><span class="kw">reflexpr</span><span class="op">(</span>T<span class="op">)</span>, <span class="kw">reflexpr</span><span class="op">(</span>U<span class="op">)})</span>;</span>
<span id="cb72-8"><a href="#cb72-8"></a>        </span>
<span id="cb72-9"><a href="#cb72-9"></a>        <span class="kw">consteval</span> <span class="kw">auto</span> <span class="kw">operator</span><span class="op">...()</span> <span class="kw">const</span> <span class="op">{</span></span>
<span id="cb72-10"><a href="#cb72-10"></a>            <span class="cf">return</span> std<span class="op">::</span>vector<span class="op">{</span></span>
<span id="cb72-11"><a href="#cb72-11"></a>                <span class="kw">reflexpr</span><span class="op">(</span>first<span class="op">)</span>,</span>
<span id="cb72-12"><a href="#cb72-12"></a>                <span class="kw">reflexpr</span><span class="op">(</span>second<span class="op">)</span></span>
<span id="cb72-13"><a href="#cb72-13"></a>            <span class="op">}</span>;</span>
<span id="cb72-14"><a href="#cb72-14"></a>        <span class="op">}</span></span>
<span id="cb72-15"><a href="#cb72-15"></a><span class="op">}</span></span></code></pre></div>
<p>In the above example, <code class="sourceCode cpp">f<span class="op">(</span>p<span class="op">.[:]...)</span></code> would evaluate as <code class="sourceCode cpp">f<span class="op">(</span>p<span class="op">.</span><span class="kw">unreflexpr</span><span class="op">(</span>p<span class="op">.</span><span class="kw">operator</span><span class="op">...())...)</span></code>.</p>
<p>It’s not clear if this direction will actually work, since you would have to disambiguate between the case where you want the identifiers and the case where actually you want the <code class="sourceCode cpp">meta<span class="op">::</span>info</code> objects themselves. Let’s call it an open question.</p>
<p>Of course, for this particular example, both the pack alias and operator could be defaulted.</p>
<h2 id="stdinteger_sequence-and-ranges"><span class="header-section-number">3.2</span> <code class="sourceCode cpp">std<span class="op">::</span>integer_sequence</code> and Ranges<a href="#stdinteger_sequence-and-ranges" class="self-link"></a></h2>
<p>There is a paper in the pre-Cologne mailing specifially wanting to opt <code class="sourceCode cpp">std<span class="op">::</span>integer_sequence</code> into expansion statements <span class="citation" data-cites="P1789R0">[<a href="#ref-P1789R0" role="doc-biblioref">P1789R0</a>]</span>. We could instead be able to opt it into the new pack protocol:</p>
<div class="sourceCode" id="cb73"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb73-1"><a href="#cb73-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> T, T<span class="op">...</span> Ints<span class="op">&gt;</span></span>
<span id="cb73-2"><a href="#cb73-2"></a><span class="kw">struct</span> integer_sequence <span class="op">{</span></span>
<span id="cb73-3"><a href="#cb73-3"></a>    std<span class="op">::</span>integral_constant<span class="op">&lt;</span>T, Ints<span class="op">&gt;</span> <span class="kw">operator</span> <span class="op">...()</span> <span class="kw">const</span> <span class="op">{</span></span>
<span id="cb73-4"><a href="#cb73-4"></a>        <span class="cf">return</span> <span class="op">{}</span>;</span>
<span id="cb73-5"><a href="#cb73-5"></a>    <span class="op">}</span></span>
<span id="cb73-6"><a href="#cb73-6"></a><span class="op">}</span>;</span></code></pre></div>
<p>One of the things we could have built on top of expansion statements was to implement tuple swap like so <span class="citation" data-cites="Stone.Swap">[<a href="#ref-Stone.Swap" role="doc-biblioref">Stone.Swap</a>]</span>:</p>
<div class="sourceCode" id="cb74"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb74-1"><a href="#cb74-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span><span class="op">...</span> TYPES<span class="op">&gt;</span></span>
<span id="cb74-2"><a href="#cb74-2"></a><span class="kw">constexpr</span></span>
<span id="cb74-3"><a href="#cb74-3"></a><span class="dt">void</span> tuple<span class="op">&lt;</span>TYPES<span class="op">...&gt;::</span>swap<span class="op">(</span>tuple<span class="op">&amp;</span> other<span class="op">)</span></span>
<span id="cb74-4"><a href="#cb74-4"></a>   <span class="kw">noexcept</span><span class="op">((</span>is_nothrow_swappable_v<span class="op">&lt;</span>TYPES<span class="op">&gt;</span> <span class="kw">and</span> <span class="op">...))</span></span>
<span id="cb74-5"><a href="#cb74-5"></a><span class="op">{</span></span>
<span id="cb74-6"><a href="#cb74-6"></a>   <span class="cf">for</span><span class="op">...(</span><span class="kw">constexpr</span> <span class="dt">size_t</span> N <span class="op">:</span> view<span class="op">::</span>iota<span class="op">(</span><span class="dv">0</span><span class="bu">u</span>, <span class="kw">sizeof</span><span class="op">...(</span>TYPES<span class="op">)))</span> <span class="op">{</span></span>
<span id="cb74-7"><a href="#cb74-7"></a>      swap<span class="op">(</span>get<span class="op">&lt;</span>N<span class="op">&gt;(*</span><span class="kw">this</span><span class="op">)</span>, get<span class="op">&lt;</span>N<span class="op">&gt;(</span>other<span class="op">))</span>;</span>
<span id="cb74-8"><a href="#cb74-8"></a>   <span class="op">}</span></span>
<span id="cb74-9"><a href="#cb74-9"></a><span class="op">}</span></span></code></pre></div>
<p>But what if I wanted to unpack a range into a function? It’s doesn’t seem so far fetched that if you can use an expansion statement over a range (which requires a known fixed size) that you should be able to use other language constructs that also require a known fixed size: structured bindings and tuple unpacking:</p>
<div class="sourceCode" id="cb75"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb75-1"><a href="#cb75-1"></a><span class="kw">auto</span> <span class="op">[</span>a, b, c<span class="op">]</span> <span class="op">=</span> view<span class="op">::</span>iota<span class="op">(</span><span class="dv">0</span>, <span class="dv">3</span><span class="op">)</span>; <span class="co">// maybe this should work</span></span>
<span id="cb75-2"><a href="#cb75-2"></a>foo<span class="op">(</span>view<span class="op">::</span>iota<span class="op">(</span><span class="dv">0</span>, <span class="dv">3</span><span class="op">).[:]...)</span>;      <span class="co">// ... and this too</span></span></code></pre></div>
<h1 id="proposal" style="border-bottom:1px solid #cccccc"><span class="header-section-number">4</span> Proposal<a href="#proposal" class="self-link"></a></h1>
<p>All the separate bits and pieces of this proposal have been presented one step at a time during the course of this paper. This section will formalize all the important notions.</p>
<h2 id="pack-declarations"><span class="header-section-number">4.1</span> Pack declarations<a href="#pack-declarations" class="self-link"></a></h2>
<p>You can declare member variable packs, namespace-scope variable packs, and block-scope variable packs. You can declare alias packs. The initializer for a pack declaration has to be either an unexpanded pack or a <em>braced-init-list</em>.</p>
<p>These can be directly unpacked when in non-dependent contexts.</p>
<p>You can declare packs within structured binding declarations (this paper may we well just subsume <span class="citation" data-cites="P1061R0">[<a href="#ref-P1061R0" role="doc-biblioref">P1061R0</a>]</span>).</p>
<h2 id="pack-like-type"><span class="header-section-number">4.2</span> Pack-like type<a href="#pack-like-type" class="self-link"></a></h2>
<p>To start with, structured bindings today works on three kinds of types:</p>
<ol type="1">
<li>Arrays</li>
<li>Tuple-Like types – defined as types that satisfy <code class="sourceCode cpp">std<span class="op">::</span>tuple_size<span class="op">&lt;</span>E<span class="op">&gt;</span></code>, <code class="sourceCode cpp">std<span class="op">::</span>tuple_element<span class="op">&lt;</span>i, E<span class="op">&gt;</span></code>, and <code class="sourceCode cpp">get<span class="op">&lt;</span>i<span class="op">&gt;()</span></code>. Note that this is a language feature that nevertheless has a library hook.</li>
<li>Types that have all of their non-static data members in the same class. This one is a little fuzzy because it’s based on accessibility.</li>
</ol>
<p>This paper proposes the notion of a <em>pack-like type</em>. A pack-like type:</p>
<ol type="1">
<li>Is an array type</li>
<li>Has one of:
<ol type="a">
<li>an unnamed pack alias type that names a pack-like type or a pack</li>
<li>a pack operator that returns a pack-like type or a pack</li>
</ol>
If any of these new special named members yields a reflection range, that range will be reified as appropriate before further consideration. If a type provides only a pack alias, it can be indexed into/unpacked as a type but not as a value. If a type provides only a pack operator, it can be indexed/unpacked as a value but not as a type.</li>
<li>Is a Tuple-Like type (as per structured bindings)</li>
<li>Is a constexpr range (the constexpr-ness is important because of the fixed size)</li>
<li>Is a type that has all of its non-static data members in the same class (as per structured bindings)</li>
</ol>
<p>This paper proposes to redefine both structured bindings and expansion statements in terms of the pack-like type concept, unifying the two ideas. Any pack-like type can be expanded over or used as the right-hand side of a structured binding declaration.</p>
<p>Any pack-like type can be indexed into, <code class="sourceCode cpp">T<span class="op">.[</span>i<span class="op">]</span></code> will yield the <code class="sourceCode cpp">i</code>th type (if <code class="sourceCode cpp">T</code> is a type) or <code class="sourceCode cpp">i</code>th value (if <code class="sourceCode cpp">T</code> is a variable) of the type. Any pack like type can be sliced and unpacked via <code class="sourceCode cpp">T<span class="op">.[:]...</span></code> or with specific indices.</p>
<p>This also unifies the special unpacking rules in <span class="citation" data-cites="P1240R0">[<a href="#ref-P1240R0" role="doc-biblioref">P1240R0</a>]</span>: a reflection range is a pack-like type, therefore it can be unpacked.</p>
<h2 id="dependent-packs"><span class="header-section-number">4.3</span> Dependent packs<a href="#dependent-packs" class="self-link"></a></h2>
<p>Member packs and block scope packs can be directly unpacked when in non-dependent contexts. We know what they are.</p>
<p>In dependent contexts, anything that is not a pack must be explicitly identified as a pack in order to be treated as one. Similar to how we need the <code class="sourceCode cpp"><span class="kw">typename</span></code> and <code class="sourceCode cpp"><span class="kw">template</span></code> keyword in many places to identify that such and such an expression is a type or a template, a preceding <code class="sourceCode cpp"><span class="op">...</span></code> (or whatever alternate spelling) will identify the expression that follows it as a pack. If that entity is <em>not</em> a pack, then the indexing or unpacking expression is ill-formed.</p>
<h1 id="acknowledgments" style="border-bottom:1px solid #cccccc"><span class="header-section-number">5</span> Acknowledgments<a href="#acknowledgments" class="self-link"></a></h1>
<p>This paper would not exist without many thorough conversations with Agustín Bergé, Matt Calabrese, and Richard Smith. Thank you.</p>
<p>Thank you to David Stone for pointing out many issues.</p>
<h1 id="references" style="border-bottom:1px solid #cccccc"><span class="header-section-number">6</span> References<a href="#references" class="self-link"></a></h1>

<div id="refs" role="doc-bibliography">
<div id="ref-Boost.Mp11">
<p>[Boost.Mp11] Peter Dimov. 2017. Boost.Mp11: A C++11 metaprogramming library - 1.70.0. <br />
<a href="https://www.boost.org/doc/libs/1_70_0/libs/mp11/doc/html/mp11.html">https://www.boost.org/doc/libs/1_70_0/libs/mp11/doc/html/mp11.html</a></p>
</div>
<div id="ref-Calabrese.Argot">
<p>[Calabrese.Argot] Matt Calabrese. 2018. C++Now 2018: Argot: Simplifying Variants, Tuples, and Futures. <br />
<a href="https://www.youtube.com/watch?v=pKVCB_Bzalk">https://www.youtube.com/watch?v=pKVCB_Bzalk</a></p>
</div>
<div id="ref-N3728">
<p>[N3728] Mike Spertus. 2013. Packaging Parameter Packs (Rev. 2). <br />
<a href="https://wg21.link/n3728">https://wg21.link/n3728</a></p>
</div>
<div id="ref-N4072">
<p>[N4072] Maurice Bos. 2014. Fixed Size Parameter Packs. <br />
<a href="https://wg21.link/n4072">https://wg21.link/n4072</a></p>
</div>
<div id="ref-N4191">
<p>[N4191] A. Sutton, R. Smith. 2014. Folding expressions. <br />
<a href="https://wg21.link/n4191">https://wg21.link/n4191</a></p>
</div>
<div id="ref-N4235">
<p>[N4235] Daveed Vandevoorde. 2014. Selecting from Parameter Packs. <br />
<a href="https://wg21.link/n4235">https://wg21.link/n4235</a></p>
</div>
<div id="ref-P0144R2">
<p>[P0144R2] Herb Sutter. 2016. Structured Bindings. <br />
<a href="https://wg21.link/p0144r2">https://wg21.link/p0144r2</a></p>
</div>
<div id="ref-P0195R2">
<p>[P0195R2] Robert Haberlach, Richard Smith. 2016. Pack expansions in <i>using-declaration</i>s. <br />
<a href="https://wg21.link/p0195r2">https://wg21.link/p0195r2</a></p>
</div>
<div id="ref-P0341R0">
<p>[P0341R0] Mike Spertus. 2016. parameter packs outside of templates. <br />
<a href="https://wg21.link/p0341r0">https://wg21.link/p0341r0</a></p>
</div>
<div id="ref-P0535R0">
<p>[P0535R0] Matthew Woehlke. 2017. Generalized Unpacking and Parameter Pack Slicing. <br />
<a href="https://wg21.link/p0535r0">https://wg21.link/p0535r0</a></p>
</div>
<div id="ref-P0780R2">
<p>[P0780R2] Barry Revzin. 2018. Allow pack expansion in lambda init-capture. <br />
<a href="https://wg21.link/p0780r2">https://wg21.link/p0780r2</a></p>
</div>
<div id="ref-P0847R2">
<p>[P0847R2] Gašper Ažman, Simon Brand, Ben Deane, Barry Revzin. 2019. Deducing this. <br />
<a href="https://wg21.link/p0847r2">https://wg21.link/p0847r2</a></p>
</div>
<div id="ref-P1061R0">
<p>[P1061R0] Barry Revzin, Jonathan Wakely. 2018. Structured Bindings can introduce a Pack. <br />
<a href="https://wg21.link/p1061r0">https://wg21.link/p1061r0</a></p>
</div>
<div id="ref-P1096R0">
<p>[P1096R0] Timur Doumler. 2018. Simplify the customization point for structured bindings. <br />
<a href="https://wg21.link/p1096r0">https://wg21.link/p1096r0</a></p>
</div>
<div id="ref-P1219R1">
<p>[P1219R1] James Touton. 2019. Homogeneous variadic function parameters. <br />
<a href="https://wg21.link/p1219r1">https://wg21.link/p1219r1</a></p>
</div>
<div id="ref-P1240R0">
<p>[P1240R0] Andrew Sutton, Faisal Vali, Daveed Vandevoorde. 2018. Scalable Reflection in C++. <br />
<a href="https://wg21.link/p1240r0">https://wg21.link/p1240r0</a></p>
</div>
<div id="ref-P1306R1">
<p>[P1306R1] Andrew Sutton, Sam Goodrick, Daveed Vandevoorde. 2019. Expansion statements. <br />
<a href="https://wg21.link/p1306r1">https://wg21.link/p1306r1</a></p>
</div>
<div id="ref-P1717R0">
<p>[P1717R0] Andrew Sutton, Wyatt Childers. 2019. Compile-time Metaprogramming in C++. <br />
<a href="https://wg21.link/p1717r0">https://wg21.link/p1717r0</a></p>
</div>
<div id="ref-P1789R0">
<p>[P1789R0] Alisdair Meredith. 2019. Library Support for Expansion Statements. <br />
<a href="https://wg21.link/p1789r0">https://wg21.link/p1789r0</a></p>
</div>
<div id="ref-Smith.Pack">
<p>[Smith.Pack] Richard Smith. 2013. A problem with generalized lambda captures and pack expansion. <br />
<a href="https://groups.google.com/a/isocpp.org/d/msg/std-discussion/ePRzn4K7VcM/Cvy8M8EL3YAJ">https://groups.google.com/a/isocpp.org/d/msg/std-discussion/ePRzn4K7VcM/Cvy8M8EL3YAJ</a></p>
</div>
<div id="ref-Stone.Swap">
<p>[Stone.Swap] David Stone. 2019. Library Support for Expansion Statements: P1789. <br />
<a href="http://lists.isocpp.org/lib-ext/2019/06/11932.php">http://lists.isocpp.org/lib-ext/2019/06/11932.php</a></p>
</div>
<div id="ref-Sutton">
<p>[Sutton] Andrew Sutton. 2019. Meta++: Language Support for Advanced Generative Programming. <br />
<a href="https://youtu.be/kjQXhuPX-Ac?t=389">https://youtu.be/kjQXhuPX-Ac?t=389</a></p>
</div>
</div>
</div>
</div>
</body>
</html>
