SFINAE 的 unspecializable std 模板是否格式错误?

Is SFINAE on unspecializable std templates ill-formed?

以下合法吗?

template<typename T>
std::enable_if_t<false, T> foo() {}

通常,我们有[temp.res]

The program is ill-formed, no diagnostic required, if:

  1. no valid specialization can be generated for a template [...] and the template is not instantiated [...]

显然,无法为 foo 生成有效的特化...除非您认为 std::enable_if 可能被特化使得 type 呈现为 void不管第一个 bool 参数。

struct S {};
template<bool B>
struct std::enable_if<B, S> : std::type_identity<void> {};

除了...您不能通过 [meta.rqmts]

std::enable_if 进行专业化

Unless otherwise specified, the behavior of a program that adds specializations for any of the templates specified in [meta] is undefined.

总而言之,如果您编写了模仿 std::enable_ifcustom enable_if,第一个片段是合法的。问题是禁止专业化 std::enable_if 是否使其成为非法?

此 post 的灵​​感来自 答案。当前形式改编自一个独立库的实现。

The question is whether the prohibition on specializing std::enable_if makes it illegal?

我会说是的,确实如此。对于初学者来说,由于这种专业化会导致未定义的行为,我们可以完全忽略这种情况发生的可能性。那里违反了合同,因此进一步讨论合法性是没有意义的1.

现在,由于我们根本不必担心专业化,我们(作为试图确定 program/implementation 行为的人)可以依赖标准中描述的行为。 std::enable_if 的描述指定当其 bool 参数为 false 时它没有 ::type 成员。所以我们保证 std::enable_if<false, T>::type 总是病式的。

这导致不可避免地满足 [temp.res]/8 中的条件。 现在程序是格式错误的 NDR。


1 - 这毕竟是您引用的 [meta] 子句的目的。它允许假设有关标准库组件行为的事情。具体来说,以便实现可以围绕所述预期行为进行优化。