noexcept,继承构造函数和对实际上完整的不完整类型的无效使用
noexcept, inheriting constructors and the invalid use of an incomplete type that is actually complete
我不确定这是 GCC 编译器的错误还是 noexcept
.
的预期行为
考虑以下示例:
struct B {
B(int) noexcept { }
virtual void f() = 0;
};
struct D: public B {
using B::B;
D() noexcept(noexcept(D{42})): B{42} { }
void f() override { }
};
int main() {
B *b = new D{};
}
如果删除 noexcept
,它会编译。
无论如何,就像在示例中一样,我从 GCC v5.3.1 得到了这个错误:
test.cpp:8:31: error: invalid use of incomplete type ‘struct D’
D() noexcept(noexcept(D{42})): B{42} { }
^
据我所知,struct D
不是一个不完整的类型,但是声明中涉及继承构造函数,看起来编译器实际上正在考虑基本结构的完整性 B
超过 D
.
这是预期行为还是合法代码?
为了清楚起见:
有关 GCC 编译器的 bugzilla,请参阅 this link 了解更多详细信息。
目前,该错误仍未得到证实。我会尽快更新问题。
您的代码是合法的,即使 GCC 另有声明。它冒犯了这个看起来很滑稽的声明:
D() noexcept(noexcept(D{42}));
最外层的 noexcept
是一个 noexcept specifier, stating that D::D()
is noexcept if and only if its constant-expression argument evaluates to true. The inner noexcept
is a noexcept operator,它在编译时检查其参数表达式(实际上未计算)是否不抛出异常。因为D::D(int)
是noexcept(继承自B),所以应该是这样。
cppreference.com 明确指出允许在说明符内使用运算符(强调已添加):
The noexcept operator performs a compile-time check that returns true if an expression is declared to not throw any exceptions.
It can be used within a function template's noexcept specifier to declare that the function will throw exceptions for some types but not others.
现在,由于标准的 §9.2.2(添加了粗体强调),在 noexcept 说明符中 class 应被视为 complete:
A class is considered a completely-defined object type (3.9) (or complete type) at the closing }
of the class-specifier. Within the class member-specification, the class is regarded as complete within function bodies, default arguments, using-declarations introducing inheriting constructors (12.9), exception-specifications, and brace-or-equal-initializers for non-static data members (including such things in nested classes). Otherwise it is regarded as incomplete within its own class member-specification.
§15.4.1 将 异常规范 定义为以下语法:
exception-specification:
dynamic-exception-specification
noexcept-specification
所以 GCC 不应该拒绝你的代码。
我不确定这是 GCC 编译器的错误还是 noexcept
.
的预期行为
考虑以下示例:
struct B {
B(int) noexcept { }
virtual void f() = 0;
};
struct D: public B {
using B::B;
D() noexcept(noexcept(D{42})): B{42} { }
void f() override { }
};
int main() {
B *b = new D{};
}
如果删除 noexcept
,它会编译。
无论如何,就像在示例中一样,我从 GCC v5.3.1 得到了这个错误:
test.cpp:8:31: error: invalid use of incomplete type ‘struct D’
D() noexcept(noexcept(D{42})): B{42} { }
^
据我所知,struct D
不是一个不完整的类型,但是声明中涉及继承构造函数,看起来编译器实际上正在考虑基本结构的完整性 B
超过 D
.
这是预期行为还是合法代码?
为了清楚起见:
有关 GCC 编译器的 bugzilla,请参阅 this link 了解更多详细信息。
目前,该错误仍未得到证实。我会尽快更新问题。
您的代码是合法的,即使 GCC 另有声明。它冒犯了这个看起来很滑稽的声明:
D() noexcept(noexcept(D{42}));
最外层的 noexcept
是一个 noexcept specifier, stating that D::D()
is noexcept if and only if its constant-expression argument evaluates to true. The inner noexcept
is a noexcept operator,它在编译时检查其参数表达式(实际上未计算)是否不抛出异常。因为D::D(int)
是noexcept(继承自B),所以应该是这样。
cppreference.com 明确指出允许在说明符内使用运算符(强调已添加):
The noexcept operator performs a compile-time check that returns true if an expression is declared to not throw any exceptions.
It can be used within a function template's noexcept specifier to declare that the function will throw exceptions for some types but not others.
现在,由于标准的 §9.2.2(添加了粗体强调),在 noexcept 说明符中 class 应被视为 complete:
A class is considered a completely-defined object type (3.9) (or complete type) at the closing
}
of the class-specifier. Within the class member-specification, the class is regarded as complete within function bodies, default arguments, using-declarations introducing inheriting constructors (12.9), exception-specifications, and brace-or-equal-initializers for non-static data members (including such things in nested classes). Otherwise it is regarded as incomplete within its own class member-specification.
§15.4.1 将 异常规范 定义为以下语法:
exception-specification:
dynamic-exception-specification
noexcept-specification
所以 GCC 不应该拒绝你的代码。