g ++ - 4.8.1认为没有异常规范的显式声明的析构函数总是noexcept(true)

时间:2013-06-18 19:35:18

标签: c++ c++11 noexcept

考虑以下计划:

#include <type_traits>

struct Thrower
{
    ~Thrower() noexcept(false) { throw 1; }
};

struct Implicit
{
    Thrower t;
};
static_assert(!std::is_nothrow_destructible<Implicit>::value, "Implicit");

struct Explicit
{
    ~Explicit() {}

    Thrower t;
};
static_assert(!std::is_nothrow_destructible<Explicit>::value, "Explicit");

使用g++-4.8.1Explicit上存在静态断言失败 - 它似乎认为~Explicit()noexcept。这与我的期望不符。根据§12.4.3:

  

没有异常规范的析构函数的声明是隐式的   被认为具有与隐式声明相同的异常规范

这里有趣的是Implicit的检查似乎是根据我对§15.4.14的解释(通过§12.4.7)。

  

...如果 f 是...析构函数...它是隐式异常 - 规范指定...如果它直接调用的每个函数都有异常规范noexcept(true)不允许例外。

g++-4.7缺少is_nothrow_destructable,我自己编写了检查4.7中的行为。该程序似乎编译得非常好。我保留完全错误的权利和我的困惑的来源:

template <typename T>
struct is_nothrow_destructible
{
    static constexpr bool value = noexcept(std::declval<T>().~T());
};

TL; DR:为什么g++-4.8.1认为没有异常规范的显式声明的析构函数总是 noexcept(true)


更新:我在此处打开了一个错误:57645。如果您确实需要解决此问题,可以向析构函数添加异常规范(例如示例中的Thrower)。

1 个答案:

答案 0 :(得分:7)

  

TL; DR:为什么g ++-4.8.1认为没有异常规范的显式声明的析构函数总是noexcept(true)

因为它有错误吗?

您对标准的解释是正确的,Clang正确实现(断言不会触发)。

  

f具有异常规范noexcept(true)如果它直接调用的每个函数都不允许例外。

析构函数直接调用所有子对象的析构函数:

§12.4 [class.dtor] p8

  

在执行析构函数的主体并销毁正文中分配的任何自动对象之后,X的析构函数调用X的直接非变量非静态数据成员的析构函数 ,[...]。