This is an unofficial snapshot of the ISO/IEC JTC1 SC22 WG21 Core Issues List revision 115e. See http://www.open-std.org/jtc1/sc22/wg21/ for the official list.
2024-11-11
An initializer list is treated differently in deducing the type of an auto specifier and in a function call. In 9.2.9.7 [dcl.spec.auto] paragraph 6, an initializer list is given special treatment so that auto is deduced as a specialization of std::initializer_list:
Once the type of a declarator-id has been determined according to 9.3.4 [dcl.meaning], the type of the declared variable using the declarator-id is determined from the type of its initializer using the rules for template argument deduction. 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 (9.4.5 [dcl.init.list]), with std::initializer_list<U>. The type deduced for the variable d is then the deduced A determined using the rules of template argument deduction from a function call (13.10.3.2 [temp.deduct.call]), where P is a function template parameter type and the initializer for d is the corresponding argument.
In a function call, however, an initializer-list argument is a non-deduced context:
Template argument deduction is done by comparing each function template parameter type (call it P) with the type of the corresponding argument of the call (call it A) as described below. If removing references and cv-qualifiers from P gives std::initializer_list<P'> for some P' and the argument is an initializer list (9.4.5 [dcl.init.list]), then deduction is performed instead for each element of the initializer list, taking P' as a function template parameter type and the initializer element as its argument. Otherwise, an initializer list argument causes the parameter to be considered a non-deduced context (13.10.3.6 [temp.deduct.type]). [Example:
template<class T> void f(std::initializer_list<T>); f({1,2,3}); // T deduced to int f({1,"asdf"}); // error: T deduced to both int and const char* template<class T> void g(T); g({1,2,3}); // error: no argument deduced for T
This seems inconsistent, but it is not clear in which direction the inconsistency should be resolved. The use of an initializer list in a range-based for is an argument in favor of the 9.2.9.7 [dcl.spec.auto] treatment, but the utility of this deduction in other contexts is not apparent.
Rationale (October, 2012):
CWG felt that this language design question would be better considered by EWG.
Additional note, April, 2015:
EWG has decided not to make a change in this area. See EWG issue 109.