ISO/IEC JTC1 SC22 WG21 N3681 - 2013-05-02
Ville Voutilainen, ville.voutilainen@gmail.comThe crux of the problem is the following:
auto x = foo(); // copy-initialization
auto x{foo}; // direct-initialization, initializes an initializer_list
int x = foo(); // copy-initialization
int x{foo}; // direct-initialization
The difference between auto and a normal type is unfortunate, counter-intuitive and surprising.
The same issue apparently arises with an init-capture:
[x = foo()](){} // copy-initialization
[x{foo()}](){} // direct-initialization, initializes an initializer_list.
Function return type deduction partially avoids the problem:
auto f()
{
return {1,2}; // ill-formed, {1,2} is not an expression
}
But the situation arises again with an auto variable:
auto f()
{
auto x{1,2}; // direct-initialization, initializes an initializer_list.
return x; // returns an initializer_list, instant UB to access it
}
We shouldn't have such bear-traps in the language. The init-capture
results in object lifetime issues, and so does the return case.
Change in 7.1.6.4 auto specifier [dcl.spec.auto] paragraph 6:
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), withstd::initializer_list<U>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. 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:auto x1 = { 1, 2 }; // decltype(x1) is std::initializer_list<int> auto x2 = { 1, 2.0 }; // error: cannot deduce element type — end example ]
[ Example:auto x1 = { 1, 2 }; // error: cannot have multiple elements in a braced-init-list with auto — end example ]
const auto &i = expr;
const auto &i{expr};
The type of i is the deduced type of the parameter u in the call f(expr) of the following invented function template: template <class U> void f(const U& u); — end example ]