<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC
    "-//W3C//DTD XHTML 1.1 plus MathML 2.0 plus SVG 1.1//EN"
    "http://www.w3.org/2002/04/xhtml-math-svg/xhtml-math-svg.dtd">
<html xml:lang='en' xmlns:svg='http://www.w3.org/2000/svg' xmlns='http://www.w3.org/1999/xhtml'>
<head><meta content='application/xhtml+xml;charset=utf-8' http-equiv='Content-type' /><title>make_array, revision 4</title></head>
<body><!-- maruku -o make_array.html make_array.md --><style type='text/css'>
pre code { display: block; margin-left: 2em; }
div { display: block; margin-left: 2em; }
ins { text-decoration: none; font-weight: bold; background-color: #A0FFA0 }
del { text-decoration: line-through; background-color: #FFA0A0 }
</style><table><tbody>
<tr><th>Doc. no.:</th>	<td>N4391</td></tr>
<tr><th>Date:</th>	<td>2015-02-26</td></tr>
<tr><th>Project:</th>	<td>Programming Language C++, Library Working Group</td></tr>
<tr><th>Revises:</th>	<td>N4315</td></tr>
<tr><th>Reply-to:</th>	<td>Zhihao Yuan &lt;zy at miator dot net&gt;</td></tr>
</tbody></table>
<h1 id='make_array_revision_4'>make_array, revision 4</h1>

<h2 id='changes_since_n4315'>Changes since N4315</h2>

<ul>
<li>Ill-form the program if the input contains <code>reference_wrapper</code>.</li>

<li>Drop <em>see below</em> in the synopsis.</li>

<li>Fix typos and formatting.</li>
</ul>

<h2 id='changes_since_n4065'>Changes since N4065</h2>

<ul>
<li>Merge <code>make_array</code> and <code>array_of</code> into one.</li>

<li>Cleanup notes for presentation.</li>
</ul>

<h2 id='changes_since_n4031'>Changes since N4031</h2>

<ul>
<li><code>make_array&lt;D&gt;</code> renamed to <code>array_of&lt;D&gt;</code>.</li>

<li>Fixed <em>cv</em>-<code>reference_wrapper&lt;T&gt;</code> detection.</li>
</ul>

<h2 id='changes_since_n3824'>Changes since N3824</h2>

<ul>
<li>Editorial wording updates.</li>

<li>Comments updates.</li>
</ul>

<h2 id='motivation'>Motivation</h2>

<p>We have <code>make_tuple</code>, <code>make_pair</code>, but not <code>make_array</code>, while <code>std::array</code> creation can also benefit from this &#8220;semiofficial&#8221; tuple-like interface to deduce both element type and array bound.</p>

<h2 id='scope'>Scope</h2>

<p><a href='http://cplusplus.github.io/LWG/lwg-closed.html#851'>LWG 851</a> intended to provide a replacement syntax to</p>

<pre><code>array&lt;T, N&gt; a = { E1, E2, ... };</code></pre>

<p>, so the following</p>

<pre><code>auto a = make_array(42u, 3.14);</code></pre>

<p>is well-formed (with additional <code>static_cast</code>s applied inside) because</p>

<pre><code>array&lt;double, 2&gt; = { 42u, 3.14 };</code></pre>

<p>is well-formed.</p>

<p>This paper intends to provide a set of <code>std::array</code> creation interfaces which are comprehensive from both <code>tuple</code>&#8217;s point of view and <code>array</code>&#8217;s point of view, so narrowing is just naturally banned. See more details driven by this direction in <a href='#design_decisions'>Design Decisions</a>.</p>

<h2 id='examples'>Examples</h2>

<pre><code>auto a1 = make_array(2, 3L);        // array&lt;long, 2&gt;
auto ax = make_array(2, 3U);        // error: narrowing

auto a2 = make_array&lt;long&gt;(2, 3U);      // explicit destination type
auto ax = make_array&lt;unsigned&gt;(2, 3U);  // error: narrowing

auto a3 = make_array(&quot;foo&quot;);        // array&lt;char const*, 1&gt;, decayed
auto a4 = to_array(&quot;foo&quot;);          // array&lt;char, 4&gt;</code></pre>

<h2 id='design_decisions'>Design Decisions</h2>

<ul>
<li>
<p>Provide both <code>make_tuple</code>-like, type-deduced interface and raw array style bound-deduced interface.</p>
</li>

<li>
<p>Ban <code>reference_wrapper</code> in the <code>make_tuple</code>-like interface. <code>make_tuple</code> and <code>make_pair</code> have special handling of <code>reference_wrapper</code>, then user might expect that the expression</p>
</li>
</ul>
<div><div><tt>make_array(ref(a), ref(b))</tt></div></div>
<blockquote>
<p>also results in a tuple-like object storing <code>T&amp;</code>. However, <code>std::array</code> does not store &#8220;real&#8221; references, and any attempts to workaround this break the interfaces in different ways. Note that &#8220;doing nothing&#8221; is not an option since, for example, <code>common_type_t&lt;reference_wrapper&lt;int&gt;, reference_wrapper&lt;long&gt;&gt;</code> is <code>long</code>, not reference or <code>reference_wrapper</code>.</p>
</blockquote>

<ul>
<li>A saperated interface to perform constructing from raw array instead of array-to-pointer conversion. <code>make_tuple</code> and <code>make_pair</code> unconditionally decay, but such a behavior, when being applied to <code>make_array</code>,</li>
</ul>
<div><div><tt>make_array("raw array")&nbsp;
// got array&lt;char const&#42;, 1&gt;</tt></div></div>
<blockquote>
<p>is inexplicable. However, to keep the interfaces consistent, I decide to name a new utility differently instead of to ban this conversion.</p>
</blockquote>

<h2 id='wording'>Wording</h2>

<p>This wording is relative to N4296.</p>

<p>Add to 23.3.1/2 &#91;sequences.general&#93;, <code>&lt;array&gt;</code> synopsis:</p>

<pre><code>namespace std {
  template &lt;class T, size_t N &gt; struct array;</code></pre>

<blockquote>
<p>&#8230;</p>
</blockquote>

<pre><code>  template &lt;class T, size_t N &gt;
    void swap(array&lt;T,N&gt;&amp; x, array&lt;T,N&gt;&amp; y) noexcept(noexcept(x.swap(y)));</code></pre>
<div><ins>
<tt>template &lt;class D = void, class... Types&gt;</tt><br />
<tt>&nbsp;&nbsp;constexpr array&lt;<i>VT</i>, sizeof...(Types)&gt;
make_array(Types&amp;&amp;...);</tt><br />
<tt>template &lt;class T, size_t N&gt;</tt><br />
<tt>&nbsp;&nbsp;constexpr array&lt;remove_cv_t&lt;T&gt;, N&gt;
to_array(T (&amp;a)&#91;N&#93;);</tt><br />
</ins></div>
<blockquote>
<p>&#8230;</p>
</blockquote>

<pre><code>}</code></pre>

<p>New section 23.3.2.9 &#91;array.creation&#93; (between &#91;array.zero&#93; and &#91;array.tuple&#93;, which was 23.3.2.9):</p>

<blockquote>
<h4 id='23329_array_creation_functions_arraycreation'>23.3.2.9 Array creation functions &#91;array.creation&#93;</h4>
</blockquote>
<div>
<tt>template &lt;class D = void, class... Types&gt;</tt><br />
<tt>&nbsp;&nbsp;constexpr array&lt;<i>VT</i>, sizeof...(Types)&gt;
make_array(Types&amp;&amp;...);</tt><br />
</div>
<blockquote>
<p>Let <em>Ui</em> be <code>decay_t&lt;</code><em>Ti</em><code>&gt;</code> for each <em>Ti</em> in <code>Types</code>.</p>
</blockquote>

<blockquote>
<p><em>Remarks:</em> The program is ill-formed if <code>D</code> is <code>void</code> and at least one <em>Ui</em> is a specialization of <code>reference_wrapper</code>.</p>
</blockquote>

<blockquote>
<p><em>Returns:</em> <code>array&lt;</code><em>VT</em><code>, sizeof...(Types)&gt;{ std::forward&lt;Types&gt;(t)... }</code>, where <em>VT</em> is <code>common_type_t&lt;Types...&gt;</code> if <code>D</code> is <code>void</code>, otherwise <em>VT</em> is <code>D</code>.</p>
</blockquote>

<blockquote>
<p><em>[Example:</em></p>
</blockquote>

<pre><code>    int i = 1; int&amp; ri = i;
    auto a1 = make_array(i, ri);         // a1 is of type array&lt;int, 2&gt;
    auto a2 = make_array(i, ri, 42L);    // a2 is of type array&lt;long, 3&gt;
    auto a3 = make_array&lt;long&gt;(i, ri);   // a3 is of type array&lt;long, 2&gt;
    auto a4 = make_array&lt;long&gt;();        // a4 is of type array&lt;long, 0&gt;
    auto a5 = make_array();              // ill-formed</code></pre>

<blockquote>
<p><em>&#8211;end example]</em></p>
</blockquote>

<p><em>[Editorial note:</em> The non-code text in the example above, such as &#8220;is of type&#8221;, &#8220;ill-formed&#8221;, should be in italic face. <em>]</em></p>
<div>
<tt>template &lt;class T, size_t N&gt;</tt><br />
<tt>&nbsp;&nbsp;constexpr array&lt;remove_cv_t&lt;T&gt;, N&gt;
to_array(T (&amp;a)&#91;N&#93;);</tt><br />
</div>
<blockquote>
<p><em>Returns:</em> An <code>array&lt;remove_cv_t&lt;T&gt;, N&gt;</code> such that each element is copy-initialized with the corresponding element of <code>a</code>.</p>
</blockquote>

<h2 id='sample_implementation'>Sample Implementation</h2>

<p>A sample implementation is available at <a href='https://gist.github.com/lichray/6034753'>https://gist.github.com/lichray/6034753</a>.</p>

<h2 id='acknowledgments'>Acknowledgments</h2>

<p>Jonathan Wakely, who showed me how <code>index_sequence</code> helps initializing <code>std::array</code> from a raw array.</p>

<p>Daniel Krügler, who explained why an explicit destination type is essential.</p>

<p>Ville Voutilainen and other people who reviewed this paper.</p>

<p>Stephan T. Lavavej, who pointed out the ambiguity issue of the two make_array overloads.</p>
</body></html>
