有人可以解释为什么曾经使用方法c(T*)
和下次d<>(int*)
?方法c
和d
似乎与我相同,我无法弄清楚为什么不是同一类型的方法。
#include <iostream>
using namespace std;
template<typename T>
void c(T){ cout <<"(T)" << endl; }
template<>
void c<>(int*){ cout <<"(int*)" << endl; }
template<typename T>
void c(T*){ cout <<"(T*)" << endl; }
template<typename T>
void d(T){ cout <<"(T)" << endl; }
template<typename T>
void d(T*){ cout <<"(T*)" << endl; }
template<>
void d<>(int*){ cout <<"(int*)" << endl; }
int main(){
int i;
c(&i);
d(&i);
return 0;
}
输出:
(T*)
(int*)
答案 0 :(得分:18)
你只是偶然发现了一个丑陋的C ++部分。
编译期间的重载决策过程是关于为当前代码找到最佳重载。它是在查找阶段选择的一组函数和函数模板上执行的,旨在识别一个(且只有一个)比其他更好的重载。
对于功能模板,它们分为两组:
并且重载解析过程有两个步骤:
在你的两个例子中,最好的&#34;基础&#34;函数是c(T*)
和d(T*)
,所以这是不同的第二步。为什么?
因为要成为函数模板的特化,所以必须首先声明所述函数模板 。
因此:
c<>(int*)
是c(T)
d<>(int*)
是d(T*)
因此,当在步骤1中选择c(T*)
时,在选择d(T*)
时没有更好的专业化,d<>(int*)
是更好的专业化。
因为这很棘手,专家的推荐......不是使用功能模板专业化。它只是奇怪地与函数模板重载混合。
答案 1 :(得分:15)
template <typename T>
void c(T); // 1: function template
template <>
void c<>(int*); // 2: specialization of 1
template<typename T>
void c(T*); // 3: overload of 1
template<typename T>
void d(T); // 4: function template
template<typename T>
void d(T*); // 5: overload of 4
template<>
void d<>(int*); // 6: specialization of 5
// ...
int i;
c(&i); // 3 is more appropriate overload than 1
d(&i); // 5 is more appropriate overload than 4
// and it has the suitable specialization 6
图:
c d
/ \ / \
overloads 1 (3) 4 (5) |
| | | priority
specializations 2 (6) V
答案 2 :(得分:2)
重载分辨率仅选择基本模板(或非模板函数,如果有的话)。只有在确定要选择哪个基本模板并且锁定了该选择之后,编译器才会查看是否有适当的特殊化模板可用,如果是,那么专业化将被使用。
对于函数c
,专门化void c<>(int*)
用于void c(T)
重载,而d
专门化void d<>(int*)
用于void d(T*)
重载。
因此,通过上面的解释,第一个void c(T)
被检查,并被忽略了更好的重载void c(T*)
(没有特化)被打印出来。对于d
,void d(T*)
重载也被锁定,但随后会注明专业化void d(int*)
,然后选择。