2017-10-12 54 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行的结束,它的工作原理。