我刚刚学习函数模板,我想研究一下函数模板实例化的一些规则。所以我写了下面的代码:
#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&lt;”double“&gt;”调用模板实例化机制,因此实际创建了“int check(int)”函数(模板参数的类型没有没有任何影响力。 当#3启用时,我有一个编译错误“错误:没有匹配函数来调用'check(int)'”,这是合理的,因为我试图调用“ check(int)“不存在的函数。我的问题是关于#2的情况:在这种情况下,我得到相同的“错误:没有匹配函数来调用'check(int)'”。不应该调用“check&lt;&gt;(10)”触发模板实例化机制吗?
答案 0 :(得分:1)
您不会在&lt;&gt;中放置任何模板参数。编译器如何知道要实例化哪个模板函数?请注意您的模板功能是:
template <typename>
int check(int x)
如果您将其更改为:
template <typename T>
int check(T x)
然后检查&lt;&gt;(10)应该没问题,因为编译器可以从参数中知道类型。
答案 1 :(得分:0)
如果没有传递模板参数,它等同于在没有模板参数的情况下查找函数(即它不实例化模板)。添加的<>
在这种情况下没有任何意义,因为没有重载。
由于你所拥有的函数实际上并没有将模板用于任何东西,因此编译器无法推断类型T,但如果你这样写:
template <typename T>
T check(T x) {
return x * 2;
}
然后所有3个案例都可以使用,因为它推断出类型T
。有关详细说明,请参阅https://stackoverflow.com/a/797632/888641。
注意:您可以使用typename
或class
,他们会在此处执行完全相同的操作。
答案 2 :(得分:0)
我不得不说通常模板不会这样:(
试试这个:
template<typename T>
T check(T x){
return x*2;
}
答案 3 :(得分:0)
#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>();
}
答案 4 :(得分:0)
您将获得的唯一模板实例化是
check<double>(10)
其他人不会实例化模板。此外,功能模板的全部功能还包括模板参数
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>