This is governed by the rules of [dcl.type.auto.deduct], particularly [dcl.type.auto.deduct]/1 and [dcl.type.auto.deduct]/4 [emphasis mine]:
[dcl.type.auto.deduct]/1
Placeholder type deduction is the process by which a type containing a
placeholder type is replaced by a deduced type.
[dcl.type.auto.deduct]/4
If the placeholder is the auto
type-specifier, the deduced type T'
replacing T
is determined using the rules for template argument
deduction. Obtain P
from T
by replacing the occurrences of
auto
with either a new invented type template parameter U
or, if
the initialization is copy-list-initialization, with
std::initializer_list<U>
. Deduce a value for U
using the
rules of template argument deduction from a function call, where P
is a function template parameter type and the corresponding argument
is e
. If the deduction fails, the declaration is ill-formed.
Otherwise, T'
is obtained by substituting the deduced U
into P
.
[ Example:
auto x1 = { 1, 2 }; // decltype(x1) is std::initializer_list<int>
auto x2 = { 1, 2.0 }; // error: cannot deduce element type
auto x3{ 1, 2 }; // error: not a single element
auto x4 = { 3 }; // decltype(x4) is std::initializer_list<int>
auto x5{ 3 }; // decltype(x5) is int
— end example ]
Your second example is using copy-list-initialization, meaning auto
is replaced by, using the rules for template argument deduction, std::initializer_list<U>
, where U
is furthermore deduced as int
.
auto n {42}; // deduced type is 'int'
auto m = {42}; // deduced type is 'std::initializer_list<int>'
These rules particularly apply to placeholder type deduction, and does thus not apply to the case of non-placeholder types; the latter example of the op already specifies the type and non type deduction applies.
// no placeholder type: type is 'double', and 'd1'
// through 'd3' simply uses different ways to initialize
// an object of (non-class fundamental) type 'double'.
double d1 = 2.3; // copy initialization
double d2 {2.3}; // direct-list initialization; no narrowing allowed
double d3 = {2.3}; // copy-list-initialization (from C++11); no narrowing allowed