Build a container with iterator list initializer

You can build a vector with an iterator range, for example:

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

But I can also compile and run the code using the syntax of standard C ++ 11 simulation (note the handcuffs), for example:

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

What's going on here?

I know that a constructor that has a list of initializers takes precedence over other forms of construction. Doesn't the compiler allow the constructor to accept a list of initializers containing 2 std::istream_iterator ? This should be an error, since std::istream_iterator cannot be converted to the std::string vector value type, right?

+6
source share
1 answer

From Β§13.3.2 / 1 ([above .match.list])

When objects of type non-aggregate class T initialized by a list (8.5.4), the constructor selects the overload resolution in two phases:

- Initially, the candidate functions are a list of initializers, constructors (8.5.4) of class T , and the list of arguments consists of a list of initializers as one argument.

- If there is no viable constructor of the initializer list, overload resolution is performed again, where the candidate functions are all constructors of class T , and the argument list consists of elements of the initializer list.

In your case, the initializer list constructor is considered non-viable (since std::istream_iterator<std::string> not converted to std::string ), and the second condition is applied. This causes the constructor to select 2 iterators.

+5
source

Source: https://habr.com/ru/post/950755/


All Articles