2017-04-11 96 views
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);  

是整数,其是远离双远不同?

+1

'为什么我需要这样做?':你不需要。 '为什么这样编译?':'T'被设置为'long'。 “长”可以隐式转换为“双”。它和'double v = m'一样; – 101010

回答

3

在这种情况下,你可以认为模板instantation是一个简单的文本替换(这并不是说远非如此),那就是一旦你的模板参数想通了。所以:

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

搞清楚模板参数后,置换制作,所以你的函数看起来像:

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

它得到compilcated,当您使用多个参数,并与继承等,等许多可能的匹配。

对于你的情况,你可以挑起等于比赛,通过使用两种不同类型的PARAMS即:GetMax(i,l)T有两个候选人:doubleint,都一样好。

这关系到著名SFINAE(取代故障不是错误)。编译器会尝试为可能的参数组合生成版本,如果失败,则不考虑最终排名。在你的情况下,两个替代是成功的。

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

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

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

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

这是法律给int通过使用double函数,隐式转换会发生。

这是完全合法的:

void f(double d) {}; 

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

底线:

搞清楚模板类型是不同的逻辑块不是调用的功能。把它看作是分开的阶段。类型演绎的目的是为了对调用有意义,但它是一个单独的事情。

+0

作为一个小的补充:如果参数是不同类型的(例如'getMax(i,l)'),那么自动类型演绎将会失败,你将得到一个编译器错误。在这种情况下,您需要使类型以某种方式显式进行编译(通过将参数转换为通用类型或通过明确指定模板类型来进行编译,就像您在案例2和3中所做的那样)。 – ComicSansMS

+0

是的,因为有两个可能的候选人同样适合替代。我将编辑1.提及它。 – luk32

+0

是否正确,如果我打电话GetMax (a,b)时省略? –

0

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

而第二个问题中扣除,没有任何错误,因为整数回退优雅翻一番,所以他们将被转换并作为双您的模板逻辑。

相关问题