Построить контейнер со списком инициализаторов итераторов

Можно построить вектор с диапазоном итераторов, например так:

std::vector<std::string> vec(std::istream_iterator<std::string>{std::cin},
                             std::istream_iterator<std::string>{});

Но я также могу скомпилировать и запустить код, используя унифицированный синтаксис C++11 (обратите внимание на скобки), например так:

std::vector<std::string> vec{std::istream_iterator<std::string>{std::cin},
                             std::istream_iterator<std::string>{}};

Что на самом деле здесь происходит?

Я знаю, что конструктор, принимающий список инициализаторов, получает приоритет над другими формами построения. Разве компилятор не должен разрешить конструктору брать список инициализаторов, содержащий 2 элемента std::istream_iterator? Это должно быть ошибкой как std::istream_iterator не может быть преобразовано в тип значения вектора std::string, право?

1 ответ

Решение

Из §13.3.2/1 ([over.match.list])

Когда объекты неагрегированного класса T инициализируются списком (8.5.4), разрешение перегрузки выбирает конструктор в два этапа:

- Первоначально функции-кандидаты являются конструкторами списка инициализаторов (8.5.4) класса T и список аргументов состоит из списка инициализаторов как единственного аргумента.

- Если жизнеспособный конструктор списка инициализаторов не найден, разрешение перегрузки выполняется снова, где все функции-кандидаты являются конструкторами класса. T и список аргументов состоит из элементов списка инициализатора.

В вашем случае конструктор списка инициализатора считается нежизнеспособным (потому что std::istream_iterator<std::string> не конвертируется в std::string), и второе условие применяется. В результате конструктор выбирает 2 итератора.

Другие вопросы по тегам