以下来自CPPreference的引用很清楚:
此规则适用于函数模板的重载决策期间:当用显式指定或推导的类型替换模板参数失败时,特化将从重载集中丢弃,而不是导致编译错误。
C++17 标准(或更新版本)中声明类型推导失败不是错误的相应引用是什么?
据我所知,C++17:17.8.2 (
[temp.deduct]
) 中的第 8 段被认为是 SFINAE 的基本引用(SFINAE 是否依赖于类型推导?,“到底是什么” SFINAE 适用的 C++11 标准中提到的“直接上下文”?):
如果替换导致无效类型或表达式,则类型推导失败。无效类型或表达式是一种格式错误的类型或表达式,如果使用替换的参数编写,则需要进行诊断。 [ 注意:如果不需要诊断,则程序仍然格式错误。访问检查是作为替换过程的一部分完成的。 ——尾注] 只有函数类型及其模板参数类型的直接上下文中的无效类型和表达式才会导致推导失败。 [ 注意:类型和表达式的替换可能会产生诸如类模板专业化和/或函数模板专业化的实例化、隐式定义函数的生成等效果。此类效果不在“直接上下文”中,并且可以导致程序格式错误。 — 尾注]
人们可以这样解释,因为
an invalid type or expression is one that would be ill-formed [...] if...
,那么这意味着它实际上在这种情况下不是格式错误的。并且由于 type deduction fails
与 an invalid type or expression
,因此类型推导失败并不是格式错误的。另一个原因可能是,由于没有明确声明为错误,因此类型推导不是错误。
但是,首先,注释指出
If no diagnostic is required, the program is still ill-formed
(现在时的“是”)。此外,虽然本节中多次重复“类型推导失败”,但并没有说明当类型推导失败时会发生什么。我还在有关重载解析和候选集生成的部分中进行了搜索(因为没有其他可行的候选集会触发编译错误),但我找不到像 CPPreference 这样的明确句子:the specialization is discarded from the overload set instead of causing a compile error
。
标准中是否还缺少其他更明确的引用,指出当类型推导在模板参数推导上失败时,程序不是格式错误的?
注意:我并不是质疑行为或机制,我只是在寻找更明确的引用。
提到的引文确实是SFINAE的前半部分:
如果替换导致无效类型或表达式,则类型推导失败。无效类型或表达式是一种格式错误的类型或表达式,如果使用替换参数在同一上下文中编写,则需要进行诊断。
翻译:替换失败导致类型推导失败。
下半场是:
如果参数推导失败或者合成函数模板特化格式不正确,则不会将此类函数添加到该模板的候选函数集中。
翻译:类型推导失败导致重载集中没有对应的候选者。
注释(注释不规范)措辞有点混乱:
[注5: 如果不需要诊断,程序仍然是错误的。访问检查是作为替换过程的一部分完成的。 — 尾注]
这来自CWG 1462。这一更改的目的是明确类型推导失败(以及 SFINAE)仅考虑可诊断的格式错误。