我正在学习c ++中的模板,并且找到了以下示例。
据我了解,如果没有匹配的非模板函数,则编译器应始终尝试使用最“专业化”的模板,但是在此示例中,第一次调用导致调用函数a(T *)而不是a(int *)。为什么?为什么第二通电话的行为有所不同?
template<typename T>
void a(T) {cout << "(T)" << endl;}
template<>
void a<>(int*) {cout << "(int)" << endl;}
template<typename T>
void a(T*) {cout << "(T*)" << endl;}
template<typename T>
void b(T) {cout << "(T)" << endl;}
template<typename T>
void b(T*) {cout << "(T*)" << endl;}
template<>
void b<>(int*) {cout << "(int)" << endl;}
int main()
{
int i;
a(&i);
b(&i);
return 0;
}
结果输出为:
(T*)
(int)
我希望它是:
(int)
(int)
答案 0 :(得分:6)
仅考虑主模板(因此无需专门化)来选择更多专门化的重载。
一旦选择了主模板,我们就会使用专业化。
现在,template<> void a<>(int*);
只能是template<typename T> void a(T)
的专业化版本(尚未看到其他版本)。
和template<> void b<>(int*);
是template<typename T> void b(T*)
的专业化(这是更专业的匹配重载)。
请注意,您可以通过提供模板而不是让编译器推论来选择b
的特化:
template<> void b<>(int*)
-> template<typename T> void b(T*) with T=int
template<> void b<int>(int*)
-> template<typename T> void b(T*) with T=int
template<> void b<int*>(int*)
-> template<typename T> void b(T) with T=int*
如此:
int i;
a(&i); // a<T*> with T=int*, no specialization for a<U*> (U=int) exist -> generic template called
b(&i); // b<T*> with T=int*, specialization for b<U*> (U=int) exists -> specialization called
答案 1 :(得分:2)
由于声明顺序的不同,专业化属于不同的主模板。
对于第一种情况,专业化属于a(T)
。对于第二种情况,专业化属于b(T*)
。在主模板之间的重载解析期间,始终选择采用T*
的版本;那么在第一种情况下,将不会考虑专业化,因为它不是a(T*
的专业化。但这是在第二种情况下选择的,因为b(T*)
具有专业性。
即
第一种情况
超载
第二种情况
超载