noexcept运算符和enable_if_t:它们一起工作吗?

sky*_*ack 5 c++ gcc clang language-lawyer noexcept

考虑以下课程:

struct S {
    template<typename T>
    std::enable_if_t<std::is_void<T>::value>
    f() noexcept {}

    template<typename T>
    std::enable_if_t<not std::is_void<T>::value>
    g() noexcept {}
};
Run Code Online (Sandbox Code Playgroud)

正如所料,这编译:

s.f<void>();
Run Code Online (Sandbox Code Playgroud)

这个不是:

s.g<void>();
Run Code Online (Sandbox Code Playgroud)

让我感到困惑的是,以下内容main与GCC(6.2)编译并且不使用clang(3.9)进行编译:

int main() {
    static_assert(noexcept(&S::f<void>), "!");
    static_assert(noexcept(&S::g<void>), "!");
}
Run Code Online (Sandbox Code Playgroud)

我会说第二个断言因为无效的专门化而失败了.两位编制者对此持不同意见.

哪一个是正确的?

Col*_*mbo 3

[例外.spec]/13 :

e如果表达式e是核心常量表达式 (5.20),则该表达式的潜在异常集为空。

也就是说,GCC 甚至不解析template-id,因为它从一开始就知道结果是true(因为g<void>不是类型具有重载的静态数据成员模板专业化operator&)。虽然很聪明,但这种行为是不符合标准的,因为任何出现template-id 都需要将参数替换到函数模板的声明中。