使用 noexcept 的程序被 msvc 和 clang 接受但被 gcc 拒绝

Ale*_*lex 3 c++ exception-specification language-lawyer narrowing noexcept

我正在使用此处列出的书籍学习 C++ 。特别是最近学习了使用《C++ Primer》noexcept这本书。现在,为了进一步明确我对这个主题的概念并确认我已经正确理解了事情,我正在编写简单的程序。下面给出了一个这样的程序,它可以使用 MSVC 和 Clang 编译,但不能使用 GCC 编译。演示

void f() noexcept(5) //accepted by msvc but rejected by gcc
{

}
Run Code Online (Sandbox Code Playgroud)

所以我的问题是哪个编译器就在这里(如果有的话)?

以下是一些主要编译器的结果:

编译器 C++版本 接受代码
海湾合作委员会 C++17
海湾合作委员会 C++20
C++17 是的
C++20
MSVC C++17 是的
MSVC C++20 是的

正如我们所看到的,该程序适用于某些编译器,但不适用于其他编译器。gcc 中的错误说: error: narrowing conversion of '5' from 'int' to 'bool'

use*_*570 9

总长DR

该程序格式不正确,并且相应的编译器在接受代码时是错误的,因为 int prvalue 表达式5不是类型的上下文转换常量表达式,bool而该类型(如果提供)需要是noexcept-specifier. 基本上,程序格式错误的原因与格式错误的原因相同bool b{5};,即,这涉及缩小转换


来自异常规范文档

1)异常规范要么隐式定义,要么通过使用 noexcept 说明符作为函数声明符的后缀显式定义

noexcept-specifier:
  noexcept ( constant-expression )
  noexcept
  throw ( )
Run Code Online (Sandbox Code Playgroud)

2)在 noexcept 说明符中,常量表达式(如果提供)应为 bool 类型的上下文转换常量表达式;该常量表达式是出现 noexcept 说明符的函数类型的异常规范。

(强调我的)

这意味着为了使程序格式良好,提供的常量表达式(在5我们的示例中)需要是 上下文转换的 bool 类型的常量表达式

现在让我们看看expr.const#4是否5是上下文转换的常量表达式:

4.10) bool 类型的上下文转换常量表达式是一个根据上下文转换为 bool 的表达式,其中转换后的表达式是常量表达式,并且转换序列仅包含上面的转换

4.7)除收缩转换之外的积分转换,

并从缩小转换

缩小转换是隐式转换

  • 从整数类型或无范围枚举类型到无法表示原始类型的所有值的整数类型,除非源是常量表达式,其整型提升后的值将适合目标类型

(强调我的)

这意味着从 int prvalue5到 bool 的转换true是缩小转换,因此5不是根据上下文转换的 bool 类型的常量表达式,因此程序格式不正确,并且相应的编译器在接受代码时是错误的。

bool b{3};基本上,程序格式错误的原因与格式错误的原因相同。您甚至可以看到您会得到相同的错误。演示


这是 msvc 错误报告:

MSVC 接受无效的缩小转换

这是 clang 错误报告:

Clang 接受无效的缩小转换