为何noexcept(true)失效而noexcept可行?编译差异与标准合规性问询
C++类内条件noexcept异常规范的编译器行为差异
代码示例
原始代码:
struct S { // 依赖foo() noexcept属性的条件异常规范 void bar() noexcept(noexcept(foo())); // 条件异常规范(true) void foo() noexcept(true); };
编译差异
- Clang编译报错:
<source>:2:34: error: exception specification is not available until end of class definition 2 | void bar() noexcept(noexcept(foo())); |
- GCC允许编译通过。
将foo()的异常说明符从noexcept(true)替换为noexcept后,两款编译器均能正常编译。
问题
- 为何
noexcept(true)会导致编译失败,而noexcept可以正常工作? - 两款编译器中谁的行为符合C++标准?
解答
问题1解答
要区分noexcept作为异常说明符的两种形式:
- 无参的
noexcept:这是C++标准规定的特殊写法,隐式等价于noexcept(true),但在类成员声明场景中,它被视为"预确定"的异常说明符,允许在类内后续成员声明完成前被前面的成员引用查询其noexcept属性。 - 显式的
noexcept(常量表达式):这种形式的异常说明符需要成员的完整声明(包括该表达式)确定后,其noexcept属性才能被查询。在类定义内部,成员是按顺序声明的,当bar()尝试查询foo()的noexcept属性时,foo()的显式noexcept(true)声明尚未完成(类定义未结束),编译器无法获取该属性,因此报错。
问题2解答
Clang的行为符合C++标准。
根据C++标准,类定义内部,对于尚未声明完成的成员函数,只有当它的异常说明符是**无参的noexcept**时,才能被前面的成员引用查询其noexcept属性;显式的noexcept(常量表达式)属于需要完整声明才能确定的属性,在类内前面的成员中无法引用后面成员的此类异常说明符。GCC的实现属于宽松处理,允许了标准不允许的场景。
内容的提问来源于stack exchange,提问作者Jan Schultke
相关产品推荐
相关产品推荐

