我知道你不能部分专门化一个函数模板,我也理解典型的函数重载。
我需要帮助的地方是了解下面4个foo()函数之间的区别。我希望它们中的一些是完全相同的不同语法?
对于每个函数,是否有人能够更好地解释究竟发生了什么?它是模板特化还是重载,以及c ++编译器如何确定要调用的内容?
//(1)
template<typename T>
void foo(T t)
{
cout << "template<T> foo(T) " << endl;
}
//(2)
template<>
void foo<int*>(int* l)
{
cout << "template<> foo<int*>(int*) " << endl;
}
//(3)
template<typename T>
void foo(T* l)
{
cout << "template<T> foo(T*) " << endl;
}
//(4)
void foo(int* l)
{
cout << "normal overload foo(int*) " << endl;
}
int main()
{
int x = 0;
foo(x);
foo(&x);
return 0;
}
节目输出:
template<T> foo(T)
normal overload foo(int*)
答案 0 :(得分:5)
评论中的解释:
// the 1st primary function template, overloaded function template
template<typename T>
void foo(T t)
// full template specialization of the 1st function template with T = int*
template<>
void foo<int*>(int* l)
// the 2nd primary function template, overloaded function template
template<typename T>
void foo(T* l)
// non-template function, overloaded function
void foo(int* l)
int main()
{
int x = 0;
foo(x); // only match the 1st function template; the others take pointer as parameter
foo(&x); // call the non-template function, which is prior to templates in overload resolution
return 0;
}
详细了解overload resolution和explicit (full) template specialization。
答案 1 :(得分:1)
让我们通过第一个电话foo(x)
。
int
不能写为指针,无法推断参数,下一步
void foo(int* l);
无法隐式地将int
转换为int*
,
template<typename T>
void foo(T t);
这似乎是一个很好的匹配,就像记住它2)。下一步
template<>
void foo<int*>(int* l);
无法隐式地将int
转换为int*
,
template<typename T>
void foo(T* l)
因此,唯一可能的匹配是2),因此template<T> foo(T)
是输出。
第二个电话,foo(&x)
。
void foo(int* l);
非模板函数,它完全匹配x
的类型。让我们记住这个。
template<typename T>
void foo(T t);
很好的比赛!但前一个仍然更好,接下来
template<>
void foo<int*>(int* l);
哦,上一个模板的特殊化与该类型完全匹配,更好,但1)仍然是更好的匹配。下一步
template<typename T>
void foo(T* l)
比专业化更好,模板没有,但没有击败非模板。
最后,调用非模板函数。非模板总是比模板更好。
答案 2 :(得分:0)
foo(x)
的分辨率很容易发现,因为除了template<typename T> void foo(T t)
之外没有其他候选函数。
所以我们的问题会缩小为:为void foo(int* l)
拨打foo(&x)
为何?
template<> void foo<int*>(int* l)
,您需要致电foo<int*>(&x)
template<typename T> void foo(T* l)
致电foo<int>(&x)
template<typename T> void foo(T t)
致电foo<int*>(&x)
正如您所看到的,调用foo(&x)
与上述三种使用显式模板调用的任何风格都不匹配。
请注意,如果没有专门的函数void foo(int* l)
,函数调用foo<int*>(&x)
将由专门的模板函数 template<> void foo<int*>(int* l)
解决非专业化模板功能 template<typename T> void foo(T t)
答案 3 :(得分:0)
在尝试确定重载时调用的函数时,规则是:始终找到需要使用最少优化的函数。
当用int调用foo()时,唯一可以使用的函数是第一个,因为你不能将int转换为int *。
与int *:
一起使用时
功能4可以在没有任何优化的情况下使用
函数3需要改变T-> int以便运行
函数1需要将T更改为指针类型,并确定T指向int
功能2是功能1的专业化
所以函数4可以立即使用,函数2需要更新模板类型,函数1,2需要更新模板类型和对象类型。
所以按顺序调用它们:4然后3然后2然后1