使用列表初始化构造变量时(例如int x{ 5 };
)the standard§8.5.4说:
如果需要缩小转换[…]来转换任何参数,则程序格式错误。 (7)缩小转换是隐式转换- (7.4)从整数类型或无作用域枚举类型到不能表示原始类型的所有值的整数类型,除非源是一个常量表达式,其整数提升后的值将适合目标类型。
那为什么要编译?
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 };
从'int'到'unsigned char'的C2397转换需要缩小的转换
引入临时方法也是如此:
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
答案 0 :(得分:11)
是的。您说得对:程序是格式错误的。
在这种情况下(标准§1.4):
符合标准的实现应至少发布一条诊断消息。
实际上,gcc
会生成一条警告消息。 clang
直接将代码视为编译器错误而拒绝。
已经针对{em> gcc 1 here讨论了此特定主题。
Visual Studio
应该会产生诊断消息(建议您检查编译选项。是否禁用了警告?您正在使用 C ++(11/14/17)进行编译吗? ...)。如果不是这种情况,那就是实现错误。
更新:
Visual Studio v19.20不会产生任何诊断消息(即使带有/Wall
标志)。
A bug report已在此处填写。
1 有关gcc缩窄检查here实现的其他信息。