Why does `bool b = 2` work well, but` bool b = {2} `gives a warning about narrowing the conversion?

Using the initializer {} in C++11 to initialize bool b = {2} gives the following warning message:

 warning: narrowing conversion of '2' from 'int' to 'bool' inside { } [-Wnarrowing] 

However, using the old style bool b = 2 does not have such a problem. What is the reason for this?


Update: I compiled the code using g++ -std=c++11 and it gave me a warning. If I add the -pedantic-errors parameter, the warning will become an error.

+7
c ++ type-conversion c ++ 11 narrowing
source share
2 answers

Narrowing the data type in the initialization list makes your C ++ 11 program poorly formed; in this situation, the compiler can either give a warning or continue.

Interestingly, you can really change it to bool b = {1} , and there is no warning, I assume that the value of bool is guaranteed to convert to 0 and 1 into integral types.

Here is a standard quote confirming the error.

A conversion narrowing is an implicit conversion - from a floating point type to an integer type, or
- from long double to double or float or from double to float, except when the source is a constant expression, and the actual value after conversion is within the range of values ​​that can be represented (even if they cannot be represented exactly), or
- from an integer or non-enumerated type to a floating-point type, unless the source is a constant expression, and the actual value after the conversion will correspond to the target type and will produce the original value when converting back to the original type, or
- from an integer type or an unenumerated enumeration type to an integer type that cannot represent all the values ​​of the source type, except when the source is a constant expression, and the actual value after conversion will fit into the target type and will produce the original value when converting back to source type.
As indicated above, such conversions are not allowed at the top level in list initialization

+8
source share

Looks like:

 bool b = {2} ; 

really is a narrowing transformation if we look at the draft C ++ 8.5.4 standard in paragraph 7 of the initialization of the list:

Narrowing a transform is an implicit transform

and enable the following bullet (my selection):

from an integer type or an enumerated type of an enumeration to an integer type that cannot represent all the values ​​of the source type , except where the source is a constant expression, the value of which after the integral, the promotions will fit into the target type.

bool cannot represent the value 2 , so this is a narrowing of the conversion in the strict sense. What makes sense, all of the initialization {} is to prevent implicit conversions and increases type safety. What old style are you referring to:

 bool b = 2 

which depends on section 4.12 Boolean transformations, which states:

[...] A null value, a null pointer value, or a null element pointer value is converted to false; any other value is converted to true. [...]

Of course, the whole premise that {2} will be a narrowing transformation, assumes that true and false are 1 and 0 , which, as far as I can tell, is not guaranteed in the standard. Although the only standard promises in conversions are implied, but if we use a literal, we do not need to rely on this assumption, we have two absolutely good boolean literals for these true and false , which are what you should use.

To complete this transformation, the narrowing is poorly formed, it requires diagnostics, therefore either a warning or an error is permissible. if we look at paragraph 3, it says:

An initialization list of an object or link of type T is defined as follows:

and enable the following bullet (my selection):

Otherwise, if there is one element of type E in the list of initializers, and either T is not a reference type, or its reference type is associated with a binding to E, an object or reference is initialized from this element; if, to convert an element to T, a restriction transformation is required (see below), the program is poorly formed .

and includes the following example:

 [ Example: int x1 {2}; // OK int x2 {2.0}; // error: narrowing β€”end example ] 
+4
source share

All Articles