Reputation: 154
I have a question concerning the following c++ program:
#include <vector>
#include <iostream>
int main(){
unsigned int i{5};
std::vector<double> v{i};
for(auto d : v){
std::cout << d << std::endl;
}
return 0;
}
g++ version 4.9.3 and g++ version 5.4 compile and generate the warning:
test.cpp:6:25: warning: narrowing conversion of ‘i’ from ‘int’ to ‘double’ inside { } [-Wnarrowing]
std::vector<double> v{i};
which I can understand, as according to the specification, the compiler wants to use the initializer list constructor of std::vector :
When objects of non-aggregate class type T are 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 T and 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 T and the argument list consists of the elements of the initializer list.
But what I can not understand is that clang version 3.8 fails to compile the program, with the same error as the warning above. I would expect that in this case the initializer-list constructor is not viable (at least clang rejects it) and the "intended" constructor of std::vector should be used instead.
My question: Narrowing conversions are syntax errors in the program and hence (in my understanding) the constructor of std::vector should be used that creates a std::vector of size 5. So why are the compilers ignoring the constructor that would lead to a valid program?
Thank you in advance!
Upvotes: 0
Views: 414
Reputation: 52471
[dcl.init.list]/3 Otherwise, if
T
is a class type, constructors are considered. The applicable constructors are enumerated and the best one is chosen through overload resolution (13.3, 13.3.1.7). If a narrowing conversion (see below) is required to convert any of the arguments, the program is ill-formed.
The necessity of narrowing conversion doesn't render a constructor non-viable. Instead, it participates in the overload resolution normally, and then, if it happens to be chosen, the program is ill-formed.
Upvotes: 1