何时提供默认参数作为模板参数

jac*_*k X 5 c++ language-lawyer

template<typename T, typename U = T>
struct Test{};
template<typename T>
void func(Test<T>){  //#1
}
int main(){
  func(Test<int>{});  //#2
}
Run Code Online (Sandbox Code Playgroud)

标准中似乎没有规则提到模板参数需要默认参数的情况。

dcl.fct.default#1 中

如果在参数声明中指定了初始值设定项子句,则该初始值设定项子句用作默认参数。默认参数将用于缺少尾随参数的调用。

在本节中,规则明确描述了何时为函数调用提供默认参数。但是,我还没有在标准中找到与上述句子类似的引用,该引用描述何时提供默认参数作为模板参数。

比如Test<T>#1。也许在#1,专业化将是Test<T,T>,这只是推理。但是,标准中没有正式的术语明确描述这一点。

将默认参数作为模板参数的唯一引用是在以下规则中:
temp#arg-8

当 simple-template-id 未命名函数时,默认模板参数在需要该默认参数的值时被隐式实例化。[?示例:
template<typename T, typename U = int> struct S { };
S<bool>* p; // p 的类型是 S<bool, int>*
U 的默认参数被实例化以形成类型S<bool, int>*。?—?结束示例?]

考虑 at 的代码#1,默认参数需要 at#1吗?如果是(在那个时候似乎需要,因为如果我没有为模板参数 U 指定默认参数,那么此时#1会发生错误。参见Godbolt 结果),根据上面的引用,默认模板-argument 需要被隐式实例化,然而此时,它T是一个模板参数,并且这种函数模板的定义没有实例化(此时只是一个函数模板定义)。那么,引述如何解释这一点?

Oli*_*liv 2

[temp.names]里面还有这一段:

模板 ID 有效,如果

  • 每个没有默认模板参数的不可推导的非包参数都有一个参数,

因此,人们可以认为需要默认参数意味着需要默认参数才能使 template-id 有效,并且当缺少模板参数时,该参数是默认参数值。但我没有在类模板的标准中找到任何明确的内容。对于函数模板来说,这是更明确的。可能没有人指出标准中的这个漏洞,因为这是一种常见模式:使用默认值代替用户未提供的内容。也许它不会改变,因为英语词典中已经给出了default的定义:

它。如果你不做出任何不同的选择,某件事将自动发生或出现的方式,尤其是在计算机上——剑桥在线词典