问题
It's possible to construct a vector with an iterator range, like this:
std::vector<std::string> vec(std::istream_iterator<std::string>{std::cin},
std::istream_iterator<std::string>{});
But I can also compile and run code using C++11 uniform initialization syntax (note the bracers), like this:
std::vector<std::string> vec{std::istream_iterator<std::string>{std::cin},
std::istream_iterator<std::string>{}};
What's really going on here?
I know that a constructor taking an initializer list gets priority over other forms of construction. Shouldn't the compiler resolve to the constructor taking an initializer list containing 2 elements of std::istream_iterator? This should be an error as a std::istream_iterator can't be converted to the vectors value type std::string, right?
回答1:
From §13.3.2/1 ([over.match.list])
When objects of non-aggregate class type
Tare list-initialized (8.5.4), overload resolution selects the constructor in two phases:— Initially, the candidate functions are the initializer-list constructors (8.5.4) of the class
Tand the argument list consists of the initializer list as a single argument.— If no viable initializer-list constructor is found, overload resolution is performed again, where the candidate functions are all the constructors of the class
Tand the argument list consists of the elements of the initializer list.
In your case the initializer list constructor is deemed non-viable (because std::istream_iterator<std::string> is not convertible to std::string), and the second condition applies. This results in the constructor taking 2 iterators to be selected.
来源:https://stackoverflow.com/questions/17979857/construct-container-with-initializer-list-of-iterators