模板类型背后的意义是什么?



通过使用模板:

template <class T>
T GetMax (T a, T b) {
return (a>b?a:b);
}

然后

int main () {
int i=5, j=6, k;
long l=10, m=5, n;
k=GetMax(i,j);           // line 1
n=GetMax<int>(l,m);      // line 2
n=GetMax<double>(l,m);   // line 3
cout << k << endl; 
cout << n << endl;
return 0;
}

我的问题是:

为什么我需要这样做:

n=GetMax<int>(l,m);      // line2

如果我能做到

n=GetMax(l,m);      // line 2

为什么要编译?

n=GetMax<double>(l,m);     

lm是与双精度相差甚远的整数时?

在这种情况下,您可以认为模板实例化是一个简单的文本替换(离它不远),也就是说,一旦您弄清楚了模板参数。所以:

  1. 让编译器从操作数中找出类型。由于它们匹配,因此T被证明是int.您可以在标准中找到对匹配模板参数进行排名的确切逻辑。你的案子很简单。

找出模板参数后,进行替换,因此您的函数如下所示:

int GetMax (int a, int b) {
return (a>b?a:b);
}

当您使用多个参数并且与继承等有许多可能的匹配项时,它确实会被编译。

对于您的情况,您可以通过对参数使用两种不同类型的参数来引发相等的匹配,即:GetMax(i,l).T有两个候选者:doubleint,两者都同样好。

这与著名的SFINAE(替换失败不是错误)有关。编译器尝试为可能的参数组合生成版本,如果失败,则不考虑最终排名。在您的案例中,两个替换成功。

  1. 你明确声明 T 是int.因此,编译器不会调用自动参数匹配。实例化版本看起来与 1 相同。

  2. 您明确指出 T 在double.同样,编译器不会调用有关类型的任何逻辑。

它盲目地生成double版本,并使用它:

double GetMax (double a, double b) {
return (a>b?a:b);
}

使用doubleint传递给函数是合法的,会发生隐式转换。

这是完全合法的:

void f(double d) {};
int main(){
int i = 5;
f(i);
}

底线:

确定模板类型与调用函数是不同的逻辑。将其视为单独的阶段。类型推导旨在对调用有意义,但这是一个单独的部分。

您可以省略模板函数上的类型,因为它们是在编译时扣除

的第二个问题,没有错误,因为整数可以优雅地回退到双精度,因此它们将被转换并在模板逻辑上用作双精度。

最新更新