Search code examples
c++member-initializationdirect-initialization

Why warning instead of hard error on ill formed program


I'm aware that uniform initialization using braced-init list don't allow narrow conversion (ex double -> int)

but member initialization using init list allows narrow conversion.

struct Mem1
{
    Mem1() { cout << "Mem1 - default" << endl; }
    Mem1(int i) { cout << "Mem1 - single arg" << endl; }
};

struct Mem2
{
    Mem2() { cout << "Mem2 - default" << endl; }
    Mem2(int i) { cout << "Mem2 - single arg" << endl; }
};

class A
{
    Mem1 m1 {5.0}; // OK, complier warning 
    Mem2 m2 {2.0}; // OK, complier warning

public:
    A() { cout << "A - default" << endl; }
    A(int i) : m1{1.0}, m2{2.0} { cout << "A - single arg" << endl; } // OK
};


int main()
{
    A a0; // OK
    cout << "-------------" << endl;
    A a1 {2}; // OK
    //A a2 {2.0}; // Error - narrow conversion
}

Output

Mem1 - single arg
Mem2 - single arg
A - default
-------------
Mem1 - single arg
Mem2 - single arg
A - single arg

msvc version - 14.16 Complier issues warning like this for m1, m2 :

warning C4244: 'argument': conversion from 'double' to 'int', possible loss of data 

but complination error doesn't occur.

Is it bug or I'm missing something?


Solution

  • A compiler is not required to fail compilation of an ill-formed program. Just providing any diagnostic, possibly a warning, is sufficient for standard-compliance. The standard imposes no other requirement on the compiler for an ill-formed program except that it shall provide at least one diagnostic of any kind to the user.

    GCC for example also decides to only warn about some categories of narrowing conversions that are ill-formed in list-initialization for backwards-compatibility reasons. (Before C++11 and in C there isn't any such rule about narrowing conversions.)

    MSVC is free to decide to only warn about your program and then still compile it as if it didn't contain an ill-formed narrowing conversion. Whether this is intentional choice of behavior or unintended by the developers, I can't tell.

    From my tests at godbolt.org it seems that latest MSVC does choose an error instead of a warning.