代码:
struct T { T() {} };
struct S
{
T t;
S() noexcept = default;
};
int main()
{
// S s;
}
g ++ 4.9.2接受这个没有错误或警告,但第7行的第3.6和3.7段报告:
error: exception specification of explicitly defaulted default constructor does not match the calculated one
但是,如果未注释掉行S s;
,g ++ 4.9.2现在会报告:
noex.cc: In function 'int main()':
noex.cc:12:7: error: use of deleted function 'S::S()'
S s;
^
noex.cc:7:5: note: 'S::S() noexcept' is implicitly deleted because its exception-specification does not match the implicit exception-specification ''
S() noexcept = default;
^
哪种编译器适合原始代码?
背景
g ++甚至允许将以下内容添加到main
:
std::cout << std::is_constructible<S>::value << '\n';
输出0
。我在使用clang编译一些复杂的代码时遇到了这个问题,这些代码大量使用了模板,SFINAE和noexcept。在该代码中,S
和T
是模板类;所以行为取决于S
实例化的类型。对于某些类型,Clang拒绝此错误,而g ++允许它,而SFINAE基于is_constructible
和类似特征工作。
答案 0 :(得分:17)
取决于您正在咨询的标准版本。
N3337 [dcl.fct.def.default] / p2:
明确默认的函数[...]可能有明确的 异常规范只有在隐式声明中与异常规范兼容(15.4)时才会出现。
会使原始代码格式不正确。
CWG issue 1778更改了这一点(N4296 [dcl.fct.def.default] / p3):
如果使用a声明显式默认的函数 异常规范与隐式声明中的异常规范不兼容(15.4),然后
- 如果函数在其第一个声明中明确默认,则将其定义为已删除;
- 否则,该程序格式不正确。
这意味着构造函数现在只被定义为已删除。 (上面的措辞包含了N4285所做的更改,这是一篇C ++之后的14篇论文,其中一些清理更改仅仅是编辑性的.N3936版本实质上是相同的。)
据推测,GCC实施了CWG1778的解决方案,而Clang则没有。