Martin Shobe said:
8.5.4.3 states, "if T is a class type, constructors are considered. If T
has an initializer-list constructor, the argument list consists of the
initializer list as a single argument"
std::string has an initializer-list constructor and the type of the
element of that constructor's argument is char, so it uses
initializer_list<char>.
I begin to see a pattern that distinguishes a
braced-init-list from an instance of ::std::initializer_list!
A braced-init-list is still open for interpretation as an
instance of ::std::initializer_list<T> with several
possibilities for the type T.
Once it has become an instance of ::std::initializer_list,
T is fixed.
For example,
of these two lines, each line is allowed:
::std::initializer_list< char >( { 65 } );
::std::initializer_list< char >il{ 65 }; ::std::string s = il;
; of these two lines, each line is /not/ allowed:
::std::initializer_list< char >( ::std::initializer_list< int >( { 65 } ));
::std::initializer_list< int >il{ 65 }; ::std::string s = il;
. There must be a paragraph in the standard that says
something like:
When a braced-init-list is used as the initializer for
an instance of type ::std::initializer_list<T>, where T
is a fixed type (not a template parameter), then each
element of the ::std::initializer_list<T> (has type T
and )is initialized (as if )by
direct-list-initialization from the corresponding
element of the braced-init-list.
One hint might be n3797,8.5.4:
»List-initialization is initialization of an object or
reference from a braced-init-list.«
It says »from a braced-init-list«, not »from an instance of
»::std::initializer_list«!
Uh, now I see this:
»A constructor is an initializer-list constructor if its
first parameter is of type std::initializer_list<E> or
reference to possibly cv-qualified
std::initializer_list<E> for some type E, and either
there are no other parameters or else all other
parameters have default arguments (8.3.6).« n3797,8.5.4p2
and then
»List-initialization of an object or reference of type T
is defined as follows:« n3797,8.5.4p3
»An object of type std::initializer_list<E> is
constructed from an initializer list as if the
implementation allocated a temporary array of N elements
of type const E, where N is the number of elements in
the initializer list. Each element of that array is
copy-initialized with the corresponding element of the
initializer list, and the std::initializer_list<E>
object is constructed to refer to that array.« 3797,8.5.4p5
I think that this 8.5.4p5 (that I just quoted) is the key,
it also has an example: »
struct X {
X(std::initializer_list<double> v);
};
X x{ 1,2,3 };
The initialization will be implemented in a way roughly
equivalent to this:
const double __a[3] = {double{1}, double{2}, double{3}};
X x(std::initializer_list<double>(__a, __a+3));«.
Note that 8.5.4p5 says:
»An object of type std::initializer_list<E> is
constructed from an initializer list«
, thus, an »object of type std::initializer_list<E>« is
/not/ the same as »an initializer list«! It is /constructed
from/ an an »initializer list«! »initializer list« here
seems to refer to what is syntactically a »braced-init-list«.