Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why gcc warns about narrowing conversion only for uniform initialization?

I am trying to convert long type variable to int type variable with uniform initialization and without it. But I get compiler warning only with uniform initialization. Why is that? Why does not gcc warn in both cases? I have tried with clang also and got similar results.

This is the code

#include <iostream>

int main() {
    long l = 1;
    int i1 = l;
    int i2 = { l };

    std::cout << i1 << std::endl;
    std::cout << i2 << std::endl;

    return 0;
}

And the only one warning I get

$ g++ -Wall -Wextra 1.cpp
1.cpp: In function ‘int main()’:
1.cpp:6:16: warning: narrowing conversion of ‘l’ from ‘long int’ to ‘int’ inside { } [-Wnarrowing]
   int i2 = { l };
like image 592
ks1322 Avatar asked Jul 24 '18 11:07

ks1322


2 Answers

Because the standard says, narrowing conversions limit is specified only for list initialization (since C++11).

list-initialization limits the allowed implicit conversions by prohibiting the following:

  • conversion from a floating-point type to an integer type
  • conversion from a long double to double or to float and conversion from double to float, except where the source is a constant expression and overflow does not occur
  • conversion from an integer type to a floating-point type, except where the source is a constant expression whose value can be stored exactly in the target type
  • conversion from integer or unscoped enumeration type to integer type that cannot represent all values of the original, except where source is a constant expression whose value can be stored exactly in the target type

For the other initialization methods (using parentheses or equal sign), narrowing conversions limit rule is not applied (added); because that might break much legacy code.

like image 168
songyuanyao Avatar answered Nov 04 '22 03:11

songyuanyao


The difference between the two is that narrowing conversions are not allowed in a list initialization. In other forms of initialization they are allowed.

The thing that often confuses people here is that when something is not allowed it doesn't mean that the compiler must refuse to compile the code. The requirement is that the compiler must "issue a diagnostic", and a warning is a valid form of diagnostic.

So the compiler is required to issue a diagnostic for a narrowing conversion in a list initialization, and that's what you're seeing. Beyond that, as others have said, you can crank up the warning level to get warnings about narrowing conversions in other contexts. But outside of list initialization diagnostics are not required, and they're often more annoying than useful, so not turned on by default.

like image 24
Pete Becker Avatar answered Nov 04 '22 03:11

Pete Becker