<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils 0.12: http://docutils.sourceforge.net/" />
<title>Generalized Unpacking and Parameter Pack Slicing</title>
<meta name="date" content="2017-02-03" />
<meta name="author" content="Matthew Woehlke (mwoehlke.floss&#64;gmail.com)" />
<style type="text/css">

/*
:Author: David Goodger (goodger@python.org)
:Id: $Id: html4css1.css 7614 2013-02-21 15:55:51Z milde $
:Copyright: This stylesheet has been placed in the public domain.

Default cascading style sheet for the HTML output of Docutils.

See http://docutils.sf.net/docs/howto/html-stylesheets.html for how to
customize this style sheet.
*/

/* used to remove borders from tables and images */
.borderless, table.borderless td, table.borderless th {
  border: 0 }

table.borderless td, table.borderless th {
  /* Override padding for "table.docutils td" with "! important".
     The right padding separates the table cells. */
  padding: 0 0.5em 0 0 ! important }

.first {
  /* Override more specific margin styles with "! important". */
  margin-top: 0 ! important }

.last, .with-subtitle {
  margin-bottom: 0 ! important }

.hidden {
  display: none }

a.toc-backref {
  text-decoration: none ;
  color: black }

blockquote.epigraph {
  margin: 2em 5em ; }

dl.docutils dd {
  margin-bottom: 0.5em }

object[type="image/svg+xml"], object[type="application/x-shockwave-flash"] {
  overflow: hidden;
}

/* Uncomment (and remove this text!) to get bold-faced definition list terms
dl.docutils dt {
  font-weight: bold }
*/

div.abstract {
  margin: 2em 5em }

div.abstract p.topic-title {
  font-weight: bold ;
  text-align: center }

div.admonition, div.attention, div.caution, div.danger, div.error,
div.hint, div.important, div.note, div.tip, div.warning {
  margin: 2em ;
  border: medium outset ;
  padding: 1em }

div.admonition p.admonition-title, div.hint p.admonition-title,
div.important p.admonition-title, div.note p.admonition-title,
div.tip p.admonition-title {
  font-weight: bold ;
  font-family: sans-serif }

div.attention p.admonition-title, div.caution p.admonition-title,
div.danger p.admonition-title, div.error p.admonition-title,
div.warning p.admonition-title, .code .error {
  color: red ;
  font-weight: bold ;
  font-family: sans-serif }

/* Uncomment (and remove this text!) to get reduced vertical space in
   compound paragraphs.
div.compound .compound-first, div.compound .compound-middle {
  margin-bottom: 0.5em }

div.compound .compound-last, div.compound .compound-middle {
  margin-top: 0.5em }
*/

div.dedication {
  margin: 2em 5em ;
  text-align: center ;
  font-style: italic }

div.dedication p.topic-title {
  font-weight: bold ;
  font-style: normal }

div.figure {
  margin-left: 2em ;
  margin-right: 2em }

div.footer, div.header {
  clear: both;
  font-size: smaller }

div.line-block {
  display: block ;
  margin-top: 1em ;
  margin-bottom: 1em }

div.line-block div.line-block {
  margin-top: 0 ;
  margin-bottom: 0 ;
  margin-left: 1.5em }

div.sidebar {
  margin: 0 0 0.5em 1em ;
  border: medium outset ;
  padding: 1em ;
  background-color: #ffffee ;
  width: 40% ;
  float: right ;
  clear: right }

div.sidebar p.rubric {
  font-family: sans-serif ;
  font-size: medium }

div.system-messages {
  margin: 5em }

div.system-messages h1 {
  color: red }

div.system-message {
  border: medium outset ;
  padding: 1em }

div.system-message p.system-message-title {
  color: red ;
  font-weight: bold }

div.topic {
  margin: 2em }

h1.section-subtitle, h2.section-subtitle, h3.section-subtitle,
h4.section-subtitle, h5.section-subtitle, h6.section-subtitle {
  margin-top: 0.4em }

h1.title {
  text-align: center }

h2.subtitle {
  text-align: center }

hr.docutils {
  width: 75% }

img.align-left, .figure.align-left, object.align-left {
  clear: left ;
  float: left ;
  margin-right: 1em }

img.align-right, .figure.align-right, object.align-right {
  clear: right ;
  float: right ;
  margin-left: 1em }

img.align-center, .figure.align-center, object.align-center {
  display: block;
  margin-left: auto;
  margin-right: auto;
}

.align-left {
  text-align: left }

.align-center {
  clear: both ;
  text-align: center }

.align-right {
  text-align: right }

/* reset inner alignment in figures */
div.align-right {
  text-align: inherit }

/* div.align-center * { */
/*   text-align: left } */

ol.simple, ul.simple {
  margin-bottom: 1em }

ol.arabic {
  list-style: decimal }

ol.loweralpha {
  list-style: lower-alpha }

ol.upperalpha {
  list-style: upper-alpha }

ol.lowerroman {
  list-style: lower-roman }

ol.upperroman {
  list-style: upper-roman }

p.attribution {
  text-align: right ;
  margin-left: 50% }

p.caption {
  font-style: italic }

p.credits {
  font-style: italic ;
  font-size: smaller }

p.label {
  white-space: nowrap }

p.rubric {
  font-weight: bold ;
  font-size: larger ;
  color: maroon ;
  text-align: center }

p.sidebar-title {
  font-family: sans-serif ;
  font-weight: bold ;
  font-size: larger }

p.sidebar-subtitle {
  font-family: sans-serif ;
  font-weight: bold }

p.topic-title {
  font-weight: bold }

pre.address {
  margin-bottom: 0 ;
  margin-top: 0 ;
  font: inherit }

pre.literal-block, pre.doctest-block, pre.math, pre.code {
  margin-left: 2em ;
  margin-right: 2em }

pre.code .ln { color: grey; } /* line numbers */
pre.code, code { background-color: #eeeeee }
pre.code .comment, code .comment { color: #5C6576 }
pre.code .keyword, code .keyword { color: #3B0D06; font-weight: bold }
pre.code .literal.string, code .literal.string { color: #0C5404 }
pre.code .name.builtin, code .name.builtin { color: #352B84 }
pre.code .deleted, code .deleted { background-color: #DEB0A1}
pre.code .inserted, code .inserted { background-color: #A3D289}

span.classifier {
  font-family: sans-serif ;
  font-style: oblique }

span.classifier-delimiter {
  font-family: sans-serif ;
  font-weight: bold }

span.interpreted {
  font-family: sans-serif }

span.option {
  white-space: nowrap }

span.pre {
  white-space: pre }

span.problematic {
  color: red }

span.section-subtitle {
  /* font-size relative to parent (h1..h6 element) */
  font-size: 80% }

table.citation {
  border-left: solid 1px gray;
  margin-left: 1px }

table.docinfo {
  margin: 2em 4em }

table.docutils {
  margin-top: 0.5em ;
  margin-bottom: 0.5em }

table.footnote {
  border-left: solid 1px black;
  margin-left: 1px }

table.docutils td, table.docutils th,
table.docinfo td, table.docinfo th {
  padding-left: 0.5em ;
  padding-right: 0.5em ;
  vertical-align: top }

table.docutils th.field-name, table.docinfo th.docinfo-name {
  font-weight: bold ;
  text-align: left ;
  white-space: nowrap ;
  padding-left: 0 }

/* "booktabs" style (no vertical lines) */
table.docutils.booktabs {
  border: 0px;
  border-top: 2px solid;
  border-bottom: 2px solid;
  border-collapse: collapse;
}
table.docutils.booktabs * {
  border: 0px;
}
table.docutils.booktabs th {
  border-bottom: thin solid;
  text-align: left;
}

h1 tt.docutils, h2 tt.docutils, h3 tt.docutils,
h4 tt.docutils, h5 tt.docutils, h6 tt.docutils {
  font-size: 100% }

ul.auto-toc {
  list-style-type: none }

</style>
</head>
<body>
<div class="document" id="generalized-unpacking-and-parameter-pack-slicing">
<h1 class="title">Generalized Unpacking and Parameter Pack Slicing</h1>
<table class="docinfo" frame="void" rules="none">
<col class="docinfo-name" />
<col class="docinfo-content" />
<tbody valign="top">
<tr class="field"><th class="docinfo-name">Document:</th><td class="field-body">P0535R0</td>
</tr>
<tr><th class="docinfo-name">Date:</th>
<td>2017-02-03</td></tr>
<tr class="field"><th class="docinfo-name">Project:</th><td class="field-body">ISO/IEC JTC1 SC22 WG21 Programming Language C++</td>
</tr>
<tr class="field"><th class="docinfo-name">Audience:</th><td class="field-body">Evolution Working Group</td>
</tr>
<tr><th class="docinfo-name">Author:</th>
<td>Matthew Woehlke (<a class="reference external" href="mailto:mwoehlke.floss&#64;gmail.com">mwoehlke.floss&#64;gmail.com</a>)</td></tr>
</tbody>
</table>
<style>
  html { color: black; background: white; }
  table.docinfo { margin: 2em 0; }
  p, li { text-align: justify; }
  li { margin-bottom: 0.5em; }
  .lit { font-weight: bold; padding: 0 0.3em; }
  .var { font-style: italic; padding: 0 0.3em; }
  .opt::after { font-size: 70%; position: relative; bottom: -0.25em; content: "opt"; }
</style><div class="section" id="abstract">
<h1><a class="toc-backref" href="#id4">Abstract</a></h1>
<p>This proposal introduces two new, related concepts: &quot;generalized unpacking&quot; (the conversion of product types to parameter packs) and parameter pack slicing. These concepts use the same syntax and may be employed concurrently.</p>
<div class="contents topic" id="contents">
<p class="topic-title first">Contents</p>
<ul class="simple">
<li><a class="reference internal" href="#abstract" id="id4">Abstract</a></li>
<li><a class="reference internal" href="#background" id="id5">Background</a></li>
<li><a class="reference internal" href="#rationale" id="id6">Rationale</a></li>
<li><a class="reference internal" href="#proposal" id="id7">Proposal</a><ul>
<li><a class="reference internal" href="#parameter-pack-slicing" id="id8">Parameter Pack Slicing</a></li>
<li><a class="reference internal" href="#generalized-unpacking" id="id9">Generalized Unpacking</a></li>
</ul>
</li>
<li><a class="reference internal" href="#additional-examples" id="id10">Additional Examples</a><ul>
<li><a class="reference internal" href="#heads-and-tails" id="id11">Heads and Tails</a></li>
<li><a class="reference internal" href="#divide-and-conquer" id="id12">Divide-and-Conquer</a></li>
<li><a class="reference internal" href="#unpacking-and-fold-expressions" id="id13">Unpacking and Fold Expressions</a></li>
<li><a class="reference internal" href="#slicing-product-types" id="id14">Slicing Product Types</a></li>
<li><a class="reference internal" href="#improving-std-apply" id="id15">Improving <code class="cpp c++"><span class="name">std</span><span class="operator">::</span><span class="name">apply</span></code></a></li>
<li><a class="reference internal" href="#reversing-a-product-type" id="id16">Reversing a product type</a></li>
<li><a class="reference internal" href="#static-value-table" id="id17">Static value table</a></li>
</ul>
</li>
<li><a class="reference internal" href="#discussion" id="id18">Discussion</a><ul>
<li><a class="reference internal" href="#what-is-a-product-type" id="id19">What is a &quot;product type&quot;?</a></li>
<li><a class="reference internal" href="#why-combine-these-features" id="id20">Why combine these features?</a></li>
<li><a class="reference internal" href="#why-choose-prefix-operator" id="id21">Why choose prefix <code class="cpp c++"><span class="keyword">operator</span><span class="punctuation">[]</span></code>?</a></li>
<li><a class="reference internal" href="#does-this-conflict-with-operator-constexpr-size-t" id="id22">Does this conflict with <code class="cpp c++"><span class="keyword">operator</span><span class="punctuation">[](</span><span class="name">constexpr</span> <span class="keyword type">size_t</span><span class="punctuation">)</span></code>?</a></li>
<li><a class="reference internal" href="#doesn-t-adding-another-operator-hurt-teachability" id="id23">Doesn't adding another operator hurt teachability?</a></li>
<li><a class="reference internal" href="#does-this-make-std-apply-and-std-make-from-tuple-obsolete" id="id24">Does this make <code class="cpp c++"><span class="name">std</span><span class="operator">::</span><span class="name">apply</span></code> (and <code class="cpp c++"><span class="name">std</span><span class="operator">::</span><span class="name">make_from_tuple</span></code>) obsolete?</a></li>
<li><a class="reference internal" href="#are-dead-accesses-to-product-type-value-elided" id="id25">Are &quot;dead&quot; accesses to product type value elided?</a></li>
<li><a class="reference internal" href="#how-does-unpacking-interact-with-temporaries" id="id26">How does unpacking interact with temporaries?</a></li>
<li><a class="reference internal" href="#what-happens-if-the-indexing-expression-contains-a-pack" id="id27">What happens if the indexing expression contains a pack?</a></li>
<li><a class="reference internal" href="#what-about-ambiguity-with-lambda-captures" id="id28">What about ambiguity with lambda captures?</a></li>
<li><a class="reference internal" href="#should-out-of-bounds-access-be-an-error" id="id29">Should out-of-bounds access be an error?</a></li>
<li><a class="reference internal" href="#why-choose-trailing-index" id="id30">Why choose trailing index?</a></li>
<li><a class="reference internal" href="#why-extend-sizeof" id="id31">Why extend <code class="cpp c++"><span class="keyword">sizeof</span><span class="punctuation">...</span></code>?</a></li>
<li><a class="reference internal" href="#can-t-we-use-a-purely-library-solution" id="id32">Can't we use a purely library solution?</a></li>
<li><a class="reference internal" href="#what-alternatives-were-considered" id="id33">What alternatives were considered?</a></li>
<li><a class="reference internal" href="#how-does-this-relate-to-p0341" id="id34">How does this relate to P0341?</a></li>
<li><a class="reference internal" href="#how-does-this-relate-to-p0478" id="id35">How does this relate to P0478?</a></li>
</ul>
</li>
<li><a class="reference internal" href="#future-direction" id="id36">Future Direction</a><ul>
<li><a class="reference internal" href="#complex-ordering" id="id37">Complex Ordering</a></li>
<li><a class="reference internal" href="#interaction-with-name-binding-unpacking" id="id38">Interaction with Name-Binding Unpacking</a></li>
<li><a class="reference internal" href="#pack-generators-lite" id="id39">Pack Generators &quot;Lite&quot;</a></li>
</ul>
</li>
<li><a class="reference internal" href="#acknowledgments" id="id40">Acknowledgments</a></li>
<li><a class="reference internal" href="#footnotes" id="id41">Footnotes</a></li>
<li><a class="reference internal" href="#references" id="id42">References</a></li>
</ul>
</div>
</div>
<div class="section" id="background">
<h1><a class="toc-backref" href="#id5">Background</a></h1>
<p>There is an increasing push in C++ to add interoperability between values and value sequences, exemplified by the recent addition of &quot;structured binding&quot;, <code class="cpp c++"><span class="name">std</span><span class="operator">::</span><span class="name">apply</span></code>, and <code class="cpp c++"><span class="name">std</span><span class="operator">::</span><span class="name">make_from_tuple</span></code> in C++17, and by proposals such as <a class="reference external" href="http://wg21.link/p0327">P0327</a><a class="footnote-reference" href="#io" id="id1">[1]</a> that work toward expanding and clarifying the concept of value sequences (using the term &quot;product type&quot;) and <a class="reference external" href="http://wg21.link/p0341">P0341</a> which proposes certain mechanisms for using product types. Similar features have long been present in other languages, with Python frequently held up as a representative example (see also <a class="reference external" href="https://www.python.org/dev/peps/pep-0448">PEP 0448</a>). While we feel that these represent steps in the right direction, there remain problems to be solved.</p>
</div>
<div class="section" id="rationale">
<h1><a class="toc-backref" href="#id6">Rationale</a></h1>
<p>Parameter pack slicing, particularly single valued slicing (i.e. indexing), solves a known problem when working with parameter packs. Several algorithms and ideas for working with parameter packs require the ability to select an item from a parameter pack by index.</p>
<p>Generalized unpacking greatly expands the ability to work with product types. Although <code class="cpp c++"><span class="name">std</span><span class="operator">::</span><span class="name">apply</span></code> and <code class="cpp c++"><span class="name">std</span><span class="operator">::</span><span class="name">make_from_tuple</span></code> attempt to fill some of these roles, their mere existence, and especially that they are two separate functions despite serving conceptually identical purposes, is indicative of the usefulness of a language feature. Moreover, these functions have significant limitations: they can only cover specific use cases, they cannot perform slicing operations on their own, and they cannot be readily used where the desired argument list <em>includes</em> but does not <em>solely consist of</em> a single product type.</p>
<p>Although we could attempt to solve these issues independently, we believe it is better to approach them together.</p>
</div>
<div class="section" id="proposal">
<h1><a class="toc-backref" href="#id7">Proposal</a></h1>
<p>We present our proposal in two parts. First, we present the proposed syntax and examine its function in the context of parameter packs. Second, we extend the application of the proposed syntax to also incorporate &quot;concrete&quot; product types.</p>
<div class="section" id="parameter-pack-slicing">
<h2><a class="toc-backref" href="#id8">Parameter Pack Slicing</a></h2>
<p>We propose to introduce a new prefix operator, <code class="lit">[</code><code class="var">slicing_expression</code><code class="lit">]</code>, which may be applied to an expression producing a parameter pack. The syntax of <code class="var">slicing_expression</code> shall be one of <code class="var">index</code> or <code class="opt var">index</code><code class="lit">:</code><code class="opt var">index</code>, where each <code class="var">index</code> is a <code class="cpp c++"><span class="name">constexpr</span></code> of integer type. For the purposes of the following specification, also let <code class="var">pack_expression</code> be the operand of the slicing expression.</p>
<p>The first form shall select a <em>single</em> element of a pack, and shall yield this value as a single value (i.e. not as a new pack). For example, the expression <code class="cpp c++"><span class="punctuation">[</span><span class="literal number integer">1</span><span class="punctuation">]</span><span class="name">pack</span></code> shall yield the second value of the parameter pack <code class="cpp c++"><span class="name">pack</span></code>. If the <code class="var">index</code> is negative, it shall first be added to <code class="cpp c++"><span class="keyword">sizeof</span><span class="punctuation">...(</span></code><code class="var">pack_expression</code><code class="cpp c++"><span class="punctuation">)</span></code>. If the index (after the preceding step, if applicable) is out of bounds, the expression shall be ill-formed.</p>
<p>The second form shall return a <em>variable</em> slice of the parameter pack, and shall yield this value as a new parameter pack. Both indices are optional and may be omitted. The first <code class="var">index</code> shall specify the index of the first pack element to yield. If omitted, the value <code class="cpp c++"><span class="literal number integer">0</span></code> shall be assumed. The second <code class="var">index</code> shall specify the <em>upper bound</em> on the indices to be yielded, meaning that the specified index is <em>not</em> included. If omitted, the value <code class="cpp c++"><span class="keyword">sizeof</span><span class="punctuation">...(</span></code><code class="var">pack_expression</code><code class="cpp c++"><span class="punctuation">)</span></code> shall be assumed<a class="footnote-reference" href="#mi" id="id2">[2]</a>. If either value is negative, it shall first be added to <code class="cpp c++"><span class="keyword">sizeof</span><span class="punctuation">...(</span></code><code class="var">pack_expression</code><code class="cpp c++"><span class="punctuation">)</span></code>. Each value shall then be clamped to the range [<code class="cpp c++"><span class="literal number integer">0</span></code>, <code class="cpp c++"><span class="keyword">sizeof</span><span class="punctuation">...(</span></code><code class="var">pack_expression</code><code class="cpp c++"><span class="punctuation">)</span></code>]. If, after normalization and clamping, the upper index is less than the lower index, an empty parameter pack shall be yielded. (Note that this means that a variable slice is never ill-formed due to out of bounds index values.)</p>
<p>This can be represented in pseudo-code:</p>
<pre class="literal-block">
// let [lower:upper](pack) represent the complete slicing expression

size = sizeof...(pack);

if lower is unspecified:
  lower = 0;
if upper is unspecified:
  upper = size;

if lower &lt; 0:
  lower = size + lower;
if upper &lt; 0:
  upper = size + upper;

lower = bound(0, lower, size);
upper = bound(0, upper, size);

for (index = lower; index &lt; upper; ++index)
  yield [index]pack;
</pre>
<p>Note that the expressions <code class="cpp c++"><span class="punctuation">[</span><span class="operator">:</span><span class="punctuation">]</span><span class="name">pack</span></code> and <code class="cpp c++"><span class="name">pack</span></code> are equivalent; that is, a slicing expression which uses the defaults for both the lower and upper indices shall produce the same parameter pack.</p>
</div>
<div class="section" id="generalized-unpacking">
<h2><a class="toc-backref" href="#id9">Generalized Unpacking</a></h2>
<p>By presenting slicing first, we may consider generalized unpacking to be an extension of parameter pack operations to work on product types. Specifically, we propose that the above described slicing operator and <code class="cpp c++"><span class="keyword">sizeof</span><span class="punctuation">...</span></code> be extended to accept product types as well as parameter packs. When used on a product type, the type is &quot;unpacked&quot; into a parameter pack.</p>
<p>For example, given a product type <code class="cpp c++"><span class="name">t</span></code> of size 3, <code class="cpp c++"><span class="keyword">sizeof</span><span class="punctuation">...(</span><span class="name">t</span><span class="punctuation">)</span></code> would be well formed and equal to 3, and the expression <code class="cpp c++"><span class="punctuation">[</span><span class="operator">:</span><span class="punctuation">]</span><span class="name">t</span></code> would expand to a parameter pack equivalent to <code class="cpp c++"><span class="name">get</span><span class="operator">&lt;</span><span class="literal number integer">0</span><span class="operator">&gt;</span><span class="punctuation">(</span><span class="name">t</span><span class="punctuation">),</span> <span class="name">get</span><span class="operator">&lt;</span><span class="literal number integer">1</span><span class="operator">&gt;</span><span class="punctuation">(</span><span class="name">t</span><span class="punctuation">),</span> <span class="name">get</span><span class="operator">&lt;</span><span class="literal number integer">2</span><span class="operator">&gt;</span><span class="punctuation">(</span><span class="name">t</span><span class="punctuation">)</span></code>. (While we use <code class="cpp c++"><span class="name">get</span><span class="operator">&lt;</span><span class="name">N</span><span class="operator">&gt;</span></code> here and throughout for illustrative purposes, this proposal would reflect any changes made to product type access. In particular, it should support all types that may be used in decomposition declarations.) Moreover, as is usual for <code class="cpp c++"><span class="keyword">sizeof</span></code>, the argument here should be <em>unevaluated</em>.</p>
<p>Accordingly, <code class="cpp c++"><span class="punctuation">[</span><span class="name">expr1</span><span class="punctuation">]</span><span class="name">expr2</span></code> would be equivalent to <code class="cpp c++"><span class="name">get</span><span class="operator">&lt;</span><span class="name">expr1</span><span class="operator">&gt;</span><span class="punctuation">(</span><span class="name">expr2</span><span class="punctuation">)</span></code>; that is, a single value rather than a parameter pack.</p>
<p>Implementing this is straight forward; if a slicing operation or <code class="cpp c++"><span class="keyword">sizeof</span><span class="punctuation">...</span></code> is used on an expression which is not a parameter pack, rather than being an error, the compiler shall attempt to proceed as if the expression produces a product type. (If this attempt also fails, then an error is raised, as usual.)</p>
<p>This makes possible uses like the following, which are not readily accomplished using library-only solutions:</p>
<pre class="code c++ literal-block">
<span class="comment single">// let a1..a3 be single values
// let t1, t2 be product types (&quot;tuple-like&quot;)
</span>
<span class="keyword">auto</span> <span class="name">x</span> <span class="operator">=</span> <span class="name">SomeType</span><span class="punctuation">(</span><span class="name">a1</span><span class="punctuation">,</span> <span class="punctuation">[</span><span class="operator">:</span><span class="punctuation">]</span><span class="name">t1</span><span class="punctuation">...,</span> <span class="punctuation">[</span><span class="literal number integer">3</span><span class="operator">:</span><span class="punctuation">]</span><span class="name">t2</span><span class="punctuation">...,</span> <span class="name">a2</span><span class="punctuation">);</span>
<span class="name">foo</span><span class="punctuation">([</span><span class="literal number integer">1</span><span class="operator">:</span><span class="punctuation">]</span><span class="name">t1</span><span class="punctuation">...,</span> <span class="name">a3</span><span class="punctuation">,</span> <span class="punctuation">[</span><span class="literal number integer">0</span><span class="punctuation">]</span><span class="name">t1</span><span class="punctuation">);</span>

<span class="comment single">// let v1, v2 be vector-like types of T that may or may not be an array, e.g.:
//   std::array&lt;int, N&gt;
//   Eigen::Vector3d
//   QPoint
//   struct Point { int x, y; }
</span>
<span class="keyword">auto</span> <span class="name">manhattan_length</span> <span class="operator">=</span> <span class="name">std</span><span class="operator">::</span><span class="name">abs</span><span class="punctuation">([</span><span class="operator">:</span><span class="punctuation">]</span><span class="name">v1</span><span class="punctuation">)</span> <span class="operator">+</span> <span class="punctuation">...;</span>
<span class="keyword">auto</span> <span class="name">manhattan_distance</span> <span class="operator">=</span> <span class="name">std</span><span class="operator">::</span><span class="name">abs</span><span class="punctuation">([</span><span class="operator">:</span><span class="punctuation">]</span><span class="name">v1</span> <span class="operator">-</span> <span class="punctuation">[</span><span class="operator">:</span><span class="punctuation">]</span><span class="name">v2</span><span class="punctuation">)</span> <span class="operator">+</span> <span class="punctuation">...;</span>
<span class="keyword">auto</span> <span class="name">dot</span> <span class="operator">=</span> <span class="punctuation">([</span><span class="operator">:</span><span class="punctuation">]</span><span class="name">v1</span> <span class="operator">*</span> <span class="punctuation">[</span><span class="operator">:</span><span class="punctuation">]</span><span class="name">v2</span><span class="punctuation">)</span> <span class="operator">+</span> <span class="punctuation">...;</span>
</pre>
<p>Note also an important implication of both the above code and many of the examples to follow; namely, that we assign the slicing/unpacking operator (prefix <code class="cpp c++"><span class="keyword">operator</span><span class="punctuation">[]</span></code>) higher precedence than fold operator (postfix <code class="cpp c++"><span class="keyword">operator</span><span class="punctuation">...</span></code>).</p>
<p>Finally, we would be remiss if we failed to note one last reason why implementing a language feature that allows indexed access to product types is useful: it can allow access to bitfield members. At this time, there is no way to implement <code class="cpp c++"><span class="name">get</span><span class="operator">&lt;</span><span class="name">N</span><span class="operator">&gt;</span></code> for an aggregate containing bitfield members that would allow assignment to those members. However, a language feature that operates in the same manner as decomposition declarations, as our proposed feature would, can accomplish this. Thus, the following example becomes possible, and has the intended effect:</p>
<pre class="code c++ literal-block">
<span class="keyword">struct</span> <span class="name">Foo</span>
<span class="punctuation">{</span>
  <span class="keyword type">int</span> <span class="name">a</span> <span class="operator">:</span> <span class="literal number integer">4</span><span class="punctuation">;</span>
  <span class="keyword type">int</span> <span class="name">b</span> <span class="operator">:</span> <span class="literal number integer">4</span><span class="punctuation">;</span>
<span class="punctuation">};</span>

<span class="name">Foo</span> <span class="name">foo</span><span class="punctuation">;</span>
<span class="punctuation">[</span><span class="literal number integer">0</span><span class="punctuation">]</span><span class="name">foo</span> <span class="operator">=</span> <span class="literal number integer">7</span><span class="punctuation">;</span>
<span class="punctuation">[</span><span class="literal number integer">1</span><span class="punctuation">]</span><span class="name">foo</span> <span class="operator">=</span> <span class="literal number integer">5</span><span class="punctuation">;</span>
</pre>
<p>Although we would prefer an eventual resolution to this issue that allows bitfields to become first class citizens (e.g. the ability to return a bitfield reference or pass a bitfield reference as a parameter), our proposed language feature would at least extend indexed access to product types with bitfield members.</p>
</div>
</div>
<div class="section" id="additional-examples">
<h1><a class="toc-backref" href="#id10">Additional Examples</a></h1>
<div class="section" id="heads-and-tails">
<h2><a class="toc-backref" href="#id11">Heads and Tails</a></h2>
<p>It should be obvious that this solves problems alluded to by <a class="reference external" href="http://wg21.link/p0478">P0478</a>:</p>
<pre class="code c++ literal-block">
<span class="comment single">// Ugly and broken
</span><span class="keyword type">void</span> <span class="name function">signal</span><span class="punctuation">(</span><span class="keyword">auto</span><span class="punctuation">...</span> <span class="name">args</span><span class="punctuation">,</span> <span class="keyword">auto</span> <span class="name">last</span><span class="punctuation">)</span>
<span class="punctuation">{</span>
  <span class="comment single">// pass first 5 arguments to callback; ignore the rest
</span>  <span class="keyword">if</span> <span class="name">constexpr</span> <span class="punctuation">(</span><span class="keyword">sizeof</span><span class="punctuation">...(</span><span class="name">args</span><span class="punctuation">)</span> <span class="operator">&gt;</span> <span class="literal number integer">5</span><span class="punctuation">)</span>
    <span class="keyword">return</span> <span class="name">signal</span><span class="punctuation">(</span><span class="name">args</span><span class="punctuation">...);</span>
  <span class="keyword">else</span> <span class="keyword">if</span> <span class="name">constexpr</span> <span class="punctuation">(</span><span class="keyword">sizeof</span><span class="punctuation">...(</span><span class="name">args</span><span class="punctuation">)</span> <span class="operator">==</span> <span class="literal number integer">4</span><span class="punctuation">)</span>
    <span class="name">callback</span><span class="punctuation">(</span><span class="name">args</span><span class="punctuation">...,</span> <span class="name">last</span><span class="punctuation">);</span>
  <span class="keyword">else</span>
    <span class="name">callback</span><span class="punctuation">(</span><span class="name">args</span><span class="punctuation">...);</span>
<span class="punctuation">}</span>

<span class="comment single">// Enormously better
</span><span class="keyword type">void</span> <span class="name function">signal</span><span class="punctuation">(</span><span class="keyword">auto</span><span class="punctuation">...</span> <span class="name">args</span><span class="punctuation">)</span>
<span class="punctuation">{</span>
  <span class="comment single">// pass first 5 arguments to callback; ignore the rest
</span>  <span class="name">callback</span><span class="punctuation">([</span><span class="operator">:</span><span class="literal number integer">5</span><span class="punctuation">]</span><span class="name">args</span><span class="punctuation">...);</span>
<span class="punctuation">}</span>
</pre>
<p>Note also that the above &quot;ugly&quot; version of the function has several issues (which we have copied from its specification in <a class="reference external" href="http://wg21.link/p0478">P0478</a>R0):</p>
<ul class="simple">
<li>It cannot be invoked with zero arguments.</li>
<li>When invoked recursively, there is a spurious <code class="cpp c++"><span class="keyword">return</span></code> statement.</li>
<li>If fewer than 5 arguments are supplied to <code class="cpp c++"><span class="name">signal</span></code>, the last argument is unintentionally dropped.</li>
</ul>
<p>The last point in particular is subtle and difficult to reason about, thus providing an excellent illustration of why needing to write code like this is bad. The version using our proposed feature is enormously cleaner and far easier to understand, and significantly reduces the chances of making such mistakes in the implementation. In addition, recursion is eliminated entirely (which, given that the example is accepting parameters by-value, could be critically important if some arguments have non-trivial copy constructors).</p>
<p>We can also improve the second example:</p>
<pre class="code c++ literal-block">
<span class="comment single">// Mostly okay
</span><span class="keyword">auto</span> <span class="name function">alternate_tuple</span><span class="punctuation">(</span><span class="keyword">auto</span> <span class="name">first</span><span class="punctuation">,</span> <span class="keyword">auto</span><span class="punctuation">...</span> <span class="name">middle</span><span class="punctuation">,</span> <span class="keyword">auto</span> <span class="name">last</span><span class="punctuation">)</span>
<span class="punctuation">{</span>
  <span class="keyword">if</span> <span class="name">constexpr</span> <span class="punctuation">(</span><span class="keyword">sizeof</span><span class="punctuation">...(</span><span class="name">items</span><span class="punctuation">)</span> <span class="operator">&lt;=</span> <span class="literal number integer">2</span><span class="punctuation">)</span>
    <span class="keyword">return</span> <span class="name">std</span><span class="operator">::</span><span class="name">tuple</span><span class="punctuation">(</span><span class="name">first</span><span class="punctuation">,</span> <span class="name">last</span><span class="punctuation">,</span> <span class="name">middle</span><span class="punctuation">...);</span>
  <span class="keyword">else</span>
    <span class="keyword">return</span> <span class="name">std</span><span class="operator">::</span><span class="name">tuple_cat</span><span class="punctuation">(</span><span class="name">std</span><span class="operator">::</span><span class="name">tuple</span><span class="punctuation">(</span><span class="name">first</span><span class="punctuation">,</span> <span class="name">last</span><span class="punctuation">),</span>
                          <span class="name">alternate_tuple</span><span class="punctuation">(</span><span class="name">middle</span><span class="punctuation">...));</span>
<span class="punctuation">}</span>

<span class="comment single">// Better
</span><span class="keyword">auto</span> <span class="name function">alternate_tuple</span><span class="punctuation">(</span><span class="keyword">auto</span><span class="punctuation">...</span> <span class="name">items</span><span class="punctuation">)</span>
<span class="punctuation">{</span>
  <span class="keyword">if</span> <span class="name">constexpr</span> <span class="punctuation">(</span><span class="keyword">sizeof</span><span class="punctuation">...(</span><span class="name">items</span><span class="punctuation">)</span> <span class="operator">&lt;</span> <span class="literal number integer">3</span><span class="punctuation">)</span>
    <span class="keyword">return</span> <span class="name">std</span><span class="operator">::</span><span class="name">tuple</span><span class="punctuation">{</span><span class="name">items</span><span class="punctuation">...};</span>
  <span class="keyword">else</span>
    <span class="keyword">return</span> <span class="name">std</span><span class="operator">::</span><span class="name">tuple</span><span class="punctuation">{[</span><span class="literal number integer">0</span><span class="punctuation">]</span><span class="name">items</span><span class="punctuation">,</span> <span class="punctuation">[</span><span class="operator">-</span><span class="literal number integer">1</span><span class="punctuation">]</span><span class="name">items</span><span class="punctuation">,</span>
                      <span class="punctuation">[</span><span class="operator">:</span><span class="punctuation">]</span><span class="name">alternate_tuple</span><span class="punctuation">([</span><span class="literal number integer">1</span><span class="operator">:-</span><span class="literal number integer">1</span><span class="punctuation">]</span><span class="name">items</span><span class="punctuation">...)...};</span>
<span class="punctuation">}</span>
</pre>
<p>As with the previous example, our version solves a boundary case (in this instance, when fewer than two items are given) that is not handled by the version given in <a class="reference external" href="http://wg21.link/p0478">P0478</a>. In particular, without slicing, one must implement an overload to handle such boundary cases, potentially resulting in duplicated code and the attendant increase in maintenance burden. With slicing, we can trivially handle such boundary cases in the same function.</p>
</div>
<div class="section" id="divide-and-conquer">
<h2><a class="toc-backref" href="#id12">Divide-and-Conquer</a></h2>
<p>The ability to slice parameter packs makes it possible to implement binary divide-and-conqueror algorithms on parameter packs, which would be difficult or impossible to achieve otherwise. Consider this example which selects the &quot;best&quot; element in a parameter pack:</p>
<pre class="code c++ literal-block">
<span class="keyword">auto</span> <span class="name function">best</span><span class="punctuation">(</span><span class="keyword">auto</span> <span class="keyword">const</span><span class="operator">&amp;</span> <span class="name">first</span><span class="punctuation">,</span> <span class="keyword">auto</span> <span class="keyword">const</span><span class="operator">&amp;</span><span class="punctuation">...</span> <span class="name">remainder</span><span class="punctuation">)</span>
<span class="punctuation">{</span>
  <span class="keyword">if</span> <span class="name">constexpr</span> <span class="punctuation">(</span><span class="keyword">sizeof</span><span class="punctuation">...(</span><span class="name">remainder</span><span class="punctuation">)</span> <span class="operator">==</span> <span class="literal number integer">0</span><span class="punctuation">)</span>
    <span class="keyword">return</span> <span class="name">first</span><span class="punctuation">;</span>
  <span class="keyword">else</span>
    <span class="keyword">return</span> <span class="name">better_of</span><span class="punctuation">(</span><span class="name">first</span><span class="punctuation">,</span> <span class="name">best</span><span class="punctuation">(</span><span class="name">remainder</span><span class="punctuation">...);</span>
<span class="punctuation">}</span>
</pre>
<p>While this example is overly simplified, what if it was significantly more efficient if the function could be written to require only <tt class="docutils literal">O(log N)</tt> recursion rather than <tt class="docutils literal">O(N)</tt> recursion? With slicing, this can be accomplished easily:</p>
<pre class="code c++ literal-block">
<span class="keyword">auto</span> <span class="name function">best</span><span class="punctuation">(</span><span class="keyword">auto</span> <span class="keyword">const</span><span class="operator">&amp;</span><span class="punctuation">...</span> <span class="name">args</span><span class="punctuation">)</span>
<span class="punctuation">{</span>
  <span class="name">constexpr</span> <span class="keyword">auto</span> <span class="name">k</span> <span class="operator">=</span> <span class="keyword">sizeof</span><span class="punctuation">...(</span><span class="name">args</span><span class="punctuation">);</span>
  <span class="keyword">if</span> <span class="name">constexpr</span> <span class="punctuation">(</span><span class="name">k</span> <span class="operator">==</span> <span class="literal number integer">1</span><span class="punctuation">)</span>
    <span class="keyword">return</span> <span class="punctuation">[</span><span class="literal number integer">0</span><span class="punctuation">]</span><span class="name">args</span><span class="punctuation">;</span>
  <span class="keyword">else</span>
    <span class="keyword">return</span> <span class="name">better_of</span><span class="punctuation">(</span><span class="name">best</span><span class="punctuation">([</span><span class="operator">:</span><span class="name">k</span><span class="operator">/</span><span class="literal number integer">2</span><span class="punctuation">]</span><span class="name">args</span><span class="punctuation">...),</span> <span class="name">best</span><span class="punctuation">([</span><span class="name">k</span><span class="operator">/</span><span class="literal number integer">2</span><span class="operator">:</span><span class="punctuation">]</span><span class="name">args</span><span class="punctuation">...));</span>
<span class="punctuation">}</span>
</pre>
<p>Note also that the above code no longer needs to accept the first argument separately. (For those wondering: no, invoking this with no arguments will not cause a runaway recursion. The compiler recognizes the recursive attempt to call the function with no arguments and rejects it because the return type has not been determined.)</p>
</div>
<div class="section" id="unpacking-and-fold-expressions">
<h2><a class="toc-backref" href="#id13">Unpacking and Fold Expressions</a></h2>
<p>Let's consider now some additional examples of how generalized unpacking allows us to write fold expressions on the elements of product types:</p>
<pre class="code c++ literal-block">
<span class="name">std</span><span class="operator">::</span><span class="name">tuple</span><span class="operator">&lt;</span><span class="keyword type">int</span><span class="operator">&gt;</span> <span class="name">t1</span> <span class="punctuation">{</span> <span class="literal number integer">1</span><span class="punctuation">,</span> <span class="literal number integer">2</span><span class="punctuation">,</span> <span class="literal number integer">3</span> <span class="punctuation">};</span>
<span class="name">std</span><span class="operator">::</span><span class="name">tuple</span><span class="operator">&lt;</span><span class="keyword type">int</span><span class="punctuation">,</span><span class="keyword type">int</span><span class="operator">&gt;</span> <span class="name">t2</span> <span class="punctuation">{</span> <span class="literal number integer">4</span><span class="punctuation">,</span> <span class="literal number integer">5</span><span class="punctuation">,</span> <span class="literal number integer">6</span> <span class="punctuation">};</span>
<span class="name">std</span><span class="operator">::</span><span class="name">tuple</span><span class="operator">&lt;</span><span class="keyword type">int</span><span class="punctuation">,</span><span class="keyword type">int</span><span class="punctuation">,</span><span class="keyword type">int</span><span class="operator">&gt;</span> <span class="name">t3</span> <span class="punctuation">{</span> <span class="literal number integer">7</span><span class="punctuation">,</span> <span class="literal number integer">8</span><span class="punctuation">,</span> <span class="literal number integer">9</span> <span class="punctuation">};</span>
<span class="keyword">auto</span> <span class="name">tt</span> <span class="operator">=</span> <span class="name">std</span><span class="operator">::</span><span class="name">make_tuple</span><span class="punctuation">(</span><span class="name">t1</span><span class="punctuation">,</span> <span class="name">t2</span><span class="punctuation">,</span> <span class="name">t3</span><span class="punctuation">);</span> <span class="comment single">// a tuple of tuples
</span>
<span class="name">f</span><span class="punctuation">([</span><span class="operator">:</span><span class="punctuation">]</span><span class="name">tt</span> <span class="punctuation">...);</span>     <span class="comment single">// f(t1, t2, t3);
</span><span class="name">f</span><span class="punctuation">(</span><span class="name">g</span><span class="punctuation">([</span><span class="operator">:</span><span class="punctuation">]</span><span class="name">tt</span><span class="punctuation">)</span> <span class="punctuation">...);</span>  <span class="comment single">// f(g(t1), g(t2), g(t3));
</span><span class="name">f</span><span class="punctuation">(</span><span class="name">g</span><span class="punctuation">([</span><span class="operator">:</span><span class="punctuation">]</span><span class="name">tt</span> <span class="punctuation">...));</span>  <span class="comment single">// f(g(t1, t2, t3));
</span>
<span class="name">f</span><span class="punctuation">(</span><span class="name">g</span><span class="punctuation">([</span><span class="operator">:</span><span class="punctuation">][</span><span class="operator">:</span><span class="punctuation">]</span><span class="name">tt</span> <span class="punctuation">...)</span> <span class="punctuation">...);</span> <span class="comment single">// ill-formed
</span><span class="name">f</span><span class="punctuation">(</span><span class="name">g</span><span class="punctuation">([</span><span class="operator">:</span><span class="punctuation">][</span><span class="operator">:</span><span class="punctuation">]</span><span class="name">tt</span> <span class="punctuation">...</span> <span class="punctuation">...));</span> <span class="comment single">// ill-formed
</span>
</pre>
<p>Note that, due to the precedence we specified, the last two lines are ill-formed. In both cases, the second <code class="cpp c++"><span class="punctuation">[</span><span class="operator">:</span><span class="punctuation">]</span></code> is redundant, resulting in an attempt to apply <code class="cpp c++"><span class="punctuation">...</span></code> to something which is not a parameter pack. Note also that a consequence of this precedence is that <code class="cpp c++"><span class="punctuation">[</span><span class="operator">:</span><span class="punctuation">]</span></code> cannot be used as the operator of a fold expression.</p>
<p>This leaves two relatively straight-forward cases that are not addressed purely by the proposed feature, but are nevertheless made significantly easier with it:</p>
<pre class="code c++ literal-block">
<span class="comment single">// f(g(1,2,3), g(4,5,6), g(7,8,9));
</span><span class="name">f</span><span class="punctuation">(</span><span class="name">std</span><span class="operator">::</span><span class="name">apply</span><span class="punctuation">(</span><span class="name">g</span><span class="punctuation">,</span> <span class="punctuation">[</span><span class="operator">:</span><span class="punctuation">]</span><span class="name">tt</span><span class="punctuation">)...);</span>

<span class="comment single">// f(g(1, 2, 3, 4, 5, 6, 7, 8, 9));
</span><span class="name">f</span><span class="punctuation">(</span><span class="name">g</span><span class="punctuation">([</span><span class="operator">:</span><span class="punctuation">]</span><span class="name">std</span><span class="operator">::</span><span class="name">tuple_cat</span><span class="punctuation">([</span><span class="operator">:</span><span class="punctuation">]</span><span class="name">tt</span><span class="punctuation">...)...));</span>
<span class="name">f</span><span class="punctuation">(</span><span class="name">std</span><span class="operator">::</span><span class="name">apply</span><span class="punctuation">(</span><span class="name">g</span><span class="punctuation">,</span> <span class="punctuation">[</span><span class="operator">:</span><span class="punctuation">]</span><span class="name">tt</span><span class="punctuation">...));</span>
</pre>
<p>For the last example, we assume an extension to <code class="cpp c++"><span class="name">std</span><span class="operator">::</span><span class="name">apply</span></code> to accept multiple product types which are &quot;flattened&quot; into the arguments for the specified function. We are not proposing this here, merely showing an example of how the task could be accomplished.</p>
<p>Although this is effective, at least for the above examples, pack generators would provide a better solution for this and other more complicated problems. See <a class="reference internal" href="#future-direction">Future Direction</a> for further discussion.</p>
</div>
<div class="section" id="slicing-product-types">
<h2><a class="toc-backref" href="#id14">Slicing Product Types</a></h2>
<p>It's harder to imagine generic uses for slicing product types, since product types come in so very many varieties. However, we have already alluded to the case of rearranging elements in a product type as one possible use. Another likely use case deals with linear algebra and geometry, particularly operations dealing with homogeneous vectors. Let us consider the simple example of converting a homogeneous vector to a normalized vector. Such an operation would normally be written out &quot;longhand&quot;, and would be difficult to adapt to vectors of arbitrary dimension. Our proposed feature allows us to write a simple and succinct implementation:</p>
<pre class="code c++ literal-block">
<span class="keyword">template</span> <span class="operator">&lt;</span><span class="keyword">typename</span> <span class="name">T</span><span class="punctuation">,</span> <span class="keyword type">size_t</span> <span class="name">N</span><span class="operator">&gt;</span>
<span class="name">std</span><span class="operator">::</span><span class="name">array</span><span class="operator">&lt;</span><span class="name">T</span><span class="punctuation">,</span> <span class="name">N</span><span class="operator">-</span><span class="literal number integer">1</span><span class="operator">&gt;</span> <span class="name">normalize</span><span class="punctuation">(</span><span class="name">std</span><span class="operator">::</span><span class="name">array</span><span class="operator">&lt;</span><span class="name">T</span><span class="punctuation">,</span> <span class="name">N</span><span class="operator">&gt;</span> <span class="name">a</span><span class="punctuation">)</span>
<span class="punctuation">{</span>
  <span class="keyword">return</span> <span class="punctuation">{[</span><span class="operator">:-</span><span class="literal number integer">1</span><span class="punctuation">]</span><span class="name">a</span> <span class="operator">/</span> <span class="punctuation">[</span><span class="operator">-</span><span class="literal number integer">1</span><span class="punctuation">]</span><span class="name">a</span><span class="punctuation">...};</span>
<span class="punctuation">}</span>
</pre>
<p>In some cases, it may be possible to write generic versions of such algorithms making use of <code class="cpp c++"><span class="name">std</span><span class="operator">::</span><span class="name">invoke</span></code>, but doing so is likely to require employing a lambda to receive the argument pack, and will almost certainly be much more unwieldy than the simple, succinct syntax our proposal makes possible.</p>
</div>
<div class="section" id="improving-std-apply">
<h2><a class="toc-backref" href="#id15">Improving <code class="cpp c++"><span class="name">std</span><span class="operator">::</span><span class="name">apply</span></code></a></h2>
<p>The previous example postulated an extension to <code class="cpp c++"><span class="name">std</span><span class="operator">::</span><span class="name">apply</span></code> to accept multiple product types. While this can of course be achieved already using <code class="cpp c++"><span class="name">std</span><span class="operator">::</span><span class="name">tuple_cat</span></code>, avoiding unnecessary copies and/or temporary objects is awkward at best. The postulated extension should be able to avoid these problems. Using our proposed feature, we can show (forwarding omitted for brevity) how this might be implemented:</p>
<pre class="code c++ literal-block">
<span class="keyword">namespace</span> <span class="name">std</span>
<span class="punctuation">{</span>
  <span class="keyword">template</span> <span class="operator">&lt;</span><span class="keyword type">int</span> <span class="name">n</span><span class="punctuation">,</span> <span class="keyword">typename</span> <span class="name">Func</span><span class="punctuation">,</span> <span class="keyword">typename</span> <span class="name">Args</span><span class="punctuation">...</span><span class="operator">&gt;</span>
  <span class="keyword">auto</span> <span class="name">apply_helper</span><span class="punctuation">(</span><span class="name">Func</span> <span class="name">func</span><span class="punctuation">,</span> <span class="name">Args</span><span class="punctuation">...</span> <span class="name">args</span><span class="punctuation">)</span>
  <span class="punctuation">{</span>
    <span class="comment single">// n is number of already-unpacked arguments
</span>    <span class="name">constexpr</span> <span class="keyword">auto</span> <span class="name">r</span> <span class="operator">=</span> <span class="keyword">sizeof</span><span class="punctuation">...(</span><span class="name">args</span><span class="punctuation">)</span> <span class="operator">-</span> <span class="name">n</span><span class="punctuation">;</span> <span class="comment single">// remaining tuples
</span>    <span class="keyword">if</span> <span class="name function">constexpr</span> <span class="punctuation">(</span><span class="name">r</span> <span class="operator">==</span> <span class="literal number integer">0</span><span class="punctuation">)</span>
      <span class="keyword">return</span> <span class="name">func</span><span class="punctuation">(</span><span class="name">args</span><span class="punctuation">...);</span>

    <span class="keyword">auto</span><span class="operator">&amp;&amp;</span> <span class="name">t</span> <span class="operator">=</span> <span class="punctuation">[</span><span class="name">n</span><span class="punctuation">]</span><span class="name">args</span><span class="punctuation">;</span>
    <span class="keyword">auto</span> <span class="name">k</span> <span class="operator">=</span> <span class="keyword">sizeof</span><span class="punctuation">...(</span><span class="name">t</span><span class="punctuation">);</span>
    <span class="keyword">return</span> <span class="name">apply_helper</span><span class="operator">&lt;</span><span class="name">n</span> <span class="operator">+</span> <span class="name">k</span><span class="operator">&gt;</span><span class="punctuation">(</span><span class="name">func</span><span class="punctuation">,</span> <span class="punctuation">[</span><span class="operator">:</span><span class="name">n</span><span class="punctuation">]</span><span class="name">args</span><span class="punctuation">,</span> <span class="punctuation">[</span><span class="operator">:</span><span class="punctuation">]</span><span class="name">t</span><span class="punctuation">...,</span> <span class="punctuation">[</span><span class="name">n</span><span class="operator">+</span><span class="literal number integer">1</span><span class="operator">:</span><span class="punctuation">]</span><span class="name">args</span><span class="punctuation">);</span>
  <span class="punctuation">}</span>

  <span class="keyword">template</span> <span class="operator">&lt;</span><span class="keyword">typename</span> <span class="name">Func</span><span class="punctuation">,</span> <span class="keyword">typename</span> <span class="name">Tuples</span><span class="punctuation">...</span><span class="operator">&gt;</span>
  <span class="keyword">auto</span> <span class="name">apply</span><span class="punctuation">(</span><span class="name">Func</span> <span class="name">func</span><span class="punctuation">,</span> <span class="name">Tuples</span><span class="punctuation">...</span> <span class="name">tuples</span><span class="punctuation">)</span>
  <span class="punctuation">{</span>
    <span class="keyword">return</span> <span class="name">apply_helper</span><span class="operator">&lt;</span><span class="literal number integer">0</span><span class="operator">&gt;</span><span class="punctuation">(</span><span class="name">func</span><span class="punctuation">,</span> <span class="name">tuples</span><span class="punctuation">);</span>
  <span class="punctuation">}</span>
<span class="punctuation">}</span>
</pre>
<p>Although this is feasible, and would ideally optimize down to a direct call of the specified function with all of the tuple values extracted directly, it is not meant to imply that this is the only possible solution, nor necessarily even the <em>best</em> solution. In particular, we would again note that pack generators would offer an even better solution to this specific problem. Rather, this example is intended to show how our proposed feature allows tail-recursive unpacking of multiple product types; in particular, without using a new tuple to wrap the values as they are unpacked.</p>
</div>
<div class="section" id="reversing-a-product-type">
<h2><a class="toc-backref" href="#id16">Reversing a product type</a></h2>
<p>The previous example inspires another function that is often cited as a use case: reversing the elements in a product type. As above, forwarding is omitted for brevity:</p>
<pre class="code c++ literal-block">
<span class="keyword">template</span> <span class="operator">&lt;</span><span class="keyword type">int</span> <span class="name">n</span><span class="punctuation">,</span> <span class="keyword">typename</span><span class="punctuation">...</span> <span class="name">Args</span><span class="operator">&gt;</span>
<span class="keyword">auto</span> <span class="name">reverse_tuple_helper</span><span class="punctuation">(</span><span class="name">Args</span><span class="punctuation">...</span> <span class="name">args</span><span class="punctuation">)</span>
<span class="punctuation">{</span>
  <span class="name">constexpr</span> <span class="keyword">auto</span> <span class="name">r</span> <span class="operator">=</span> <span class="keyword">sizeof</span><span class="punctuation">...(</span><span class="name">args</span><span class="punctuation">)</span> <span class="operator">-</span> <span class="name">n</span><span class="punctuation">;</span> <span class="comment single">// remaining elements
</span>  <span class="keyword">if</span> <span class="name function">constexpr</span> <span class="punctuation">(</span><span class="name">r</span> <span class="operator">&lt;</span> <span class="literal number integer">2</span><span class="punctuation">)</span>
    <span class="keyword">return</span> <span class="name">make_tuple</span><span class="punctuation">(</span><span class="name">args</span><span class="punctuation">...);</span>

  <span class="keyword">return</span> <span class="name">reverse_tuple_helper</span><span class="operator">&lt;</span><span class="name">n</span> <span class="operator">+</span> <span class="literal number integer">1</span><span class="operator">&gt;</span><span class="punctuation">(</span><span class="name">args</span><span class="punctuation">[</span><span class="operator">:</span><span class="name">n</span><span class="punctuation">]...,</span> <span class="name">args</span><span class="punctuation">[</span><span class="operator">-</span><span class="literal number integer">1</span><span class="punctuation">],</span> <span class="name">args</span><span class="punctuation">[</span><span class="name">n</span><span class="operator">:-</span><span class="literal number integer">1</span><span class="punctuation">]...);</span>
<span class="punctuation">}</span>

<span class="keyword">template</span> <span class="operator">&lt;</span><span class="keyword">typename</span> <span class="name">T</span><span class="operator">&gt;</span>
<span class="keyword">auto</span> <span class="name">reverse_tuple</span><span class="punctuation">(</span><span class="name">T</span> <span class="name">tuple</span><span class="punctuation">)</span>
<span class="punctuation">{</span>
  <span class="keyword">return</span> <span class="name">reverse_tuple_helper</span><span class="operator">&lt;</span><span class="literal number integer">0</span><span class="operator">&gt;</span><span class="punctuation">([</span><span class="operator">:</span><span class="punctuation">]</span><span class="name">tuple</span><span class="punctuation">...);</span>
<span class="punctuation">}</span>
</pre>
<p>A more complicated implementation could reduce the number of template instantiations by about half, by swapping pairs of arguments starting with the first and last and working inwards. This approach avoids the need for index sequences and can be applied to parameter packs without creation of a temporary tuple to hold the pack.</p>
</div>
<div class="section" id="static-value-table">
<h2><a class="toc-backref" href="#id17">Static value table</a></h2>
<p>It's not entirely unusual to have an array (often a C-style array) or other entity which holds static, immutable data which uses an initializer list to set up the data. For example:</p>
<pre class="code c++ literal-block">
<span class="keyword type">double</span> <span class="name">sin64</span><span class="punctuation">[]</span> <span class="operator">=</span> <span class="punctuation">{</span>
  <span class="name">_constexpr_sin</span><span class="punctuation">(</span><span class="literal number float">2.0</span> <span class="operator">*</span> <span class="literal number float">0.0</span> <span class="operator">*</span> <span class="name">M_PI</span> <span class="operator">/</span> <span class="literal number float">64.0</span><span class="punctuation">),</span>
  <span class="name">_constexpr_sin</span><span class="punctuation">(</span><span class="literal number float">2.0</span> <span class="operator">*</span> <span class="literal number float">1.0</span> <span class="operator">*</span> <span class="name">M_PI</span> <span class="operator">/</span> <span class="literal number float">64.0</span><span class="punctuation">),</span>
  <span class="name">_constexpr_sin</span><span class="punctuation">(</span><span class="literal number float">2.0</span> <span class="operator">*</span> <span class="literal number float">2.0</span> <span class="operator">*</span> <span class="name">M_PI</span> <span class="operator">/</span> <span class="literal number float">64.0</span><span class="punctuation">),</span>
  <span class="name">_constexpr_sin</span><span class="punctuation">(</span><span class="literal number float">2.0</span> <span class="operator">*</span> <span class="literal number float">3.0</span> <span class="operator">*</span> <span class="name">M_PI</span> <span class="operator">/</span> <span class="literal number float">64.0</span><span class="punctuation">),</span>
  <span class="comment single">// ...and so forth</span>
</pre>
<p>At present, it is typically necessary to write out such data tables by hand (or to write a program to generate source code). Unpacking suggests an alternative approach:</p>
<pre class="code c++ literal-block">
<span class="keyword">template</span> <span class="operator">&lt;</span><span class="keyword type">size_t</span> <span class="name">Size</span><span class="operator">&gt;</span>
<span class="keyword">struct</span> <span class="keyword type">sin_table_t</span>
<span class="punctuation">{</span>
<span class="name label">public:</span>
  <span class="name">constexpr</span> <span class="keyword">static</span> <span class="keyword type">size_t</span> <span class="name">tuple_size</span><span class="punctuation">()</span>
  <span class="punctuation">{</span> <span class="keyword">return</span> <span class="name">Size</span><span class="punctuation">;</span> <span class="punctuation">}</span>

  <span class="keyword">template</span> <span class="operator">&lt;</span><span class="keyword type">size_t</span> <span class="name">N</span><span class="operator">&gt;</span> <span class="name">constexpr</span> <span class="keyword type">double</span> <span class="name">get</span><span class="punctuation">()</span> <span class="keyword">const</span>
  <span class="punctuation">{</span>
    <span class="keyword">return</span> <span class="name">_constexpr_sin</span><span class="punctuation">(</span><span class="keyword">static_cast</span><span class="operator">&lt;</span><span class="keyword type">double</span><span class="operator">&gt;</span><span class="punctuation">(</span><span class="name">N</span><span class="punctuation">)</span> <span class="operator">*</span> <span class="name">K</span><span class="punctuation">);</span>
  <span class="punctuation">}</span>

<span class="name label">private:</span>
  <span class="name">constexpr</span> <span class="keyword">static</span> <span class="keyword">auto</span> <span class="name">K</span> <span class="operator">=</span> <span class="literal number float">2.0</span> <span class="operator">*</span> <span class="name">M_PI</span> <span class="operator">/</span> <span class="keyword">static_cast</span><span class="operator">&lt;</span><span class="keyword type">double</span><span class="operator">&gt;</span><span class="punctuation">(</span><span class="name">Size</span><span class="punctuation">);</span>
<span class="punctuation">};</span>

<span class="keyword type">double</span> <span class="name">sin64</span><span class="punctuation">[]</span> <span class="operator">=</span> <span class="punctuation">{</span> <span class="punctuation">[</span><span class="operator">:</span><span class="punctuation">](</span><span class="keyword type">sin_table_t</span><span class="operator">&lt;</span><span class="literal number integer">64</span><span class="operator">&gt;</span><span class="punctuation">{})...</span> <span class="punctuation">};</span>
</pre>
<p>While this example still entails some boilerplate, it shows how unpacking makes it possible to define the elements of an initializer list using <code class="cpp c++"><span class="name">constexpr</span></code> functions.</p>
</div>
</div>
<div class="section" id="discussion">
<h1><a class="toc-backref" href="#id18">Discussion</a></h1>
<div class="section" id="what-is-a-product-type">
<h2><a class="toc-backref" href="#id19">What is a &quot;product type&quot;?</a></h2>
<p>This is an excellent question which deserves its own paper. <a class="reference external" href="http://wg21.link/p0327">P0327</a> makes a good start. When we get to the point of specifying wording, this will need to be addressed; ideally, this will have happened in parallel. Some &quot;working definitions&quot; which may be used to help with consideration of this proposal are &quot;types which define <code class="cpp c++"><span class="name">tuple_size</span></code> and <code class="cpp c++"><span class="name">get</span></code>&quot;, or &quot;types to which decomposition declarations may be applied&quot;. While we have generally specified that the behavior of our proposed feature should mirror that of decomposition declarations, we would like to see a more general specification of these issues.</p>
</div>
<div class="section" id="why-combine-these-features">
<h2><a class="toc-backref" href="#id20">Why combine these features?</a></h2>
<p>We prefer to think of this proposal as not two separate features (parameter pack slicing, generalized unpacking), but rather a single feature (product type slicing) that works on <em>both</em> &quot;concrete&quot; product types and parameter packs. Seen in this light, the case for the feature is strengthened, as it presents a single syntax that solves multiple problems.</p>
</div>
<div class="section" id="why-choose-prefix-operator">
<h2><a class="toc-backref" href="#id21">Why choose prefix <code class="cpp c++"><span class="keyword">operator</span><span class="punctuation">[]</span></code>?</a></h2>
<p>Before answering, let us look at some other alternatives that have been proposed or considered:</p>
<ul>
<li><p class="first"><code class="cpp c++"><span class="name">t</span><span class="punctuation">.</span><span class="name">N</span></code>, <code class="cpp c++"><span class="name">t</span><span class="operator">~</span><span class="name">N</span></code></p>
<p>While these work for at least the single value case, they are less conducive to slicing, nor are they as readily extended to generalized unpacking. The use of an integer in place of an identifier also seems unusual; worse, there is a potential conflict when using a <code class="cpp c++"><span class="name">constexpr</span></code> expression as the index (although this could be solved by enclosing the expression in <tt class="docutils literal">()</tt>s).</p>
</li>
<li><p class="first"><code class="cpp c++"><span class="name">t</span><span class="punctuation">.[</span><span class="name">L</span><span class="operator">:</span><span class="name">U</span><span class="punctuation">]</span></code>, <code class="cpp c++"><span class="name">t</span><span class="operator">~</span><span class="punctuation">(</span><span class="name">L</span><span class="operator">:</span><span class="name">U</span><span class="punctuation">)</span></code></p>
<p>These support slicing, but the syntax is starting to look rather strange.</p>
</li>
<li><p class="first"><code class="cpp c++"><span class="operator">^</span><span class="name">t</span><span class="punctuation">...[</span><span class="name">L</span><span class="operator">:</span><span class="name">U</span><span class="punctuation">]</span></code></p>
<p>This approach, based heavily on a suggestion by Bengt Gustafsson, introduces indexing/slicing and unpacking as completely separate operations and binds indexing/slicing to fold expansion:</p>
<pre class="code c++ literal-block">
<span class="name">pack</span><span class="punctuation">...[</span><span class="name">i</span><span class="punctuation">]</span>            <span class="comment single">// equivalent to our [i]pack...
</span><span class="name">pack</span><span class="punctuation">...[</span><span class="name">l</span><span class="operator">:</span><span class="name">u</span><span class="punctuation">]</span>          <span class="comment single">// equivalent to our [l:u]pack...
</span><span class="operator">^</span><span class="name">pt</span>                   <span class="comment single">// equivalent to our [:]pt
</span><span class="operator">^</span><span class="name">pt</span><span class="punctuation">...[</span><span class="name">i</span><span class="punctuation">]</span>             <span class="comment single">// equivalent to our [i]pt
</span><span class="keyword">sizeof</span><span class="punctuation">...(</span><span class="operator">^</span><span class="name">pt</span><span class="punctuation">)</span>        <span class="comment single">// equivalent to our sizeof...(pt)</span>
</pre>
<p>This has the advantage of being tightly coupled to expansion, and thereby makes moot the difference between indexing (which produces a value) and slicing (which produces a pack). However, this also precludes composition of slicing or indexing (see <a class="reference internal" href="#why-choose-trailing-index">Why choose trailing index?</a> for an example where composition may be useful). Separating indexing/slicing from unpacking enforces a distinction between product types and parameter packs, which may or may not be desirable. It also results in more roundabout and verbose syntax for indexed access to a product type.</p>
</li>
</ul>
<p>The exact syntax for these features can be debated. We prefer prefix <code class="cpp c++"><span class="keyword">operator</span><span class="punctuation">[]</span></code> because C++ programmers are already familiar with <code class="cpp c++"><span class="keyword">operator</span><span class="punctuation">[]</span></code> as an indexing operator, which is essentially what we are proposing (especially for the single value case), and because the proposed syntax is very similar to Python, which will already be familiar to some C++ programmers. At the same time, the choice of a prefix as opposed to postfix syntax makes it clear that the slicing operation — which we like to think of as <em>compile-time indexing</em> — is different from the usual <em>run-time indexing</em>. The proposed syntax also applies &quot;naturally&quot; to both parameter packs and product types, which gives us a single feature with broad applicability, rather than two entirely orthogonal features.</p>
<p>See also <a class="reference internal" href="#what-alternatives-were-considered">What alternatives were considered?</a> for a discussion of alternatives which may achieve comparable operations but do not fit within the same general framework as our proposal.</p>
</div>
<div class="section" id="does-this-conflict-with-operator-constexpr-size-t">
<h2><a class="toc-backref" href="#id22">Does this conflict with <code class="cpp c++"><span class="keyword">operator</span><span class="punctuation">[](</span><span class="name">constexpr</span> <span class="keyword type">size_t</span><span class="punctuation">)</span></code>?</a></h2>
<p>One &quot;obvious&quot; argument against product type slicing is that <code class="cpp c++"><span class="name">constexpr</span></code> parameters will make it irrelevant. We feel that this should not be given great weight against this proposal for several reasons:</p>
<ul>
<li><p class="first">We don't have <code class="cpp c++"><span class="name">constexpr</span></code> parameters yet. At this time, we are not even aware of a proposal for such a feature.</p>
</li>
<li><p class="first">There are several interesting implications to a <code class="cpp c++"><span class="keyword">operator</span><span class="punctuation">[](</span><span class="name">constexpr</span> <span class="keyword type">size_t</span><span class="punctuation">)</span></code>, including the (mostly) novel notion that the return type will depend on the <em>function arguments</em>. It is unclear if this is desirable.</p>
</li>
<li><p class="first">Even if we get <code class="cpp c++"><span class="keyword">operator</span><span class="punctuation">[](</span><span class="name">constexpr</span> <span class="keyword type">size_t</span><span class="punctuation">)</span></code>, will such an operator be implicitly generated for all product types? Given the difficulty with other &quot;provide operators by default&quot; proposals, this seems dubious at best.</p>
</li>
<li><p class="first">While our proposed feature may be equivalent to <code class="cpp c++"><span class="keyword">operator</span><span class="punctuation">[]</span></code> for some types, this may not be the case for <em>all</em> types. For example, a span might present itself as a product type consisting of either a begin/end or begin/size, while <code class="cpp c++"><span class="keyword">operator</span><span class="punctuation">[]</span></code> provides indexed access to the span. A novel operator is appropriate unless we are prepared to <em>unconditionally specify</em> that <code class="cpp c++"><span class="name">get</span><span class="operator">&lt;</span><span class="name">N</span><span class="operator">&gt;</span></code> and <code class="cpp c++"><span class="keyword">operator</span><span class="punctuation">[](</span><span class="name">constexpr</span><span class="punctuation">)</span></code> shall be synonyms.</p>
</li>
<li><p class="first">We would still require a language feature for indexed access to parameter packs, and a postfix <code class="cpp c++"><span class="punctuation">[]</span></code> may be ambiguous:</p>
<pre class="code c++ literal-block">
<span class="keyword">template</span> <span class="operator">&lt;</span><span class="keyword">typename</span> <span class="name">T</span><span class="punctuation">,</span> <span class="keyword type">size_t</span> <span class="name">N</span><span class="punctuation">,</span> <span class="keyword">typename</span><span class="punctuation">...</span> <span class="name">Vecs</span><span class="operator">&gt;</span>
<span class="name">std</span><span class="operator">::</span><span class="name">array</span><span class="operator">&lt;</span><span class="name">T</span><span class="punctuation">,</span> <span class="name">N</span><span class="operator">&gt;</span> <span class="name">sum</span><span class="punctuation">(</span><span class="name">Vecs</span><span class="punctuation">...</span> <span class="name">operands</span><span class="punctuation">)</span>
<span class="punctuation">{</span>
  <span class="name">std</span><span class="operator">::</span><span class="name">array</span><span class="operator">&lt;</span><span class="name">T</span><span class="punctuation">,</span> <span class="name">N</span><span class="operator">&gt;</span> <span class="name">result</span><span class="punctuation">;</span>
  <span class="keyword">for</span> <span class="punctuation">(</span><span class="keyword type">int</span> <span class="name">i</span> <span class="operator">=</span> <span class="literal number integer">0</span><span class="punctuation">;</span> <span class="name">i</span> <span class="operator">&lt;</span> <span class="name">N</span><span class="punctuation">;</span> <span class="operator">++</span><span class="name">i</span><span class="punctuation">)</span>
    <span class="name">result</span><span class="punctuation">[</span><span class="name">i</span><span class="punctuation">]</span> <span class="operator">=</span> <span class="name">operands</span><span class="punctuation">[</span><span class="name">i</span><span class="punctuation">]</span> <span class="operator">+</span> <span class="punctuation">...;</span>
<span class="punctuation">}</span>
</pre>
</li>
<li><p class="first">Such an operator still cannot provide slicing. See also <a class="reference internal" href="#what-alternatives-were-considered">What alternatives were considered?</a></p>
</li>
</ul>
<p>Our proposed language feature avoids these issues by being clearly distinct from existing <code class="cpp c++"><span class="keyword">operator</span><span class="punctuation">[]</span></code>; it is in essence a novel operator<a class="footnote-reference" href="#no" id="id3">[3]</a>. This is especially salient in the case of multi-valued slicing / unpacking, but also serves to make it more obvious to the user that a language feature is being employed rather than a traditional operator function.</p>
</div>
<div class="section" id="doesn-t-adding-another-operator-hurt-teachability">
<h2><a class="toc-backref" href="#id23">Doesn't adding another operator hurt teachability?</a></h2>
<p>Obviously, <em>any</em> new feature is something new to teach. The major concern, of course, is that we have two ways of doing &quot;the same thing&quot;. However, this is already the case; we already may have both <code class="cpp c++"><span class="name">get</span><span class="operator">&lt;</span><span class="name">N</span><span class="operator">&gt;</span></code> and <code class="cpp c++"><span class="keyword">operator</span><span class="punctuation">[]</span></code> for a type. Critically, we are <em>not</em> adding a third operation; our proposed operator is <em>always</em> a synonym for <code class="cpp c++"><span class="name">get</span><span class="operator">&lt;</span><span class="name">N</span><span class="operator">&gt;</span></code> (if it exists). It would be better to think of this proposal as <em>replacing</em> the spelling of product type indexed access, with <code class="cpp c++"><span class="name">get</span><span class="operator">&lt;</span><span class="name">N</span><span class="operator">&gt;</span></code> being the customization point for the same. Thus, <code class="cpp c++"><span class="punctuation">[</span><span class="name">i</span><span class="punctuation">]</span><span class="name">pt</span></code> and <code class="cpp c++"><span class="name">get</span><span class="operator">&lt;</span><span class="name">i</span><span class="operator">&gt;</span><span class="punctuation">(</span><span class="name">pt</span><span class="punctuation">)</span></code> are equivalent in much the way that <code class="cpp c++"><span class="name">a</span> <span class="operator">+</span> <span class="name">b</span></code> and <code class="cpp c++"><span class="name">a</span><span class="punctuation">.</span><span class="keyword">operator</span><span class="operator">+</span><span class="punctuation">(</span><span class="name">b</span><span class="punctuation">)</span></code> are equivalent. If this proposal is accepted, we expect that writing the latter of each case will become similarly rare.</p>
</div>
<div class="section" id="does-this-make-std-apply-and-std-make-from-tuple-obsolete">
<h2><a class="toc-backref" href="#id24">Does this make <code class="cpp c++"><span class="name">std</span><span class="operator">::</span><span class="name">apply</span></code> (and <code class="cpp c++"><span class="name">std</span><span class="operator">::</span><span class="name">make_from_tuple</span></code>) obsolete?</a></h2>
<p>No. There will almost certainly remain cases where <code class="cpp c++"><span class="name">std</span><span class="operator">::</span><span class="name">apply</span></code> and/or <code class="cpp c++"><span class="name">std</span><span class="operator">::</span><span class="name">make_from_tuple</span></code> are useful; for example, when using the operation as a functor that gets passed as an argument, or when expansions are nested. In fact, we used <code class="cpp c++"><span class="name">std</span><span class="operator">::</span><span class="name">apply</span></code> in one of the preceding examples <em>in conjunction with</em> our proposed feature.</p>
<p>That said, we do expect that <em>most</em> uses of <code class="cpp c++"><span class="name">std</span><span class="operator">::</span><span class="name">apply</span></code> and <code class="cpp c++"><span class="name">std</span><span class="operator">::</span><span class="name">make_from_tuple</span></code> can be replaced with the use of this feature.</p>
</div>
<div class="section" id="are-dead-accesses-to-product-type-value-elided">
<h2><a class="toc-backref" href="#id25">Are &quot;dead&quot; accesses to product type value elided?</a></h2>
<p>Consider the following code:</p>
<pre class="code c++ literal-block">
<span class="comment single">// let t be a product type (&quot;tuple-like&quot;) of size 3
</span><span class="keyword">auto</span> <span class="name">x</span> <span class="operator">=</span> <span class="punctuation">[</span><span class="literal number integer">1</span><span class="punctuation">]</span><span class="name">t</span><span class="punctuation">;</span>
</pre>
<p>What code is actually generated by the above?</p>
<pre class="code c++ literal-block">
<span class="comment single">// option 1
</span><span class="punctuation">[[</span><span class="name">maybe_unused</span><span class="punctuation">]]</span> <span class="name">get</span><span class="operator">&lt;</span><span class="literal number integer">0</span><span class="operator">&gt;</span><span class="punctuation">(</span><span class="name">t</span><span class="punctuation">);</span>
<span class="keyword">auto</span> <span class="name">x</span> <span class="operator">=</span> <span class="name">get</span><span class="operator">&lt;</span><span class="literal number integer">1</span><span class="operator">&gt;</span><span class="punctuation">(</span><span class="name">t</span><span class="punctuation">);</span>
<span class="punctuation">[[</span><span class="name">maybe_unused</span><span class="punctuation">]]</span> <span class="name">get</span><span class="operator">&lt;</span><span class="literal number integer">2</span><span class="operator">&gt;</span><span class="punctuation">(</span><span class="name">t</span><span class="punctuation">);</span>

<span class="comment single">// option 2
</span><span class="keyword">auto</span> <span class="name">x</span> <span class="operator">=</span> <span class="name">get</span><span class="operator">&lt;</span><span class="literal number integer">1</span><span class="operator">&gt;</span><span class="punctuation">(</span><span class="name">t</span><span class="punctuation">);</span>
</pre>
<p>In most cases, the question should be irrelevant; the compiler would eliminate the superfluous calls to <code class="cpp c++"><span class="name">get</span></code> as having no side effects. However, if <code class="cpp c++"><span class="name">get</span></code> has side effects (however much we might be inclined to consider that poor design), this could matter.</p>
<p>Certainly in the above example, we believe that the compiler should elide the &quot;superfluous&quot; value accesses, as this feels like the most natural consequence of combining the unpacking and slicing operations. A more interesting question, which we believe should be open to committee input, is what to do if slicing and unpacking are explicitly separated, as in <code class="cpp c++"><span class="punctuation">[</span><span class="literal number integer">1</span><span class="punctuation">][</span><span class="operator">:</span><span class="punctuation">]</span><span class="name">t</span></code>. While our inclination is that this form should be exactly equivalent to <code class="cpp c++"><span class="punctuation">[</span><span class="literal number integer">1</span><span class="punctuation">]</span><span class="name">t</span></code>, an argument could be made that writing out the operations separately implies that the programmer intends for each value of <code class="cpp c++"><span class="name">t</span></code> to be accessed, with any resulting side effects incurred, before reducing the resulting parameter pack to only the value at index <tt class="docutils literal">1</tt>.</p>
<p>If we consider an initializer list to be a product type, conceivably a user desiring side effects could obtain them by writing <code class="cpp c++"><span class="punctuation">[</span><span class="literal number integer">1</span><span class="punctuation">]{[</span><span class="operator">:</span><span class="punctuation">]</span><span class="name">t</span><span class="punctuation">...}</span></code>, which makes the intent to evaluate all values of <code class="cpp c++"><span class="name">t</span></code> prior to selecting a single value even more explicit.</p>
<p>(Note that one strong reason to consider <code class="cpp c++"><span class="punctuation">[</span><span class="literal number integer">1</span><span class="punctuation">][</span><span class="operator">:</span><span class="punctuation">]</span><span class="name">pt</span></code> and <code class="cpp c++"><span class="punctuation">[</span><span class="literal number integer">1</span><span class="punctuation">]</span><span class="name">pt</span></code> equivalent is for cases when the user actually writes something like <code class="cpp c++"><span class="punctuation">[</span><span class="operator">:</span><span class="name">n</span><span class="punctuation">][</span><span class="name">i</span><span class="operator">:</span><span class="punctuation">]</span><span class="name">pt</span></code>, i.e. '<code class="cpp c++"><span class="name">n</span></code> elements of <code class="cpp c++"><span class="name">pt</span></code> starting with index <code class="cpp c++"><span class="name">i</span></code>'. In this case, evaluation of all indices starting with <code class="cpp c++"><span class="name">i</span></code> is not necessarily desired, but restructuring the code to avoid this requires a more complicated expression that is especially difficult if <code class="cpp c++"><span class="name">i</span></code> and/or <code class="cpp c++"><span class="name">n</span></code> are expressions. Introducing an exception would make this feature more difficult to teach.)</p>
</div>
<div class="section" id="how-does-unpacking-interact-with-temporaries">
<h2><a class="toc-backref" href="#id26">How does unpacking interact with temporaries?</a></h2>
<p>Consider the following code:</p>
<pre class="code c++ literal-block">
<span class="comment single">// let foo() be a function returning a newly constructed product type
</span><span class="name">bar</span><span class="punctuation">([</span><span class="operator">:</span><span class="punctuation">]</span><span class="name">foo</span><span class="punctuation">()...);</span>
</pre>
<p>What does this mean with respect to object lifetime? Obviously, we do not want for <code class="cpp c++"><span class="name">foo</span><span class="punctuation">()</span></code> to be called <code class="cpp c++"><span class="keyword">sizeof</span><span class="punctuation">...(</span><span class="name">foo</span><span class="punctuation">())</span></code> times. Rather, the compiler should internally generate a temporary, whose lifetime shall be the same as if the unpacked expression had not been subject to unpacking.</p>
</div>
<div class="section" id="what-happens-if-the-indexing-expression-contains-a-pack">
<h2><a class="toc-backref" href="#id27">What happens if the indexing expression contains a pack?</a></h2>
<p>Consider the following example:</p>
<pre class="code c++ literal-block">
<span class="comment single">// let x be a pack of integers
// let p be a pack of values
</span><span class="name">foo</span><span class="punctuation">([</span><span class="name">x</span><span class="punctuation">]</span><span class="name">p</span><span class="punctuation">...);</span>
</pre>
<p>What does this mean? Indexing is specified as having higher precedence than expansion, but the indexing expression is itself a pack. The &quot;easy&quot; answer is to make this an error (the indexing expression is not a <code class="cpp c++"><span class="name">constexpr</span></code> integer, as required), but one could also argue that expansion in this case should occur first, which would make the code equivalent to:</p>
<pre class="code c++ literal-block">
<span class="name">foo</span><span class="punctuation">([([</span><span class="literal number integer">0</span><span class="punctuation">]</span><span class="name">x</span><span class="punctuation">)]([</span><span class="literal number integer">0</span><span class="punctuation">]</span><span class="name">p</span><span class="punctuation">),</span> <span class="punctuation">[([</span><span class="literal number integer">1</span><span class="punctuation">]</span><span class="name">x</span><span class="punctuation">)]([</span><span class="literal number integer">1</span><span class="punctuation">]</span><span class="name">p</span><span class="punctuation">),</span> <span class="punctuation">...,</span> <span class="punctuation">[([</span><span class="name">N</span><span class="punctuation">]</span><span class="name">x</span><span class="punctuation">)]([</span><span class="name">N</span><span class="punctuation">]</span><span class="name">p</span><span class="punctuation">));</span>
</pre>
<p>We are strongly inclined to take the easy answer and make this ill-formed. This leaves room for a future proposal to give such code meaning, should we ever desire to do so.</p>
</div>
<div class="section" id="what-about-ambiguity-with-lambda-captures">
<h2><a class="toc-backref" href="#id28">What about ambiguity with lambda captures?</a></h2>
<p>A lambda capture is required to be a variable in the current scope. As such, the compiler can determine if a <code class="cpp c++"><span class="punctuation">[</span></code> starts a lambda capture or a slicing expression by parsing at most three additional tokens. If the first token following the <code class="cpp c++"><span class="punctuation">[</span></code> is not a variable eligible for lambda capture (for example, an integer literal), then the <code class="cpp c++"><span class="punctuation">[</span></code> starts a slicing expression. If the first token matches an in-scope (and <code class="cpp c++"><span class="name">constexpr</span></code>) variable name, and the second token is not a <code class="cpp c++"><span class="punctuation">,</span></code> or <code class="cpp c++"><span class="punctuation">]</span></code>, then the <code class="cpp c++"><span class="punctuation">[</span></code> starts a slicing expression. In all other cases, the <code class="cpp c++"><span class="punctuation">[</span></code> shall be taken to start a lambda capture, as in current C++. (If the first token is <code class="cpp c++"><span class="operator">&amp;</span></code>, the preceding rules may be applied with the token counts shifted by 1. However, this assumes that there exists a case where unary <code class="cpp c++"><span class="keyword">operator</span><span class="operator">&amp;</span></code> is <code class="cpp c++"><span class="name">constexpr</span></code>. This may not be reasonable, in which case <code class="cpp c++"><span class="punctuation">[</span><span class="operator">&amp;</span></code> would always indicate a lambda capture, and at most only two tokens following <code class="cpp c++"><span class="punctuation">[</span></code> must be parsed.)</p>
<p>Consider the following example:</p>
<pre class="code c++ literal-block">
<span class="name">constexpr</span> <span class="keyword type">int</span> <span class="name">a</span> <span class="operator">=</span> <span class="punctuation">...;</span>
<span class="punctuation">[</span><span class="name">a</span><span class="punctuation">]</span><span class="name">t</span><span class="punctuation">;</span>
</pre>
<p>By the above logic, this would be ill-formed. Although a slicing expression is intended, the compiler would be unable to disambiguate from a lambda until after the <code class="cpp c++"><span class="punctuation">]</span></code>, and following the above logic, the statement is parsed as a lambda. Such an expression calls for disambiguation:</p>
<pre class="code c++ literal-block">
<span class="name">constexpr</span> <span class="keyword type">int</span> <span class="name">a</span> <span class="operator">=</span> <span class="punctuation">...;</span>
<span class="punctuation">[(</span><span class="name">a</span><span class="punctuation">)]</span><span class="name">t</span><span class="punctuation">;</span>
</pre>
<p>The addition of parentheses does not change the intended meaning of the statement, but precludes the statement from being parsed as a lambda capture. We believe that this is an acceptable trade-off to prevent unreasonable complexity in selecting between a slicing expression and a lambda capture.</p>
<p>Note also:</p>
<pre class="code c++ literal-block">
<span class="keyword">template</span> <span class="operator">&lt;</span><span class="keyword type">int</span> <span class="name">n</span><span class="operator">&gt;</span> <span class="keyword">auto</span> <span class="name">get_and_apply</span><span class="punctuation">(</span><span class="keyword">auto</span> <span class="name">func</span><span class="punctuation">,</span> <span class="keyword">auto</span><span class="punctuation">...</span> <span class="name">items</span><span class="punctuation">)</span>
<span class="punctuation">{</span>
  <span class="keyword">return</span> <span class="name">func</span><span class="punctuation">([</span><span class="name">n</span><span class="punctuation">]</span><span class="name">args</span><span class="punctuation">);</span>
<span class="punctuation">}</span>
</pre>
<p>Although this example appears at first to be the same as the preceding example, <code class="cpp c++"><span class="name">n</span></code> here is a template parameter and is not eligible for lambda capture, so the expression is parsed as a slicing expression instead (as intended). Again, this seems like a reasonable trade-off, but we would be amenable to requiring parentheses in all cases where the index-expression is just an identifier.</p>
<p>An alternative approach, albeit one requiring additional look-ahead, is to consider the token following the closing <code class="cpp c++"><span class="punctuation">]</span></code>. If the token is not <code class="cpp c++"><span class="punctuation">(</span></code>, then we have a slicing expression. If it is <code class="cpp c++"><span class="punctuation">(</span></code> and the next token is <em>not</em> a type name, then we have a slicing expression. Otherwise, we have a lambda capture. This may be more robust, at the cost of being more difficult to implement in compilers. (This also runs into the difficulty that future proposals may allow additional syntaxes for lambdas. A better expression would be that the compiler attempts first to treat the code as a lambda, and falls back to a slicing expression if that fails. Perhaps compilers could implement this as a non-conforming extension.)</p>
</div>
<div class="section" id="should-out-of-bounds-access-be-an-error">
<h2><a class="toc-backref" href="#id29">Should out-of-bounds access be an error?</a></h2>
<p>This is a reasonable question. Consider:</p>
<pre class="code c++ literal-block">
<span class="keyword type">void</span> <span class="name function">foo</span><span class="punctuation">(</span><span class="name">args</span><span class="punctuation">...)</span> <span class="punctuation">{</span> <span class="name">bar</span><span class="punctuation">(</span><span class="name">args</span><span class="punctuation">[</span><span class="operator">:</span><span class="literal number integer">3</span><span class="punctuation">]...);</span> <span class="punctuation">}</span>
<span class="name">foo</span><span class="punctuation">(</span><span class="literal number integer">1</span><span class="punctuation">,</span> <span class="literal number integer">2</span><span class="punctuation">);</span>
</pre>
<p>In the above, <cite>foo</cite> asks for <em>up to</em> the first 3 elements of a pack, but in the invocation shown, the pack only has two elements. Should this be an error? On the one hand, experience with Python suggests that silently truncating to the available range has many uses, and where this is not intended, a <code class="cpp c++"><span class="name">static_assert</span></code> could be used to ensure the size of the pack is as expected. On the other, <code class="cpp c++"><span class="name">constexpr</span></code> forms of <code class="cpp c++"><span class="name">std</span><span class="operator">::</span><span class="name">min</span></code> and <code class="cpp c++"><span class="name">std</span><span class="operator">::</span><span class="name">max</span></code>, or simply writing out ternary expressions, could be used to emulate this behavior, which might make programmer intent more clear.</p>
<p>While we are inclined to the former position, with the behavior as presented in this paper, this does not represent a hard position, and we would welcome committee input on this matter.</p>
<p>Note that this only applies to slicing. Out of bounds <em>indexing</em> should certainly be an error.</p>
</div>
<div class="section" id="why-choose-trailing-index">
<h2><a class="toc-backref" href="#id30">Why choose trailing index?</a></h2>
<p>The choice of the second value as a non-inclusive index, rather than a count, was made for consistency with existing convention (specifically, Python), because it is consistent with counting indices given a lower and upper bound, and because it simplifies the computation of the upper index when a negative value is given.</p>
<p>It is also worth noting that more complicated index expressions may be used to obtain a first-and-count slice using lower-until-upper notation or vice versa. More importantly, however, a first-and-count slice may be obtained like <code class="cpp c++"><span class="punctuation">[</span><span class="operator">:</span><span class="name">count</span><span class="punctuation">][</span><span class="name">first</span><span class="operator">:</span><span class="punctuation">]</span><span class="name">pack</span></code>, but obtaining a lower-until-upper slice with first-and-count syntax is more verbose.</p>
</div>
<div class="section" id="why-extend-sizeof">
<h2><a class="toc-backref" href="#id31">Why extend <code class="cpp c++"><span class="keyword">sizeof</span><span class="punctuation">...</span></code>?</a></h2>
<p>The short answer is &quot;symmetry&quot;. It seems logical to us that if slicing works on both parameter packs and &quot;concrete&quot; product types that <code class="cpp c++"><span class="keyword">sizeof</span><span class="punctuation">...</span></code> should do likewise. However, this modification could be dropped without significantly harming the proposal.</p>
</div>
<div class="section" id="can-t-we-use-a-purely-library-solution">
<h2><a class="toc-backref" href="#id32">Can't we use a purely library solution?</a></h2>
<p>No. While it may be possible to implement a standardized library function to extract a <em>single</em> element from a parameter pack, slicing requires <em>some</em> form of language solution (see also next question), or else the creation of temporary objects that will only be destroyed again immediately. (Additionally, we dislike any solution that creates a temporary product type because it is difficult for the user to control what type is used for this purpose. This is also why we dislike using a library function to slice product types. By producing a parameter pack, the pack can be used directly when that is desired, or used to construct a product type of the user's choice as needed.) A library solution would also be much more verbose, and may result in poorer code generation, whereas language level slicing of parameter packs is trivially accomplished by the compiler.</p>
</div>
<div class="section" id="what-alternatives-were-considered">
<h2><a class="toc-backref" href="#id33">What alternatives were considered?</a></h2>
<p>There are at least three possible alternatives that could provide features similar to generalized unpacking, as proposed here. The first alternative is first class support for multiple return values, where such are treated as parameter packs. The second is modifying decomposition declarations (which we like to also call &quot;name-binding unpacking&quot;, for symmetry with &quot;generalized unpacking&quot;) to support specifying a parameter pack as one of the unpacked values. The third is to introduce parameter pack generators.</p>
<ul class="simple">
<li>First class support for multiple return values (which is effectively proposed by <a class="reference external" href="http://wg21.link/p0341">P0341</a>) is an ambitious feature with assorted difficulties (see next question). Moreover, if <a class="reference external" href="http://wg21.link/p0536">P0536</a> is accepted, the need for true first class multiple return values would be significantly lessened.</li>
<li>Modifying name-binding unpacking (e.g. <code class="cpp c++"><span class="keyword">auto</span><span class="operator">&amp;&amp;</span> <span class="punctuation">[</span><span class="name">x</span><span class="punctuation">,</span> <span class="name">p</span><span class="punctuation">...,</span> <span class="name">y</span><span class="punctuation">]</span> <span class="operator">=</span> <span class="name">t</span><span class="punctuation">;</span></code>) is likewise a language change of similar caliber to what we propose, with the added drawback of requiring additional declarations for many use cases.</li>
<li>Parameter pack generation is interesting (in fact, we would like to see parameter pack generation <em>in addition</em> to this proposal), but still requires the ability to extract a single element from a pack.</li>
</ul>
<p>All of these would require greater verbosity for even simple use cases.</p>
<p>We believe that our proposal is the best solution, as it solves a crucial need not addressed by these alternatives (extracting a single value from a parameter pack) and further leverages that syntax to maximum versatility with minimal overhead compared to the minimum possible functionality.</p>
<p>We have yet to see a competing direction that can offer comparable functionality with comparable complexity, even ignoring those parts of competing directions which would have wider applicability (e.g. <code class="cpp c++"><span class="name">constexpr</span></code> function parameters). Every competing direction has, at some point, necessarily proposed some feature of similar or greater complexity which serves only to provide a feature that our proposal would already provide, and <em>every</em> competing direction involves much more &quot;wordiness&quot; for any of the use cases our proposal would address.</p>
</div>
<div class="section" id="how-does-this-relate-to-p0341">
<h2>How does this relate to <a class="reference external" href="http://wg21.link/p0341">P0341</a>?</h2>
<p>We would be remiss to not discuss <a class="reference external" href="http://wg21.link/p0341">P0341</a>, especially in light of our proposed generalized unpacking feature. Leaving aside various concerns as far as returning parameter packs (which are also discussed in <a class="reference external" href="http://wg21.link/p0536">P0536</a>), generalized unpacking obviates a major use case for some of the features proposed by <a class="reference external" href="http://wg21.link/p0341">P0341</a>. In particular, <a class="reference external" href="http://wg21.link/p0341">P0341</a> gives this example:</p>
<pre class="code c++ literal-block">
<span class="operator">&lt;</span><span class="keyword type">double</span><span class="punctuation">,</span> <span class="keyword type">double</span><span class="operator">&gt;</span> <span class="name">calculateTargetCoordinates</span><span class="punctuation">();</span>
<span class="keyword type">double</span> <span class="name function">distanceFromMe</span><span class="punctuation">(</span><span class="keyword type">double</span> <span class="name">x</span><span class="punctuation">,</span> <span class="keyword type">double</span> <span class="name">y</span><span class="punctuation">);</span>

<span class="keyword type">void</span> <span class="name function">launch</span><span class="punctuation">()</span> <span class="punctuation">{</span>
  <span class="keyword">if</span><span class="punctuation">(</span><span class="name">distanceFromMe</span><span class="punctuation">(</span><span class="name">calculateTargetCoordinates</span><span class="punctuation">()...))</span>
    <span class="name">getOuttaHere</span><span class="punctuation">();</span>
<span class="punctuation">}</span>
</pre>
<p>The utility of being able to invoke the postulated <code class="cpp c++"><span class="name">distanceFromMe</span></code> function taking two parameters is obvious. However, the solution proposed by <a class="reference external" href="http://wg21.link/p0341">P0341</a> is strictly limited in that it requires that the function providing the input values — <code class="cpp c++"><span class="name">calculateTargetCoordinates</span></code> — must provide them as a parameter pack. Moreover, it is not obvious at the point of use that <code class="cpp c++"><span class="name">calculateTargetCoordinates</span></code> returns a parameter pack rather than a regular type.</p>
<p>Generalized unpacking provides a much better solution:</p>
<pre class="code c++ literal-block">
<span class="name">std</span><span class="operator">::</span><span class="name">tuple</span><span class="operator">&lt;</span><span class="keyword type">double</span><span class="punctuation">,</span> <span class="keyword type">double</span><span class="operator">&gt;</span> <span class="name">calculateTargetCoordinates</span><span class="punctuation">();</span>
<span class="keyword type">double</span> <span class="name function">distanceFromMe</span><span class="punctuation">(</span><span class="keyword type">double</span> <span class="name">x</span><span class="punctuation">,</span> <span class="keyword type">double</span> <span class="name">y</span><span class="punctuation">);</span>

<span class="keyword type">void</span> <span class="name function">launch</span><span class="punctuation">()</span> <span class="punctuation">{</span>
  <span class="keyword">if</span><span class="punctuation">(</span><span class="name">distanceFromMe</span><span class="punctuation">([</span><span class="operator">:</span><span class="punctuation">]</span><span class="name">calculateTargetCoordinates</span><span class="punctuation">()...))</span>
    <span class="name">getOuttaHere</span><span class="punctuation">();</span>
<span class="punctuation">}</span>
</pre>
<p>The return type of <code class="cpp c++"><span class="name">calculateTargetCoordinates</span></code> is a regular type, and we can call <code class="cpp c++"><span class="name">distanceFromMe</span></code> on any product type value that can convert (or be sliced) to a pair of <code class="cpp c++"><span class="keyword type">double</span></code>s.</p>
<p>Another issue which concerns us with <a class="reference external" href="http://wg21.link/p0341">P0341</a>, or any proposal for functions returning parameter packs, is the ambiguity it introduces. Consider the following statement:</p>
<pre class="code c++ literal-block">
<span class="keyword">auto</span> <span class="name">x</span> <span class="operator">=</span> <span class="name">foo</span><span class="punctuation">();</span>
</pre>
<p>At present, <code class="cpp c++"><span class="name">x</span></code> here is a value, for virtually anything that <code class="cpp c++"><span class="name">foo</span><span class="punctuation">()</span></code> might return. If we allow parameter packs as return types, this will no longer be the case; users will be uncertain if a particular expression yields a single object, or a parameter pack. If we attempt to solve this by allowing parameter packs to be treated as single objects, we are piling on additional language changes, on top of which one must ask why parameter packs — being objects, like many other types — should be given uniquely special treatment in fold expressions. This could be especially confusing to novice readers:</p>
<pre class="code c++ literal-block">
<span class="keyword">auto</span> <span class="name">x</span> <span class="operator">=</span> <span class="name">foo</span><span class="punctuation">();</span>
<span class="keyword">auto</span> <span class="name">y</span> <span class="operator">=</span> <span class="name">x</span> <span class="operator">+</span> <span class="punctuation">...;</span> <span class="comment single">// why can 'x' be used in a fold expression?
</span>
</pre>
<p>At least with parameter packs as they exist today, it is obvious at the declaration site when an identifier names a parameter pack. Using a new syntax to create parameter packs from product types provides a similarly obvious indicator when a parameter pack comes into being.</p>
</div>
<div class="section" id="how-does-this-relate-to-p0478">
<h2>How does this relate to <a class="reference external" href="http://wg21.link/p0478">P0478</a>?</h2>
<p>After picking on their examples, it would be unfair if we did not follow up by asking if our proposed feature makes <a class="reference external" href="http://wg21.link/p0478">P0478</a> unnecessary. As with <code class="cpp c++"><span class="name">std</span><span class="operator">::</span><span class="name">apply</span></code>, we feel that the answer is &quot;not necessarily&quot;, even though our feature significantly reduces the need for <a class="reference external" href="http://wg21.link/p0478">P0478</a>. However, there are two use cases for combining pack and non-pack arguments. One case, which our proposal addresses in a significantly better manner, is artificial separation as a means for slicing parameter packs. The example we deconstructed above, as well as the many functions of the form <code class="cpp c++"><span class="name">T</span> <span class="name">first</span><span class="punctuation">,</span> <span class="name">Args</span><span class="punctuation">...</span> <span class="name">remainder</span></code>, clearly fall into this category. In these cases, this artificial decomposition of the argument list is detrimental to the clarity of the function's interface, and as shown can lead to implementation bugs.</p>
<p>Another case, however, is where the separation is non-artificial; where, for whatever reason, a function accepts a variadic argument pack followed by one or more arguments that are logically unrelated to the pack. For such cases, <a class="reference external" href="http://wg21.link/p0478">P0478</a> would provide improved clarity at the interface level, as well as the ability to specify (or at least, separately name) types for the trailing arguments.</p>
<p>That said, in light of our proposed feature, it may well be that a much more compelling rationale for <a class="reference external" href="http://wg21.link/p0478">P0478</a> would be desired in order for that feature to be accepted.</p>
</div>
</div>
<div class="section" id="future-direction">
<h1><a class="toc-backref" href="#id36">Future Direction</a></h1>
<div class="section" id="complex-ordering">
<h2><a class="toc-backref" href="#id37">Complex Ordering</a></h2>
<p>This feature is not intended to solve all cases of value sequence compositions and decompositions by itself. We specifically are not attempting to provide a language mechanism for reversing a value sequence, selecting indices (e.g. every other item) from a value sequence, or interleaving value sequences. We believe that there is significant room for library features to bring added value to this area. Such features would likely leverage this feature under the covers. (Parameter pack generation, which as noted is a feature we would like to see, almost certainly would use at least single-value indexing into parameter packs.)</p>
</div>
<div class="section" id="interaction-with-name-binding-unpacking">
<h2><a class="toc-backref" href="#id38">Interaction with Name-Binding Unpacking</a></h2>
<p>As stated several times, this feature is intended to continue in a direction first taken by name-binding unpacking. Despite that, combining these features presents an interesting challenge. Consider:</p>
<pre class="code c++ literal-block">
<span class="keyword">auto</span> <span class="punctuation">[</span><span class="name">a</span><span class="punctuation">,</span> <span class="name">b</span><span class="punctuation">]</span> <span class="operator">=</span> <span class="punctuation">[</span><span class="operator">:</span><span class="literal number integer">2</span><span class="punctuation">]</span><span class="name">pt</span><span class="punctuation">;</span>
<span class="keyword">auto</span> <span class="punctuation">[</span><span class="name">a</span><span class="punctuation">,</span> <span class="name">b</span><span class="punctuation">]</span> <span class="operator">=</span> <span class="punctuation">{[</span><span class="operator">:</span><span class="literal number integer">2</span><span class="punctuation">]</span><span class="name">pt</span><span class="punctuation">...};</span>
</pre>
<p>It seems natural to desire that one or both of these syntaxes should be permitted, but at this time (even with full adoption of this proposal as presented), both are ill-formed. The latter possibly will become valid if and when general product type access is extended to initializer lists, with the assumption that such extension will include the ability to use an initializer list on the RHS of a decomposition declaration. However, there are potential lifetime issues involved. For this reason and others, it may be interesting to extend decomposition declarations to also work directly with parameter packs, with the added stipulation that a product type converted to a parameter pack is &quot;pass through&quot; when appearing as the RHS of a decomposition declaration; that is, the decomposition declaration would be aware of the original product type for the purpose of object lifetime. We do not feel that this feature is necessary initially, but would recommend a follow-up paper if the feature proposed is accepted.</p>
</div>
<div class="section" id="pack-generators-lite">
<h2><a class="toc-backref" href="#id39">Pack Generators &quot;Lite&quot;</a></h2>
<p>In the <a class="reference internal" href="#static-value-table">Static value table</a> example, we showed how to create a &quot;product type&quot; that exists solely to be unpacked and used as a value generator. This involved some boilerplate code. From the version of the example given, it should be readily apparent how one might rewrite the example as follows:</p>
<pre class="code c++ literal-block">
<span class="keyword">auto</span> <span class="name">generate_sin64</span> <span class="operator">=</span> <span class="punctuation">[](</span><span class="keyword type">size_t</span> <span class="name">n</span><span class="punctuation">)</span> <span class="punctuation">{</span>
  <span class="keyword">return</span> <span class="name">_builtin_sin</span><span class="punctuation">(</span><span class="literal number float">2.0</span> <span class="operator">*</span> <span class="name">M_PI</span> <span class="operator">*</span> <span class="keyword">static_cast</span><span class="operator">&lt;</span><span class="keyword type">double</span><span class="operator">&gt;</span><span class="punctuation">(</span><span class="name">n</span><span class="punctuation">)</span> <span class="operator">/</span> <span class="literal number float">64.0</span><span class="punctuation">);</span> <span class="punctuation">}</span>

<span class="keyword type">double</span> <span class="name">sin64</span><span class="punctuation">[]</span> <span class="operator">=</span> <span class="punctuation">{</span>
  <span class="punctuation">[</span><span class="operator">:</span><span class="punctuation">](</span><span class="name">std</span><span class="operator">::</span><span class="keyword type">generate_pack_t</span><span class="operator">&lt;</span><span class="literal number integer">64</span><span class="punctuation">,</span> <span class="name">generate_sin64</span><span class="operator">&gt;</span><span class="punctuation">{})...</span> <span class="punctuation">};</span>
</pre>
<p>Here we show how a standard library type might be provided to take care of most of the boilerplate in order to allow the direct conversion of a lambda to a parameter pack. This lacks the expressive power of full pack generators, and makes it rather painfully obvious that we'd like to have <code class="cpp c++"><span class="name">constexpr</span></code> parameters, but despite these limitations, the possibilities are interesting.</p>
</div>
</div>
<div class="section" id="acknowledgments">
<h1><a class="toc-backref" href="#id40">Acknowledgments</a></h1>
<p>We wish to thank everyone on the <tt class="docutils literal"><span class="pre">std-proposals</span></tt> forum that has contributed over the long period for which this has been marinating. We also wish to thank everyone that worked to bring decomposition declarations to C++17, as well as the authors of all cited papers for their contributions to this field.</p>
</div>
<div class="section" id="footnotes">
<h1><a class="toc-backref" href="#id41">Footnotes</a></h1>
<table class="docutils footnote" frame="void" id="io" rules="none">
<colgroup><col class="label" /><col /></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#id1">[1]</a></td><td>In particular, we would encourage that this proposal be considered as providing the product type indexing operator to which <a class="reference external" href="http://wg21.link/p0327">P0327</a> alludes, noting particularly <a class="reference external" href="http://wg21.link/p0327">P0327</a>'s reference to a &quot;concrete proposal for parameter packs direct access&quot;.</td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="mi" rules="none">
<colgroup><col class="label" /><col /></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#id2">[2]</a></td><td>Given index truncation, we could also specify &quot;a large number&quot; (<code class="cpp c++"><span class="name">std</span><span class="operator">::</span><span class="name">numeric_limits</span><span class="operator">&lt;</span><span class="keyword type">size_t</span><span class="operator">&gt;::</span><span class="name">max</span><span class="punctuation">()</span></code>) and obtain equivalent behavior. The implementation should be allowed to vary, so long as an omitted upper bound has the expected effect.</td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="no" rules="none">
<colgroup><col class="label" /><col /></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#id3">[3]</a></td><td>Particularly, it is the novel operator alluded to in <a class="reference external" href="http://wg21.link/p0327">P0327</a>, as has been previously noted.</td></tr>
</tbody>
</table>
</div>
<div class="section" id="references">
<h1><a class="toc-backref" href="#id42">References</a></h1>
<ul>
<li><p class="first"><a class="reference external" href="http://wg21.link/n4235">N4235</a> Selecting from Parameter Packs</p>
<p><a class="reference external" href="http://wg21.link/n4235">http://wg21.link/n4235</a></p>
</li>
</ul>
<ul>
<li><p class="first"><a class="reference external" href="http://wg21.link/p0222">P0222</a> Allowing Anonymous Structs as Return Values</p>
<p><a class="reference external" href="http://wg21.link/p0222">http://wg21.link/p0222</a></p>
</li>
</ul>
<ul>
<li><p class="first"><a class="reference external" href="http://wg21.link/p0311">P0311</a> A Unified Vision for Manipulating Tuple-like Objects</p>
<p><a class="reference external" href="http://wg21.link/p0311">http://wg21.link/p0311</a></p>
</li>
</ul>
<ul>
<li><p class="first"><a class="reference external" href="http://wg21.link/p0327">P0327</a> Product Types Access</p>
<p><a class="reference external" href="http://wg21.link/p0327">http://wg21.link/p0327</a></p>
</li>
</ul>
<ul>
<li><p class="first"><a class="reference external" href="http://wg21.link/p0341">P0341</a> Parameter Packs Outside of Templates</p>
<p><a class="reference external" href="http://wg21.link/p0341">http://wg21.link/p0341</a></p>
</li>
</ul>
<ul>
<li><p class="first"><a class="reference external" href="http://wg21.link/p0478">P0478</a> Template argument deduction for non-terminal function parameter packs</p>
<p><a class="reference external" href="http://wg21.link/p0478">http://wg21.link/p0478</a></p>
</li>
</ul>
<ul>
<li><p class="first"><a class="reference external" href="http://wg21.link/p0536">P0536</a> Implicit Return Type and Allowing Anonymous Types as Return Values</p>
<p><a class="reference external" href="http://wg21.link/p0536">http://wg21.link/p0536</a></p>
</li>
</ul>
<ul>
<li><p class="first"><a class="reference external" href="https://www.python.org/dev/peps/pep-0448">PEP 0448</a> Additional Unpacking Generalizations</p>
<p><a class="reference external" href="https://www.python.org/dev/peps/pep-0448">https://www.python.org/dev/peps/pep-0448</a></p>
</li>
</ul>
<!-- .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. -->
<!-- kate: hl reStructuredText -->
</div>
</div>
</body>
</html>
