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



考虑以下程序:

#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.1,在Explicit上存在静态断言失败——它似乎认为~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) ?


Update:我打开了一个bug: 57645。如果您确实需要解决这个问题,您可以向析构函数添加异常规范(就像示例中的Thrower一样)。

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

因为它有bug?

你对标准的解释是正确的,Clang正确地实现了它(assert没有触发)。

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

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

§12.4 [class.dtor] p8:

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

最新更新