If initializer_list
was defined as std::initializer_list<type, size>
, then any function that takes an initializer_list<type>
, where type
is some concrete type, would now have to be a template function based on that list's size. Or they would have to require that users pass an initializer_list
of a specific type and size.
Both of these are pretty unacceptable. Not everyone writes all of their code as templates.
You can initialize a std::array
from a braced-init-list ({}
with stuff in the middle). But that's not the same thing as a std::intiializer_list
. The array
class is an aggregate type. It is a struct that contains a single element, which is a public array. Therefore, on a conforming C++11 implementations, this should compile:
std::array<int, 3> myArray = {1, 3, 5};
However, {1, 3, 5}
is not a std::initializer_list
object; it is merely a braced-init-list, which can be used to initialize appropriate types.
You cannot pass a std::initializer_list
object to the constructor of an aggegate (because aggregates have no constructors), but you can use a braced-init-list to invoke aggregate initialization to initialize a std::array
, just as you would for any struct containing an array.
The difference between a std::initializer_list
and a braced-init-list is a bit like the difference between an int
and the literal 0
. It's not (usually) legal to implicitly convert an int
object into a pointer type, but it is legal to implicitly convert an integer literal 0 into a pointer type. The way braced-init-lists work is like that:
int i = 0; //Legal
void *j = 0; //Legal
void *k = i; //Not legal
std::array<int, 3> myArray = {1, 3, 5}; //Legal
std::initializer_list<int> myInitList = {1, 3, 5}; //Legal
std::array<int, 3> myArray = myInitList; //Not legal
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…