2017-02-19 55 views
-2

的說我有這樣的代碼:使用模板<typename>

#include <iostream> 

template<typename> 
void printnum(int i) { 

    std::cout<<"in int method:"<<std::endl; 
    std::cout<< i<<std::endl; 
} 

template<typename> 
void printnum(char i) { 

    std::cout<<"in char method:"<<std::endl; 
    std::cout<<(int)i<<std::endl; 
} 

int main() { 

    printnum<int>(2); 
    printnum<char>(3); 
} 

輸出:

in int method: 
2 
in int method: 
3 

我對這個測試代碼的意圖是要確認/未確認我的使用(自然)的認識的template<typename>模板。因爲給定的模板類型沒有參數,所以我認爲這樣的結構將有助於重載分辨率。也就是說,如果沒有模板註釋,很顯然我會得到上面的輸出。但是通過模板註釋,我可能會認爲我可能會強制編譯器(3-callprintnum()函數的char-variant(事實並非如此)。

所以我一般的問題是:template<typename>構造的用途是什麼?

+0

其用途是用一個模板參數定義一個模板:一個類。就是這樣。 「2」和「3」都是「int」,因此採用「int」參數的函數被選中。模板參數不是一個因素。 –

+0

肯定有「使用」。 C++庫中有許多模板將一個類作爲參數。 –

+0

嗯,是的,但這並沒有回答 – FloriHe

回答

1

的主要原因是允許爭論明確專門化。試想一下:

#include <iostream> 

template<typename> void printnum(int i); 

template<> 
void printnum<int>(int i) { 
    std::cout<<"in int method: "<<i<<std::endl; 
} 

template<> 
void printnum<char>(int i) { 
    std::cout<<"in char method: "<<i<<std::endl; 
} 

int main() { 
    printnum<int>(2); 
    printnum<char>(3); 
} 

這個程序打印:

in int method: 2 
in char method: 3 

它創建了由明確的模板參數選擇兩種不同的printnum(int)功能。主要用途是當您想從某個具有T類型參數的其他模板函數調用printnum<T>(int)時。

+0

謝謝,那正是我所尋找的,這是有道理的。 – FloriHe

1

你有一個家庭的功能,爲各類T,以int作爲一個參數(有Tint之間沒有連接);順便說一句,所有人都在做同樣的事情。你有另一個功能家族,所有類型爲T,以char作爲參數。

省略名稱T並未傳達功能模板上的任何神奇屬性:template <typename T> void f();template <typename> void f();完全相同。

printnum<int>(2)從第一個家族(對於T == int)和第二個家族中的一個功能實例化一個功能,並對它們執行重載解析。來自第一家庭的功能獲勝。同樣的,printnum<char>(3)


你可能會想模板特殊化的:

template <typename T> void printnum(T); 

template<> 
void printnum(int i) { 

    std::cout<<"in int method:"<<std::endl; 
    std::cout<< i<<std::endl; 
} 

template<typename> 
void printnum(char i) { 

    std::cout<<"in char method:"<<std::endl; 
    std::cout<<(int)i<<std::endl; 
} 

Demo

這裏,有功能的一個家庭。實際上只定義了這個族的兩個成員(嘗試使用任何其他實例會導致鏈接器錯誤)。模板參數明確地選擇了一個特定的家庭成員;因爲只有一個可用的函數可以調用,所以不會執行重載解析。

+0

謝謝,這是一個很好的解釋。所以通常唯一的影響是創建一個函數族,在編譯時選擇一個函數族,這與家族所有其他函數相同。但我不明白爲什麼這是有道理的。 – FloriHe

+0

它通常不會。目前還不清楚爲什麼要創建一個函數模板,而不是使用它的模板參數。 –

-1

這是因爲被調用的函數是由參數類型決定的。 23都是(文字值)int類型,所以第一個「變體」(我想不出更好的描述)被稱爲。

如果你沒有

printnum<int>('A'); 
printnum<char>('B'); 

,你會發現你的函數的第二種形式被稱爲在這兩種情況下。

無論如何,您都在濫用模板。濫用語言功能是質疑該功能價值的一個糟糕的前奏。

更有效的用法就像是;

template<typename T> 
void printnum(T i) 
{ 
    std::cout<< i << std::endl; 
} 

這將意味着

printnum(1); 
printnum("ABC"); 

將打印,隨後在不同的行的字符串ABC數字1。

如果你想做一些對int變種不同,你可以 - 前面的模板定義後 -

template<> printnum<int>(int x) 
{ 
    std::cout<<"in int method:"<<std::endl; // different output here 
    std::cout<< i<<std::endl; 
} 

這將被調用printnum(1)(給定類型的任何其他值或printnum()int) 。同樣,如果你想專門爲其他類型。

+0

是的,我完全理解這一點。該示例沒有被選擇顯示出好的代碼。它被選爲這個問題的中介:模板有什麼用? – FloriHe

+0

問題是,通過這樣做,你迫使人們解釋你使用的代碼有什麼問題。而且,由於代碼質量差,你會得到像我所給出的例子一樣的使用示例....展示瞭如何執行你對代碼給出的期望。 – Peter

+0

無論如何,這個問題「模板」的用法是什麼?「結構太籠統 - 太多可能的答案與您用來介紹問題的例子無關。所以我已經投票決定在這個基礎上結束這個問題。 – Peter

0

template<typename> 
void printnum(int i) { 
    std::cout<<"in int method:"<<std::endl; 
    std::cout<< i<<std::endl; 
} 

相同

template<typename T> 
void printnum(int i) { 
    std::cout<<"in int method:"<<std::endl; 
    std::cout<< i<<std::endl; 
} 

不同之處在於,所述參數是未命名。由於參數沒有以任何方式使用(你不能使用它 - 它沒有名字),它不影響任何東西。

模板參數沒有名稱。而已。但是該函數仍然是一個模板,所以需要將它傳遞給一個類型參數。與避免命名函數參數以避免「未使用的參數」警告相同,您可以在此處執行相同的操作。

(有時你必須未使用的功能參數,因爲回調有一個給定的簽名,因爲回調簽名要求它必須聲明一個參數,但它只是碰巧你不使用它)

+0

因此,這個構造是無用的。否則,你可以舉一個例子,爲什麼這個構造不是無用的。 – FloriHe

+0

@FloriHe避免命名模板參數與避免命名函數參數一樣有用:避免「未使用參數」警告。 – milleniumbug