2013-06-18 28 views
16

考虑下面的程序:克++ - 4.8.1认为,没有例外规范的明确声明的析构函数总是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.1,有一个静态断言失败上Explicit - 它似乎认为~Explicit()noexcept。这与我的预期不符。据§12.4.3:

不具有异常规格析构函数的声明是隐含 认为具有相同的异常规格为隐式声明

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

...如果˚F是...析构函数......这是隐含的异常规范规定... 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)


更新:我开了一个bug这个:57645。如果你真的需要解决这个问题,你可以添加一个异常规范到析构函数中(例如Thrower)。

+0

这就是Andy Prowl如何用1000 + upvotes写出答案。 – 2013-06-18 20:06:51

+0

@ H2CO3:lol,不,我只是觉得这是一个编译器bug,我没有机会说任何与之相关的东西;) –

回答

7

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

因为它有一个错误?

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

f有异常规范noexcept(true)如果每次调用直接作用允许没有例外。

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

§12.4 [class.dtor] p8

执行析构函数的主体和破坏人体内分配的任何自动对象,类析构函数之后X调用X的直接非变体非静态数据成员的析构函数,[...]。

+2

哦,是的,请提交一个bugreport [在GCC的bugtracker上](http:// gcc。 gnu.org/bugzilla/)。 – Xeo

+0

我希望我错了,而不是编译器......这是一个更舒适的事情。我打开了一个错误。 –