2013-06-18 31 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

我希望我錯了,而不是編譯器......這是一個更舒適的事情。我打開了一個錯誤。 –