我正在学习函数模板,我想研究一下函数模板实例化的一些规则。所以我写了下面的代码:
#include <iostream>
template <typename>
int check(int x) {
return x * 2;
}
int main() {
std::cout << check<double>(10) << std::endl; // #1
std::cout << check<>(10) << std::endl; // #2
std::cout << check(10) << std::endl; // #3
return 0;
}
#1、#2和#3行没有一起编译,每次尝试我只留下其中一行,并注释其余的。因此,当启用#1时,我没有编译错误,并且打印了正确的答案"20"。据我所知,"check<"double">"调用模板实例化机制,所以"函数被真正创建(模板参数的类型没有任何影响)。当#3启用时,我有一个编译错误"错误:没有匹配的函数来调用'check(int)'",这是合理的,因为我试图调用"check(int) "函数不存在。我的问题是关于#2的情况:在这种情况下,我得到相同的"错误:没有匹配的函数调用'check(int)'"。不应该调用"check<>(10)触发模板实例化机制?
不要在<>中放置任何模板参数。编译器如何知道实例化哪个模板函数?请注意你的模板函数是:
template <typename>
int check(int x)
如果你把它改成这样:
template <typename T>
int check(T x)
then check<>(10)应该没问题,因为编译器可以从参数中知道类型。
我不得不说通常模板不会那样做:(
试试这个:
template<typename T>
T check(T x){
return x*2;
}
您将获得的唯一模板实例化是使用
check<double>(10)
其他的不实例化模板。此外,要获得函数模板的全部功能,请将template参数包含为
template<typename T>
T check(T x) {
return x*2;
}
然后使用模板参数演绎的力量,你可以调用
check(10.0); // instantiates check<dobule>
check(3); // instantiates check<int>
或
a = MyObject();
check(a); // instantiates check<MyObject>
#2
在模板参数可以推导的情况下是有效的。
#include <iostream>
template <class T>
void foo(T t)
{
std::cout << "Template " << t << 'n';
}
void foo(int n)
{
std::cout << "Not template " << n << 'n';
}
int main()
{
foo(10); //calls non-template function
//because matching non-template preferred over function templates
foo<>(10); //calls the template function, empty brackets indicate you want
//the template overload, type is deduced from passed argument.
}
另一种可能,如果函数模板有默认实参(仅在c++ 11中合法)。
template <class T = void>
int foo()
{
return 10;
}
int main()
{
return foo<>(); //same as foo<void>();
}
如果你不传递模板参数,这相当于寻找没有模板参数的函数(即它没有实例化模板)。在这种情况下,添加的<>
没有任何意义,因为没有超载。
因为你的函数实际上没有使用模板做任何事情,编译器因此不能推断类型T,但是如果你这样写:
template <typename T>
T check(T x) {
return x * 2;
}
那么所有3种情况将工作,因为它推断类型T
。详见https://stackoverflow.com/a/797632/888641
注意:您可以使用typename
或class
,它们在这里做完全相同的事情。