Можно построить вектор с диапазоном итераторов, например так:
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
, право?
Из §13.3.2 / 1 ([over.match.list])
Когда объекты неагрегированного класса
T
инициализируются списком
(8.5.4), разрешение перегрузки выбирает конструктор в два этапа:— Первоначально функции-кандидаты представляют собой список инициализаторов.
конструкторы (8.5.4) классаT
и список аргументов состоит из
список инициализаторов как один аргумент.— Если нет жизнеспособных
Найден конструктор списка инициализаторов, разрешение перегрузки
выполняется снова, где функции-кандидаты все
конструкторы классаT
и список аргументов состоит из
элементы списка инициализатора.
В вашем случае конструктор списка инициализатора считается нежизнеспособным (потому что std::istream_iterator<std::string>
не конвертируется в std::string
), и второе условие применяется. В результате конструктор выбирает 2 итератора.
Других решений пока нет …