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

前端 未结 4 1304
小蘑菇
小蘑菇 2020-12-01 17:54

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         


        
相关标签:
4条回答
  • 2020-12-01 18:20

    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
    
    0 讨论(0)
  • 2020-12-01 18:27

    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.

    0 讨论(0)
  • 2020-12-01 18:36

    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?

    0 讨论(0)
  • 2020-12-01 18:37

    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.

    0 讨论(0)
提交回复
热议问题