20

编码:

struct T { T() {} };

struct S
{
    T t;

    S() noexcept = default;
};

int main()
{
//    S s;
}

g++ 4.9.2 接受了这一点,没有错误或警告,但是 clang 3.6 和 3.7 报告第 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的复杂代码时遇到了这个问题。在该代码中ST是模板类;所以行为取决于S实例化的类型。对于某些类型,Clang 会因为此错误而拒绝它,而 g++ 允许它,并且 SFINAE 基于is_constructible和类似的特征工作。

4

1 回答 1

22

取决于您咨询的标准版本。

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 没有。

于 2015-04-07T03:32:54.210 回答