17

I have the following code:

class A { public: A(const unsigned int val) : value(val) {} unsigned int value; }; int main() { int val = 42; A a(val); A b{val}; // <--- Warning in GCC, error in Microsoft Visual Studio 2015 return 0; } 

Why does the narrowing conversion warning appear only in case of list initialization usage?

3 Answers 3

18

list initialization was introduced since C++11 with the feature prohibiting implicit narrowing conversions among built-in types. At the same time, the other two "old-style" (since C++98) initialization forms which use parentheses and equal-sign like

int val = 42; A a(val); A a = val; 

don't change their behavior to accord with list initialization, because that could break plenty of legacy code bases.

Sign up to request clarification or add additional context in comments.

4 Comments

Is there a compiler flag to introduce that prohibition consistently?
int i = 0; char c[] = { i }; was an old-style initialisation form too, valid C++03 but invalid C++11. Legacy code was in fact broken by the change.
@Schwern -Wsign-conversion seems to work for me on GCC and Clang, no idea for MSVC.
And for MSVC it seems C4365 works but others may also be required.
9

Under the standard, narrowing conversions are illegal in that context. They are legal in the other context. (By "illegal", I mean make the program ill-formed).

The standard requires that a compiler issue a diagnostic in that particular case (of making the program ill-formed). What the compiler does after emitting the diagnostic the standard leaves undefined.

MSVC chooses to halt compilation. Gcc chooses to emit nasal demons pretend the program makes sense, and do the conversion, and continue to compile.

Both warnings and errors are diagnostics as far as the standard is concerned. Traditionally errors are what you call diagnostics that preceed the compiler stopping compilation.

Also note that compilers are free to emit diagnostics whenever they want.

Traditionally warnings are used when you do something the standard dictates is a well formed program yet the compiler authors consider ill advised, and errors when the standard detects an ill-formed program, but most compilers do not enforce that strictly.

1 Comment

Until C99 added the #error directive, an implementation could have satisfied all requirements for diagnostics by unconditionally outputting "This is a diagnostic" before it even looked at any of the source text. The Standard defines the #error directive much more explicitly, but still leaves all other requirements uselessly vague.
0

The reason behind the warning is already explained by other answers.

This is how to fix this warning/error. Create a constructor which takes initializer_list as argument.

A(std::initializer_list<int> l) : value(*(l.begin())) { cout << "constructor taking initializer list called\n"; } 

1 Comment

This "fix" is nonsensical. To allow int val = 0; A b{val};, you add code allowing A b1{1,2,3,4,5}; and disallowing unsigned int val = 42; A c{val};.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.