【发布时间】:2020-07-13 11:49:09
【问题描述】:
template<typename T, typename U = T>
struct Test{};
template<typename T>
void func(Test<T>){ //#1
}
int main(){
func(Test<int>{}); //#2
}
标准中似乎没有规定提到模板参数需要默认参数的情况。
如果在参数声明中指定了初始化子句,则该初始化子句用作默认参数。默认参数将用于缺少尾随参数的调用。
在本节中,规则明确描述了何时为函数调用提供默认参数。但是,我没有在标准中找到与上面描述何时将默认参数作为模板参数提供的句子类似的引用。
如Test<T>#1。也许在#1,专业化是Test<T,T>,这只是推理。但是,标准中没有正式的术语明确描述这一点。
将默认参数作为模板参数的唯一引用在以下规则中:
temp#arg-8
当 simple-template-id 没有命名函数时,默认模板参数在需要该默认参数的值时隐式实例化。 [ 示例:
模板struct S { };
S* p; // p 的类型是 S*
U 的默认参数是实例化以形成类型 S*。 — 结束示例 ]
考虑#1 处的代码,是否需要#1 处的默认参数?如果是(这时候似乎需要,因为如果我没有为模板参数U指定默认参数,那么在#1会发生错误。见godbolt outcome),根据上面的引用,默认的模板参数需要隐式实例化,但是此时T是一个模板参数,并且这样的函数模板的定义什么都没有实例化(这只是一个函数模板定义观点)。那么,这句话是如何解释的呢?
【问题讨论】:
-
@StoryTeller-UnslanderMonica 在写这个问题之前我已经读过了。我的阅读是引用只是关于默认参数将在什么情况下隐式实例化
-
不只是。例子并非巧合。
-
我实际上没有。该标准的读者能够理解“在需要时”的情况包括未提供显式参数的情况。它还可能包含更多内容(我认为这是设计使然)。
-
函数模板定义没有实例化任何东西。这会在调用站点的模板参数推导过程中稍后发生。这可能是规范性文本与“需要时”相配的原因。
标签: c++ language-lawyer