SFINAE在不可特化的std模板上是格式错误的吗?
以下是否合法?
template<typename T>
std::enable_if_t<false, T> foo() {}
通常,我们有[temp.res]
程序格式错误,无需诊断,如果:
- 无法为模板生成有效的专业化 [...] 并且模板未实例化 [...]
显然,不能为foo...生成有效的特化,除非您认为它std::enable_if可能被特type化为void无论第一个bool参数如何都存在。
struct S {};
template<bool B>
struct std::enable_if<B, S> : std::type_identity<void> {};
除非......你不能专注std::enable_if通过[meta.rqmts]
除非另有说明,为 [meta] 中指定的任何模板添加专业化的程序的行为是未定义的。
总而言之,如果您编写了一个模仿的自定义enable_ifstd::enable_if,则第一个片段是合法的。问题是禁止专攻是否std::enable_if使其违法?
这篇文章的灵感来自这个答案。当前形式改编自独立库的实现。
回答
问题是禁止专攻是否
std::enable_if使其违法?
我会说是的,确实如此。首先,由于这种专业化会导致未定义的行为,我们可以完全忽略这种情况发生的可能性。合同在那里被违反,所以进一步讨论合法性是没有实际意义的1。
现在,由于我们根本不必担心专业化,我们(作为试图确定程序/实现行为的人)可以依赖于标准中描述的行为。的描述std::enable_if指定::type当它的 bool 参数为 时它没有成员false。所以我们保证std::enable_if<false, T>::type总是格式错误的。
这导致不可避免地满足 [temp.res]/8 中的标准。而现在的方案是形成不良的NDR。
1 - 毕竟这就是您引用的 [meta] 子句的目的。它允许对标准库组件的行为进行假设。具体来说,以便实现可以围绕所述预期行为进行优化。