#include ‹initializer_list› требуется для использования списка инициализаторов на основе диапазона для?

Окончательный стандарт С++ 11 включает положения о том, что на основе диапазона for «просто работает» для собственных массивов без необходимости включать <iterator> или любой другой заголовок. Насколько я могу судить, впервые это было рассмотрено в рабочем документе n2900 в результате комментариев UK 78 и 79.

Это предложение также включало положение о неявном #include <initializer_list> в каждой единице перевода, так что, например. программа

#include <iostream>

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

будет соответствовать стандарту даже без включения <initializer_list>.

Однако, когда концепции были удалены из C++11, диапазон for был пересмотрен, как показано в n2930. Хотя положение о том, что массивы «просто работают», остается, нет упоминания о том, что то же самое верно и для списков инициализаторов; действительно, спецификация, согласно которой заголовки контейнеров различных стандартных библиотек будут #include <initializer_list>, и окончательный текст 8.5.4.2 подразумевает обратное для меня.

Насколько я могу судить, это довольно близко к окончательной формулировке по теме. Итак, является ли приведенная выше программа корректной по отношению к окончательному стандарту, или мне нужно #include <initializer_list> даже использовать ее в диапазоне? Иными словами, является ли использование списка инициализаторов в диапазоне for «использованием std::initializer_list --- даже неявным использованием, в котором тип не назван» в соответствии с 8.5.4.2 FDIS?


person Derrick Turk    schedule 18.01.2012    source источник
comment
Уверен, что да. Что еще будет повторяться в вашем цикле, если не список инициализаторов?   -  person Kerrek SB    schedule 18.01.2012


Ответы (2)


Я бы сказал да. Согласно §6.5.4[stmt.ranged]/1 оператор

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

просто эквивалентно

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

и это означает, что используется initializer_list<int>, и необходимо включить заголовок <initializer_list>.

person kennytm    schedule 18.01.2012
comment
Это было мое подозрение, но оно кажется каким-то неинтуитивным. Это напоминает мне, как для С++ 03 каждый учебник будет использовать std::endl, но включать только <iostream>, а не iomanip. - person Derrick Turk; 19.01.2012
comment
@DerrickTurk std::endl определяется в <ostream>, а не <iomanip>. - person L. F.; 13.10.2019

GCC 7.1 выдает следующую ошибку, если <initializer_list> не включен:

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

Чтобы увидеть эту ошибку, нужно опустить <iostream>, потому что включение <iostream> также включает <initializer_list>.

person Evg    schedule 16.07.2018