Ami*_*rsh 8 c++ language-lawyer noexcept constexpr c++17
[expr.unary.noexcept]的措辞在C++17 中发生了变化。
以前(n4140, 5.3.7 noexcept operator [expr.unary.noexcept]),我的重点是:
- 如果在潜在求值的上下文中表达式将包含,则 noexcept 运算符的结果为 false
(3.1) 对不具有非抛出异常规范 ([except.spec]) 的函数、成员函数、函数指针或成员函数指针的潜在求值调用,除非调用是常量表达式 ([ expr.const]) ...
现在1(7.6.2.6 noexcept 运算符 [expr.unary.noexcept]):
- 除非表达式可能抛出异常 ([except.spec]),否则noexcept 运算符的结果为真。
- 如果函数声明没有 noexcept 说明符,则该声明具有潜在的抛出异常说明,除非...
但是14.5(3)的除非列表未列出constexpr,因此可能会抛出...
1 LF 在评论中添加的指向 C++17 n4659的链接。
constexpr int f(int i) { return i; }
std::cout << boolalpha << noexcept(f(7)) << std::endl;
int a = 7;
std::cout << boolalpha << noexcept(f(a)) << std::endl;
Run Code Online (Sandbox Code Playgroud)
用于打印(使用 gcc 8.3):
true
false
Run Code Online (Sandbox Code Playgroud)
使用-std=c++11和-std=c++2a 编译时
但是现在打印相同的代码(使用 gcc 9.2):
false
false
Run Code Online (Sandbox Code Playgroud)
使用-std=c++11和-std=c++2a 编译时
顺便说一句,Clang 是非常一致的,因为 3.4.1和:
false
false
Run Code Online (Sandbox Code Playgroud)
旁注:noexcept对constexpr函数的推导会影响这个技巧。
每个规范的正确行为是什么?
true false在 C++17 之前,false false从 C++17 开始。
规范有真正的变化吗?如果是这样,这种变化的原因是什么?
是的。请参阅下面的 Clang 错误报告中的引用。
如果规范中的变化影响或与过去的行为相矛盾,强调这种变化及其影响是否是一种常见的做法?如果没有强调这一变化,是否意味着它可能是一个疏忽?
是的; 是的(但 CWG 后来找到了证明监督合理的理由,所以它保持原样)。
如果这是一个真正的预期更改,它是否被认为是应该返回到规范的先前版本的错误修复,编译器是否正确地将新行为追溯至 C++11?
我不知道。请参阅下面的 Clang 错误报告中的引用。
我搜索了很多地方,到目前为止我能找到的最接近的是对相关错误报告的评论:
GCC 错误 87603 - [C++17] noexcept 不再是常量表达式的特例
CWG 1129(最终出现在 C++11 中)
noexcept为常量表达式添加了一个特殊情况,以便:Run Code Online (Sandbox Code Playgroud)constexpr void f() {} static_assert(noexcept(f()));CWG 1351(最终在 C++14 中)显着改变了措辞,但特殊情况仍然存在,形式不同。
P0003R5(最终出现在 C++17 中)再次改变了措辞,但特例被删除了(偶然),所以现在:
Run Code Online (Sandbox Code Playgroud)constexpr void f() {} static_assert(!noexcept(f()));根据 LLVM 15481 中 Richard Smith 的说法,CWG 对此进行了讨论,但决定保持原样。目前,clang 为 C++17 做了正确的事情(故意为 C++14 和 C++11 失败)。然而,g++ 已经实现了 C++11 的特殊情况,但没有实现 C++17 的变化。目前,icc 和 msvc 似乎表现得像 g++。
Clang 错误 15481 - noexcept 应检查表达式是否为常量表达式
wg21.link/p0003 删除了常量表达式特例——显然是偶然的。我正在调查它是否会消失。
您是否采取了任何措施来避免深度嵌套表达式的二次运行时间?
[...]
CWG 讨论的结论:我们将保持原样。
noexcept对于常量表达式没有特殊规则。事实证明,这对于正确的库功能来说实际上是必不可少的:例如,如果
noexcept尝试评估其操作数,那么(例如)会is_nothrow_swappable被 make 破坏std::swapconstexpr,因为std::swap<T>通常在T完成之前最终会被实例化。因此,我还将将此更改视为针对 C++11 和 C++14 的有效 DR……但如果我们看到许多用户投诉,我愿意重新考虑。
换句话说,特殊规则被P0003意外删除,但 CWG 决定保留删除。
| 归档时间: |
|
| 查看次数: |
260 次 |
| 最近记录: |