#include required to use initializer

2019-02-21 12:24发布

问题:

The final C++11 standard includes provisions for range-based for to "just work" for native arrays without having to include <iterator> or any other header. This was addressed first, as far as I can tell, in working paper n2900 as a result of comments UK 78 and 79.

This proposal also included a provision to implicitly #include <initializer_list> in every translation unit, so that e.g. the program

#include <iostream>

int main()
{
    for (auto i : { 1, 2, 3, 4, 5 })
        std::cout << i << "\n";
}

would be standard-conforming even without including <initializer_list>.

However, when concepts were removed from C++11, range-based for was revised as seen in n2930. While the provision for arrays to "just work" remains, there is no mention that the same is true for initializer lists; indeed the specification that various standard library container headers will #include <initializer_list> and the final text of 8.5.4.2 implies the opposite to me.

As far as I can tell, this is pretty close to the final wording on the topic. So, is the program above well-formed with regard to the final standard, or do I need to #include <initializer_list> even to use it in a range-based for? Put another way, does the use of an initializer list in a range-based for constitute a "use of std::initializer_list---even an implicit use in which the type is not named" per 8.5.4.2 of the FDIS?

回答1:

I'd say yes. According to §6.5.4[stmt.ranged]/1, the statement

for (auto i : { 1, 2, 3, 4, 5 })
    ...

is just equivalent to

auto&& __range = { 1, 2, 3, 4, 5 };
...

and that means an initializer_list<int> is used, and the <initializer_list> header needs to be included.



回答2:

GCC 7.1 produces the following error if <initializer_list> is not included:

error: deducing from brace-enclosed initializer list requires #include <initializer_list>
     for (auto i : { 1, 2, 3, 4, 5 })
                                   ^

To see this error one should omit <iostream>, because including <iostream> will also include <initializer_list>.