<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
   "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>

<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">

<style type="text/css">

body { color: #000000; background-color: #FFFFFF; }
del { text-decoration: line-through; color: #8B0040; }
ins { text-decoration: underline; color: #005100; }

p.example { margin-left: 2em; }
pre.example { margin-left: 2em; }
div.example { margin-left: 2em; }

code.extract { background-color: #F5F6A2; }
pre.extract { margin-left: 2em; background-color: #F5F6A2;
  border: 1px solid #E1E28E; }

p.function { }
.attribute { margin-left: 2em; }
.attribute dt { float: left; font-style: italic;
  padding-right: 1ex; }
.attribute dd { margin-left: 0em; }

blockquote.std { color: #000000; background-color: #F1F1F1;
  border: 1px solid #D1D1D1;
  padding-left: 0.5em; padding-right: 0.5em; }
blockquote.stddel { text-decoration: line-through;
  color: #000000; background-color: #FFEBFF;
  border: 1px solid #ECD7EC;
  padding-left: 0.5empadding-right: 0.5em; ; }

blockquote.stdins { text-decoration: underline;
  color: #000000; background-color: #C8FFC8;
  border: 1px solid #B3EBB3; padding: 0.5em; }

table { border: 1px solid black; border-spacing: 0px;
  margin-left: auto; margin-right: auto; }
th { text-align: left; vertical-align: top;
  padding-left: 0.8em; border: none; }
td { text-align: left; vertical-align: top;
  padding-left: 0.8em; border: none; }

</style>

<title>Auto and braced-init-lists</title>
</head>
<body>
<h1>Auto and braced-init-lists</h1>

<p>
ISO/IEC JTC1 SC22 WG21 N3681 - 2013-05-02
</p>

<address>
Ville Voutilainen, ville.voutilainen@gmail.com
</address>

<h2><a name="Abstract">Abstract</a></h2>

Auto and braced initializers cause a teachability problem; we want
to teach people to use uniform initialization, but we need to
specifically tell programmers to avoid braces with auto. In C++14,
we now have more cases where auto and braces are problematic; return
type deduction for functions partially avoids the problem, since
returning a braced-list won't work as it's not an expression. However,
returning an auto variable initialized from a braced initializer
still returns an initializer_list, inviting undefined behaviour.
Lambda init captures have the same problem. This paper proposes
to change a brace-initialized auto to not deduce to an initializer
list, and to ban brace-initialized auto for cases where the 
braced-initializer has more than one element.

<h2><a name="Introduction">Introduction</a></h2>

<p>
The crux of the problem is the following:
<pre>
<code>
auto x = foo(); // copy-initialization
auto x{foo}; // direct-initialization, initializes an initializer_list
int x = foo(); // copy-initialization
int x{foo}; // direct-initialization
</code>
</pre>

The difference between auto and a normal type is unfortunate, counter-intuitive and surprising.

The same issue apparently arises with an init-capture:
<pre>
<code>
[x = foo()](){} // copy-initialization
[x{foo()}](){} // direct-initialization, initializes an initializer_list.
</code>
</pre>

Function return type deduction partially avoids the problem:

<pre>
<code>
auto f()
{
    return {1,2}; // ill-formed, {1,2} is not an expression
}
</code>
</pre>

But the situation arises again with an auto variable:

<pre>
<code>
auto f()
{
    auto x{1,2}; // direct-initialization, initializes an initializer_list.
    return x; // returns an initializer_list, instant UB to access it
}
</code>
</pre>

We shouldn't have such bear-traps in the language. The init-capture
results in object lifetime issues, and so does the return case.


</p>
<h2><a name="Proposed_solution">Proposed solution</a></h2>

<p>
Change in 7.1.6.4 auto specifier [dcl.spec.auto] paragraph 6:
<blockquote>
Let T be the type that has been determined for a variable identifier d. Obtain P from T by
replacing the occurrences of auto with either a new invented type template parameter U or, if the initializer
is a braced-init-list (8.5.4), with <del>std::initializer_list&lt;U></del><ins>a new invented type template parameter U that is the declared type of the expression in the braced-init-list. If the braced-init-list has more than one element, the program is ill-formed</ins>. The type deduced for the variable d is then
the deduced A determined using the rules of template argument deduction from a function call (14.8.2.1),
where P is a function template parameter type and the initializer for d is the corresponding argument. If
the deduction fails, the declaration is ill-formed. [ Example:
<del>
<pre>
<code>
auto x1 = { 1, 2 }; // decltype(x1) is std::initializer_list&lt;int>
auto x2 = { 1, 2.0 }; // error: cannot deduce element type

— end example ]
</code>
</pre>
</del>
<ins>
<pre>
<code>
auto x1 = { 1, 2 }; // error: cannot have multiple elements in a braced-init-list with auto


— end example ]
</code>
</pre>

</ins>
[ Example:
<pre>
<code>
const auto &i = expr;
</pre>
</code>
<ins>
<pre>
<code>
const auto &i{expr};
</pre>
</code>
</ins>
<pre>
<code>
The type of i is the deduced type of the parameter u in the call f(expr) of the following invented
function template:

template &lt;class U> void f(const U& u);

— end example ]
</code>
</pre>
</blockquote>
</p>


</body>
</html>
