Search code examples
c++diagnosticstype-narrowing

Why different diagnostics by clang on similar issue?


Here is my code:

#include <vector>

int main()
{
    std::vector<int> a = {1, 2.2};
}

As expected this does not compile because of the illegal narrowing conversion:

$ clang++ -std=c++11 foo.cpp
foo.cpp:5:30: error: type 'double' cannot be narrowed to 'int' in initializer list [-Wc++11-narrowing]
    std::vector<int> a = {1, 2.2};
                             ^~~

Why does this compile then with only a warning?

#include <complex>

int main()
{
    std::complex<int> a = {1, 2.2};
}

Here is the warning:

$ clang++ -std=c++11 foo.cpp 
foo.cpp:5:31: warning: implicit conversion from 'double' to 'std::__1::complex<int>::value_type' (aka 'int') changes value from 2.2 to 2 [-Wliteral-conversion]
    std::complex<int> a = {1, 2.2};
                          ~   ^~~
1 warning generated.

I understand the notion of diagnostics and that the C++ compiler is only required to issue a diagnostic either in the form of error or warning.

But I want to be sure that I am not misunderstanding any concept here. Especially, I want to know if there is any C++ concept that I need to know why in the first case the c++11-narrowing diagnostic was issued but in the second case literal-conversion diagnostic was issued.


Solution

  • Two different things are happening, which as you can see result in different diagnostics:

    • In the first case, you're using copy-list-initialization and finding a constructor of std::vector which takes an std::initializer_lsit.

    • In the second case, you're using copy-list-initialization on a LiteralType, which results in aggregate initialization.

    They both should prevent narrowing conversions, but it seems that clang implements the diagnostics differently.