Построить контейнер со списком инициализаторов итераторов
Можно построить вектор с диапазоном итераторов, например так:
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 итератора.