2017-04-11 139 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

您可以省略模板函數的類型,因爲它們是在編譯時

而第二個問題中扣除,沒有任何錯誤,因爲整數回退優雅翻一番,所以他們將被轉換並作爲雙您的模板邏輯。