ove*_*eas 9 c++ language-lawyer noexcept c++17
请考虑以下代码段:
版本(1)
void q() {}
class B {
void f() noexcept(noexcept(q())) {q(); }
decltype(&B::f) f2;
};
Run Code Online (Sandbox Code Playgroud)
版本(2)
void q() {}
class B {
void f() noexcept(true) {q(); }
decltype(&B::f) f2;
};
Run Code Online (Sandbox Code Playgroud)
版本(3)
void q() {}
class B {
void f() noexcept {q(); }
decltype(&B::f) f2;
};
Run Code Online (Sandbox Code Playgroud)
所有版本的GCC都会编译这些代码片段而不会出现任何错误或警告(包括trunk-version).支持C++ 17的所有版本的Clang拒绝版本(1)和(2),但不支持版本(3),并出现以下错误:
<source>:4:16: error: exception specification is not available until end of class definition
decltype(&B::f) f2;
^
Run Code Online (Sandbox Code Playgroud)
考虑到标准定义noexcept为等同于noexcept(true)[except.spec].因此,版本(2)和版本(3)应该是等价的,它们不适用于clang.
因此,以下问题:在什么时候需要根据C++ 17标准评估异常规范?并且,如果上面的某些代码无效,背后的理性是什么?
感兴趣的人的抽象背景:
template <typename F>
struct result_type;
template<typename R, typename C, typename... Args>
struct result_type<R(C::*)(Args...)> {
using type = R;
}; // there may be other specializations ...
class B {
int f() noexcept(false) { return 3; }
typename result_type<decltype(&B::f)>::type a;
};
Run Code Online (Sandbox Code Playgroud)
此代码至少应该在C++ 14之前有效,因为noexcept它不是函数类型的一部分(对于clang,它编译为版本3.9.1).对于C++ 17,没有办法做到这一点.
这是CWG 1330的结果.
基本上,该类在其noexcept-specifier中被认为是完整的(在上面的缺陷的解决方案中称为异常规范).
这使我们处于以下情况:
void q() {}
class B {
void f() noexcept(noexcept(q())) {q(); }
// ~~~~~~~~~~~~~
// evaluated in the context of complete B
decltype(&B::f) f2;
//~~~~~~~~~~~~~~~
//cannot wait until B is complete to evaluate
};
Run Code Online (Sandbox Code Playgroud)
我们需要知道decltype(&B::f)要处理的声明B::f2,但为了知道类型,我们需要知道的是什么noexcept说明符的B::f是(因为现在是这样的类型系统的一部分),但是为了做那,我们需要在完整的上下文中评估noexcept-specifierB.
该计划格式不正确,铿锵是正确的.
我将参考所有相关资源亲自回答这个问题。
让我引用 Richard Smith 来论证为什么这是一个缺陷,以及为什么所有示例都是格式错误的,因为异常规范仅在类末尾进行解析。
Clang 拒绝该代码大致是正确的。
根据 C++ DR1330,异常规范在我们到达类末尾之前不会被解析(它们可以命名稍后声明的类成员,并且类在其中完成),就像成员函数体、默认成员初始值设定项和默认参数一样。
最后,还有 C++ DR361(遗憾的是,在提交 16 年后仍然开放),其中 CWG 的结论是,如果您在课程结束之前使用延迟解析构造,则程序的格式不正确。但我们还没有实际的标准措辞来支持这一点,只是一个如果不修复该缺陷就无法实现的标准。
LLVM Bug 37559,还请参阅Google Groups、CWG 361、CWG 1330
此外,noexcept原则上应该完全等价noexcept(true)于 [ except.spec] 中所述,并且接受noexcept但拒绝显然是错误的noexcept(true)。
因此,结论是所有示例都是格式错误的,即使这不是所需的行为。
| 归档时间: |
|
| 查看次数: |
207 次 |
| 最近记录: |