2012-11-03 20 views
4

下面是我不理解如何是模板,和專門的模板

#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) 
} 

的代碼有5個函數調用calc下,所以我稱它們爲:1) - 5)根據他們的位置。

1)有道理。 0是一個整數,ival是一個整數,所以calc(T,T)被調用是有意義的。雖然我覺得我的理由是錯誤的。畢竟,它們都是雙打的,所以如果調用calc(double,double),那也是有意義的。所以在這裏尋找澄清。

2)沒有戲劇,都是雙打,打電話calc(雙,雙)。簡單。

3)fd是一個浮點數。可以調用calc(T,T)或calc(double,double)。因爲1)導致了對calc(T,T)的調用,我會假設同樣會在這裏持續下去,因爲我們再次有一個參數爲0,但是這叫做calc(double,double)。所以這使我感到困惑,特別是這與1)

4)我的第一個想法是0是一個有效的字符,所以是'J',所以它調用calc(char,char)。它可能使用普通類型的整數調用calc(T,T)。但不是,都是錯誤的,它叫calc(雙倍,雙倍)。我對這個很困惑。對我沒有意義。

5)是有道理的,但只有當我應用與4)相同的邏輯時,這在4)是錯誤的,所以如果我看到另一個使用模板的例子,我不確定什麼是什麼適用的邏輯。

所以尋找解釋爲什麼這個程序做它做的。

謝謝。

+0

在靜態綁定中,編譯器更喜歡普通的重載規則來模板專門化:只有當它無法找出對於參數在手的很好的重載時,它纔會使用後者。不過,我不能引用標準的相關部分。 – akappa

+0

如果函數模板參數不完全匹配*(即需要隱式類型轉換),則不會將該模板視爲候選項。 –

+0

@n.m .:但即使在這種情況下,編譯器也會更喜歡重載,即使它需要一些轉換才能調用它,對嗎? – akappa

回答

1

首先,當您在源代碼中寫入文字「0」時,它的類型爲「int」。當尋找要調用的函數時,編譯器會選擇最匹配的函數。如果不可用,編譯器將執行一些隱式類型轉換以使其工作。

1)兩個0和IVAL是INT

2)爲雙和雙,計算值(雙,雙)恰好

3)爲int和浮子,沒有匹配的發現相匹配,所以兩個轉換爲雙

4)對於int和炭相同,3)

5)炭和炭,鈣(焦炭,焦炭)完全匹配

1

,我建議你在01讀到:

選擇最合適的重載函數或運算符的過程稱爲重載解析。

假設f是一個重載的函數名稱。當您調用 重載函數f()時,編譯器將創建一組候選函數 。這組函數包括所有名爲f 的函數,這些函數可以從您調用f()的地方訪問。編譯器 可以包括作爲候選功能的替代表示 這些可訪問功能中的一個名稱爲f以便於過載 分辨率。

創建了一組候選函數之後,編譯器創建了一組可用函數 。這組函數是 候選函數的一個子集。每個可用函數 的參數數量與您用於調用f()的參數數量一致。

編譯器選擇最佳可行函數,函數 聲明C++運行時環境在從可用函數集調用f()時將使用f()。編譯器通過 隱式轉換序列執行此操作。隱式轉換序列是將函數 調用中的參數轉換爲函數 聲明中相應參數的類型所需的轉換序列。隱式轉換序列是排名的;一些 隱式轉換序列比其他更好。功能最好的 函數是其參數都優於或等於所有其他 可用函數的等排序隱式轉換序列的函數。編譯器將不允許編譯器能夠找到多個最佳可行函數的程序。

1,2和5都完全匹配,所以不需要轉換。

要解釋3和4,請注意,如果刪除double, double函數,則程序將無法編譯。這是因爲3和4的模板參數cannot be deduced(因爲參數類型不匹配)。因此,只有double, double函數被視爲候選函數。