It looks like:
bool b = {2} ;
is indeed a narrowing conversion if we look at the draft C++ standard section 8.5.4
List-initialization paragraph 7 says:
A narrowing conversion is an implicit conversion
and include the following bullet (emphasis mine):
from an integer type or unscoped enumeration type to an integer type
that cannot represent all the values of the original type, except
where the source is a constant expression whose value after integral
promotions will fit into the target type.
bool
can not represent the value 2
so this is a narrowing conversion in the strictest sense. Which makes sense the whole point of {}
initialization is to prevent implicit conversions and increase type safety. Which the old style that you refer to here relies on:
bool b = 2
which depends on the section 4.12
Boolean conversions which says:
[...] A zero value, null pointer value, or null member pointer value
is converted to false; any other value is converted to true. [...]
Of course the whole premise that {2}
would be a narrowing conversion relies the assumption that the value of true and false is 1
and 0
, which as far as I can tell is not guaranteed in the standard. Although it is implied the only thing the standard promises in conversions but if we are going to use a literal we don't need to rely on this assumption we have two perfectly good boolean literals for this true
and false
which is what you should be using.
For completeness sake, this narrowing conversion is ill-formed, it requires a diagnostic, so either a warning or an error is acceptable. if we look at paragraph 3, it says:
List-initialization of an object or reference of type T is defined as
follows:
and include the following bullet (emphasis mine):
Otherwise, if the initializer list has a single element of type E and either T is not a reference type or its referenced type is reference-related to E, the object or reference is initialized from that element; if a narrowing conversion (see below) is required to convert the element to T, the program is ill-formed.
and includes the following example:
[ Example:
int x1 {2}; // OK
int x2 {2.0}; // error: narrowing
—end example ]
anything not 0
and0
astrue
andfalse
as far as I can tell the standard gives you no promise thattrue
andfalse
are1
and0
respectively, it just guarantees conversions. So if you are going to use a literal then usetrue
andfalse
, which will never be a narrowing conversion. – Cinematograph