【问题标题】:Why is this narrowing conversion not detected?为什么没有检测到这种缩小转换?
【发布时间】:2019-11-02 01:59:33
【问题描述】:

在使用列表初始化构造变量时(如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

【问题讨论】:

  • clang gives 错误,而 gcc 给出警告。
  • 你使用什么编译标志?是否使用了-Wall-Wnarrowing? (或他们的视觉工作室等价物。)
  • 似乎 Biagio Festa 的答案是正确的,但存在视觉工作室错误。

标签: c++ visual-studio c++11 list-initialization


【解决方案1】:

是的。你是对的:程序是格式错误的

在这种情况下(标准 §1.4):

符合要求的实现应发出至少一条诊断消息。

确实,gcc 会产生警告消息。 clang直接拒绝代码为编译错误。

这个特定的话题已经在heregcc1 讨论过。

Visual Studio 应该会生成一条诊断消息(我建议您检查编译选项。您是否禁用了警告?您是否使用 C++(11/14/17) 进行编译?,.. .)。如果不是这种情况,那就是实现错误。

更新:

Visual Studio v19.20 不会产生任何诊断消息(即使带有/Wall 标志)。

A bug report这里已经填好了。


1有关 gcc 实施以缩小检查的更多信息here

【讨论】:

  • 您使用的是哪个 C++ 标准?如果您填写错误报告,我认为将链接添加为对此答案的评论可能会很有用。谢谢
  • 我实际上切换了 C++11 - C++14 - C++17 看看它是否有所作为,但没有,所以我只是在帖子中标记了 C++11。
  • 是的,你只需要 C++11 或更高版本
  • 是的,我写了一个简短的摘要并链接了这篇文章。会有帮助吗?
猜你喜欢
  • 1970-01-01
  • 2017-11-05
  • 1970-01-01
  • 2022-01-23
  • 2010-12-01
  • 2010-10-25
  • 2020-12-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多