1

通过使用模板:

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是与双精度相差甚远的整数时?

4

2 回答 2

3

在这种情况下,您可以认为模板实例化是一种简单的文本替换(离它不远),即一旦您确定了模板参数。所以:

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

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

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

当您使用多个参数并且与继承等有许多可能的匹配时,它确实会变得复杂。

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

这和著名的SFINAE有关(替换失败不是错误)。编译器尝试为可能的参数组合生成版本,如果失败,则不考虑最终排名。在你的情况下,两次换人成功。

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

  2. 您明确声明 T in double。同样,编译器不会调用任何关于类型的逻辑。

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

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

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

这是完全合法的:

void f(double d) {};

int main(){
    int i = 5;
    f(i);
}

底线:

找出模板类型与调用函数是不同的逻辑。将其视为单独的阶段。类型推导旨在使调用有意义,但它是另一回事。

于 2017-04-11T10:38:43.577 回答
0

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

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

于 2017-04-11T10:38:32.410 回答