Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What are the consequences of ignoring narrowing conversions in C++0x

Since switching on the C++0x standard in g++, I've started seeing 'narrowing conversion' errors, particularly when converting from an 'int' to a 'short' although I understand the error covers a much broader swath of conversions.

Can anyone shed some light on the rational for introducing this extra level of safety?, What are the possible consequences of disabling this error? (apart from the potential loss of precision).

Thanks.

like image 390
Gearoid Murphy Avatar asked Dec 20 '11 16:12

Gearoid Murphy


1 Answers

From Assignment and compound assignment operators [expr.ass]

The meaning of x={v}, where T is the scalar type of the expression x, is that of x=T(v) except that no narrowing conversion (8.5.4) is allowed.

and from List-initialization [dcl.ini.list]

If a narrowing conversion (see below) is required to convert any of the arguments, the program is ill-formed.

So basically you can't ignore it, your program is ill-formed in presence of narrowing conversions.

From Implementation compliance:

Implementations are required to diagnose programs that use such extensions that are ill-formed according to this International Standard. Having done so, however, they can compile and execute such programs.

Bjarne Stroustroup say this:

Preventing narrowing

The problem: C and C++ implicitly truncates:

   int x = 7.3;        // Ouch!
    void f(int);
    f(7.3);         // Ouch!

However, in C++0x, {} initialization doesn't narrow:

int x0 {7.3};   // error: narrowing
int x1 = {7.3}; // error: narrowing
double d = 7;
int x2{d};      // error: narrowing (double to int)
char x3{7};     // ok: even though 7 is an int, this is not narrowing
vector<int> vi = { 1, 2.3, 4, 5.6 };    // error: double to int narrowing

The way C++0x avoids a lot of incompatibilities is by relying on the actual values of initializers (such as 7 in the example above) when it can (and not just type) when deciding what is a narrowing conversion. If a value can be represented exactly as the target type, the conversion is not narrowing.

char c1{7};      // OK: 7 is an int, but it fits in a char
char c2{77777};  // error: narrowing 

Note that floating-point to integer conversions are always considered narrowing -- even 7.0 to 7.

So in a way, narrowing also increases type safety.

like image 83
Sebastian Mach Avatar answered Sep 20 '22 11:09

Sebastian Mach