<!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="2020-01-08" />
  <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; }
div.quote {
border-left: 7px solid #ccc;
background: #f9f9f9;
margin: 1.5em 10px;
padding-left: 20px;
}
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>P1858R1</td>
  </tr>
  <tr>
    <td>Date: </td>
    <td>2020-01-08</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">
<div id="TOC" role="doc-toc">
<h1 id="toctitle">Contents</h1>
<ul>
<li><a href="#revision-history"><span class="toc-section-number">1</span> Revision History<span></span></a></li>
<li><a href="#introduction-and-motivation"><span class="toc-section-number">2</span> Introduction and Motivation<span></span></a></li>
<li><a href="#packs-packs-packs"><span class="toc-section-number">3</span> Packs, packs, packs<span></span></a><ul>
<li><a href="#member-packs"><span class="toc-section-number">3.1</span> Member packs<span></span></a></li>
<li><a href="#empty-variable-pack"><span class="toc-section-number">3.2</span> Empty variable pack<span></span></a></li>
<li><a href="#constructor-and-initializer-packs"><span class="toc-section-number">3.3</span> Constructor and initializer packs<span></span></a></li>
<li><a href="#pack-indexing"><span class="toc-section-number">3.4</span> Pack Indexing<span></span></a></li>
<li><a href="#extending-structured-bindings"><span class="toc-section-number">3.5</span> Extending Structured Bindings<span></span></a></li>
<li><a href="#packs-at-block-scope"><span class="toc-section-number">3.6</span> Packs at block scope<span></span></a></li>
<li><a href="#implementing-variant"><span class="toc-section-number">3.7</span> Implementing variant<span></span></a></li>
<li><a href="#other-examples"><span class="toc-section-number">3.8</span> Other Examples<span></span></a></li>
</ul></li>
<li><a href="#expanding-a-type-into-a-pack"><span class="toc-section-number">4</span> Expanding a type into a pack<span></span></a><ul>
<li><a href="#generalized-unpacking-with"><span class="toc-section-number">4.1</span> Generalized unpacking with <code class="sourceCode cpp"><span class="op">[:]</span></code><span></span></a></li>
<li><a href="#syntax-free-unpacking"><span class="toc-section-number">4.2</span> Syntax-free unpacking?<span></span></a></li>
<li><a href="#other-examples-of-unpacking"><span class="toc-section-number">4.3</span> Other examples of unpacking<span></span></a></li>
<li><a href="#generalizing-slicing-further"><span class="toc-section-number">4.4</span> Generalizing slicing further<span></span></a></li>
<li><a href="#examples-with-boost.mp11"><span class="toc-section-number">4.5</span> Examples with Boost.Mp11<span></span></a></li>
</ul></li>
<li><a href="#can-functions-return-a-pack"><span class="toc-section-number">5</span> Can functions return a pack?<span></span></a></li>
<li><a href="#disambiguation"><span class="toc-section-number">6</span> Disambiguation<span></span></a><ul>
<li><a href="#disambiguating-dependent"><span class="toc-section-number">6.1</span> Disambiguating Dependent Packs<span></span></a></li>
<li><a href="#disambiguating-packs"><span class="toc-section-number">6.2</span> Disambiguating packs of tuples<span></span></a></li>
<li><a href="#nested-pack-expansions"><span class="toc-section-number">6.3</span> Nested pack expansions<span></span></a></li>
</ul></li>
<li><a href="#what-about-reflection"><span class="toc-section-number">7</span> What about Reflection?<span></span></a></li>
<li><a href="#what-about-stdpair"><span class="toc-section-number">8</span> What about <code class="sourceCode cpp">std<span class="op">:</span>pair</code>?<span></span></a></li>
<li><a href="#proposal"><span class="toc-section-number">9</span> Proposal<span></span></a><ul>
<li><a href="#pack-declarations"><span class="toc-section-number">9.1</span> Pack declarations<span></span></a></li>
<li><a href="#dependent-packs"><span class="toc-section-number">9.2</span> Dependent packs<span></span></a></li>
<li><a href="#structured-bindings"><span class="toc-section-number">9.3</span> Structured Bindings<span></span></a></li>
<li><a href="#pack-indexing-1"><span class="toc-section-number">9.4</span> Pack Indexing<span></span></a></li>
<li><a href="#adding-a-layer-of-packness"><span class="toc-section-number">9.5</span> Adding a layer of packness<span></span></a></li>
<li><a href="#pack-slicing"><span class="toc-section-number">9.6</span> Pack slicing<span></span></a></li>
</ul></li>
<li><a href="#acknowledgments"><span class="toc-section-number">10</span> Acknowledgments<span></span></a></li>
<li><a href="#references"><span class="toc-section-number">11</span> References<span></span></a></li>
</ul>
</div>
<h1 id="revision-history" style="border-bottom:1px solid #cccccc"><span class="header-section-number">1</span> Revision History<a href="#revision-history" class="self-link"></a></h1>
<p>R0 <span class="citation" data-cites="P1858R0">[<a href="#ref-P1858R0" role="doc-biblioref">P1858R0</a>]</span> was presented in EWGI in Belfast <span class="citation" data-cites="EWGI.Belfast">[<a href="#ref-EWGI.Belfast" role="doc-biblioref">EWGI.Belfast</a>]</span>, where further work was encouraged (9-4-1-0-0). Since then, several substantial changes have been made to this paper.</p>
<ul>
<li>The overloadable <code class="sourceCode cpp"><span class="kw">operator</span><span class="op">...()</span></code> and <code class="sourceCode cpp"><span class="kw">using</span> <span class="op">...</span></code> were removed.</li>
<li>Pack expansion is now driven through structured bindings, which are extended on the library side as well.</li>
<li><code class="sourceCode cpp"><span class="kw">constexpr</span></code> ranges removed from this paper, should be handled by expansion statements.</li>
<li>Discussion of functions returning packs - no longer being proposed due to ambiguity of what it actually could mean.</li>
<li>Discussion of pack literals.</li>
</ul>
<h1 id="introduction-and-motivation" style="border-bottom:1px solid #cccccc"><span class="header-section-number">2</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 implementations for a library <code class="sourceCode cpp">tuple</code> and <code class="sourceCode cpp">variant</code>, ones that ends up being much easier to implement, more compiler friendly, and more ergonomic. The paper will piecewise introduce the necessary language features, increasing in complexity as it goes, and is divided into two broad sections:</p>
<ul>
<li>introducing the ability to declare packs in more places and to index into them</li>
<li>introducing the ability to convert types to packs and to index into them</li>
</ul>
<h1 id="packs-packs-packs" style="border-bottom:1px solid #cccccc"><span class="header-section-number">3</span> Packs, packs, packs<a href="#packs-packs-packs" class="self-link"></a></h1>
<p>This section will propose several new language features, with the motivating example being a far simpler implementation of <code class="sourceCode cpp">tuple</code>, but which are generally applicable to all uses of variadic templates in C++ today.</p>
<h2 id="member-packs"><span class="header-section-number">3.1</span> Member packs<a href="#member-packs" class="self-link"></a></h2>
<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">3.2</span> Empty variable pack<a href="#empty-variable-pack" class="self-link"></a></h2>
<p>What does <code class="sourceCode cpp">xstd<span class="op">::</span>tuple<span class="op">&lt;&gt;</span> t;</code> mean here? 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="constructor-and-initializer-packs"><span class="header-section-number">3.3</span> Constructor and initializer packs<a href="#constructor-and-initializer-packs" 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>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">3.4</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">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>Notably, in an earlier example we constructed the pack as a single entity and here we are constructing each element of the pack separately. Both are fine. We’ll see a simpler way to do this <a href="#tuple-pair">later</a>.</p>
<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> std <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="dt">size_t</span> I, <span class="kw">typename</span><span class="op">...</span> Ts<span class="op">&gt;</span></span>
<span id="cb8-3"><a href="#cb8-3"></a>    <span class="kw">struct</span> tuple_element<span class="op">&lt;</span>I, xstd<span class="op">::</span>tuple<span class="op">&lt;</span>Ts<span class="op">...&gt;&gt;</span></span>
<span id="cb8-4"><a href="#cb8-4"></a>    <span class="op">{</span></span>
<span id="cb8-5"><a href="#cb8-5"></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-6"><a href="#cb8-6"></a>    <span class="op">}</span>;</span>
<span id="cb8-7"><a href="#cb8-7"></a><span class="op">}</span></span></code></pre></div>
<p>And a member <code class="sourceCode cpp">get</code>:</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">template</span> <span class="op">&lt;</span><span class="dt">size_t</span> I<span class="op">&gt;</span></span>
<span id="cb9-6"><a href="#cb9-6"></a>        <span class="kw">auto</span> get<span class="op">()</span> <span class="kw">const</span><span class="op">&amp;</span> <span class="op">-&gt;</span> Ts<span class="op">...[</span>I<span class="op">]</span> <span class="kw">const</span><span class="op">&amp;</span> <span class="op">{</span></span>
<span id="cb9-7"><a href="#cb9-7"></a>            <span class="cf">return</span> elems<span class="op">...[</span>I<span class="op">]</span>;</span>
<span id="cb9-8"><a href="#cb9-8"></a>        <span class="op">}</span></span>
<span id="cb9-9"><a href="#cb9-9"></a>    </span>
<span id="cb9-10"><a href="#cb9-10"></a>    <span class="kw">private</span><span class="op">:</span></span>
<span id="cb9-11"><a href="#cb9-11"></a>        Ts<span class="op">...</span> elems;</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>This is a lot nicer than status quo. Consider just the implementation complexity difference between these two versions (where the status quo is taken from the libc++ implementation). I’m including just the pieces I’ve shown up ’til now: the default constructor, n-ary converting constructor, <code class="sourceCode cpp">pair</code> converting constructor, and the structured bindings opt-in as a member.</p>
<p>When considering the differences below, don’t just look at the difference in number of lines. Consider also the difference in complexity. You almost don’t even really have to think about how to implement the “proposed” version, whereas the status quo, you really have to plan quite carefully and think a lot at every step of the way.</p>
<p>Also I’m cheating a little and using Boost.Mp11 for pack indexing.</p>
<table>
<thead>
<tr class="header">
<th><div style="text-align:center">
<strong>Status Quo</strong>
</div></th>
<th><div style="text-align:center">
<strong>Proposed</strong>
</div></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><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">template</span> <span class="op">&lt;</span><span class="kw">typename</span><span class="op">...&gt;</span> <span class="kw">class</span> tuple;</span>
<span id="cb10-2"><a href="#cb10-2"></a></span>
<span id="cb10-3"><a href="#cb10-3"></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-4"><a href="#cb10-4"></a><span class="kw">struct</span> std<span class="op">::</span>tuple_size<span class="op">&lt;</span>tuple<span class="op">&lt;</span>Ts<span class="op">...&gt;&gt;</span></span>
<span id="cb10-5"><a href="#cb10-5"></a>    <span class="op">:</span> integral_constant<span class="op">&lt;</span><span class="dt">size_t</span>, <span class="kw">sizeof</span><span class="op">...(</span>Ts<span class="op">)&gt;</span></span>
<span id="cb10-6"><a href="#cb10-6"></a><span class="op">{</span> <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>, <span class="kw">typename</span><span class="op">...</span> Ts<span class="op">&gt;</span></span>
<span id="cb10-9"><a href="#cb10-9"></a><span class="kw">struct</span> std<span class="op">::</span>tuple_element<span class="op">&lt;</span>I, tuple<span class="op">&lt;</span>Ts<span class="op">...&gt;&gt;</span></span>
<span id="cb10-10"><a href="#cb10-10"></a><span class="op">{</span></span>
<span id="cb10-11"><a href="#cb10-11"></a>    <span class="kw">using</span> type <span class="op">=</span> mp_at_c<span class="op">&lt;</span>I, mp_list<span class="op">&lt;</span>Ts<span class="op">...&gt;&gt;</span>;</span>
<span id="cb10-12"><a href="#cb10-12"></a><span class="op">}</span>;</span>
<span id="cb10-13"><a href="#cb10-13"></a></span>
<span id="cb10-14"><a href="#cb10-14"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="dt">size_t</span> Idx, <span class="kw">typename</span> T<span class="op">&gt;</span></span>
<span id="cb10-15"><a href="#cb10-15"></a><span class="kw">class</span> tuple_leaf <span class="op">{</span></span>
<span id="cb10-16"><a href="#cb10-16"></a>    <span class="op">[[</span><span class="at">no_unique_address</span><span class="op">]]</span> T value;</span>
<span id="cb10-17"><a href="#cb10-17"></a>    <span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span><span class="op">...&gt;</span> <span class="kw">friend</span> <span class="kw">class</span> tuple;</span>
<span id="cb10-18"><a href="#cb10-18"></a>    </span>
<span id="cb10-19"><a href="#cb10-19"></a><span class="kw">public</span><span class="op">:</span></span>
<span id="cb10-20"><a href="#cb10-20"></a>    <span class="kw">constexpr</span> tuple_leaf<span class="op">()</span></span>
<span id="cb10-21"><a href="#cb10-21"></a>        <span class="kw">requires</span> std<span class="op">::</span>is_default_constructible<span class="op">&lt;</span>T<span class="op">&gt;</span></span>
<span id="cb10-22"><a href="#cb10-22"></a>      <span class="op">:</span> value<span class="op">()</span></span>
<span id="cb10-23"><a href="#cb10-23"></a>    <span class="op">{</span> <span class="op">}</span></span>
<span id="cb10-24"><a href="#cb10-24"></a>    </span>
<span id="cb10-25"><a href="#cb10-25"></a>    <span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> U<span class="op">&gt;</span></span>
<span id="cb10-26"><a href="#cb10-26"></a>    <span class="kw">constexpr</span> tuple_leaf<span class="op">(</span>std<span class="op">::</span>in_place_t, U<span class="op">&amp;&amp;</span> u<span class="op">)</span></span>
<span id="cb10-27"><a href="#cb10-27"></a>        <span class="op">:</span> value<span class="op">(</span>std<span class="op">::</span>forward<span class="op">&lt;</span>U<span class="op">&gt;(</span>u<span class="op">))</span></span>
<span id="cb10-28"><a href="#cb10-28"></a>    <span class="op">{</span> <span class="op">}</span></span>
<span id="cb10-29"><a href="#cb10-29"></a><span class="op">}</span>;</span>
<span id="cb10-30"><a href="#cb10-30"></a></span>
<span id="cb10-31"><a href="#cb10-31"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> Indices, <span class="kw">typename</span><span class="op">...</span> Ts<span class="op">&gt;</span></span>
<span id="cb10-32"><a href="#cb10-32"></a><span class="kw">class</span> tuple_impl;</span>
<span id="cb10-33"><a href="#cb10-33"></a></span>
<span id="cb10-34"><a href="#cb10-34"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="dt">size_t</span><span class="op">...</span> Is, <span class="kw">typename</span><span class="op">...</span> Ts<span class="op">&gt;</span></span>
<span id="cb10-35"><a href="#cb10-35"></a><span class="kw">class</span> tuple_impl<span class="op">&lt;</span>index_sequence<span class="op">&lt;</span>Is<span class="op">...&gt;</span>, Ts<span class="op">...&gt;</span></span>
<span id="cb10-36"><a href="#cb10-36"></a>    <span class="op">:</span> <span class="kw">public</span> tuple_leaf<span class="op">&lt;</span>Is, Ts<span class="op">&gt;...</span></span>
<span id="cb10-37"><a href="#cb10-37"></a><span class="op">{</span></span>
<span id="cb10-38"><a href="#cb10-38"></a><span class="kw">public</span><span class="op">:</span></span>
<span id="cb10-39"><a href="#cb10-39"></a>    tuple_impl<span class="op">()</span> <span class="op">=</span> <span class="cf">default</span>;</span>
<span id="cb10-40"><a href="#cb10-40"></a>    </span>
<span id="cb10-41"><a href="#cb10-41"></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>
<span id="cb10-42"><a href="#cb10-42"></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>
<span id="cb10-43"><a href="#cb10-43"></a>                <span class="op">!</span>std<span class="op">::</span>derived_from<span class="op">&lt;</span></span>
<span id="cb10-44"><a href="#cb10-44"></a>                    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>, </span>
<span id="cb10-45"><a href="#cb10-45"></a>                    tuple_impl<span class="op">&gt;)</span></span>
<span id="cb10-46"><a href="#cb10-46"></a>    <span class="kw">constexpr</span> tuple_impl<span class="op">(</span>Us<span class="op">&amp;&amp;...</span> us<span class="op">)</span></span>
<span id="cb10-47"><a href="#cb10-47"></a>        <span class="op">:</span> tuple_leaf<span class="op">&lt;</span>Is, Ts<span class="op">&gt;(</span></span>
<span id="cb10-48"><a href="#cb10-48"></a>            std<span class="op">::</span>in_place, 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="cb10-49"><a href="#cb10-49"></a>    <span class="op">{</span> <span class="op">}</span></span>
<span id="cb10-50"><a href="#cb10-50"></a>    </span>
<span id="cb10-51"><a href="#cb10-51"></a>    <span class="kw">template</span> <span class="op">&lt;</span>std<span class="op">::</span>convertible_to<span class="op">&lt;</span></span>
<span id="cb10-52"><a href="#cb10-52"></a>                mp_at_c<span class="op">&lt;</span><span class="dv">0</span>, mp_list<span class="op">&lt;</span>Ts<span class="op">...&gt;&gt;</span> T,</span>
<span id="cb10-53"><a href="#cb10-53"></a>              std<span class="op">::</span>convertible_to<span class="op">&lt;</span></span>
<span id="cb10-54"><a href="#cb10-54"></a>                mp_at_c<span class="op">&lt;</span><span class="dv">1</span>, mp_list<span class="op">&lt;</span>Ts<span class="op">...&gt;&gt;</span> U<span class="op">&gt;</span></span>
<span id="cb10-55"><a href="#cb10-55"></a>        <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> <span class="dv">2</span><span class="op">)</span></span>
<span id="cb10-56"><a href="#cb10-56"></a>    <span class="kw">constexpr</span> tuple_impl<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="cb10-57"><a href="#cb10-57"></a>        <span class="op">:</span> tuple_impl<span class="op">(</span>p<span class="op">.</span>first, p<span class="op">.</span>second<span class="op">)</span></span>
<span id="cb10-58"><a href="#cb10-58"></a>    <span class="op">{</span> <span class="op">}</span></span>
<span id="cb10-59"><a href="#cb10-59"></a><span class="op">}</span>;</span>
<span id="cb10-60"><a href="#cb10-60"></a></span>
<span id="cb10-61"><a href="#cb10-61"></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-62"><a href="#cb10-62"></a><span class="kw">class</span> tuple <span class="op">:</span> <span class="kw">public</span> tuple_impl<span class="op">&lt;</span></span>
<span id="cb10-63"><a href="#cb10-63"></a>    make_index_sequence<span class="op">&lt;</span><span class="kw">sizeof</span><span class="op">...(</span>Ts<span class="op">)&gt;</span>, Ts<span class="op">...&gt;</span></span>
<span id="cb10-64"><a href="#cb10-64"></a><span class="op">{</span>   </span>
<span id="cb10-65"><a href="#cb10-65"></a><span class="kw">public</span><span class="op">:</span></span>
<span id="cb10-66"><a href="#cb10-66"></a>    <span class="kw">using</span> tuple<span class="op">::</span>tuple_impl<span class="op">::</span>tuple_impl;</span>
<span id="cb10-67"><a href="#cb10-67"></a></span>
<span id="cb10-68"><a href="#cb10-68"></a>    <span class="kw">template</span> <span class="op">&lt;</span><span class="dt">size_t</span> I<span class="op">&gt;</span></span>
<span id="cb10-69"><a href="#cb10-69"></a>    <span class="kw">constexpr</span> <span class="kw">auto</span> get<span class="op">()</span> <span class="op">-&gt;</span> tuple_element_t<span class="op">&lt;</span>I, tuple<span class="op">&gt;</span> <span class="kw">const</span><span class="op">&amp;</span>  <span class="op">{</span></span>
<span id="cb10-70"><a href="#cb10-70"></a>        <span class="kw">using</span> leaf <span class="op">=</span> tuple_leaf<span class="op">&lt;</span>I, tuple_element_t<span class="op">&lt;</span>I, tuple<span class="op">&gt;&gt;</span>;</span>
<span id="cb10-71"><a href="#cb10-71"></a>        <span class="cf">return</span> <span class="kw">static_cast</span><span class="op">&lt;</span>leaf <span class="kw">const</span><span class="op">&amp;&gt;(*</span><span class="kw">this</span><span class="op">).</span>value;</span>
<span id="cb10-72"><a href="#cb10-72"></a>    <span class="op">}</span></span>
<span id="cb10-73"><a href="#cb10-73"></a><span class="op">}</span>;</span></code></pre></div></td>
<td><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">template</span> <span class="op">&lt;</span><span class="kw">typename</span><span class="op">...&gt;</span> <span class="kw">class</span> tuple;</span>
<span id="cb11-2"><a href="#cb11-2"></a></span>
<span id="cb11-3"><a href="#cb11-3"></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-4"><a href="#cb11-4"></a><span class="kw">struct</span> tuple_size<span class="op">&lt;</span>tuple<span class="op">&lt;</span>Ts<span class="op">...&gt;&gt;</span></span>
<span id="cb11-5"><a href="#cb11-5"></a>    <span class="op">:</span> integral_constant<span class="op">&lt;</span><span class="dt">size_t</span>, <span class="kw">sizeof</span><span class="op">...(</span>Ts<span class="op">)&gt;</span></span>
<span id="cb11-6"><a href="#cb11-6"></a><span class="op">{</span> <span class="op">}</span>;</span>
<span id="cb11-7"><a href="#cb11-7"></a></span>
<span id="cb11-8"><a href="#cb11-8"></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="cb11-9"><a href="#cb11-9"></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>
<span id="cb11-10"><a href="#cb11-10"></a><span class="op">{</span></span>
<span id="cb11-11"><a href="#cb11-11"></a>    <span class="kw">using</span> type <span class="op">=</span> Ts<span class="op">...[</span>I<span class="op">]</span>;</span>
<span id="cb11-12"><a href="#cb11-12"></a><span class="op">}</span>;</span>
<span id="cb11-13"><a href="#cb11-13"></a></span>
<span id="cb11-14"><a href="#cb11-14"></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-15"><a href="#cb11-15"></a><span class="kw">class</span> tuple <span class="op">{</span></span>
<span id="cb11-16"><a href="#cb11-16"></a>    <span class="op">[[</span><span class="at">no_unique_address</span><span class="op">]]</span> Ts<span class="op">...</span> elems;</span>
<span id="cb11-17"><a href="#cb11-17"></a></span>
<span id="cb11-18"><a href="#cb11-18"></a><span class="kw">public</span><span class="op">:</span></span>
<span id="cb11-19"><a href="#cb11-19"></a>    <span class="kw">constexpr</span> tuple<span class="op">()</span></span>
<span id="cb11-20"><a href="#cb11-20"></a>        <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="cb11-21"><a href="#cb11-21"></a>      <span class="op">:</span> elems<span class="op">()...</span></span>
<span id="cb11-22"><a href="#cb11-22"></a>    <span class="op">{</span> <span class="op">}</span></span>
<span id="cb11-23"><a href="#cb11-23"></a></span>
<span id="cb11-24"><a href="#cb11-24"></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>
<span id="cb11-25"><a href="#cb11-25"></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>
<span id="cb11-26"><a href="#cb11-26"></a>                <span class="op">!</span>std<span class="op">::</span>derived_from<span class="op">&lt;</span></span>
<span id="cb11-27"><a href="#cb11-27"></a>                    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>, </span>
<span id="cb11-28"><a href="#cb11-28"></a>                    tuple<span class="op">&gt;)</span></span>
<span id="cb11-29"><a href="#cb11-29"></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="cb11-30"><a href="#cb11-30"></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="cb11-31"><a href="#cb11-31"></a>    <span class="op">{</span> <span class="op">}</span></span>
<span id="cb11-32"><a href="#cb11-32"></a></span>
<span id="cb11-33"><a href="#cb11-33"></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="cb11-34"><a href="#cb11-34"></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="cb11-35"><a href="#cb11-35"></a>        <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> <span class="dv">2</span><span class="op">)</span></span>
<span id="cb11-36"><a href="#cb11-36"></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="cb11-37"><a href="#cb11-37"></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="cb11-38"><a href="#cb11-38"></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="cb11-39"><a href="#cb11-39"></a>    <span class="op">{</span> <span class="op">}</span></span>
<span id="cb11-40"><a href="#cb11-40"></a>    </span>
<span id="cb11-41"><a href="#cb11-41"></a>    <span class="kw">template</span> <span class="op">&lt;</span><span class="dt">size_t</span> I<span class="op">&gt;</span></span>
<span id="cb11-42"><a href="#cb11-42"></a>    <span class="kw">constexpr</span> <span class="kw">auto</span> get<span class="op">()</span> <span class="kw">const</span><span class="op">&amp;</span> <span class="op">-&gt;</span> Ts<span class="op">...[</span>I<span class="op">]</span> <span class="kw">const</span><span class="op">&amp;</span> <span class="op">{</span></span>
<span id="cb11-43"><a href="#cb11-43"></a>        <span class="cf">return</span> elems<span class="op">...[</span>I<span class="op">]</span>;</span>
<span id="cb11-44"><a href="#cb11-44"></a>    <span class="op">}</span>    </span>
<span id="cb11-45"><a href="#cb11-45"></a><span class="op">}</span>;</span></code></pre></div></td>
</tr>
</tbody>
</table>
<h2 id="extending-structured-bindings"><span class="header-section-number">3.5</span> Extending Structured Bindings<a href="#extending-structured-bindings" class="self-link"></a></h2>
<p>Currently, there are three kinds of types that can be used with structured bindings <span class="citation" data-cites="P0144R2">[<a href="#ref-P0144R2" role="doc-biblioref">P0144R2</a>]</span>:</p>
<ol type="1">
<li><p>Arrays (specifically <code class="sourceCode cpp">T<span class="op">[</span>N<span class="op">]</span></code> and not <code class="sourceCode cpp">std<span class="op">::</span>array<span class="op">&lt;</span>T, N<span class="op">&gt;</span></code>).</p></li>
<li><p>Tuple-like: those tupes that 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 either provide a member or non-member <code class="sourceCode cpp">get<span class="op">()</span></code>.</p></li>
<li><p>Types where all of their members are public members of the same class (approximately).</p></li>
</ol>
<p>The problem with the tuple-like protocol here is that we need to instantiate a lot of templates. A declaration like:</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">auto</span> <span class="op">[</span>v<sub>1</sub>, v<sub>2</sub>, <span class="op">...</span>, v<sub>N</sub><span class="op">]</span> <span class="op">=</span> tuple;</span></code></pre></div>
<p>requires <code class="sourceCode cpp"><span class="dv">2</span><span class="er">N</span><span class="op">+</span><span class="dv">1</span></code> template instantiations: one for <code class="sourceCode cpp">std<span class="op">::</span>tuple_size</code>, <code class="sourceCode cpp">N</code> for <code class="sourceCode cpp">std<span class="op">::</span>tuple_element</code>, and another <code class="sourceCode cpp">N</code> for all the <code class="sourceCode cpp">get</code>s). That’s pretty wasteful. Additionally, the tuple-like protocol is tedious for users to implement. 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>This proposal reduces the customization surface in a different way that does not even require including <code class="sourceCode cpp"><span class="op">&lt;</span>tuple<span class="op">&gt;</span></code> for user-defined types. In the same way that this paper proposes defining member variable packs, it also allows member type alias packs. We can have our <code class="sourceCode cpp">tuple</code> declare a pack of its element types:</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="kw">namespace</span> xstd <span class="op">{</span></span>
<span id="cb13-2"><a href="#cb13-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="cb13-3"><a href="#cb13-3"></a>    <span class="kw">struct</span> tuple <span class="op">{</span></span>
<span id="cb13-4"><a href="#cb13-4"></a>        <span class="kw">using</span> <span class="op">...</span>tuple_element <span class="op">=</span> Ts;</span>
<span id="cb13-5"><a href="#cb13-5"></a>    <span class="op">}</span>;</span>
<span id="cb13-6"><a href="#cb13-6"></a><span class="op">}</span></span></code></pre></div>
<p>The advantage here is that the <code class="sourceCode cpp">tuple_element</code> pack provides both the size <em>and</em> all the types. We could then change add specializations to <code class="sourceCode cpp">std<span class="op">::</span>tuple_size</code> and <code class="sourceCode cpp">std<span class="op">::</span>tuple_element</code> to understand this:</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> T<span class="op">&gt;</span></span>
<span id="cb14-2"><a href="#cb14-2"></a>    <span class="kw">requires</span> <span class="op">(</span><span class="kw">sizeof</span><span class="op">...(</span>T<span class="op">::...</span>tuple_element<span class="op">))</span></span>
<span id="cb14-3"><a href="#cb14-3"></a><span class="kw">struct</span> tuple_size<span class="op">&lt;</span>T<span class="op">&gt;</span></span>
<span id="cb14-4"><a href="#cb14-4"></a>    <span class="op">:</span> integral_constant<span class="op">&lt;</span><span class="dt">size_t</span>, <span class="kw">sizeof</span><span class="op">...(</span>T<span class="op">::...</span>tuple_element<span class="op">)&gt;</span></span>
<span id="cb14-5"><a href="#cb14-5"></a><span class="op">{</span> <span class="op">}</span>;</span>
<span id="cb14-6"><a href="#cb14-6"></a></span>
<span id="cb14-7"><a href="#cb14-7"></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="cb14-8"><a href="#cb14-8"></a>    <span class="kw">requires</span> <span class="op">(</span><span class="kw">sizeof</span><span class="op">...(</span>T<span class="op">::...</span>tuple_element<span class="op">))</span></span>
<span id="cb14-9"><a href="#cb14-9"></a><span class="kw">struct</span> tuple_element<span class="op">&lt;</span>I, T<span class="op">&gt;</span></span>
<span id="cb14-10"><a href="#cb14-10"></a><span class="op">{</span></span>
<span id="cb14-11"><a href="#cb14-11"></a>    <span class="kw">using</span> type <span class="op">=</span> T<span class="op">::...</span>tuple_element<span class="op">...[</span>I<span class="op">]</span>;</span>
<span id="cb14-12"><a href="#cb14-12"></a><span class="op">}</span>;</span></code></pre></div>
<p>The extra preceding <code class="sourceCode cpp"><span class="op">...</span></code>s in the above code block are not typos, and will be explained in a <a href="#disambiguating-dependent">later section</a>.</p>
<p>At this point, we’d reduce the structured bindings protocol surface (<code class="sourceCode cpp">xstd<span class="op">::</span>tuple</code> did not have to specialize anything), so this is arguably better. You don’t have to leave your own namespace at all. But we still require all those extra instantiations.</p>
<p>What this paper proposes instead is to extend the language rules for structured bindings themselves to look directly for a member pack alias named <code class="sourceCode cpp">tuple_element</code>. That is, a type now is tuple-like if it <em>either</em>:</p>
<ol type="a">
<li>Has member pack alias <code class="sourceCode cpp">tuple_element</code>, in which case its size is the size of that pack and the element types are the constituents of that pack.</li>
<li>Has specialized <code class="sourceCode cpp">std<span class="op">::</span>tuple_size</code> and <code class="sourceCode cpp">std<span class="op">::</span>tuple_element</code>, as status quo.</li>
</ol>
<p>This library API change would allow for a complete structured bindings opt-in for our new <code class="sourceCode cpp">tuple</code> to be:</p>
<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">namespace</span> xstd <span class="op">{</span></span>
<span id="cb15-2"><a href="#cb15-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="cb15-3"><a href="#cb15-3"></a>    <span class="kw">class</span> tuple <span class="op">{</span></span>
<span id="cb15-4"><a href="#cb15-4"></a>        Ts<span class="op">...</span> elems;</span>
<span id="cb15-5"><a href="#cb15-5"></a>    <span class="kw">public</span><span class="op">:</span></span>
<span id="cb15-6"><a href="#cb15-6"></a>        <span class="kw">using</span> <span class="op">...</span>tuple_element <span class="op">=</span> Ts;</span>
<span id="cb15-7"><a href="#cb15-7"></a>    </span>
<span id="cb15-8"><a href="#cb15-8"></a>        <span class="kw">template</span> <span class="op">&lt;</span><span class="dt">size_t</span> I<span class="op">&gt;</span> <span class="kw">requires</span> I <span class="op">&lt;</span> <span class="kw">sizeof</span><span class="op">...(</span>Ts<span class="op">)</span></span>
<span id="cb15-9"><a href="#cb15-9"></a>        <span class="kw">auto</span> get<span class="op">()</span> <span class="op">&amp;</span> <span class="op">-&gt;</span> Ts<span class="op">...[</span>I<span class="op">]</span> <span class="op">&amp;</span> <span class="op">{</span></span>
<span id="cb15-10"><a href="#cb15-10"></a>            <span class="cf">return</span> elems<span class="op">...[</span>I<span class="op">]</span>;</span>
<span id="cb15-11"><a href="#cb15-11"></a>        <span class="op">}</span></span>
<span id="cb15-12"><a href="#cb15-12"></a>        </span>
<span id="cb15-13"><a href="#cb15-13"></a>        <span class="co">// + other overloads of get()</span></span>
<span id="cb15-14"><a href="#cb15-14"></a>    <span class="op">}</span>;</span>
<span id="cb15-15"><a href="#cb15-15"></a><span class="op">}</span>    </span>
<span id="cb15-16"><a href="#cb15-16"></a></span>
<span id="cb15-17"><a href="#cb15-17"></a><span class="dt">int</span> i <span class="op">=</span> <span class="dv">42</span>;</span>
<span id="cb15-18"><a href="#cb15-18"></a>tuple<span class="op">&lt;</span><span class="dt">int</span>, <span class="dt">int</span><span class="op">&amp;&gt;</span> t<span class="op">(</span><span class="dv">4</span>, i<span class="op">)</span>;</span>
<span id="cb15-19"><a href="#cb15-19"></a></span>
<span id="cb15-20"><a href="#cb15-20"></a><span class="co">// proposed okay with only the library code shown above</span></span>
<span id="cb15-21"><a href="#cb15-21"></a><span class="co">// no further specializations necessary</span></span>
<span id="cb15-22"><a href="#cb15-22"></a><span class="co">// decltype(val) is int</span></span>
<span id="cb15-23"><a href="#cb15-23"></a><span class="co">// decltype(ref) is int&amp;</span></span>
<span id="cb15-24"><a href="#cb15-24"></a><span class="kw">auto</span><span class="op">&amp;&amp;</span> <span class="op">[</span>val, ref<span class="op">]</span> <span class="op">=</span> t;</span></code></pre></div>
<p>Structured binding declarations for this new kind of tuple would only require <code class="sourceCode cpp">N</code> template instantiations (the <code class="sourceCode cpp">N</code> invocations to the member or non-member <code class="sourceCode cpp">get</code>), saving us a full <code class="sourceCode cpp">N<span class="op">+</span><span class="dv">1</span></code> instantiations (the ones for <code class="sourceCode cpp">std<span class="op">::</span>tuple_size</code> and <code class="sourceCode cpp">std<span class="op">::</span>tuple_element</code>).</p>
<h2 id="packs-at-block-scope"><span class="header-section-number">3.6</span> Packs at block scope<a href="#packs-at-block-scope" class="self-link"></a></h2>
<p>This section has thus far proposed the ability to declare member variable packs and member alias packs, which can greatly help implementing a type like <code class="sourceCode cpp">tuple</code>. For thoroughness, this paper also proposes the ability to declare variable packs and alias packs at block scope. That is:</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><span class="op">...</span> Ts<span class="op">&gt;</span></span>
<span id="cb16-2"><a href="#cb16-2"></a><span class="dt">void</span> foo<span class="op">(</span>Ts<span class="op">&amp;&amp;...</span> ts<span class="op">)</span> <span class="op">{</span></span>
<span id="cb16-3"><a href="#cb16-3"></a>    <span class="kw">using</span> <span class="op">...</span>decayed <span class="op">=</span> std<span class="op">::</span>decay_t<span class="op">&lt;</span>Ts<span class="op">&gt;</span>;</span>
<span id="cb16-4"><a href="#cb16-4"></a>    <span class="kw">auto</span><span class="op">...</span> copies <span class="op">=</span> std<span class="op">::</span>forward<span class="op">&lt;</span>Ts<span class="op">&gt;(</span>ts<span class="op">)</span>;</span>
<span id="cb16-5"><a href="#cb16-5"></a><span class="op">}</span></span></code></pre></div>
<h2 id="implementing-variant"><span class="header-section-number">3.7</span> Implementing variant<a href="#implementing-variant" class="self-link"></a></h2>
<p>The ability to declare a member pack and index into packs would also make it substantially easier to implement <code class="sourceCode cpp">variant</code>. In the same way that this paper is proposing allowing a member pack of a class type:</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><span class="op">...</span> Ts<span class="op">&gt;</span></span>
<span id="cb17-2"><a href="#cb17-2"></a><span class="kw">struct</span> tuple <span class="op">{</span></span>
<span id="cb17-3"><a href="#cb17-3"></a>    Ts<span class="op">...</span> vals;</span>
<span id="cb17-4"><a href="#cb17-4"></a><span class="op">}</span>;</span></code></pre></div>
<p>This paper also proposes allowing a member pack of a union type:</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>
<span id="cb18-2"><a href="#cb18-2"></a><span class="kw">union</span> variant <span class="op">{</span></span>
<span id="cb18-3"><a href="#cb18-3"></a>    Ts<span class="op">...</span> alts;</span>
<span id="cb18-4"><a href="#cb18-4"></a><span class="op">}</span>;</span></code></pre></div>
<p>This doesn’t just fall out naturally in the same way the class type case does. Packs behave as a single entity in the language today, and yet here we would need to have a part of an entity - we wouldn’t initialize the pack <code class="sourceCode cpp">alts<span class="op">...</span></code>, we would necessarily only have to initialize exactly one of element of that pack. But I don’t think that’s a huge stretch. And it makes for a substantial improvement in how user-friendly the implementation is.</p>
<p>As with the earlier tuple example, with the proposed language changes, this is something you can just sit down and implement. It practically rolls off the page, because the language would let you express your intent better. With the status quo, this is just a lot more design work in order to eventually produce a lot more code that is harder to understand and takes longer to compile.</p>
<p>The following is an implementation solely of the default constructor, the destructor, and <code class="sourceCode cpp">get_if</code>:</p>
<table>
<thead>
<tr class="header">
<th><div style="text-align:center">
<strong>Status Quo</strong>
</div></th>
<th><div style="text-align:center">
<strong>Proposed</strong>
</div></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><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="dt">size_t</span> I, <span class="kw">typename</span><span class="op">...</span> Ts<span class="op">&gt;</span></span>
<span id="cb19-2"><a href="#cb19-2"></a><span class="kw">union</span> impl <span class="op">{</span> <span class="op">}</span>;</span>
<span id="cb19-3"><a href="#cb19-3"></a></span>
<span id="cb19-4"><a href="#cb19-4"></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="kw">typename</span><span class="op">...</span> Ts<span class="op">&gt;</span></span>
<span id="cb19-5"><a href="#cb19-5"></a><span class="kw">union</span> impl<span class="op">&lt;</span>I, T, Ts<span class="op">...&gt;</span></span>
<span id="cb19-6"><a href="#cb19-6"></a><span class="op">{</span></span>
<span id="cb19-7"><a href="#cb19-7"></a><span class="kw">public</span><span class="op">:</span></span>
<span id="cb19-8"><a href="#cb19-8"></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="cb19-9"><a href="#cb19-9"></a>    <span class="kw">constexpr</span> impl<span class="op">(</span>in_place_index_t<span class="op">&lt;</span><span class="dv">0</span><span class="op">&gt;</span>, Args<span class="op">&amp;&amp;...</span> args<span class="op">)</span></span>
<span id="cb19-10"><a href="#cb19-10"></a>        <span class="op">:</span> head<span class="op">(</span>std<span class="op">::</span>forward<span class="op">&lt;</span>Args<span class="op">&gt;(</span>args<span class="op">)...)</span></span>
<span id="cb19-11"><a href="#cb19-11"></a>    <span class="op">{</span> <span class="op">}</span></span>
<span id="cb19-12"><a href="#cb19-12"></a>    </span>
<span id="cb19-13"><a href="#cb19-13"></a>    <span class="kw">template</span> <span class="op">&lt;</span><span class="dt">size_t</span> J, <span class="kw">typename</span><span class="op">...</span> Args<span class="op">&gt;</span></span>
<span id="cb19-14"><a href="#cb19-14"></a>    <span class="kw">constexpr</span> impl<span class="op">(</span>in_place_index_t<span class="op">&lt;</span>J<span class="op">&gt;</span>,</span>
<span id="cb19-15"><a href="#cb19-15"></a>            Args<span class="op">&amp;&amp;...</span> args<span class="op">)</span></span>
<span id="cb19-16"><a href="#cb19-16"></a>        <span class="op">:</span> tail<span class="op">(</span>in_place_index<span class="op">&lt;</span>J<span class="op">-</span><span class="dv">1</span><span class="op">&gt;</span>,</span>
<span id="cb19-17"><a href="#cb19-17"></a>            std<span class="op">::</span>forward<span class="op">&lt;</span>Args<span class="op">&gt;(</span>args<span class="op">)...)</span></span>
<span id="cb19-18"><a href="#cb19-18"></a>    <span class="op">{</span> <span class="op">}</span></span>
<span id="cb19-19"><a href="#cb19-19"></a>    </span>
<span id="cb19-20"><a href="#cb19-20"></a>    <span class="op">~</span>impl<span class="op">()</span></span>
<span id="cb19-21"><a href="#cb19-21"></a>        <span class="kw">requires</span> std<span class="op">::</span>is_trivially_destructible_v<span class="op">&lt;</span>T<span class="op">&gt;</span></span>
<span id="cb19-22"><a href="#cb19-22"></a>        <span class="op">=</span> <span class="cf">default</span>;</span>
<span id="cb19-23"><a href="#cb19-23"></a>    <span class="op">~</span>impl<span class="op">()</span> <span class="op">{</span> <span class="op">}</span></span>
<span id="cb19-24"><a href="#cb19-24"></a>    </span>
<span id="cb19-25"><a href="#cb19-25"></a>    <span class="kw">auto</span> get<span class="op">(</span>in_place_index_t<span class="op">&lt;</span><span class="dv">0</span><span class="op">&gt;)</span> <span class="op">-&gt;</span> T<span class="op">&amp;</span> <span class="op">{</span></span>
<span id="cb19-26"><a href="#cb19-26"></a>        <span class="cf">return</span> head;</span>
<span id="cb19-27"><a href="#cb19-27"></a>    <span class="op">}</span></span>
<span id="cb19-28"><a href="#cb19-28"></a>    <span class="kw">template</span> <span class="op">&lt;</span><span class="dt">size_t</span> J<span class="op">&gt;</span></span>
<span id="cb19-29"><a href="#cb19-29"></a>    <span class="kw">auto</span> get<span class="op">(</span>in_place_index_t<span class="op">&lt;</span>J<span class="op">&gt;)</span> <span class="op">-&gt;</span> <span class="kw">auto</span><span class="op">&amp;</span> <span class="op">{</span></span>
<span id="cb19-30"><a href="#cb19-30"></a>        <span class="cf">return</span> tail<span class="op">.</span>get<span class="op">(</span>in_place_index<span class="op">&lt;</span>J<span class="op">-</span><span class="dv">1</span><span class="op">&gt;)</span>;</span>
<span id="cb19-31"><a href="#cb19-31"></a>    <span class="op">}</span></span>
<span id="cb19-32"><a href="#cb19-32"></a><span class="kw">private</span><span class="op">:</span></span>
<span id="cb19-33"><a href="#cb19-33"></a>    <span class="dt">char</span> _;</span>
<span id="cb19-34"><a href="#cb19-34"></a>    T head;</span>
<span id="cb19-35"><a href="#cb19-35"></a>    impl<span class="op">&lt;</span>I<span class="op">+</span><span class="dv">1</span>, Ts<span class="op">...&gt;</span> tail;</span>
<span id="cb19-36"><a href="#cb19-36"></a><span class="op">}</span>;</span>
<span id="cb19-37"><a href="#cb19-37"></a></span>
<span id="cb19-38"><a href="#cb19-38"></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="cb19-39"><a href="#cb19-39"></a><span class="kw">class</span> variant <span class="op">{</span></span>
<span id="cb19-40"><a href="#cb19-40"></a>    <span class="dt">int</span> index_;</span>
<span id="cb19-41"><a href="#cb19-41"></a>    impl impl_;</span>
<span id="cb19-42"><a href="#cb19-42"></a></span>
<span id="cb19-43"><a href="#cb19-43"></a><span class="kw">public</span><span class="op">:</span></span>
<span id="cb19-44"><a href="#cb19-44"></a>    <span class="kw">constexpr</span> variant<span class="op">()</span></span>
<span id="cb19-45"><a href="#cb19-45"></a>        <span class="kw">requires</span> std<span class="op">::</span>default_constructible<span class="op">&lt;</span></span>
<span id="cb19-46"><a href="#cb19-46"></a>            mp_at_c<span class="op">&lt;</span><span class="dv">0</span>, mp_list<span class="op">&lt;</span>Ts<span class="op">...&gt;&gt;</span></span>
<span id="cb19-47"><a href="#cb19-47"></a>        <span class="op">:</span> index_<span class="op">(</span><span class="dv">0</span><span class="op">)</span></span>
<span id="cb19-48"><a href="#cb19-48"></a>        , impl_<span class="op">(</span>in_place_index<span class="op">&lt;</span><span class="dv">0</span><span class="op">&gt;)</span></span>
<span id="cb19-49"><a href="#cb19-49"></a>    <span class="op">{</span> <span class="op">}</span></span>
<span id="cb19-50"><a href="#cb19-50"></a>    </span>
<span id="cb19-51"><a href="#cb19-51"></a>    <span class="op">~</span>variant<span class="op">()</span></span>
<span id="cb19-52"><a href="#cb19-52"></a>      <span class="kw">requires</span> <span class="op">(</span>std<span class="op">::</span>is_trivially_destructible_v<span class="op">&lt;</span>Ts<span class="op">&gt;</span> <span class="op">&amp;&amp;</span> <span class="op">...)</span></span>
<span id="cb19-53"><a href="#cb19-53"></a>      <span class="op">=</span> <span class="cf">default</span>;</span>
<span id="cb19-54"><a href="#cb19-54"></a>    <span class="op">~</span>variant<span class="op">()</span> <span class="op">{</span></span>
<span id="cb19-55"><a href="#cb19-55"></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="cb19-56"><a href="#cb19-56"></a>            <span class="op">[](</span><span class="kw">auto</span> I<span class="op">)</span> <span class="op">{</span></span>
<span id="cb19-57"><a href="#cb19-57"></a>                <span class="kw">auto</span><span class="op">&amp;</span> alt <span class="op">=</span> impl<span class="op">.</span>get<span class="op">(</span>in_place_index<span class="op">&lt;</span>I<span class="op">&gt;)</span>;</span>
<span id="cb19-58"><a href="#cb19-58"></a>                std<span class="op">::</span>destroy_at<span class="op">(&amp;</span>alt<span class="op">)</span>;</span>
<span id="cb19-59"><a href="#cb19-59"></a>            <span class="op">})</span>;</span>
<span id="cb19-60"><a href="#cb19-60"></a>    <span class="op">}</span></span>
<span id="cb19-61"><a href="#cb19-61"></a><span class="op">}</span>;</span>
<span id="cb19-62"><a href="#cb19-62"></a></span>
<span id="cb19-63"><a href="#cb19-63"></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="cb19-64"><a href="#cb19-64"></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="cb19-65"><a href="#cb19-65"></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="cb19-66"><a href="#cb19-66"></a>    <span class="cf">if</span> <span class="op">(</span>v <span class="op">&amp;&amp;</span> v<span class="op">-&gt;</span>index_ <span class="op">==</span> I<span class="op">)</span> <span class="op">{</span></span>
<span id="cb19-67"><a href="#cb19-67"></a>        <span class="cf">return</span> <span class="op">&amp;</span>v<span class="op">-&gt;</span>impl<span class="op">.</span>get<span class="op">(</span>in_place_index<span class="op">&lt;</span>I<span class="op">&gt;)</span>;</span>
<span id="cb19-68"><a href="#cb19-68"></a>    <span class="op">}</span> <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb19-69"><a href="#cb19-69"></a>        <span class="cf">return</span> <span class="kw">nullptr</span>;</span>
<span id="cb19-70"><a href="#cb19-70"></a>    <span class="op">}</span></span>
<span id="cb19-71"><a href="#cb19-71"></a><span class="op">}</span></span></code></pre></div></td>
<td><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">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-2"><a href="#cb20-2"></a><span class="kw">class</span> variant <span class="op">{</span></span>
<span id="cb20-3"><a href="#cb20-3"></a>    <span class="dt">int</span> index_;</span>
<span id="cb20-4"><a href="#cb20-4"></a>    <span class="kw">union</span> <span class="op">{</span></span>
<span id="cb20-5"><a href="#cb20-5"></a>        Ts<span class="op">...</span> alts_;</span>
<span id="cb20-6"><a href="#cb20-6"></a>    <span class="op">}</span>;</span>
<span id="cb20-7"><a href="#cb20-7"></a><span class="kw">public</span><span class="op">:</span></span>
<span id="cb20-8"><a href="#cb20-8"></a>    <span class="kw">constexpr</span> variant<span class="op">()</span></span>
<span id="cb20-9"><a href="#cb20-9"></a>      <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="cb20-10"><a href="#cb20-10"></a>      <span class="op">:</span> index_<span class="op">(</span><span class="dv">0</span><span class="op">)</span></span>
<span id="cb20-11"><a href="#cb20-11"></a>      , alts_<span class="op">...[</span><span class="dv">0</span><span class="op">]()</span></span>
<span id="cb20-12"><a href="#cb20-12"></a>    <span class="op">{</span> <span class="op">}</span></span>
<span id="cb20-13"><a href="#cb20-13"></a></span>
<span id="cb20-14"><a href="#cb20-14"></a>    <span class="op">~</span>variant<span class="op">()</span></span>
<span id="cb20-15"><a href="#cb20-15"></a>      <span class="kw">requires</span> <span class="op">(</span>std<span class="op">::</span>is_trivially_destructible_v<span class="op">&lt;</span>Ts<span class="op">&gt;</span> <span class="op">&amp;&amp;</span> <span class="op">...)</span></span>
<span id="cb20-16"><a href="#cb20-16"></a>      <span class="op">=</span> <span class="cf">default</span>;</span>
<span id="cb20-17"><a href="#cb20-17"></a>    <span class="op">~</span>variant<span class="op">()</span> <span class="op">{</span></span>
<span id="cb20-18"><a href="#cb20-18"></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="cb20-19"><a href="#cb20-19"></a>            <span class="op">[](</span><span class="kw">auto</span> I<span class="op">){</span></span>
<span id="cb20-20"><a href="#cb20-20"></a>                std<span class="op">::</span>destroy_at<span class="op">(&amp;</span>alts_<span class="op">...[</span>I<span class="op">])</span>;</span>
<span id="cb20-21"><a href="#cb20-21"></a>            <span class="op">})</span>;</span>
<span id="cb20-22"><a href="#cb20-22"></a>    <span class="op">}</span></span>
<span id="cb20-23"><a href="#cb20-23"></a><span class="op">}</span>;</span>
<span id="cb20-24"><a href="#cb20-24"></a></span>
<span id="cb20-25"><a href="#cb20-25"></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="cb20-26"><a href="#cb20-26"></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="cb20-27"><a href="#cb20-27"></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="cb20-28"><a href="#cb20-28"></a>    <span class="cf">if</span> <span class="op">(</span>v <span class="op">&amp;&amp;</span> v<span class="op">-&gt;</span>index_ <span class="op">==</span> I<span class="op">)</span> <span class="op">{</span></span>
<span id="cb20-29"><a href="#cb20-29"></a>        <span class="cf">return</span> <span class="op">&amp;</span>v<span class="op">-&gt;</span>alts_<span class="op">...[</span>I<span class="op">]</span>;</span>
<span id="cb20-30"><a href="#cb20-30"></a>    <span class="op">}</span> <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb20-31"><a href="#cb20-31"></a>        <span class="cf">return</span> <span class="kw">nullptr</span>;</span>
<span id="cb20-32"><a href="#cb20-32"></a>    <span class="op">}</span></span>
<span id="cb20-33"><a href="#cb20-33"></a><span class="op">}</span></span></code></pre></div></td>
</tr>
</tbody>
</table>
<h2 id="other-examples"><span class="header-section-number">3.8</span> Other Examples<a href="#other-examples" class="self-link"></a></h2>
<h3 id="enumerating-over-a-pack"><span class="header-section-number">3.8.1</span> Enumerating over a pack<a href="#enumerating-over-a-pack" class="self-link"></a></h3>
<p>Pack indexing would also allow for the ability to enumerate over a pack, by iterating over the indices:</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><span class="op">...</span> Ts<span class="op">&gt;</span></span>
<span id="cb21-2"><a href="#cb21-2"></a><span class="dt">void</span> enumerate<span class="op">(</span>Ts<span class="op">...</span> ts<span class="op">)</span></span>
<span id="cb21-3"><a href="#cb21-3"></a><span class="op">{</span></span>
<span id="cb21-4"><a href="#cb21-4"></a>    <span class="kw">template</span> <span class="cf">for</span> <span class="op">(</span><span class="kw">constexpr</span> <span class="kw">auto</span> I <span class="op">:</span> views<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="cb21-5"><a href="#cb21-5"></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="cb21-6"><a href="#cb21-6"></a>    <span class="op">}</span></span>
<span id="cb21-7"><a href="#cb21-7"></a><span class="op">}</span></span></code></pre></div>
<h3 id="stdinteger_sequence-and-structured-bindings"><span class="header-section-number">3.8.2</span> <code class="sourceCode cpp">std<span class="op">::</span>integer_sequence</code> and structured bindings<a href="#stdinteger_sequence-and-structured-bindings" class="self-link"></a></h3>
<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 structured bindings:</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> T, T<span class="op">...</span> Values<span class="op">&gt;</span></span>
<span id="cb22-2"><a href="#cb22-2"></a><span class="kw">struct</span> integer_sequence <span class="op">{</span></span>
<span id="cb22-3"><a href="#cb22-3"></a>    <span class="kw">using</span> <span class="op">...</span>tuple_element <span class="op">=</span> integral_constant<span class="op">&lt;</span>T, Values<span class="op">&gt;</span>;</span>
<span id="cb22-4"><a href="#cb22-4"></a>    </span>
<span id="cb22-5"><a href="#cb22-5"></a>    <span class="kw">template</span> <span class="op">&lt;</span><span class="dt">size_t</span> I<span class="op">&gt;</span></span>
<span id="cb22-6"><a href="#cb22-6"></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>Values<span class="op">))</span></span>
<span id="cb22-7"><a href="#cb22-7"></a>    <span class="kw">constexpr</span> <span class="kw">auto</span> get<span class="op">()</span> <span class="kw">const</span> <span class="op">-&gt;</span> integral_constant<span class="op">&lt;</span>T, Values<span class="op">...[</span>I<span class="op">]&gt;</span> <span class="op">{</span></span>
<span id="cb22-8"><a href="#cb22-8"></a>        <span class="cf">return</span> <span class="op">{}</span>;</span>
<span id="cb22-9"><a href="#cb22-9"></a>    <span class="op">}</span></span>
<span id="cb22-10"><a href="#cb22-10"></a><span class="op">}</span>;</span></code></pre></div>
<p>We’ll see an even more interesting use of this proposal’s interaction with <code class="sourceCode cpp">index_sequence</code> in a <a href="#mp-with-index">later section</a>.</p>
<h1 id="expanding-a-type-into-a-pack" style="border-bottom:1px solid #cccccc"><span class="header-section-number">4</span> Expanding a type into a pack<a href="#expanding-a-type-into-a-pack" class="self-link"></a></h1>
<p>At this point, this paper has introduced:</p>
<ul>
<li>the ability to declare a packs in more places (member variable and member alias packs as well as block scope variable and alias packs)</li>
<li>the ability to index into a pack using the <code class="sourceCode cpp">pack<span class="op">...[</span>I<span class="op">]</span></code> syntax</li>
<li>an extension of structured bindings to look for a specific member alias pack named <code class="sourceCode cpp">tuple_element</code>, to reduce the API footprint.</li>
</ul>
<p>These, in of themselves, provide a lot of value. But I think there’s another big step that we could take that could provide a lot of value. This paper has proposed 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>. But there’s a lot of similarity between a pack of types and a tuple - which is basically a pack of types in single type form. And while we can index into a tuple (that’s what <code class="sourceCode cpp">tuple_element</code> does), the syntax difference between the two is rather large:</p>
<table>
<tr>
<th>
</th>
<th>
Pack
</th>
<th>
Tuple
</th>
</tr>
<tr>
<td style="vertical-align:middle">
Types
</td>
<td>
<div class="sourceCode" id="cb23"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb23-1"><a href="#cb23-1"></a>Types<span class="op">...[</span>I<span class="op">]</span></span></code></pre></div>
</td>
<td>
<div class="sourceCode" id="cb24"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb24-1"><a href="#cb24-1"></a>tuple_element_t<span class="op">&lt;</span>I, Tuple<span class="op">&gt;</span></span></code></pre></div>
</td>
</tr>
<tr>
<td style="vertical-align:middle">
Values
</td>
<td>
<div class="sourceCode" id="cb25"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb25-1"><a href="#cb25-1"></a>vals<span class="op">...[</span>I<span class="op">]</span></span></code></pre></div>
</td>
<td>
<div class="sourceCode" id="cb26"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb26-1"><a href="#cb26-1"></a>std<span class="op">::</span>get<span class="op">&lt;</span>I<span class="op">&gt;(</span>tuple<span class="op">)</span></span></code></pre></div>
</td>
</tr>
</table>
<p>The problem is that we’re used to having the thing we’re indexing on the left and the index on the right, and in the tuple case - this is inverted. If we could turn the <code class="sourceCode cpp">tuple</code> into a pack of its constituents, we could use the pack indexing operation. <span class="citation" data-cites="P1061R1">[<a href="#ref-P1061R1" role="doc-biblioref">P1061R1</a>]</span>, coupled with this paper thus far, would allow:</p>
<div class="sourceCode" id="cb27"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb27-1"><a href="#cb27-1"></a><span class="co">// structured bindings can now introduce a pack, so this is a</span></span>
<span id="cb27-2"><a href="#cb27-2"></a><span class="co">// tuple --&gt; pack conversion</span></span>
<span id="cb27-3"><a href="#cb27-3"></a><span class="kw">auto</span> <span class="op">[...</span>elems<span class="op">]</span> <span class="op">=</span> tuple;</span>
<span id="cb27-4"><a href="#cb27-4"></a></span>
<span id="cb27-5"><a href="#cb27-5"></a><span class="co">// pack indexing as usual</span></span>
<span id="cb27-6"><a href="#cb27-6"></a><span class="kw">auto</span> first <span class="op">=</span> elems<span class="op">...[</span><span class="dv">0</span><span class="op">]</span>;</span></code></pre></div>
<p>Note also that <span class="citation" data-cites="P1045R1">[<a href="#ref-P1045R1" role="doc-biblioref">P1045R1</a>]</span> would allow adding an <code class="sourceCode cpp"><span class="kw">operator</span><span class="op">[]</span></code> to <code class="sourceCode cpp">tuple</code> such that <code class="sourceCode cpp">tuple<span class="op">[</span><span class="dv">0</span><span class="op">]</span></code> actually works.</p>
<p>This paper proposes a more direct mechanism to accomplish this.</p>
<h2 id="generalized-unpacking-with"><span class="header-section-number">4.1</span> Generalized unpacking with <code class="sourceCode cpp"><span class="op">[:]</span></code><a href="#generalized-unpacking-with" class="self-link"></a></h2>
<p>This paper proposes a non-overloadable <code class="sourceCode cpp"><span class="op">[:]</span></code> operator which can be thought of as the “add a layer of packness” operator. The semantics of this operator are to unpack an object into the elements that would make up its respective structured binding declaration. For a <code class="sourceCode cpp">std<span class="op">::</span>tuple</code>, this would mean calls to <code class="sourceCode cpp">std<span class="op">::</span>get<span class="op">&lt;</span><span class="dv">0</span><span class="op">&gt;</span></code>, <code class="sourceCode cpp">std<span class="op">::</span>get<span class="op">&lt;</span><span class="dv">1</span><span class="op">&gt;</span></code>, … For an aggregate, this would mean aliases into its members. For the <code class="sourceCode cpp">xstd<span class="op">::</span>tuple</code> we defined earlier, this would be calls into the members <code class="sourceCode cpp">get<span class="op">&lt;</span><span class="dv">0</span><span class="op">&gt;()</span></code>, <code class="sourceCode cpp">get<span class="op">&lt;</span><span class="dv">1</span><span class="op">&gt;()</span>, <span class="op">...</span></code>. For arrays, this would be the elements of the array.</p>
<p>Once we add a layer of packness, the entity becomes a pack - and so all the usual rules around interacting with packs apply.</p>
<table>
<tr>
<th>
</th>
<th>
Pack
</th>
<th>
Tuple
</th>
</tr>
<tr>
<td style="vertical-align:middle">
Types
</td>
<td>
<div class="sourceCode" id="cb28"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb28-1"><a href="#cb28-1"></a>Types<span class="op">...[</span>I<span class="op">]</span></span></code></pre></div>
</td>
<td>
<div class="sourceCode" id="cb29"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb29-1"><a href="#cb29-1"></a>Tuple<span class="op">::[:]...[</span>I<span class="op">]</span></span></code></pre></div>
</td>
</tr>
<tr>
<td style="vertical-align:middle">
Values
</td>
<td>
<div class="sourceCode" id="cb30"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb30-1"><a href="#cb30-1"></a>vals<span class="op">...[</span>I<span class="op">]</span></span></code></pre></div>
</td>
<td>
<div class="sourceCode" id="cb31"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb31-1"><a href="#cb31-1"></a>tuple<span class="op">.[:]...[</span>I<span class="op">]</span></span></code></pre></div>
</td>
</tr>
</table>
<p>That’s a fairly involved syntax for a simple and common operation, so this paper proposes the shorthand <code class="sourceCode cpp">Tuple<span class="op">::[</span>I<span class="op">]</span></code> for that syntax. This is not a typo. The syntax for indexing into a pack (<code class="sourceCode cpp">Ts<span class="op">...[</span>I<span class="op">]</span></code>) and the syntax for indexing into a type (<code class="sourceCode cpp">Ts<span class="op">::[</span>I<span class="op">]</span></code>) are different and it’s important that they are different. A proper discussion of the motivation for the differing syntax will <a href="#disambiguating-packs">follow</a>, but the key is that these syntaxes be unambiguous.</p>
<table>
<tr>
<th>
</th>
<th>
Pack
</th>
<th>
Tuple
</th>
<th>
Tuple, sugared
</th>
</tr>
<tr>
<td style="vertical-align:middle">
Types
</td>
<td>
<div class="sourceCode" id="cb32"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb32-1"><a href="#cb32-1"></a>Types<span class="op">...[</span>I<span class="op">]</span></span></code></pre></div>
</td>
<td>
<div class="sourceCode" id="cb33"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb33-1"><a href="#cb33-1"></a>Tuple<span class="op">::[:]...[</span>I<span class="op">]</span></span></code></pre></div>
</td>
<td>
<div class="sourceCode" id="cb34"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb34-1"><a href="#cb34-1"></a>Tuple<span class="op">::[</span>I<span class="op">]</span></span></code></pre></div>
</td>
</tr>
<tr>
<td style="vertical-align:middle">
Values
</td>
<td>
<div class="sourceCode" id="cb35"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb35-1"><a href="#cb35-1"></a>vals<span class="op">...[</span>I<span class="op">]</span></span></code></pre></div>
</td>
<td>
<div class="sourceCode" id="cb36"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb36-1"><a href="#cb36-1"></a>tuple<span class="op">.[:]...[</span>I<span class="op">]</span></span></code></pre></div>
</td>
<td>
<div class="sourceCode" id="cb37"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb37-1"><a href="#cb37-1"></a>tuple<span class="op">.[</span>I<span class="op">]</span></span></code></pre></div>
</td>
</tr>
</table>
<p>This means we can take our tuple implementation from the previous section:</p>
<div class="sourceCode" id="cb38"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb38-1"><a href="#cb38-1"></a><span class="kw">namespace</span> xstd <span class="op">{</span></span>
<span id="cb38-2"><a href="#cb38-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="cb38-3"><a href="#cb38-3"></a>    <span class="kw">class</span> tuple <span class="op">{</span></span>
<span id="cb38-4"><a href="#cb38-4"></a>        Ts<span class="op">...</span> elems;</span>
<span id="cb38-5"><a href="#cb38-5"></a>    <span class="kw">public</span><span class="op">:</span></span>
<span id="cb38-6"><a href="#cb38-6"></a>        tuple<span class="op">(</span>Ts<span class="op">...</span> ts<span class="op">)</span> <span class="op">:</span> elems<span class="op">(</span>ts<span class="op">)...</span> <span class="op">{</span> <span class="op">}</span></span>
<span id="cb38-7"><a href="#cb38-7"></a>    </span>
<span id="cb38-8"><a href="#cb38-8"></a>        <span class="kw">using</span> <span class="op">...</span>tuple_element <span class="op">=</span> Ts;</span>
<span id="cb38-9"><a href="#cb38-9"></a>    </span>
<span id="cb38-10"><a href="#cb38-10"></a>        <span class="kw">template</span> <span class="op">&lt;</span><span class="dt">size_t</span> I<span class="op">&gt;</span> <span class="kw">requires</span> I <span class="op">&lt;</span> <span class="kw">sizeof</span><span class="op">...(</span>Ts<span class="op">)</span></span>
<span id="cb38-11"><a href="#cb38-11"></a>        <span class="kw">auto</span> get<span class="op">()</span> <span class="kw">const</span><span class="op">&amp;</span> <span class="op">-&gt;</span> Ts<span class="op">...[</span>I<span class="op">]&amp;</span> <span class="op">{</span> <span class="cf">return</span> elems<span class="op">...[</span>I<span class="op">]</span>; <span class="op">}</span></span>
<span id="cb38-12"><a href="#cb38-12"></a>    <span class="op">}</span>;</span>
<span id="cb38-13"><a href="#cb38-13"></a><span class="op">}</span></span></code></pre></div>
<p>And that is already sufficient to write:</p>
<div class="sourceCode" id="cb39"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb39-1"><a href="#cb39-1"></a>xstd<span class="op">::</span>tuple vals<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="cb39-2"><a href="#cb39-2"></a><span class="co">// direct indexing</span></span>
<span id="cb39-3"><a href="#cb39-3"></a><span class="ot">assert</span><span class="op">(</span>vals<span class="op">.[</span><span class="dv">0</span><span class="op">]</span> <span class="op">+</span> vals<span class="op">.[</span><span class="dv">1</span><span class="op">]</span> <span class="op">+</span> vals<span class="op">.[</span><span class="dv">2</span><span class="op">]</span> <span class="op">==</span> <span class="dv">6</span><span class="op">)</span>;</span>
<span id="cb39-4"><a href="#cb39-4"></a></span>
<span id="cb39-5"><a href="#cb39-5"></a><span class="co">// direct unpacking</span></span>
<span id="cb39-6"><a href="#cb39-6"></a><span class="kw">auto</span> sum <span class="op">=</span> <span class="op">(</span>vals<span class="op">.[:]</span> <span class="op">+</span> <span class="op">...)</span>;</span>
<span id="cb39-7"><a href="#cb39-7"></a><span class="ot">assert</span><span class="op">(</span>sum <span class="op">==</span> <span class="dv">6</span><span class="op">)</span>;</span></code></pre></div>
<p>Here <code class="sourceCode cpp">vals<span class="op">.[</span><span class="dv">0</span><span class="op">]</span></code> is the first structured binding, which for this tuple-like type means <code class="sourceCode cpp">vals<span class="op">.</span>get<span class="op">&lt;</span><span class="dv">0</span><span class="op">&gt;()</span></code>. <code class="sourceCode cpp">vals<span class="op">.[:]</span></code> is the pack consisting of all of the structured bindings, which means the pack <code class="sourceCode cpp"><span class="op">{</span>vals<span class="op">.</span>get<span class="op">&lt;</span><span class="dv">0</span><span class="op">&gt;()</span>, vals<span class="op">.</span>get<span class="op">&lt;</span><span class="dv">1</span><span class="op">&gt;()</span>, vals<span class="op">.</span>get<span class="op">&lt;</span><span class="dv">2</span><span class="op">&gt;()}</span></code>.</p>
<h2 id="syntax-free-unpacking"><span class="header-section-number">4.2</span> Syntax-free unpacking?<a href="#syntax-free-unpacking" class="self-link"></a></h2>
<p>The last example demonstrates the ability to turn the tuple <code class="sourceCode cpp">vals</code> into a pack by way of <code class="sourceCode cpp">vals<span class="op">.[:]</span></code>, at which point we can do any of the nice pack things with that entity (e.g. use a <em>fold-expression</em>, invoke a function, etc). Why do we need that though? Can’t we just have:</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> sum <span class="op">=</span> <span class="op">(</span>vals <span class="op">+</span> <span class="op">...)</span>;</span></code></pre></div>
<p>The problem is this direction would lead to ambiguities (as almost everything in this space inherently does):</p>
<div class="sourceCode" id="cb41"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb41-1"><a href="#cb41-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="cb41-2"><a href="#cb41-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="cb41-3"><a href="#cb41-3"></a><span class="op">{</span></span>
<span id="cb41-4"><a href="#cb41-4"></a>    <span class="co">// Is this intended to add &#39;t&#39; to each element in &#39;us&#39;</span></span>
<span id="cb41-5"><a href="#cb41-5"></a>    <span class="co">// or is intended to pairwise sum the tuple &#39;t&#39; and</span></span>
<span id="cb41-6"><a href="#cb41-6"></a>    <span class="co">// the pack &#39;us&#39;?</span></span>
<span id="cb41-7"><a href="#cb41-7"></a>    f<span class="op">((</span>t <span class="op">+</span> us<span class="op">)...)</span>;</span>
<span id="cb41-8"><a href="#cb41-8"></a><span class="op">}</span></span></code></pre></div>
<p>Both meanings are reasonable - so it’s left up to the programmer to express their intent:</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="co">// This adds &#39;t&#39; to each element in &#39;us&#39;</span></span>
<span id="cb42-2"><a href="#cb42-2"></a>f<span class="op">((</span>t <span class="op">+</span> us<span class="op">)...)</span>;</span>
<span id="cb42-3"><a href="#cb42-3"></a></span>
<span id="cb42-4"><a href="#cb42-4"></a><span class="co">// This adds each element in &#39;t&#39; to each element in &#39;us&#39;,</span></span>
<span id="cb42-5"><a href="#cb42-5"></a><span class="co">// if the two packs have different sizes, ill-formed</span></span>
<span id="cb42-6"><a href="#cb42-6"></a>f<span class="op">((</span>t<span class="op">.[:]</span> <span class="op">+</span> us<span class="op">)...)</span>;</span></code></pre></div>
<h2 id="other-examples-of-unpacking"><span class="header-section-number">4.3</span> Other examples of unpacking<a href="#other-examples-of-unpacking" class="self-link"></a></h2>
<p>Arrays are the easiest kind of structured binding. With <code class="sourceCode cpp"><span class="op">[:]</span></code>, they would unpack into all of their elements - which have the same type. Note that <code class="sourceCode cpp">arr<span class="op">[</span>i<span class="op">]</span></code> and <code class="sourceCode cpp">arr<span class="op">.[</span>i<span class="op">]</span></code> mean the same thing, except that in the latter case the index must be a constant expression.</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">void</span> bar<span class="op">(</span><span class="dt">int</span>, <span class="dt">int</span><span class="op">)</span>;</span>
<span id="cb43-2"><a href="#cb43-2"></a></span>
<span id="cb43-3"><a href="#cb43-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="cb43-4"><a href="#cb43-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>This directly allows unpacking types with all-public members as well:</p>
<div class="sourceCode" id="cb44"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb44-1"><a href="#cb44-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="cb44-2"><a href="#cb44-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="cb44-3"><a href="#cb44-3"></a></span>
<span id="cb44-4"><a href="#cb44-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="cb44-5"><a href="#cb44-5"></a>    <span class="co">// equivalent to: return x.i + x.j + y.k * y.k + y.m * y.m</span></span>
<span id="cb44-6"><a href="#cb44-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="cb44-7"><a href="#cb44-7"></a><span class="op">}</span></span></code></pre></div>
<p>And because for such types, structured binding calls the bindings themselves aliases rather than new variables, this works with bitfields:</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">struct</span> B <span class="op">{</span></span>
<span id="cb45-2"><a href="#cb45-2"></a>    <span class="dt">uint8_t</span> i <span class="op">:</span> <span class="dv">4</span>;</span>
<span id="cb45-3"><a href="#cb45-3"></a>    <span class="dt">uint8_t</span> j<span class="op">:</span> <span class="dv">4</span>;</span>
<span id="cb45-4"><a href="#cb45-4"></a><span class="op">}</span>;</span>
<span id="cb45-5"><a href="#cb45-5"></a>B b<span class="op">{.</span>i <span class="op">=</span> <span class="dv">2</span>, <span class="op">.</span>j <span class="op">=</span> <span class="dv">4</span><span class="op">}</span>;</span>
<span id="cb45-6"><a href="#cb45-6"></a><span class="ot">assert</span><span class="op">(</span>b<span class="op">.[</span><span class="dv">0</span><span class="op">]</span> <span class="op">+</span> b<span class="op">.[</span><span class="dv">1</span><span class="op">]</span> <span class="op">==</span> <span class="dv">6</span><span class="op">)</span>;</span></code></pre></div>
<h3 id="fixed-size-homogeneous-pack"><span class="header-section-number">4.3.1</span> Fixed-size homogeneous pack<a href="#fixed-size-homogeneous-pack" class="self-link"></a></h3>
<p>This 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="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> T, <span class="dt">int</span> N<span class="op">&gt;</span></span>
<span id="cb46-2"><a href="#cb46-2"></a><span class="kw">class</span> Vector <span class="op">{</span></span>
<span id="cb46-3"><a href="#cb46-3"></a><span class="kw">public</span><span class="op">:</span></span>
<span id="cb46-4"><a href="#cb46-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="cb46-5"><a href="#cb46-5"></a>    <span class="co">// expands directly into that</span></span>
<span id="cb46-6"><a href="#cb46-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="cb46-7"><a href="#cb46-7"></a><span class="op">}</span>;</span></code></pre></div>
<p>The type <code class="sourceCode cpp">Vector<span class="op">&lt;</span><span class="dt">int</span>, <span class="dv">3</span><span class="op">&gt;</span></code> will have a <em>non-template</em> constructor that takes three <code class="sourceCode cpp"><span class="dt">int</span></code>s. This works because <code class="sourceCode cpp"><span class="dt">int</span><span class="op">[</span><span class="dv">3</span><span class="op">]</span></code> is a type that can be used with structured bindings (being an array), so <code class="sourceCode cpp"><span class="dt">int</span><span class="op">[</span><span class="dv">3</span><span class="op">]::[:]</span></code> is the pack of types that would be the types of the bindings (i.e. <code class="sourceCode cpp"><span class="op">{</span><span class="dt">int</span>, <span class="dt">int</span>, <span class="dt">int</span><span class="op">}</span></code>). Which then expands into three <code class="sourceCode cpp"><span class="dt">int</span></code>s.</p>
<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> (I’m not claiming one behavior is better than the other - just noting the difference):</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">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="cb47-2"><a href="#cb47-2"></a><span class="kw">class</span> Vector2 <span class="op">{</span></span>
<span id="cb47-3"><a href="#cb47-3"></a><span class="kw">public</span><span class="op">:</span></span>
<span id="cb47-4"><a href="#cb47-4"></a>    <span class="co">// independently deduces each ts and requires that</span></span>
<span id="cb47-5"><a href="#cb47-5"></a>    <span class="co">// they all deduce to T. As opposed to the previous</span></span>
<span id="cb47-6"><a href="#cb47-6"></a>    <span class="co">// implementation which behaves as if the constructor</span></span>
<span id="cb47-7"><a href="#cb47-7"></a>    <span class="co">// were not a template, just that it took N T&#39;s.</span></span>
<span id="cb47-8"><a href="#cb47-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="cb47-9"><a href="#cb47-9"></a><span class="op">}</span>;</span></code></pre></div>
<p>For instance:</p>
<div class="sourceCode" id="cb48"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb48-1"><a href="#cb48-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="cb48-2"><a href="#cb48-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>
<h3 id="tuple-pair"><span class="header-section-number">4.3.2</span> Construct a <code class="sourceCode cpp">tuple</code> from a <code class="sourceCode cpp">pair</code><a href="#tuple-pair" class="self-link"></a></h3>
<p>We can also simplify the example we saw earlier where we were constructing a <code class="sourceCode cpp">tuple</code> from a <code class="sourceCode cpp">pair</code>:</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">namespace</span> xstd <span class="op">{</span></span>
<span id="cb49-2"><a href="#cb49-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="cb49-3"><a href="#cb49-3"></a>    <span class="kw">class</span> tuple <span class="op">{</span></span>
<span id="cb49-4"><a href="#cb49-4"></a>    <span class="kw">public</span><span class="op">:</span></span>
<span id="cb49-5"><a href="#cb49-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">&gt;...</span> Us<span class="op">&gt;</span></span>
<span id="cb49-6"><a href="#cb49-6"></a>        <span class="kw">constexpr</span> tuple<span class="op">(</span>std<span class="op">::</span>pair<span class="op">&lt;</span>Us<span class="op">...&gt;</span> <span class="kw">const</span><span class="op">&amp;</span> p<span class="op">)</span></span>
<span id="cb49-7"><a href="#cb49-7"></a>            <span class="op">:</span> elems<span class="op">(</span>p<span class="op">.[:])...</span></span>
<span id="cb49-8"><a href="#cb49-8"></a>        <span class="op">{</span> <span class="op">}</span></span>
<span id="cb49-9"><a href="#cb49-9"></a>    <span class="kw">private</span><span class="op">:</span></span>
<span id="cb49-10"><a href="#cb49-10"></a>        Ts<span class="op">...</span> elems;</span>
<span id="cb49-11"><a href="#cb49-11"></a>    <span class="op">}</span>;</span>
<span id="cb49-12"><a href="#cb49-12"></a><span class="op">}</span></span></code></pre></div>
<h3 id="mp-with-index"><span class="header-section-number">4.3.3</span> Implementing <code class="sourceCode cpp">make_index_sequence</code> without a compiler builtin<a href="#mp-with-index" class="self-link"></a></h3>
<p>You have always been able to implement a version of <code class="sourceCode cpp">make_index_sequence</code> that would decompose into a sequence of integral constants:</p>
<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="dt">size_t</span> N<span class="op">&gt;</span></span>
<span id="cb50-2"><a href="#cb50-2"></a><span class="kw">struct</span> index_seq <span class="op">{</span></span>
<span id="cb50-3"><a href="#cb50-3"></a>    <span class="kw">template</span> <span class="op">&lt;</span><span class="dt">size_t</span> I<span class="op">&gt;</span></span>
<span id="cb50-4"><a href="#cb50-4"></a>    <span class="kw">constexpr</span> <span class="kw">auto</span> get<span class="op">()</span> <span class="kw">const</span> <span class="op">-&gt;</span> std<span class="op">::</span>integral_constant<span class="op">&lt;</span><span class="dt">size_t</span>, I<span class="op">&gt;</span> <span class="op">{</span></span>
<span id="cb50-5"><a href="#cb50-5"></a>        <span class="cf">return</span> <span class="op">{}</span>;</span>
<span id="cb50-6"><a href="#cb50-6"></a>    <span class="op">}</span></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>
<span id="cb50-9"><a href="#cb50-9"></a><span class="kw">namespace</span> std <span class="op">{</span></span>
<span id="cb50-10"><a href="#cb50-10"></a>    <span class="kw">template</span> <span class="op">&lt;</span><span class="dt">size_t</span> N<span class="op">&gt;</span></span>
<span id="cb50-11"><a href="#cb50-11"></a>    <span class="kw">struct</span> tuple_size<span class="op">&lt;</span>index_seq<span class="op">&lt;</span>N<span class="op">&gt;&gt;</span></span>
<span id="cb50-12"><a href="#cb50-12"></a>        <span class="op">:</span> integral_constant<span class="op">&lt;</span><span class="dt">size_t</span>, N<span class="op">&gt;</span></span>
<span id="cb50-13"><a href="#cb50-13"></a>    <span class="op">{</span> <span class="op">}</span>;</span>
<span id="cb50-14"><a href="#cb50-14"></a>    </span>
<span id="cb50-15"><a href="#cb50-15"></a>    <span class="kw">template</span> <span class="op">&lt;</span><span class="dt">size_t</span> I, <span class="dt">size_t</span> N<span class="op">&gt;</span></span>
<span id="cb50-16"><a href="#cb50-16"></a>    <span class="kw">struct</span> tuple_element<span class="op">&lt;</span>I, index_seq<span class="op">&lt;</span>N<span class="op">&gt;&gt;</span> <span class="op">{</span></span>
<span id="cb50-17"><a href="#cb50-17"></a>        <span class="kw">using</span> type <span class="op">=</span> integral_constant<span class="op">&lt;</span><span class="dt">size_t</span>, I<span class="op">&gt;</span>;</span>
<span id="cb50-18"><a href="#cb50-18"></a>    <span class="op">}</span>;</span>
<span id="cb50-19"><a href="#cb50-19"></a><span class="op">}</span></span>
<span id="cb50-20"><a href="#cb50-20"></a></span>
<span id="cb50-21"><a href="#cb50-21"></a><span class="co">// a is an integral_constant&lt;size_t, 0&gt;</span></span>
<span id="cb50-22"><a href="#cb50-22"></a><span class="co">// b is an integral_constant&lt;size_t, 1&gt;</span></span>
<span id="cb50-23"><a href="#cb50-23"></a><span class="kw">auto</span> <span class="op">[</span>a, b<span class="op">]</span> <span class="op">=</span> index_seq<span class="op">&lt;</span><span class="dv">2</span><span class="op">&gt;()</span>;</span></code></pre></div>
<p>But this is actually totally useless because you need to know the number of identifiers to declare. With <span class="citation" data-cites="P1061R1">[<a href="#ref-P1061R1" role="doc-biblioref">P1061R1</a>]</span>, this becomes useful since you can write</p>
<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">auto</span> <span class="op">[...</span>Is<span class="op">]</span> <span class="op">=</span> index_seq<span class="op">&lt;</span>N<span class="op">&gt;()</span>;</span></code></pre></div>
<p>and now you don’t need to indirect through a lambda. With this proposal, it becomes more useful still since you don’t even need the extra declaration. You can implement Boost.Mp11’s <a href="https://www.boost.org/doc/libs/develop/libs/mp11/doc/html/mp11.html#mp_with_indexni_f"><code class="sourceCode cpp">mp_with_index</code></a> in a one liner:</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="dt">size_t</span> N, <span class="kw">typename</span> F<span class="op">&gt;</span></span>
<span id="cb52-2"><a href="#cb52-2"></a><span class="kw">decltype</span><span class="op">(</span><span class="kw">auto</span><span class="op">)</span> with_index<span class="op">(</span><span class="dt">size_t</span> i, F fn<span class="op">)</span></span>
<span id="cb52-3"><a href="#cb52-3"></a><span class="op">{</span>   </span>
<span id="cb52-4"><a href="#cb52-4"></a>    <span class="cf">return</span> array<span class="op">{</span></span>
<span id="cb52-5"><a href="#cb52-5"></a>        <span class="op">+[](</span>F<span class="op">&amp;</span> f<span class="op">)</span> <span class="op">-&gt;</span> <span class="kw">decltype</span><span class="op">(</span><span class="kw">auto</span><span class="op">)</span> <span class="op">{</span> <span class="cf">return</span> f<span class="op">(</span>index_seq<span class="op">&lt;</span>N<span class="op">&gt;{}.[:])</span>; <span class="op">}...</span></span>
<span id="cb52-6"><a href="#cb52-6"></a>    <span class="op">}[</span>i<span class="op">](</span>fn<span class="op">)</span>;</span>
<span id="cb52-7"><a href="#cb52-7"></a><span class="op">}</span></span></code></pre></div>
<h2 id="generalizing-slicing-further"><span class="header-section-number">4.4</span> Generalizing slicing further<a href="#generalizing-slicing-further" class="self-link"></a></h2>
<p>The reason the syntax <code class="sourceCode cpp"><span class="op">[:]</span></code> is chosen as the “add a layer of packness” operator is because it allows a further generlization. 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 sections of the pack.</p>
<p>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 type. <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 type. <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 of only 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="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">typename</span><span class="op">...</span> Args<span class="op">&gt;</span></span>
<span id="cb53-2"><a href="#cb53-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="cb53-3"><a href="#cb53-3"></a>    <span class="cf">return</span> std<span class="op">::</span>visit<span class="op">(</span></span>
<span id="cb53-4"><a href="#cb53-4"></a>        <span class="co">// the function first</span></span>
<span id="cb53-5"><a href="#cb53-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="cb53-6"><a href="#cb53-6"></a>        <span class="co">// all the variants next</span></span>
<span id="cb53-7"><a href="#cb53-7"></a>        <span class="co">// note that both slices on both Args and args are necessary, otherwise</span></span>
<span id="cb53-8"><a href="#cb53-8"></a>        <span class="co">// we end up with two packs of different sizes that need to get expanded</span></span>
<span id="cb53-9"><a href="#cb53-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="cb53-10"><a href="#cb53-10"></a><span class="op">}</span></span></code></pre></div>
<p>The seemingly excessive amount of dots is actually necessary. <code class="sourceCode cpp">args</code> is a pack, <code class="sourceCode cpp">args<span class="op">...</span></code> unpacks it, <code class="sourceCode cpp">args<span class="op">...[:-</span><span class="dv">1</span><span class="op">]</span></code> adds a layer of pack on it again - so it again needs to be expanded. Hence, <code class="sourceCode cpp">args<span class="op">...[:-</span><span class="dv">1</span><span class="op">]...</span></code> is a pack expansion consisting of all but the last element of the pack (which would be ill-formed for an empty pack).</p>
<p>It would also allow for a single-overload variadic fold:</p>
<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">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="cb54-2"><a href="#cb54-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="cb54-3"><a href="#cb54-3"></a><span class="op">{</span></span>
<span id="cb54-4"><a href="#cb54-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="cb54-5"><a href="#cb54-5"></a>        <span class="cf">return</span> z;</span>
<span id="cb54-6"><a href="#cb54-6"></a>    <span class="op">}</span> <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb54-7"><a href="#cb54-7"></a>        <span class="co">// we need to invoke f on z and the first elem in rest...</span></span>
<span id="cb54-8"><a href="#cb54-8"></a>        <span class="co">// and recurse, passing the rest of rest...</span></span>
<span id="cb54-9"><a href="#cb54-9"></a>        <span class="cf">return</span> fold<span class="op">(</span>f,</span>
<span id="cb54-10"><a href="#cb54-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="cb54-11"><a href="#cb54-11"></a>            rest<span class="op">...[</span><span class="dv">1</span><span class="op">:]...)</span>;</span>
<span id="cb54-12"><a href="#cb54-12"></a></span>
<span id="cb54-13"><a href="#cb54-13"></a>        <span class="co">// alternate formulation</span></span>
<span id="cb54-14"><a href="#cb54-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="cb54-15"><a href="#cb54-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="cb54-16"><a href="#cb54-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="cb54-17"><a href="#cb54-17"></a>    <span class="op">}</span></span>
<span id="cb54-18"><a href="#cb54-18"></a><span class="op">}</span></span></code></pre></div>
<h2 id="examples-with-boost.mp11"><span class="header-section-number">4.5</span> Examples with Boost.Mp11<a href="#examples-with-boost.mp11" class="self-link"></a></h2>
<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="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> pack_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><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> 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="cb55-4"><a href="#cb55-4"></a>    <span class="co">// a pack alias for the template arguments</span></span>
<span id="cb55-5"><a href="#cb55-5"></a>    <span class="kw">using</span> <span class="op">...</span>tuple_element <span class="op">=</span> Ts;</span>
<span id="cb55-6"><a href="#cb55-6"></a>    </span>
<span id="cb55-7"><a href="#cb55-7"></a>    <span class="co">// an alias template for the class template itself</span></span>
<span id="cb55-8"><a href="#cb55-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="cb55-9"><a href="#cb55-9"></a><span class="op">}</span>;</span>
<span id="cb55-10"><a href="#cb55-10"></a></span>
<span id="cb55-11"><a href="#cb55-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="cb55-12"><a href="#cb55-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="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 class="kw">struct</span> mp_front_impl;</span>
<span id="cb56-2"><a href="#cb56-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="cb56-3"><a href="#cb56-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="cb56-4"><a href="#cb56-4"></a>    <span class="kw">using</span> type <span class="op">=</span> T;</span>
<span id="cb56-5"><a href="#cb56-5"></a><span class="op">}</span>;</span>
<span id="cb56-6"><a href="#cb56-6"></a></span>
<span id="cb56-7"><a href="#cb56-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="cb56-8"><a href="#cb56-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="cb57"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb57-1"><a href="#cb57-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="cb57-2"><a href="#cb57-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="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 class="kw">struct</span> mp_pop_front_impl;</span>
<span id="cb58-2"><a href="#cb58-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="cb58-3"><a href="#cb58-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="cb58-4"><a href="#cb58-4"></a>    <span class="kw">using</span> type <span class="op">=</span> T;</span>
<span id="cb58-5"><a href="#cb58-5"></a><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="op">&gt;</span></span>
<span id="cb58-8"><a href="#cb58-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="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">class</span> L<span class="op">&gt;</span></span>
<span id="cb59-2"><a href="#cb59-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="cb59-3"><a href="#cb59-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="cb60"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb60-1"><a href="#cb60-1"></a><span class="co">// you get the idea</span></span>
<span id="cb60-2"><a href="#cb60-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="cb60-3"><a href="#cb60-3"></a><span class="kw">using</span> mp_second <span class="op">=</span> <span class="co">/* ... */</span>;</span>
<span id="cb60-4"><a href="#cb60-4"></a></span>
<span id="cb60-5"><a href="#cb60-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="cb60-6"><a href="#cb60-6"></a><span class="kw">using</span> mp_third <span class="op">=</span> <span class="co">/* ... */</span>;</span>
<span id="cb60-7"><a href="#cb60-7"></a></span>
<span id="cb60-8"><a href="#cb60-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="cb60-9"><a href="#cb60-9"></a><span class="kw">using</span> mp_push_front <span class="op">=</span> <span class="co">/* ... */</span>;</span>
<span id="cb60-10"><a href="#cb60-10"></a></span>
<span id="cb60-11"><a href="#cb60-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="cb60-12"><a href="#cb60-12"></a><span class="kw">using</span> mp_push_back <span class="op">=</span> <span class="co">/* ... */</span>;</span>
<span id="cb60-13"><a href="#cb60-13"></a></span>
<span id="cb60-14"><a href="#cb60-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="cb60-15"><a href="#cb60-15"></a><span class="kw">using</span> mp_replace_front <span class="op">=</span> <span class="co">/* ... */</span>;</span>
<span id="cb60-16"><a href="#cb60-16"></a></span>
<span id="cb60-17"><a href="#cb60-17"></a><span class="co">// ...</span></span></code></pre></div></td>
<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="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> L<span class="op">&gt;</span></span>
<span id="cb61-2"><a href="#cb61-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="cb61-3"><a href="#cb61-3"></a></span>
<span id="cb61-4"><a href="#cb61-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="cb61-5"><a href="#cb61-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="cb61-6"><a href="#cb61-6"></a></span>
<span id="cb61-7"><a href="#cb61-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="cb61-8"><a href="#cb61-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="cb61-9"><a href="#cb61-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="cb61-10"><a href="#cb61-10"></a></span>
<span id="cb61-11"><a href="#cb61-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="cb61-12"><a href="#cb61-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="cb61-13"><a href="#cb61-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="cb61-14"><a href="#cb61-14"></a></span>
<span id="cb61-15"><a href="#cb61-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="cb61-16"><a href="#cb61-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="cb61-17"><a href="#cb61-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>
<h1 id="can-functions-return-a-pack" style="border-bottom:1px solid #cccccc"><span class="header-section-number">5</span> Can functions return a pack?<a href="#can-functions-return-a-pack" class="self-link"></a></h1>
<p>The previous draft of this paper <span class="citation" data-cites="P1858R0">[<a href="#ref-P1858R0" role="doc-biblioref">P1858R0</a>]</span> also proposed the ability to have a function return a pack. This revision removes that part of the proposal. Consider:</p>
<div class="sourceCode" id="cb62"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb62-1"><a href="#cb62-1"></a><span class="dt">void</span> observe<span class="op">()</span>;</span>
<span id="cb62-2"><a href="#cb62-2"></a><span class="dt">void</span> consume<span class="op">(</span><span class="kw">auto</span><span class="op">...)</span>;</span>
<span id="cb62-3"><a href="#cb62-3"></a></span>
<span id="cb62-4"><a href="#cb62-4"></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="cb62-5"><a href="#cb62-5"></a><span class="kw">struct</span> copy_tuple <span class="op">{</span></span>
<span id="cb62-6"><a href="#cb62-6"></a>    Ts<span class="op">...</span> elems;</span>
<span id="cb62-7"><a href="#cb62-7"></a>    </span>
<span id="cb62-8"><a href="#cb62-8"></a>    Ts<span class="op">...</span> get<span class="op">()</span> <span class="kw">const</span> <span class="op">{</span></span>
<span id="cb62-9"><a href="#cb62-9"></a>        observe<span class="op">()</span>;</span>
<span id="cb62-10"><a href="#cb62-10"></a>        <span class="cf">return</span> elems;</span>
<span id="cb62-11"><a href="#cb62-11"></a>    <span class="op">}</span></span>
<span id="cb62-12"><a href="#cb62-12"></a><span class="op">}</span>;</span>
<span id="cb62-13"><a href="#cb62-13"></a></span>
<span id="cb62-14"><a href="#cb62-14"></a>copy_tuple<span class="op">&lt;</span>X, Y, Z<span class="op">&gt;</span> tuple<span class="op">(</span>x, y, z<span class="op">)</span>;</span>
<span id="cb62-15"><a href="#cb62-15"></a></span>
<span id="cb62-16"><a href="#cb62-16"></a><span class="co">// #1</span></span>
<span id="cb62-17"><a href="#cb62-17"></a>consume<span class="op">(</span>tuple<span class="op">.</span>get<span class="op">()...)</span>;</span>
<span id="cb62-18"><a href="#cb62-18"></a></span>
<span id="cb62-19"><a href="#cb62-19"></a><span class="co">// #2</span></span>
<span id="cb62-20"><a href="#cb62-20"></a>consume<span class="op">(</span>tuple<span class="op">.</span>get<span class="op">()...[</span><span class="dv">0</span><span class="op">])</span>;</span>
<span id="cb62-21"><a href="#cb62-21"></a></span>
<span id="cb62-22"><a href="#cb62-22"></a><span class="co">// #3</span></span>
<span id="cb62-23"><a href="#cb62-23"></a>consume<span class="op">(</span>tuple<span class="op">.</span>get<span class="op">()...[</span><span class="dv">0</span><span class="op">]</span>, tuple<span class="op">.</span>get<span class="op">()...[</span><span class="dv">1</span><span class="op">])</span>;</span></code></pre></div>
<p>There are two questions we have to answer for each call to <code class="sourceCode cpp">consume</code> there:</p>
<ol type="1">
<li>How many times is <code class="sourceCode cpp">observe<span class="op">()</span></code> invoked?</li>
<li>How many times are the <code class="sourceCode cpp">X</code>, <code class="sourceCode cpp">Y</code>, and <code class="sourceCode cpp">Z</code> copied?</li>
</ol>
<p>There are two models we can think about for how the <code class="sourceCode cpp">get<span class="op">()</span></code> function might work:</p>
<h3 id="language-tuple" class="unnumbered">Language Tuple<a href="#language-tuple" class="self-link"></a></h3>
<p><code class="sourceCode cpp">get<span class="op">()</span></code> behaves as if it returns a language tuple. That is, it’s syntax sugar for:</p>
<div class="sourceCode" id="cb63"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb63-1"><a href="#cb63-1"></a>tuple<span class="op">&lt;</span>Ts<span class="op">...&gt;</span> get<span class="op">()</span> <span class="kw">const</span> <span class="op">{</span></span>
<span id="cb63-2"><a href="#cb63-2"></a>    observe<span class="op">()</span>;</span>
<span id="cb63-3"><a href="#cb63-3"></a>    <span class="cf">return</span> <span class="op">{</span>elems<span class="op">...}</span>;</span>
<span id="cb63-4"><a href="#cb63-4"></a><span class="op">}</span></span></code></pre></div>
<p>Except that it’s already a pack. With this model, every call to <code class="sourceCode cpp">get<span class="op">()</span></code> calls <code class="sourceCode cpp">observe<span class="op">()</span></code> a single time and copies every element.</p>
<h3 id="pack-of-functions" class="unnumbered">Pack of functions<a href="#pack-of-functions" class="self-link"></a></h3>
<p><code class="sourceCode cpp">get<span class="op">()</span></code> behaves as if it declares a pack of functions. That is, it’s syntax sugar for:</p>
<div class="sourceCode" id="cb64"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb64-1"><a href="#cb64-1"></a>Ts<span class="op">...[</span><span class="dv">0</span><span class="op">]</span> get<span class="op">&lt;</span><span class="dv">0</span><span class="op">&gt;()</span> <span class="kw">const</span> <span class="op">{</span></span>
<span id="cb64-2"><a href="#cb64-2"></a>    observe<span class="op">()</span>;</span>
<span id="cb64-3"><a href="#cb64-3"></a>    <span class="cf">return</span> elems<span class="op">...[</span><span class="dv">0</span><span class="op">]</span>;</span>
<span id="cb64-4"><a href="#cb64-4"></a><span class="op">}</span></span>
<span id="cb64-5"><a href="#cb64-5"></a></span>
<span id="cb64-6"><a href="#cb64-6"></a>Ts<span class="op">...[</span><span class="dv">1</span><span class="op">]</span> get<span class="op">&lt;</span><span class="dv">1</span><span class="op">&gt;()</span> <span class="kw">const</span> <span class="op">{</span></span>
<span id="cb64-7"><a href="#cb64-7"></a>    observe<span class="op">()</span>;</span>
<span id="cb64-8"><a href="#cb64-8"></a>    <span class="cf">return</span> elems<span class="op">...[</span><span class="dv">1</span><span class="op">]</span>;</span>
<span id="cb64-9"><a href="#cb64-9"></a><span class="op">}</span></span>
<span id="cb64-10"><a href="#cb64-10"></a></span>
<span id="cb64-11"><a href="#cb64-11"></a><span class="co">// etc.</span></span></code></pre></div>
<p>With this model, each individual element access incurs a call to <code class="sourceCode cpp">observe<span class="op">()</span></code>, but only the desired element is copied.</p>
<h3 id="which-is-better" class="unnumbered">Which is better?<a href="#which-is-better" class="self-link"></a></h3>
<p>The problem is, both models are reasonable mental models and yet both models lead to some jarringly strange results:</p>
<ul>
<li><p>If we consider the language tuple model, then the example <code class="sourceCode cpp"><span class="pp">#3</span></code> - <code class="sourceCode cpp">consume<span class="op">(</span>tuple<span class="op">.</span>get<span class="op">()...[</span><span class="dv">0</span><span class="op">]</span>, tuple<span class="op">.</span>get<span class="op">()...[</span><span class="dv">1</span><span class="op">])</span></code> - would end up copying every element in the tuple, twice. Six copies, to get two elements?</p></li>
<li><p>If we consider the pack of functions mode, then the example <code class="sourceCode cpp"><span class="pp">#1</span></code> - <code class="sourceCode cpp">consume<span class="op">(</span>tuple<span class="op">.</span>get<span class="op">()...)</span></code> - would end up calling <code class="sourceCode cpp">observe<span class="op">()</span></code> three times. But it only looks like we’re invoking a single function?</p></li>
</ul>
<p>I don’t think either model is better than the other, so this paper punts on this problem entirely. There is no longer a proposal to allow functions returning packs.</p>
<h1 id="disambiguation" style="border-bottom:1px solid #cccccc"><span class="header-section-number">6</span> Disambiguation<a href="#disambiguation" class="self-link"></a></h1>
<p>There are many aspects of this proposal that require careful disambiguation. This section goes through those cases in turn.</p>
<h2 id="disambiguating-dependent"><span class="header-section-number">6.1</span> Disambiguating Dependent Packs<a href="#disambiguating-dependent" class="self-link"></a></h2>
<p>If we have a dependnet name that’s a pack, we need a way to disambiguate that it’s actually a pack. From <span class="citation" data-cites="Smith.Pack">[<a href="#ref-Smith.Pack" role="doc-biblioref">Smith.Pack</a>]</span>:</p>
<div class="quote">
<div class="sourceCode" id="cb65"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb65-1"><a href="#cb65-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="cb65-2"><a href="#cb65-2"></a>  f<span class="op">(</span>t<span class="op">.</span>x <span class="op">...)</span></span>
<span id="cb65-3"><a href="#cb65-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.</p>
</div>
<p>We need some kind of disambiguation. Perhaps some sort of context-sensitive keyword like <code class="sourceCode cpp">pack</code>?</p>
<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> T<span class="op">&gt;</span></span>
<span id="cb66-2"><a href="#cb66-2"></a>    <span class="kw">requires</span> <span class="op">(</span><span class="kw">sizeof</span><span class="op">...(</span>T<span class="op">::</span>pack tuple_element<span class="op">))</span></span>
<span id="cb66-3"><a href="#cb66-3"></a><span class="co">//                      ~~~^^^^^~~~~~~~~~~~~~</span></span>
<span id="cb66-4"><a href="#cb66-4"></a><span class="kw">struct</span> tuple_size<span class="op">&lt;</span>T<span class="op">&gt;</span></span>
<span id="cb66-5"><a href="#cb66-5"></a>    <span class="op">:</span> integral_constant<span class="op">&lt;</span><span class="dt">size_t</span>, <span class="kw">sizeof</span><span class="op">...(</span>T<span class="op">::</span>pack tuple_element<span class="op">)&gt;</span></span>
<span id="cb66-6"><a href="#cb66-6"></a>    <span class="co">//                                    ~~~^^^^^~~~~~~~~~~~~~</span></span>
<span id="cb66-7"><a href="#cb66-7"></a><span class="op">{</span> <span class="op">}</span>;</span></code></pre></div>
<p>Unfortunately that doesn’t work because of the possibility of something like:</p>
<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>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="cb67-2"><a href="#cb67-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="cb67-3"><a href="#cb67-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="cb67-4"><a href="#cb67-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. One thing we could consider is <code><span class="kw">packname</span></code> - which has the pleasant feature of having the same number of letters in it as both <code class="sourceCode cpp"><span class="kw">template</span></code> and <code class="sourceCode cpp"><span class="kw">typename</span></code>. But this paper suggests going a different direction instead.</p>
<h3 id="introducers"><span class="header-section-number">6.1.1</span> Pack introducers<a href="#introducers" class="self-link"></a></h3>
<p>As a brief aside, it’s worth enumerating the places in the language where we can introduce a pack today - because they all have an important feature in common:</p>
<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>T<span class="op">&gt;</span> <span class="co">// template parameter pack</span></span>
<span id="cb68-2"><a href="#cb68-2"></a><span class="dt">void</span> f<span class="op">(</span>T <span class="op">...</span>t<span class="op">)</span>           <span class="co">// function parameter pack</span></span>
<span id="cb68-3"><a href="#cb68-3"></a><span class="op">{</span></span>
<span id="cb68-4"><a href="#cb68-4"></a>   <span class="op">[...</span>u<span class="op">=</span>t<span class="op">]{}</span>;           <span class="co">// init-capture pack</span></span>
<span id="cb68-5"><a href="#cb68-5"></a><span class="op">}</span></span></code></pre></div>
<p>What these have in common is that is that the <code class="sourceCode cpp"><span class="op">...</span></code> always <em>precedes</em> the name that it introduces as a pack.</p>
<h3 id="proposed-disambigutation"><span class="header-section-number">6.1.2</span> Proposed disambigutation<a href="#proposed-disambigutation" class="self-link"></a></h3>
<p>To that end, an appropriate and consistent mechanism to disambiguate a dependent member pack might also be to use <em>preceding</em> ellipses (which still need to be separated by a space). That is:</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">template</span> <span class="op">&lt;</span><span class="kw">typename</span> T<span class="op">&gt;</span></span>
<span id="cb69-2"><a href="#cb69-2"></a>    <span class="kw">requires</span> <span class="op">(</span><span class="kw">sizeof</span><span class="op">...(</span>T<span class="op">::...</span>tuple_element<span class="op">))</span></span>
<span id="cb69-3"><a href="#cb69-3"></a><span class="kw">struct</span> tuple_size<span class="op">&lt;</span>T<span class="op">&gt;</span></span>
<span id="cb69-4"><a href="#cb69-4"></a>    <span class="op">:</span> integral_constant<span class="op">&lt;</span><span class="dt">size_t</span>, <span class="kw">sizeof</span><span class="op">...(</span>T<span class="op">::...</span>tuple_element<span class="op">)&gt;</span></span>
<span id="cb69-5"><a href="#cb69-5"></a><span class="op">{</span> <span class="op">}</span>;</span></code></pre></div>
<p>And once we disambiguated that <code class="sourceCode cpp">T<span class="op">::</span>tuple_element</code> is a pack, we still need to expand it - which may also require trailing ellipses:</p>
<div class="sourceCode" id="cb70"><pre class="sourceCode default"><code class="sourceCode default"><span id="cb70-1"><a href="#cb70-1"></a>template &lt;size_t I, typename T&gt;</span>
<span id="cb70-2"><a href="#cb70-2"></a>    requires (sizeof...(T::...tuple_element))</span>
<span id="cb70-3"><a href="#cb70-3"></a>struct tuple_element&lt;I, T&gt;</span>
<span id="cb70-4"><a href="#cb70-4"></a>{</span>
<span id="cb70-5"><a href="#cb70-5"></a>    using type = T::...tuple_element...[I];</span>
<span id="cb70-6"><a href="#cb70-6"></a>};</span></code></pre></div>
<p>That’s admittedly a lot of dots fairly close together. If that isn’t acceptable, then we can introduce a new disambiguating keyword:</p>
<div class="sourceCode" id="cb71"><pre class="sourceCode default"><code class="sourceCode default"><span id="cb71-1"><a href="#cb71-1"></a>template &lt;size_t I, typename T&gt;</span>
<span id="cb71-2"><a href="#cb71-2"></a>    requires (sizeof...(T::packname tuple_element))</span>
<span id="cb71-3"><a href="#cb71-3"></a>struct tuple_element&lt;I, T&gt;</span>
<span id="cb71-4"><a href="#cb71-4"></a>{</span>
<span id="cb71-5"><a href="#cb71-5"></a>    using type = T::packname tuple_element...[I];</span>
<span id="cb71-6"><a href="#cb71-6"></a>};</span></code></pre></div>
<h2 id="disambiguating-packs"><span class="header-section-number">6.2</span> Disambiguating packs of tuples<a href="#disambiguating-packs" 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">6.3</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="cb72"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb72-1"><a href="#cb72-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="cb72-2"><a href="#cb72-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="cb72-3"><a href="#cb72-3"></a>    bar<span class="op">(</span>e<span class="op">.[:]...</span> <span class="op">...)</span>;</span>
<span id="cb72-4"><a href="#cb72-4"></a><span class="op">}</span></span>
<span id="cb72-5"><a href="#cb72-5"></a></span>
<span id="cb72-6"><a href="#cb72-6"></a><span class="co">// what does this do?</span></span>
<span id="cb72-7"><a href="#cb72-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="cb73"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb73-1"><a href="#cb73-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="cb74"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb74-1"><a href="#cb74-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="cb75"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb75-1"><a href="#cb75-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="cb75-2"><a href="#cb75-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="cb75-3"><a href="#cb75-3"></a>    <span class="cf">return</span> std<span class="op">::</span>invoke<span class="op">(</span></span>
<span id="cb75-4"><a href="#cb75-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="cb75-5"><a href="#cb75-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="cb75-6"><a href="#cb75-6"></a><span class="op">}</span></span></code></pre></div>
<p>which, again more concretely, expands into something like:</p>
<div class="sourceCode" id="cb76"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb76-1"><a href="#cb76-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="cb76-2"><a href="#cb76-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="cb76-3"><a href="#cb76-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="cb76-4"><a href="#cb76-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="cb76-5"><a href="#cb76-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="cb76-6"><a href="#cb76-6"></a>        <span class="op">...</span></span>
<span id="cb76-7"><a href="#cb76-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="cb76-8"><a href="#cb76-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="cb77"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb77-1"><a href="#cb77-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="cb77-2"><a href="#cb77-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="cb77-3"><a href="#cb77-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="cb77-4"><a href="#cb77-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="cb78"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb78-1"><a href="#cb78-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="cb78-2"><a href="#cb78-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="cb78-3"><a href="#cb78-3"></a>    <span class="cf">return</span> std<span class="op">::</span>invoke<span class="op">(</span></span>
<span id="cb78-4"><a href="#cb78-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="cb78-5"><a href="#cb78-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="cb78-6"><a href="#cb78-6"></a><span class="op">}</span></span></code></pre></div>
<p>Admittedly, 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>
<h1 id="what-about-reflection" style="border-bottom:1px solid #cccccc"><span class="header-section-number">7</span> What about Reflection?<a href="#what-about-reflection" class="self-link"></a></h1>
<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>
<p>Note that one notable example missing here is a constructor for <code class="sourceCode cpp">tuple</code> - I really don’t know how to implement any of those constructors on top of reflection.</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="cb79"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb79-1"><a href="#cb79-1"></a><span class="co">// member pack declaration (P1717)</span></span>
<span id="cb79-2"><a href="#cb79-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="cb79-3"><a href="#cb79-3"></a><span class="kw">class</span> tuple <span class="op">{</span></span>
<span id="cb79-4"><a href="#cb79-4"></a>  <span class="kw">consteval</span> <span class="op">{</span></span>
<span id="cb79-5"><a href="#cb79-5"></a>    <span class="dt">int</span> counter <span class="op">=</span> <span class="dv">0</span>;</span>
<span id="cb79-6"><a href="#cb79-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="cb79-7"><a href="#cb79-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="cb79-8"><a href="#cb79-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="cb79-9"><a href="#cb79-9"></a>      <span class="op">}</span>;</span>
<span id="cb79-10"><a href="#cb79-10"></a>      <span class="op">-&gt;</span> fragment;</span>
<span id="cb79-11"><a href="#cb79-11"></a>      <span class="op">++</span>counter;</span>
<span id="cb79-12"><a href="#cb79-12"></a>    <span class="op">}</span></span>
<span id="cb79-13"><a href="#cb79-13"></a>  <span class="op">}</span></span>
<span id="cb79-14"><a href="#cb79-14"></a><span class="op">}</span>;</span></code></pre></div></td>
<td><div class="sourceCode" id="cb80"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb80-1"><a href="#cb80-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="cb80-2"><a href="#cb80-2"></a><span class="kw">class</span> tuple <span class="op">{</span></span>
<span id="cb80-3"><a href="#cb80-3"></a>  Types<span class="op">...</span> element;</span>
<span id="cb80-4"><a href="#cb80-4"></a><span class="op">}</span>;</span></code></pre></div></td>
</tr>
<tr class="even">
<td><div class="sourceCode" id="cb81"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb81-1"><a href="#cb81-1"></a><span class="co">// pack indexing (P1240)</span></span>
<span id="cb81-2"><a href="#cb81-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="cb81-3"><a href="#cb81-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="cb82"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb82-1"><a href="#cb82-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="cb82-2"><a href="#cb82-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="cb83"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb83-1"><a href="#cb83-1"></a><span class="co">// generalized pack indexing (P1240)</span></span>
<span id="cb83-2"><a href="#cb83-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="cb83-3"><a href="#cb83-3"></a><span class="kw">struct</span> tuple <span class="op">{</span></span>
<span id="cb83-4"><a href="#cb83-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="cb83-5"><a href="#cb83-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="cb83-6"><a href="#cb83-6"></a>  <span class="op">}</span></span>
<span id="cb83-7"><a href="#cb83-7"></a><span class="op">}</span>;</span>
<span id="cb83-8"><a href="#cb83-8"></a></span>
<span id="cb83-9"><a href="#cb83-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="cb83-10"><a href="#cb83-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="cb84"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb84-1"><a href="#cb84-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="cb84-2"><a href="#cb84-2"></a><span class="kw">struct</span> tuple <span class="op">{</span></span>
<span id="cb84-3"><a href="#cb84-3"></a>    <span class="kw">using</span> <span class="op">...</span> <span class="op">=</span> Types;</span>
<span id="cb84-4"><a href="#cb84-4"></a><span class="op">}</span>;</span>
<span id="cb84-5"><a href="#cb84-5"></a></span>
<span id="cb84-6"><a href="#cb84-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="cb84-7"><a href="#cb84-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="cb85"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb85-1"><a href="#cb85-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="cb85-2"><a href="#cb85-2"></a><span class="kw">struct</span> tuple <span class="op">{</span></span>
<span id="cb85-3"><a href="#cb85-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="cb85-4"><a href="#cb85-4"></a>    <span class="co">// return some range of vector&lt;meta::info&gt;</span></span>
<span id="cb85-5"><a href="#cb85-5"></a>    <span class="co">// here that represents the data members.</span></span>
<span id="cb85-6"><a href="#cb85-6"></a>    <span class="co">// I am not sure how to implement that</span></span>
<span id="cb85-7"><a href="#cb85-7"></a>  <span class="op">}</span></span>
<span id="cb85-8"><a href="#cb85-8"></a><span class="op">}</span>;</span>
<span id="cb85-9"><a href="#cb85-9"></a></span>
<span id="cb85-10"><a href="#cb85-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="cb85-11"><a href="#cb85-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="cb85-12"><a href="#cb85-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="cb85-13"><a href="#cb85-13"></a><span class="op">}</span></span></code></pre></div></td>
<td><div class="sourceCode" id="cb86"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb86-1"><a href="#cb86-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="cb86-2"><a href="#cb86-2"></a><span class="kw">struct</span> tuple <span class="op">{</span></span>
<span id="cb86-3"><a href="#cb86-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="cb86-4"><a href="#cb86-4"></a>  </span>
<span id="cb86-5"><a href="#cb86-5"></a>  Types<span class="op">...</span> elems;</span>
<span id="cb86-6"><a href="#cb86-6"></a><span class="op">}</span>;</span>
<span id="cb86-7"><a href="#cb86-7"></a></span>
<span id="cb86-8"><a href="#cb86-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="cb86-9"><a href="#cb86-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="cb86-10"><a href="#cb86-10"></a>  <span class="cf">return</span> f<span class="op">(</span>t<span class="op">.[:]...)</span>;</span>
<span id="cb86-11"><a href="#cb86-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. 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: neither from the perspective of declaring a pack (as in for <code class="sourceCode cpp">tuple</code> or <code class="sourceCode cpp">variant</code>) nor from the perspective of unpacking a tuple into a function or other expression.</p>
<p>If reflection can produce something much closer to what is being proposed here, I would happily table this proposal. But it seems to me that it’s fairly far off, and the functionality presented herein would be very useful.</p>
<h1 id="what-about-stdpair" style="border-bottom:1px solid #cccccc"><span class="header-section-number">8</span> What about <code class="sourceCode cpp">std<span class="op">:</span>pair</code>?<a href="#what-about-stdpair" 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 neither <code class="sourceCode cpp">std<span class="op">::</span>tuple<span class="op">&lt;</span>Ts<span class="op">...&gt;</span></code> nor <code class="sourceCode cpp">std<span class="op">::</span>variant<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>
<p>The nice thing about implementing <code class="sourceCode cpp">tuple</code> with the new structured bindings direction is that because everything <code class="sourceCode cpp">tuple</code> is already a pack, staying in the pack world remains very easy. But <code class="sourceCode cpp">pair</code> doesn’t have any packs, so it is missing out:</p>
<div class="sourceCode" id="cb87"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb87-1"><a href="#cb87-1"></a><span class="kw">namespace</span> xstd <span class="op">{</span></span>
<span id="cb87-2"><a href="#cb87-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="cb87-3"><a href="#cb87-3"></a>    <span class="kw">struct</span> pair <span class="op">{</span></span>
<span id="cb87-4"><a href="#cb87-4"></a>        T first;</span>
<span id="cb87-5"><a href="#cb87-5"></a>        U second;</span>
<span id="cb87-6"><a href="#cb87-6"></a>        </span>
<span id="cb87-7"><a href="#cb87-7"></a>        <span class="kw">using</span> <span class="op">...</span>tuple_element <span class="op">=</span> <span class="op">????</span>;</span>
<span id="cb87-8"><a href="#cb87-8"></a>        </span>
<span id="cb87-9"><a href="#cb87-9"></a>        <span class="kw">template</span> <span class="op">&lt;</span><span class="dt">size_t</span> I<span class="op">&gt;</span></span>
<span id="cb87-10"><a href="#cb87-10"></a>        <span class="kw">auto</span> get<span class="op">()</span> <span class="kw">const</span><span class="op">&amp;</span> <span class="op">-&gt;</span> tuple_element<span class="op">...[</span>I<span class="op">]</span> <span class="kw">const</span><span class="op">&amp;</span></span>
<span id="cb87-11"><a href="#cb87-11"></a>        <span class="op">{</span></span>
<span id="cb87-12"><a href="#cb87-12"></a>            <span class="cf">if</span> <span class="kw">constexpr</span> <span class="op">(</span>I <span class="op">==</span> <span class="dv">0</span><span class="op">)</span> <span class="cf">return</span> first;</span>
<span id="cb87-13"><a href="#cb87-13"></a>            <span class="cf">else</span> <span class="cf">if</span> constepxr <span class="op">(</span>I <span class="op">==</span> <span class="dv">1</span><span class="op">)</span> <span class="cf">return</span> second;</span>
<span id="cb87-14"><a href="#cb87-14"></a>        <span class="op">}</span></span>
<span id="cb87-15"><a href="#cb87-15"></a>    <span class="op">}</span>;</span>
<span id="cb87-16"><a href="#cb87-16"></a><span class="op">}</span></span></code></pre></div>
<p>How would we fill in the <code class="sourceCode cpp"><span class="op">????</span></code>s here? We need a pack there.</p>
<p>We could implement this in terms of tuple. <code class="sourceCode cpp">tuple<span class="op">&lt;</span>T, U<span class="op">&gt;::[:]</span></code> is a pack of two types, <code class="sourceCode cpp">T</code> and <code class="sourceCode cpp">U</code>. This works directly with the proposal as presented. It’s also a little odd, and indirect. But it works.</p>
<p>We could also come up with a way to introduce the pack we need directly, in-line, by way of a pack literal. Borrowing from the insight about how <a href="#introducers">pack introducers</a> work, this would either be <code class="sourceCode cpp"><span class="op">...&lt;</span>T, U<span class="op">&gt;</span></code> (using the syntax from <span class="citation" data-cites="P0341R0">[<a href="#ref-P0341R0" role="doc-biblioref">P0341R0</a>]</span> with the extra preceding ellipsis) or <code class="sourceCode cpp"><span class="op">...{</span>T, U<span class="op">}</span></code> (which would be in line with how gcc reports template errors when packs are involved).</p>
<p>A pack literal direction would also lead to a pack literal of values, which would add more fun with initialization:</p>
<div class="sourceCode" id="cb88"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb88-1"><a href="#cb88-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="cb88-2"><a href="#cb88-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 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.</p>
<p>Pack literals would also allow for adding default arguments to packs:</p>
<div class="sourceCode" id="cb89"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb89-1"><a href="#cb89-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">...&lt;</span><span class="dt">int</span><span class="op">&gt;&gt;</span></span>
<span id="cb89-2"><a href="#cb89-2"></a><span class="dt">void</span> foo<span class="op">(</span>Ts<span class="op">...</span> ts <span class="op">=</span> <span class="op">...{</span><span class="dv">0</span><span class="op">})</span>;</span>
<span id="cb89-3"><a href="#cb89-3"></a></span>
<span id="cb89-4"><a href="#cb89-4"></a>foo<span class="op">()</span>; <span class="co">// calls foo&lt;int&gt;(0);</span></span></code></pre></div>
<p>I’m not sure if this is sufficiently motivated to pursue, but would be curious to hear what people think about this matter.</p>
<h1 id="proposal" style="border-bottom:1px solid #cccccc"><span class="header-section-number">9</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">9.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 an unexpanded pack - which would then be expanded.</p>
<h2 id="dependent-packs"><span class="header-section-number">9.2</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>
<p>Non-dependent packs do not need any disambiguation (the disambiguation is allowed, but unnecessary).</p>
<h2 id="structured-bindings"><span class="header-section-number">9.3</span> Structured Bindings<a href="#structured-bindings" class="self-link"></a></h2>
<p>This paper proposes both that:</p>
<ol type="1">
<li><p><code class="sourceCode cpp">std<span class="op">::</span>tuple_size</code> and <code class="sourceCode cpp">std<span class="op">::</span>tuple_element</code> add specializations that look for a member pack named <code class="sourceCode cpp">tuple_element</code>, and drive their answers from that.</p></li>
<li><p>The tuple-like protocol for structured bindings itself directly first looks for a member pack named <code class="sourceCode cpp">tuple_element</code> before looking for specializations of the two <code class="sourceCode cpp">tuple</code> traits.</p></li>
</ol>
<h2 id="pack-indexing-1"><span class="header-section-number">9.4</span> Pack Indexing<a href="#pack-indexing-1" class="self-link"></a></h2>
<p>A pack can be indexed by expanding it and applying <code class="sourceCode cpp"><span class="op">[</span>I<span class="op">]</span></code> to the result. <code class="sourceCode cpp">p<span class="op">...[</span><span class="dv">0</span><span class="op">]</span></code> is the first element of the pack <code class="sourceCode cpp">p</code> (which can be a value, type, or template based on the kind of pack that <code class="sourceCode cpp">p</code> is).</p>
<p>This is a “sfinae-friendly” operation, so given:</p>
<div class="sourceCode" id="cb90"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb90-1"><a href="#cb90-1"></a><span class="kw">template</span> <span class="op">&lt;</span>typenae<span class="op">...</span> Ts<span class="op">&gt;</span></span>
<span id="cb90-2"><a href="#cb90-2"></a><span class="kw">auto</span> first<span class="op">(</span>Ts<span class="op">...</span> ts<span class="op">)</span> <span class="op">-&gt;</span> Ts<span class="op">...[</span><span class="dv">0</span><span class="op">]</span> <span class="op">{</span></span>
<span id="cb90-3"><a href="#cb90-3"></a>    <span class="cf">return</span> ts<span class="op">...[</span><span class="dv">0</span><span class="op">]</span>;</span>
<span id="cb90-4"><a href="#cb90-4"></a><span class="op">}</span></span></code></pre></div>
<p><code class="sourceCode cpp">first<span class="op">()</span></code> triggers a substitution failure, rather than a hard error.</p>
<h2 id="adding-a-layer-of-packness"><span class="header-section-number">9.5</span> Adding a layer of packness<a href="#adding-a-layer-of-packness" class="self-link"></a></h2>
<p>Given a value of a type that can be used on the right-hand side of a structured binding declaration, the <code class="sourceCode cpp"><span class="op">.[:]</span></code> operator may be applied to “add a layer of packness” - turning it into a pack of values consisting of what the structured bindings would have been.</p>
<p>A type that can be used in structured bindings can have the <code class="sourceCode cpp"><span class="op">::[:]</span></code> operator applied to it to likewise turn it into a pack of types.</p>
<div class="sourceCode" id="cb91"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb91-1"><a href="#cb91-1"></a><span class="dt">void</span> f<span class="op">(</span>std<span class="op">::</span>tuple<span class="op">&lt;</span><span class="dt">int</span>, <span class="dt">char</span>, <span class="dt">double</span><span class="op">&gt;</span> t<span class="op">)</span> <span class="op">{</span></span>
<span id="cb91-2"><a href="#cb91-2"></a>    <span class="co">// equivalent to g(std::get&lt;0&gt;(t), std::get&lt;1&gt;(t), std::get&lt;2&gt;(t))</span></span>
<span id="cb91-3"><a href="#cb91-3"></a>    <span class="co">// or, possibly, std::apply(g, t)</span></span>
<span id="cb91-4"><a href="#cb91-4"></a>    g<span class="op">(</span>t<span class="op">.[:]...)</span>;</span>
<span id="cb91-5"><a href="#cb91-5"></a>    </span>
<span id="cb91-6"><a href="#cb91-6"></a>    <span class="co">// decltype(u) is the same as T - just a really complex way to</span></span>
<span id="cb91-7"><a href="#cb91-7"></a>    <span class="co">// get there</span></span>
<span id="cb91-8"><a href="#cb91-8"></a>    <span class="kw">using</span> T <span class="op">=</span> <span class="kw">decltype</span><span class="op">(</span>t<span class="op">)</span>;</span>
<span id="cb91-9"><a href="#cb91-9"></a>    std<span class="op">::</span>tuple<span class="op">&lt;</span>T<span class="op">::[:]...&gt;</span> u <span class="op">=</span> t;</span>
<span id="cb91-10"><a href="#cb91-10"></a><span class="op">}</span></span></code></pre></div>
<p>The syntaxes <code class="sourceCode cpp">v<span class="op">.[</span>I<span class="op">]</span></code> and <code class="sourceCode cpp">T<span class="op">::[</span>I<span class="op">]</span></code> are shorthand for the syntaxes <code class="sourceCode cpp">v<span class="op">.[:]...[</span>I<span class="op">]</span></code> and <code class="sourceCode cpp">T<span class="op">::[:]...[</span>I<span class="op">]</span></code>, respectively.</p>
<h2 id="pack-slicing"><span class="header-section-number">9.6</span> Pack slicing<a href="#pack-slicing" class="self-link"></a></h2>
<p>While <code class="sourceCode cpp"><span class="op">.[:]</span></code> and <code class="sourceCode cpp"><span class="op">::[:]</span></code> add a layer of packness, turning the expression into a pack consisting of all of the underlying elements, the slice notation can also include either a start or end index, or both, to get just part of the pack.</p>
<div class="sourceCode" id="cb92"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb92-1"><a href="#cb92-1"></a><span class="dt">void</span> h<span class="op">(</span>std<span class="op">::</span>tuple<span class="op">&lt;</span><span class="dt">int</span>, <span class="dt">char</span>, <span class="dt">double</span><span class="op">&gt;</span> t<span class="op">)</span> <span class="op">{</span></span>
<span id="cb92-2"><a href="#cb92-2"></a>    <span class="co">// a is a tuple&lt;int, char, double&gt;</span></span>
<span id="cb92-3"><a href="#cb92-3"></a>    <span class="kw">auto</span> a <span class="op">=</span> std<span class="op">::</span>tuple<span class="op">(</span>t<span class="op">.[:]...)</span>;</span>
<span id="cb92-4"><a href="#cb92-4"></a>    </span>
<span id="cb92-5"><a href="#cb92-5"></a>    <span class="co">// b is a tuple&lt;char, double&gt;</span></span>
<span id="cb92-6"><a href="#cb92-6"></a>    <span class="kw">auto</span> b <span class="op">=</span> std<span class="op">::</span>tuple<span class="op">(</span>t<span class="op">.[</span><span class="dv">1</span><span class="op">:]...)</span>;</span>
<span id="cb92-7"><a href="#cb92-7"></a>    </span>
<span id="cb92-8"><a href="#cb92-8"></a>    <span class="co">// c is a tuple&lt;int, char&gt;</span></span>
<span id="cb92-9"><a href="#cb92-9"></a>    <span class="kw">auto</span> c <span class="op">=</span> std<span class="op">::</span>tuple<span class="op">(</span>t<span class="op">.[:-</span><span class="dv">1</span><span class="op">]...)</span>;</span>
<span id="cb92-10"><a href="#cb92-10"></a>    </span>
<span id="cb92-11"><a href="#cb92-11"></a>    <span class="co">// d is a tuple&lt;char&gt;</span></span>
<span id="cb92-12"><a href="#cb92-12"></a>    <span class="kw">auto</span> d <span class="op">=</span> std<span class="op">::</span>tuple<span class="op">(</span>t<span class="op">.[</span><span class="dv">1</span><span class="op">:</span><span class="dv">2</span><span class="op">]...)</span>;</span>
<span id="cb92-13"><a href="#cb92-13"></a><span class="op">}</span></span></code></pre></div>
<h1 id="acknowledgments" style="border-bottom:1px solid #cccccc"><span class="header-section-number">10</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">11</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-EWGI.Belfast">
<p>[EWGI.Belfast] EWGI. 2019. EWGI Discussion of P1858R0. <br />
<a href="http://wiki.edg.com/bin/view/Wg21belfast/P1858">http://wiki.edg.com/bin/view/Wg21belfast/P1858</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-P1045R1">
<p>[P1045R1] David Stone. 2019. constexpr Function Parameters. <br />
<a href="https://wg21.link/p1045r1">https://wg21.link/p1045r1</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-P1061R1">
<p>[P1061R1] Barry Revzin, Jonathan Wakely. 2019. Structured Bindings can introduce a Pack. <br />
<a href="https://wg21.link/p1061r1">https://wg21.link/p1061r1</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-P1858R0">
<p>[P1858R0] Barry Revzin. 2019. Generalized pack declaration and usage. <br />
<a href="https://wg21.link/p1858r0">https://wg21.link/p1858r0</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>
</div>
</div>
</body>
</html>
