【发布时间】:2012-10-23 19:52:34
【问题描述】:
这是我不理解的代码
#include<iostream>
using namespace std;
template <typename T>
T calc(T, T) { cout << "template calc" << endl; }
double calc(double, double) { cout << "ordinary calc" << endl; }
template <>
char calc<char>(char, char) { cout << "template specialisation calc" << endl; }
int main() {
int ival;
double dval;
float fd;
calc(0, ival); // calls the generic calc(T, T)
// the following all call calc(double, double)
calc(0.25, dval);
calc(0, fd);
calc(0, 'J');
calc('I', 'J'); // calls calc(char, char)
}
calc 有 5 个函数调用,所以我将它们称为 1) - 5),具体取决于它们的位置。
1) 有点道理。 0 是整数,ival 是整数,调用 calc(T, T) 是有意义的。尽管如此,我觉得我对此的推理是错误的。毕竟,它们都是双精度数,所以如果调用 calc(double, double),那也是有意义的。所以在这里寻求澄清。
2) 没有戏剧,都是双打,调用 calc(double, double)。很简单。
3) fd 是一个浮点数。可以调用 calc(T, T) 或 calc(double, double)。因为 1) 导致了对 calc(T, T) 的调用,所以我假设这里也是如此,因为我们再次有一个参数为 0,但是,这调用了 calc(double, double)。所以这让我很困惑,特别是 this 和 1) 之间的区别
4) 我的第一个想法是 0 是有效字符,'J' 也是如此,所以它调用 calc(char, char)。它可能会使用常见的整数类型调用 calc(T, T)。但是不,两者都错了,它调用 calc(double, double)。我对这个很困惑。对我来说毫无意义。
5) 是有道理的,但前提是我应用与 4) 相同的逻辑,这在 4) 中是错误的,所以如果我要看到另一个使用模板的示例,我将不确定是什么逻辑申请。
所以寻找解释为什么这个程序会这样做。
谢谢。
【问题讨论】:
-
在静态绑定中,编译器更喜欢普通的重载规则而不是模板特化:只有当它无法确定手头的参数可以接受的重载时,它才会求助于后者。不过,我不能引用标准的相关部分。
-
如果函数模板参数不匹配完全(即需要隐式类型转换),则模板不被视为候选。
-
@n.m.:但即使在这种情况下,编译器也更喜欢重载,即使它需要一些转换才能调用它,对吧?
-
您还应该问的问题是,如果 calc(double,double) 根本不在图片中,其中有多少会编译,我的意思是专门针对第四个。试试看。
标签: c++ template-specialization