What Is a Curly-Brace Enclosed List If Not an intializer_list?

寵の児 提交于 2019-11-26 14:27:09

问题


I asked a question here: Lifetime Extension of a initializer_list return involving the non-functional code:

const auto foo = [](const auto& a, const auto& b, const auto& c) { return {a, b, c}; };

I believed the lambda was trying to return an intializer_list (that's bad, don't do that.) But I got a comment:

It's not an initializer_list, it's an initializer list. Two different things.

I just thought that any time you did a curly-braced list you were creating an intializer_list. If that's not what's happening, what is a list in curly-braces?


回答1:


There are three distinct, but related concepts here:

  1. braced-init-list: The grammatical rule associated with curly-brace-enclosed lists in certain contexts.

  2. Initializer list: The name for the braced-init-list initializer used in list-initialization.

  3. std::initializer_list: A class wrapping a temporary array which is created in some contexts involving braced-init-lists.

Some examples:

//a braced-init-list and initializer list, 
//but doesn't create a std::initializer_list
int a {4}; 

//a braced-init-list and initializer list,
//creates a std::initializer_list
std::vector b {1, 2, 3};

//a braced-init-list and initializer list,
//does not create a std::initializer_list (aggregate initialization)
int c[] = {1, 2, 3};

//d is a std::initializer_list created from an initializer list
std::initializer_list d {1, 2, 3};

//e is std::initializer_list<int>
auto e = { 4 };

//f used to be a std::initializer_list<int>, but is now int after N3922
auto f { 4 };

You might want to read N3922, which changed some of the rules involving auto and std::initializer_list.




回答2:


It is an braced-init-list. A braced-init-list existed before std::initializer_list and is used to initialize aggregates.

int arr[] = {1,2,3,4,5};

The above used a braced-init-list to initialize the array, no std::initializer_list is created. On the other hand when you do

std::vector<int> foo = {1,2,3,4,5};

foo is not an aggregate so the braced-init-list is used to create a std::initializer_list which is in turned passed to the constructor of foo that accepts a std::initializer_list.

A thing to note about a braced-init-list is that is has no type so special rules were developed for use with it and auto. It has the following behavior (since the adoption of N3922)

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

And you can get more information on history of this behavior and why it was changed at: Why does auto x{3} deduce an initializer_list?




回答3:


I just thought that any time you did a curly-braced list you were creating an intializer_list.

That's not correct.

If that's not what's happening, what is a list in curly-braces?

struct Foo {int a; int b;};
Foo f = {10, 20};

The {10, 20} part is not an initializer_list. It's just a syntactic form to use a list of objects to create another object.

int a[] = {10, 20, 30};

Once again, it's a syntactic form to create an array.

The name for the syntactic form is braced-init-list.




回答4:


You have two different things when use {}

  1. A Type std::initializer_list<T> where the values can be implicitly converted to T
  2. A type that can be initialized with the values of the list.

The first type forces a homogeneous list and the second type don't. In the next example:

struct S{ 
    int a; 
    string b 
};

void f1( S s );
void f2( int i );
void f3( std::initializer_list<int> l );

f1( {1, "zhen"} ); // construct a temporal S
f2( {1} );         // construct a temporal int
f3( {1,2,3} );     // construct a temporal list of ints

The functions f1 and f2 use the first type and f3 use the second type. You should know that if there is ambiguity, the std::initializer_list is prefered. E.g:

void f( S s );
void f( int i );
void f( std::initializer_list<int> l );

f( {1, "zhen"} ); // calls with struct S
f( {1} );         // calls with int list with one element
f( {1,2,3} );     // calls with int list with three elements


来源:https://stackoverflow.com/questions/37682392/what-is-a-curly-brace-enclosed-list-if-not-an-intializer-list

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!