Why Doesn't Narrowing Conversion Used with Curly-Brace-Delimited Initializer Cause an Error

Narrowing conversion of list initialization is an error or just a warning?

The Standard specifies that a diagnostic is required in case that a program is ill-formed. Which is the case when a narrowing-conversion takes place inside a braced-initializer.

That is, the standard doesn't distinguish between an error and a warning.

1.3.6 diagnostic message [defns.diagnostic]

message belonging to an implementation-defined subset of the
implementation's output messages

Why is the initializer list allowing type narrowing in C++?

With gcc variants you need to specify -Werror=narrowing to make this into error instead of warning. clang and vc++ are more strict and issue an error by default.

C++ curly brace delimited initializer lists

A more current version of gcc (4.8.1), treats this as a warning:

trash9.cpp: In function 'int main(int, const char**)':
trash9.cpp:11:14: warning: narrowing conversion of '7.2000000000000002e+0' from
'double' to 'int' inside { } [-Wnarrowing]
int i2 {7.2};

The standard requires that the compiler issue a "diagnostic", so (with the right documentation) this undoubtedly qualifies. The compiler is free to continue compiling the code afterwards.

VC++ does closer to what you apparently want:

trash9.cpp(11) : error C2397: conversion from 'double' to 'int' requires a narro
wing conversion

g++4.9 and g++5 different behaviour when narrowing in initializing list

The standard never says anything "should not compile" (except for #error). Certain ill-formed programs must emit a diagnostic and issuing a warning satisfies that.

You can cause gcc to stop compilation on all diagnostics by using the switch -Werror. It can be narrowed to specific warnings, e.g. -Werror=narrowing.

If you are compiling in GNU++ or whatever the default mode is instead of C++11 then the compiler can do whatever it likes, including accepting narrowing conversions without complaint.

Reference: N3936 [intro.compliance]/2

  • If a program contains a violation of any diagnosable rule [...], a conforming implementation shall issue at least one diagnostic message.

  • If a program contains a violation of a rule for which no diagnostic is required, this International Standard places no requirement on implementations with respect to that program.

[defns.diagnostic]

diagnostic message

message belonging to an implementation-defined subset of the implementation’s output messages

Note also from the first bullet point that it is not required that the number or content of messages corresponds to the number or content of the violations.

The standard leaves it completely up to the compiler to decide how to organize its errors and/or warnings, with the proviso that for certain violations it can't silently ignore it.

Narrowing conversion to bool in list-initialization - strange behaviour

This simply looks like a bug, if we try the following:

bool b {3} ;

both gcc and clang issue a diagnostic, for example gcc says:

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

This is covered in the draft C++11 standard by section 8.5.4 List-initialization paragraph 7 which says:

A narrowing conversion is an implicit conversion

[...]

  • 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 and the actual value after
    conversion will fit into the target type and will produce the original
    value when converted back to the original type.

This is same paragraph that covers your example and the following simpler example:

bool a {3.0} ;

which would be covered by this bullet from paragraph 7 quoted above:

  • from a floating-point type to an integer type, or

From paragraph 3, this is ill-formed an requires a diagnostic:

List-initialization of an object or reference of type T is defined as follows:

[...]

  • Otherwise, if the initializer list has a single element, 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.

which gcc produces no diagnostic but clang does provide the following warning, although not the narrowing conversion warning we should see:

warning: implicit conversion from 'double' to 'bool' changes value from 3 to true [-Wliteral-conversion]

Note, section 3.9.1 [basic.fundamental] says:

Types bool, char, char16_t, char32_t, wchar_t, and the signed and unsigned integer types are collectively
called integral types.48 A synonym for integral type is integer type.

You should file a bug report with both clang and gcc.

Jonathan Wakely notes that the EDG compiler gives a narrowing error for the OPs code, which is a strong indication that this indeed should produce a diagnostic.

Update

I submitted a gcc and clang bug report.

The clang bug report has been updated as fixed:

Fixed in r229792.

The gcc bug report has been updated as fixed:

Fixed.

and a live example seems to confirm this.

Does the C++ standard specify that for some cases the compiling should fail with an error?

The standard doesn't use the terms "error" and "warning", it only talks about cases where the compiler must "issue a diagnostic".

In your example, if the program is "ill-formed", the compiler is required to tell you that somehow - issue a diagnostic.

After that, it can do anything it likes - including compiling and running the program anyway. The standard only specifies what happens for conforming code, everything else is undefined. And then, as we know, anything can happen.



Related Topics



Leave a reply



Submit