考虑以下课程:
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 {}
};
正如所料,这编译:
s.f<void>();
这个不是:
s.g<void>();
让我感到困惑的是,以下main
与GCC(6.2)编译并且不与clang(3.9)编译:
int main() {
static_assert(noexcept(&S::f<void>), "!");
static_assert(noexcept(&S::g<void>), "!");
}
我会说第二个断言失败是因为无效的专业化。两位编制者对此持不同意见。
哪一个是正确的?
答案 0 :(得分:3)
如果
e
为a,则表达式e
的潜在异常集为空 核心常数表达式(5.20)。
也就是说,GCC甚至不解析 template-id ,因为它从一开始就知道结果是true
(因为g<void>
不是静态数据成员模板特化,其类型具有重载operator&
)。虽然聪明,但行为是不一致的,因为任何出现的 template-id 都需要将参数替换为函数模板的声明。