GCC bug. [dcl.spec.auto]/p7 (quoting N4527):
When a variable declared using a placeholder type is initialized,
[…] the deduced return type or variable type is determined from the
type of its initializer. […] Otherwise, letT
be the declared type
of the variable […]. If the placeholder is theauto
type-specifier, the deduced type is determined using the rules for template argument deduction. If the initialization is
direct-list-initialization […]. […] Otherwise, obtainP
fromT
by replacing the occurrences ofauto
with either a new invented
type template parameterU
or, if the initialization is
copy-list-initialization, withstd::initializer_list<U>
. Deduce a value forU
using the rules of template argument deduction from a
function call (14.8.2.1), whereP
is a function template parameter
type and the corresponding argument is the initializer […]. If the
deduction fails, the declaration is ill-formed. Otherwise, the type
deduced for the variable or return type is obtained by substituting
the deducedU
intoP
.
Thus, in const auto l2 = { 1, 2, 3 };
, deduction is performed as if for the function template
template<class U> void meow(const std::initializer_list<U>);
given the call meow({1, 2, 3})
.
Now consider the const-less case auto l3 = { 1, 2, 3 };
(which GCC correctly deduces as std::initializer_list<int>
). Deduction in this case is performed as if for the function template
template<class U> void purr(std::initializer_list<U>);
given the call purr({1, 2, 3})
.
Since top-level cv-qualification of function parameters are ignored, it should be obvious that the two deduction should yield the same type.
[temp.deduct.call]/p1:
Template argument deduction is done by comparing each function
template parameter type (call itP
) with the type of the
corresponding argument of the call (call itA
) as described below.
IfP
is a dependent type, removing references and cv-qualifiers from
P
givesstd::initializer_list<P'>
[…] for someP'
[…] and
the argument is a non-empty initializer list (8.5.4), 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.
Deducing P'
(which is U
) against 1
, 2
, or 3
, all literals of type int
, obviously yields int
.