为什么未检测到这种缩小转换?
Why is this narrowing conversion not detected?
使用列表初始化构造变量时(如 int x{ 5 };
)the standard §8.5.4 说:
If a narrowing conversion […] is required to convert any of the arguments, the program is ill-formed.
(7) A narrowing conversion is an implicit conversion -
(7.4) 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.
那么为什么会编译?
char c{ 'A' };
char x{ c + c };
提醒一下,c + c
会产生 int
static_assert(std::is_same_v<decltype(c + c), int>, "");
所以编译器应该抱怨一个肯定不是常量表达式的窄化转换。
有趣的是,将 x
声明为 unsigned char
正确编译失败:
char c{ 'A' };
unsigned char x{ c + c };
C2397 conversion from 'int' to 'unsigned char' requires a narrowing conversion
与引入临时对象一样:
char c{ 'A' };
int sum{ c + c };
char x{ sum }; //C2397 conversion from 'int' to 'char' requires [...]
那么为什么第一个版本可以编译?我正在使用 Visual Studio 社区 2017 版本 15.9.5 并使用 /wall
编译它,所有警告都是在 x64
调试版本中启用的错误。设置标准 C++11、C++14 和 C++17 都可以编译。
我提交了错误报告 here
是的。你是对的:程序是ill-formed.
在这种情况下(标准§1.4):
a conforming implementation shall issue at least one diagnostic message.
的确,gcc
产生了一条警告消息。 clang
直接拒绝代码作为编译器错误。
此特定主题已针对 gcc1.
进行了讨论 here
Visual Studio
应该会产生一条诊断消息(我建议您检查您的编译选项。您是否禁用了警告?您是否使用 C++(11/14/17)?, ...)。如果不是这种情况,则为实现错误。
更新:
Visual Studio v19.20 不会产生任何诊断消息(即使带有 /Wall
标志)。
A bug report这里已经填好了
1 有关缩小检查的 gcc 实现的更多信息 here。
使用列表初始化构造变量时(如 int x{ 5 };
)the standard §8.5.4 说:
If a narrowing conversion […] is required to convert any of the arguments, the program is ill-formed. (7) A narrowing conversion is an implicit conversion - (7.4) 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.
那么为什么会编译?
char c{ 'A' };
char x{ c + c };
提醒一下,c + c
会产生 int
static_assert(std::is_same_v<decltype(c + c), int>, "");
所以编译器应该抱怨一个肯定不是常量表达式的窄化转换。
有趣的是,将 x
声明为 unsigned char
正确编译失败:
char c{ 'A' };
unsigned char x{ c + c };
C2397 conversion from 'int' to 'unsigned char' requires a narrowing conversion
与引入临时对象一样:
char c{ 'A' };
int sum{ c + c };
char x{ sum }; //C2397 conversion from 'int' to 'char' requires [...]
那么为什么第一个版本可以编译?我正在使用 Visual Studio 社区 2017 版本 15.9.5 并使用 /wall
编译它,所有警告都是在 x64
调试版本中启用的错误。设置标准 C++11、C++14 和 C++17 都可以编译。
我提交了错误报告 here
是的。你是对的:程序是ill-formed.
在这种情况下(标准§1.4):
a conforming implementation shall issue at least one diagnostic message.
的确,gcc
产生了一条警告消息。 clang
直接拒绝代码作为编译器错误。
此特定主题已针对 gcc1.
进行了讨论 hereVisual Studio
应该会产生一条诊断消息(我建议您检查您的编译选项。您是否禁用了警告?您是否使用 C++(11/14/17)?, ...)。如果不是这种情况,则为实现错误。
更新:
Visual Studio v19.20 不会产生任何诊断消息(即使带有 /Wall
标志)。
A bug report这里已经填好了
1 有关缩小检查的 gcc 实现的更多信息 here。