简体   繁体   中英

How to list-initialize an initializer_list from another initializer_list

When I'm trying to compile the following code, the compiler complains:

int main(void)
{
  std::initializer_list<int> lst1{};
  std::initializer_list<int> lst2{lst1}; // error
}

The compiler (gcc) gives me the following error:

 error: could not convert '{lst1}' from '<brace-enclosed initializer list>' to 'std::initializer_list<int>'

But when I tried to use direct-initialization the program compiles fines:

 std::initializer_list<int> lst2(lst1); // OK

Why this is well-formed? Why the compiler rejects the list-initialization and allows direct-initialization? Is there's a rule from the standard for that?

Aslo, Is the following code is well-formed? I mean, Can I do this:

int main(void)
{
  std::initializer_list<int> lst1{};
  std::initializer_list<std::initializer_list<int>> lst2{lst1}; //OK
}

?

The reason why you can't list-initialize a std::initializer_list<int> from the same type is that there is a special rule for list-initialization of a std::initializer_list<E> , which takes precedence over the other rules for list-initialization. The rule is [dcl.init.list]/3.6 :

Otherwise, if T is a specialization of std::initializer_list<E> , the object is constructed as described below.

"Below" can only be referring to [dcl.init.list]/5 (and /6):

An object of type std::initializer_list<E> is constructed from an initializer list as if the implementation generated and materialized ([conv.rval]) a prvalue of type "array of N 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. [...]

That means that when list-initializating std::initializer_list<E> , the only possible interpretation of such an initialization is that the elements of the braced-init-list are used to initialize the elements of the std::initialize_list<E> object. Even though this is ill-formed, the compiler cannot go back and try the next rule even though it might be well-formed ( ie , [dcl.init.list]/3.7, which can select a copy constructor).

[dcl.init.list]/5 also governs the meaning of the other initialization you ask about:

std::initializer_list<std::initializer_list<int>> lst2{lst1};

It is well-formed with an obvious meaning.

Is there's a rule from the standard for that?

Yes

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM