使用gcc接受的"noexcept"构造函数的程序,被clang拒绝

M.M*_*M.M 15 c++ gcc clang noexcept c++11

代码:

struct T { T() {} };

struct S
{
    T t;

    S() noexcept = default;
};

int main()
{
//    S s;
}
Run Code Online (Sandbox Code Playgroud)

g ++ 4.9.2接受此但没有错误或警告,但第7行的clang 3.6和3.7报告:

error: exception specification of explicitly defaulted default constructor does not match the calculated one
Run Code Online (Sandbox Code Playgroud)

但是,如果该行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;
     ^
Run Code Online (Sandbox Code Playgroud)

哪个编译器适合原始代码?


背景:

g ++甚至允许将以下内容添加到main:

std::cout << std::is_constructible<S>::value << '\n';
Run Code Online (Sandbox Code Playgroud)

哪个输出0.我在使用clang编译一些复杂的代码时遇到了这个问题,这些代码大量使用了模板,SFINAE和noexcept.在该代码中ST是模板类; 所以行为取决于S实例化的类型.对于某些类型,Clang拒绝它有这个错误,而g ++允许它和SFINAE基于is_constructible和类似的特征工作.

T.C*_*.C. 19

取决于您正在咨询的标准版本.

N3337 [dcl.fct.def.default]/p2:

显式默认函数[...] 只有在与隐式声明的异常规范兼容(15.4)时才有明确的 异常规范.

这会使您的原始代码格式不正确.

这被CWG问题1778改为阅读(N4296 [dcl.fct.def.default]/p3):

如果明确违约函数声明有 异常规范是不兼容的(15.4)与隐式声明的异常规范,则

  • 如果函数在其第一个声明中明确默认,则将其定义为已删除;
  • 否则,该计划是不正确的.

这意味着构造函数现在只被定义为已删除.(上面的措辞包含了N4285所做的更改,这是一篇关于 C++之后的14篇论文,它做了一些纯粹的编辑修改.N3936版本实质上是相同的.)

据推测,GCC实现了CWG1778的分辨率,而Clang则没有.