return and auto deduce std::initializer_list

Well, because the Standard says so, and because a braced-init-list is not an expression. Per paragraph 5.1.2/4 of the C++11 Standard:

[...] If a lambda-expression does not include a trailing-return-type, it is as if the trailing-return-type denotes the following type:

— if the compound-statement is of the form

{ attribute-specifier-seq(opt) return expression ; }

the type of the returned expression after lvalue-to-rvalue conversion (4.1), array-to-pointer conversion (4.2), and function-to-pointer conversion (4.3);

— otherwise, void.

The above makes it clear that the return type will be deduced to be anything else then void if and only if the return statement is followed by an expression, and a braced-init-list is not in itself an expression - it does not have a type, and it does not yield a value. It is just a language construct that can be used in the context of initialization.

The above paragraph also provides an example:

[ Example:

auto x1 = [](int i){ return i; }; // OK: return type is int
auto x2 = []{ return { 1, 2 }; }; // error: the return type is void (a
                                  // braced-init-list is not an expression)

end example ]

Finally, if the question is:

"Why a special rule was introduced for deducing the type of an auto variable initialized from a braced-init-list, while a similar rule was not introduced for deducing the return type of a lambda when return is followed by a braced-init-list?"

Then the question is not constructive. Also notice, that type deduction for templates does not work with braced-init-lists either:

template<typename T>
void foo(T);

foo({1, 2}); // ERROR! T is NOT deduced to be std::initializer_list<int>

Tags:

C++

C++11