使用列表初始化构造变量时(如 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 Community 2017 版本 15.9.5 并使用 /wall
进行编译,所有警告都是在 x64
调试版本中启用的错误。设置标准的 C++11、C++14 和 C++17 都可以编译。
我提交了错误报告 here
最佳答案
是的。你是对的:程序是格式错误的。
在这种情况下(标准 §1.4):
a conforming implementation shall issue at least one diagnostic message.
确实,gcc
会产生警告消息。 clang
直接将代码拒绝为编译器错误。
这个特定的话题已经讨论过了here对于 gcc1.
Visual Studio
应该会生成一条诊断消息(我建议您检查您的编译选项。您是否禁用了警告?您是否使用 C++(11/14/17) 进行编译?, ...)。如果不是这种情况,那就是实现错误。
更新:
Visual Studio v19.20不会产生任何诊断消息(即使带有 /Wall
标志)。
A bug report这里已经填好了。
1 有关 gcc 实现以进行缩小检查的更多信息 here .
关于c++ - 为什么没有检测到这种缩小转换?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56665797/