<html>
<head>
<title>
New Rules for auto deduction from braced-init-list.
</title>
<style type="text/css">
  .term { font-style:italic }
  .comment { font-style:italic; font-family:serif }
  ins { text-decoration:none; font-weight:bold; background-color:#A0FFA0 }
  del { text-decoration:line-through; background-color:#FFA0A0 }
  strong { font-weight: inherit; color: #2020ff }
</style>

</head>
<body>
<h1>New Rules for auto deduction from braced-init-list</h2>

<p>
ISO/IEC JTC1 SC22 WG21 N3922 - 2014-02-13
</p>

<address>
James Dennett, james.dennett@gmail.com
</address>

<h2>Synopsis</h2>
<p>This paper provides proposed wording to change the rules for auto
  deduction from a braced-init-list.  In particular, the rules for
  deduction of init-captures from braced-init-list are modified.</p>
<h2>Background</h2>
<p>For background information see
  <a href="http://open-std.org/JTC1/SC22/WG21/docs/papers/2013/n3681.html">
    N3681</a>, "Auto and braced-init-lists", by Voutilainen, and
    N3912, "Auto and braced-init-lists, continued", also by Voutilainen.
</p>

<p>In Issaquah, EWG considered two alternative resolutions; this paper
  offers wording for one of the two, and mentions the other only as an
  acceptable alternative in case CWG uncovers fatal problems with EWG's
  preferred resolution.</p>

<p>Direction from EWG is that we consider this a defect in C++14.</p>

<h2>Summary of Proposed Changes</h2>

<p>For copy-list-initialization, auto deduction will either deduce a
  std::initializer_list (if the types of entries in the
  braced-init-list are all identical) or be ill-formed otherwise.</p>

<p>For direct list-initialization:
<ol>
  <li>For a braced-init-list with only a single element, auto deduction
    will deduce from that entry;</li>
  <li>For a braced-init-list with more than one element, auto deduction
    will be ill-formed.</li>
</ol>
</p>

<p>The rules for range-based <code>for</code> are unaffected by the changes
  proposed here, as the rules for copy-list-initialization are unmodified.<p>

<p>Note: C++14 already disallows deduction of an function return type from
  a braced-init-list, and that's a good thing.</p>

<h2>Alternative</h2>

<p>There was also support (though less strong) in EWG for an
  alternative proposal in which auto deduction does not distinguish
  between direct list-initialization and copy list-initialization,
  and which allows auto deduction from a braced-init-list only in
  the case where the braced-init-list consists of a single item.
  Possible wording was for that alternative was included in
  <a href="http://open-std.org/JTC1/SC22/WG21/docs/papers/2013/n3681.html">
  N3681</a> by Voutilainen.</p>

<h2>Wording</h2>

<p>Modify 7.1.6.4p7 [dcl.spec.auto] as shown below:</p>

<p>When a variable declared using a placeholder type is initialized,
  or a <code>return</code> statement occurs in a function declared
  with a return type that contains a placeholder type, the deduced
  return type or variable type is determined from 
  the type of its initializer.
  In the case of a <code>return</code> with no operand,
  the initializer is considered to
  be <code>void()</code>. Let <code>T</code> be the declared type of 
  the variable or return type of the function. 

  If the placeholder is
  the <code>auto</code> <span class="term">type-specifier</span>
  the deduced type is determined using the rules for template argument
  deduction.

  <ins>If the initialization is direct-list-initialization then the 
  <span class="term">braced-init-list</span> shall contain only a single
  <span class="term">initializer-clause</span> <code>L</code>.</ins>

  If the deduction is for a return statement and the
  initializer is a <span class="term">braced-init-list</span> (8.5.4),
  the program is ill-formed.

  Otherwise, obtain <code>P</code> from <code>T</code>
  by replacing the occurrences of <code>auto</code>
  with either a new invented type template parameter <code>U</code>
  or, if 
  <del>the initializer is a braced-init-list, </del>
  <ins>the initialization is copy-list-initialization,</ins>
  with <code>std::initializer_list&lt;U&gt;</code>.

  Deduce a value for <code>U</code> using the rules of template argument
  deduction from a function call (14.8.2.1), where <code>P</code> is a function
  template parameter type and
  <del>the initializer is the corresponding argument.</del>
  <ins>the corresponding argument is the initializer, or <code>L</code> in the case
  of direct-list-initialization.</ins>

  If the deduction fails, the declaration is
  ill-formed. Otherwise, the type deduced for the variable or return
  type is obtained by substituting the deduced <code>U</code> into
  <code>P</code>. 
</p>
<p>and</p>

<p>
[<i>Example:</i>
<pre>
auto x1 = { 1, 2 }; // decltype(x1) <span class="comment">is</span> std::initializer_list&lt;int&gt;
auto x2 = { 1, 2.0 }; // <span class="comment">error: cannot deduce element type</span>
<ins>auto x3{ 1, 2 }; // <span class="comment">error: not a single element</span>
auto x4 = { 3 }; // decltype(x4) <span class="comment">is</span> std::initializer_list&lt;int&gt;
auto x5{ 3 }; // decltype(x5) <span class="comment">is</span> int</ins></pre>
<i>-- end example</i>]

<h2>Acknowledgements</h2>
<p>Thanks to Daveed Vandevoorde and Richard Smith for reviewing this
  paper, and to Ville Voutilainen for writing the papers preceding
  this one.</p>

</body>
</html>
