<?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</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>N3824</td></tr>
<tr><th>Date:</th>	<td>2013-10-22</td></tr>
<tr><th>Project:</th>	<td>Programming Language C++, Library Evolution Working Group</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'>make_array</h1>

<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.</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 N3797, which contains the resolution of <a href='http://cplusplus.github.io/LWG/lwg-defects.html#2141'>LWG 2141</a>.</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... Types&gt;</tt><br />
<tt>&nbsp;&nbsp;constexpr <i>see below</i> make_array(Types&amp;&amp;...);</tt><br />
<tt>template &lt;class D, class... Types&gt;</tt><br />
<tt>&nbsp;&nbsp;constexpr <i>see below</i> make_array(Types&amp;&amp;...);</tt><br />
<tt>template &lt;class T, size_t N&gt;</tt><br />
<tt>&nbsp;&nbsp;constexpr <i>see below</i> 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>

<pre><code>template &lt;class... Types&gt;
  constexpr array&lt;CT, sizeof...(Types)&gt; make_array(Types&amp;&amp;...);</code></pre>

<blockquote>
<p>Let <em><code>Ui</code></em> be <code>remove_reference&lt;</code><em><code>Ti</code></em><code>&gt;::type</code> for each <em><code>Ti</code></em> in <code>Types</code>.</p>
</blockquote>

<blockquote>
<p><em>Remarks:</em> This function shall not participate in overload resolution unless each <em><code>Ui</code></em> is not <code>reference_wrapper&lt;</code><em><code>Ti</code></em><code>&gt;</code>.</p>
</blockquote>

<p><em>[Just a note:</em> This one is banned for genericity reason, so use SFINAE to allow users to handle them in generic code. <em>&#8211;end note]</em></p>

<blockquote>
<p><em>Returns:</em> An <code>array&lt;CT, sizeof...(Types)&gt;</code> initialized with <code>{ std::forward&lt;Types&gt;(t))... }</code>, where <code>CT</code> is <code>common_type&lt;Types...&gt;::type</code>.</p>
</blockquote>

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

<pre><code>    int i = 1; int&amp; ri = i;
    make_array(i, ri, 42L)</code></pre>

<blockquote>
<p>creates an <code>array</code> of type</p>
</blockquote>

<pre><code>    array&lt;long, 3&gt;</code></pre>

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

<pre><code>template &lt;class D, class... Types&gt;
  constexpr array&lt;D, sizeof...(Types)&gt; make_array(Types&amp;&amp;...);</code></pre>

<blockquote>
<p><em>Returns:</em> An <code>array&lt;D, sizeof...(Types)&gt;</code> initialized with <code>{ std::forward&lt;Types&gt;(t))... }</code>.</p>
</blockquote>

<pre><code>template &lt;class T, size_t N&gt;
  constexpr array&lt;V, N&gt; to_array(T (&amp;a)[N]);</code></pre>

<blockquote>
<p><em>Returns:</em> An <code>array&lt;V, N&gt;</code> such that each element is copy-initialized with the corresponding element of <code>a</code>, where <code>V</code> is <code>remove_cv&lt;T&gt;::type</code>.</p>
</blockquote>

<p><em>[Just a note:</em> The <code>remove_cv</code> here functionally performs decay, while intentionally kills constructing from multidimensional array with a hard error, because <code>std::array</code> is not aware of multidimensional array (yet), and I don&#8217;t want user to try anything may silently break their code in the future. On the other hand, if you understand multidimensional <code>std::array</code> as <code>array</code> of <code>array</code>s, it might be more convenient and clear to write</p>

<pre><code>make_array(make_array(1, 2, 3), make_array(4, 5, 6)...)</code></pre>

<p>instead of to adapt a raw array. <em>&#8211;end note]</em></p>

<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>
</body></html>
