C++ 当函数模板参数是具有默认参数的类模板时,模板参数推断如何执行 模板 结构测试{}; 模板 无效函数(测试){/#1 } int main(){ func(Test{});/#2 }
考虑上述代码,在调用函数模板C++ 当函数模板参数是具有默认参数的类模板时,模板参数推断如何执行 模板 结构测试{}; 模板 无效函数(测试){/#1 } int main(){ func(Test{});/#2 },c++,templates,language-lawyer,C++,Templates,Language Lawyer,考虑上述代码,在调用函数模板func时,参数类型为Test,调用函数模板时,将执行模板参数推断 函数调用的模板参数推断规则为: 模板参数推导是通过将包含参与模板参数推导的模板参数的每个函数模板参数类型(称为p)与调用的相应参数类型(称为A)进行比较来完成的,如下所述 我很确定A的类型是Test,但是我不确定p的类型是什么。是Test还是Test,根据规则,似乎P的类型是Test,然后执行演绎过程以确定参与模板参数演绎的T的值。然后根据这些规则描述如下: 一般来说,演绎过程试图找到模板参数值,
func
时,参数类型为Test
,调用函数模板时,将执行模板参数推断
函数调用的模板参数推断规则为:模板参数推导是通过将包含参与模板参数推导的模板参数的每个函数模板参数类型(称为p)与调用的相应参数类型(称为A)进行比较来完成的,如下所述 我很确定
A
的类型是Test
,但是我不确定p
的类型是什么。是Test
还是Test
,根据规则,似乎P
的类型是Test
,然后执行演绎过程以确定参与模板参数演绎的T
的值。然后根据这些规则描述如下:
一般来说,演绎过程试图找到模板参数值,使演绎的A与A相同(在类型A如上所述转换后)
当从默认模板参数推导或获取所有模板参数时,模板和函数类型的模板参数列表中模板参数的所有使用都将替换为相应的推导或默认参数值
因为类模板Test
有一个默认参数,因此推导出的T
被替换为默认参数。这意味着导出的A
是Test
,它与参数类型Test
相同
然而,这只是我的理解。我不确定这里的P
是什么类型的。如果将函数参数的类型更改为测试
,则将报告:
candidate template ignored: deduced conflicting types for parameter 'T' ('int' vs. 'double')
结果看起来好像p
是Test
,并且T
的第一个值与T
的第二个值冲突
所以,我的问题是:
这里的
p
是Test
还是Test
?为什么呢?我试着想出一个只强制进行类推导而不强制进行函数推导的代码。此处没有函数实例化,但编译器仍会发出错误:
template<typename T, typename U = T>
struct Test{};
template<typename T>
void func(Test<T, T>){
}
template<typename T>
void func(Test<T>){
}
模板
结构测试{};
模板
无效函数(测试){
}
模板
无效函数(测试){
}
重新定义“模板无效功能(测试)”
GCC:叮当声: 先前的错误答案: p是模板参数,而不是模板本身。在声明
Test
P指的是T,而不是Test。因此在实例化Test
T是int,就像调用中的A也是int一样
没有语言律师的回答
没有类型Test
实际上是Test
的“速记”
就像默认函数参数一样,如果你有
intfoo(inta,intb=24)
函数的类型是int(int,int)
,任何像foo(11)
这样的调用实际上都是foo(11,24)
p
必须是类型而不是模板test
是一个模板id,但标准中没有明确说明模板idtest
等同于test
。唯一要说的是:
模板id在以下情况下有效:
- [……]
- 每个不可推断的非打包参数都有一个参数,该参数没有默认的模板参数[…]
p
是Test
还是Test
?为什么
p
是Test
我认为我们可以同意,规则也适用于类模板;e、 g.涉及类模板专门化的偏序,完全基于将类模板重新写入(发明的)函数模板的概念,并将函数模板的规则应用于偏序分析下与原始类模板相对应的发明函数模板的规则。与函数模板相比,类模板的标准段落非常简短,结合这一事实,我认为下面的参考文献也适用于类模板 现在,从[强调我的]: 引用函数模板专用化时,所有模板参数应具有值。可以明确指定值,或者在某些情况下,可以从使用中推断出值,或者从默认的模板参数中获得值。[……] 从[强调我的]: 指定显式模板参数列表时,模板参数必须与模板参数列表兼容,并且必须产生如下所述的有效函数类型;否则类型扣除失败。具体而言,在针对给定函数模板计算显式指定的模板参数列表时,将执行以下步骤:
- (2.1)指定的模板参数必须与实物模板参数相匹配(即类型、非类型、模板)。除非[…],否则参数的数量不得超过参数的数量
func(Test<int>{});
func(Test<int, int>{});
// (Ex1)
template<typename T, typename U = T>
struct Test{};
template<typename T>
void func(Test<T>) {}
int main() {
func(Test<int, double>{});
}
// (Ex2)
struct Foo {};
template<typename T> struct Test {};
template<typename T> void f(T) {}
int main() {
f<Test<int>>(Test<Foo>{});
}
// (Ex1)
// GCC
error: no matching function for call to 'func(Test<int, double>)'
note: template argument deduction/substitution failed:
deduced conflicting types for parameter 'T' ('int' and 'double')
// Clang
error: no matching function for call to 'func'
note: candidate template ignored: deduced
conflicting types for parameter 'T' ('int' vs. 'double')
// (Ex2)
// GCC
error: could not convert 'Test<Foo>{}' from 'Test<Foo>' to 'Test<int>'
// Clang
error: no matching function for call to 'f'
note: candidate function template not viable:
no known conversion from 'Test<Foo>' to 'Test<int>' for 1st argument
template<typename T, typename U = T>
struct Test{};
template<typename T>
void func(Test<T>) {}
int main() {
func<int>(Test<int, double>{});
}