我正在使用此处列出的书籍学习C++。特别是,我最近使用C++初级读本一书了解了noexcept
。现在,为了进一步明确我对这个主题的概念,并确认我已经正确理解了事情,我正在编写简单的程序。下面给出了一个用MSVC和Clang编译但不用GCC编译的这样的程序。演示。
void f() noexcept(5) //accepted by msvc but rejected by gcc
{
}
所以我的问题是哪一个编译器就在这里(如果有的话(?
以下是一些主要编译器的结果:
编译器 | C++版本 | 接受代码|
---|---|---|
GCC | C++17 | 否|
GCC | C++20 | 否 |
Clang | C++17是 | |
Clang | C++20 | 否 |
MSVC | C++17 | 是 |
MSVC | C++20是 |
TLDR
程序是格式不正确的,并且相应的编译器在接受代码时是错误的,因为int prvalue表达式5
不是类型为bool
的上下文转换的常量表达式,noexcept-specifier
要求该常量表达式(如果提供(是上下文转换的常数表达式。基本上,程序格式错误的原因与bool b{5};
格式错误的相同,即这涉及缩小转换。
来自异常规范文档:
1(异常规范要么是隐式定义的,或通过使用noexcept说明符作为函数声明符的后缀来显式定义
noexcept-specifier: noexcept ( constant-expression ) noexcept throw ( )
2(在noexcept说明符中,常量表达式(如果提供(应为bool类型的上下文转换常量表达式;该常量表达式是noexcept说明符出现的函数类型的异常规范。
(强调矿(
这意味着,为了使程序形成良好的格式,所提供的常量表达式(在我们的示例中为5
(需要是bool类型的上下文转换的常量表达式。
现在让我们从表达式const#4中了解5
是否是上下文转换的常量表达式:
4.10(bool类型的上下文转换的常量表达式是上下文转换为bool的表达式,其中转换的表达式是常量表达式,并且转换序列仅包含上面的转换。
4.7(积分转换而非窄化转换,
从缩小转换
缩小转换是一种隐式转换
- 从整数类型或无范围枚举类型到不能表示原始类型的所有值的整数类型,除非源是一个常量表达式,其值在整数提升后将适合目标类型
(强调矿(
这意味着从int prvalue5
到booltrue
的转换是一个窄化转换,因此5
不是bool类型的上下文转换的常量表达式,因此程序格式不正确,各个编译器在接受代码时都是错误的。
基本上,程序格式不良的原因与bool b{3};
格式不良的理由相同。你甚至可以看到你会得到同样的错误。演示
这是msvc错误报告:
MSVC接受无效的缩小转换
这是叮当声错误报告:
Clang接受无效的缩小转换