2017-10-12 24 views
4

這MWE可能會出現人爲後會失敗,但失敗的static_assert是令人驚訝的仍然:noexcept操作的調用指針到成員函數

#include <utility> 

struct C { 
    void f() noexcept { } 
    using F = void(C::*)(); 

    static constexpr F handler() noexcept { 
    return &C::f; 
    } 

    void g() noexcept(noexcept((this->*handler())())) { 
    } 
}; 

int main() { 
    static_assert(noexcept(std::declval<C>().g())); 
} 

Wandbox鏈接:https://wandbox.org/permlink/a8HSyfuyX1buGrbZ

我希望它可以工作在鏘但不是GCC由於其不同的治療方法「這個」在運營商noexcept的情況下。

+0

什麼是你的問題? – aschepler

+0

如果其中一個答案回答你的問題,你能接受它。如果兩人都沒有回答你的問題,你能解釋一下爲什麼這麼說,我們可以提高我們的答案? – Justin

+0

很抱歉,很長的延遲;我對答案不滿意,但我會接受一個答案,因爲他們回答了這個問題。但是,在我的情況下,「f」是庫的用戶傳遞的模板參數,所以我需要查詢函數類型的noexcept-ness以正確地聲明指向成員函數的noexcept說明符。不幸的是,即使我添加noexcept到類型別名,它也不會編譯,因爲我的F別名是模板化的,這會導致內部編譯器錯誤。我會發布關於這個的Clang bug。 – Jackie

回答

7

鑑於你static_assert沒有字符串參數,您使用的是C++ 17。在C++ 17中,noexcept成爲類型系統的一部分。這意味着,給定:

using F = void(C::*)(); 

這PMF不是noexcept。調用它相當於調用noexcept(false)成員函數。您需要標記功能類型爲noexcept

using F = void(C::*)() noexcept; 

這一變化讓你的代碼編譯:

#include <utility> 

struct C { 
    void f() noexcept { } 
    using F = void(C::*)() noexcept; 

    static constexpr F handler() noexcept { 
    return &C::f; 
    } 

    void g() noexcept(noexcept((this->*handler())())) { 
    } 
}; 

int main() { 
    static_assert(noexcept(std::declval<C>().g())); 
} 

On Godbolt

3

fnoexcept,但指針是不。所以在g定義,this->*handler()返回PMF這是不noexcept(即使你碰巧返回MF的地址noexcept,所以當你調用寫(this->*handler())()那麼你調用一個函數,而不是noexcept,所以noexcept條款有返回false

添加noexcept至5行的結束,它的工作原理。