Bluescreen
Bluescreen

Reputation: 154

Why does std::vector<double> v{unsigned int} does not choose a valid constructor?

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

Answers (1)

Igor Tandetnik
Igor Tandetnik

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

Related Questions