2012-08-01 32 views
4

我不知道爲什麼模板專業化有意義?爲什麼要使用模板專業化?

下面的東西不是等價的嗎?

模板專業化:

template <typename T> 
void f(T t) { 
    something(t); 
} 

template <> 
void f<int>(int t) { 
    somethingelse(t); 
} 

非模板函數,而不是專業化:

void f(int t) { 
    somethingelse(t); 
} 

我相信這些是相同的,因爲非模板函數將始終是首選。

+0

您正在專門討論* function *模板專業化。這些被認爲是棄用和糟糕的風格。類模板的專業化非常有意義。 – Xeo 2012-08-01 11:29:26

+0

哦,這很有趣。你能提供一個鏈接嗎?快速搜索沒有任何結果。 – Sarien 2012-08-01 11:31:30

+0

http://www.gotw.ca/publications/mill17.htm – interjay 2012-08-01 11:34:26

回答

3

問題歸結爲確定什麼時候使用專門化,超載不能。在這種情況下,雖然它們不夠普遍,但存在不同情況,並且很容易出現錯誤,因此一般建議是將重載更改爲專業化。

  • 當調用者顯式地請求使用模板時。在您提供的代碼示例中,如果調用爲f<int>(42)或甚至f<42>(),則不會使用超載。

  • 如果您無法提供所需的重載,或者無法在呼叫地點解決超載問題。例如,如果類型不是函數參數(它或者是不或僅在返回類型簽名本之一:

    模板 五六();

在這種情況下,您不能提供過載int f();double f();,但您可以根據需要提供儘可能多的模板特化,並且由用戶決定是否強制選擇其中一個。請注意,這可以被視爲以前的子項案例:因爲模板參數不參與函數參數,所以用戶需要提供模板參數,所以調用明確指向模板。

  • 當你想放置的參數的組合特殊的限制和抑制的隱式轉換:

    模板 無效F(T,T); //兩個參數必須是同一類型

因爲模板參數推導只進行完美的匹配,該模板只能當兩個參數都完全相同的類型的使用,如果添加過載void f(int,int)那過載可以用於隱式轉換爲int的類型的任意組合,如f(5, 3.0),但專業化不會。

一般來說,對於大多數情況,上述情況都不適用,因此應該優先選擇超載。


可能有更多,但這些都是我能回憶起了我的頭頂部

+0

我們對這個主題有一個最近的討論,請參閱這個問題的答案的評論:http://stackoverflow.com/questions/11034759 – Gorpik 2012-08-01 13:05:05

+0

@Gorpik:我剛剛讀過它們(粗略閱讀了評論),你想提出什麼? – 2012-08-01 13:15:57

+0

討論的一部分討論了使用專門化是否有效作爲爲調用者提供更乾淨的接口的方法。這與你所建議的原因相似。並不是所有人都同意:有些人從未使用過功能模板專業化。 – Gorpik 2012-08-03 12:36:05

4

這是我想出了答案:

這是不同的,如果模板參數不是正在定義的函數的參數:

template <typename T> 
void f() { 
    T t; 
    something(t); 
} 

template <> 
void f<int>() { 
    int t; 
    somethingelse(t); 
} 

在這種情況下定義:

void f() { 
    int t; 
    somethingelse(t); 
} 

會使所有的模板版本不可用。

也許別人有更好的想法。 :)

+1

這基本上是我的推理。如果你在模板中使用這個函數,並且你需要得到正確的函數,你可以稱它爲'f ()'。哪些不會發現過載。 – 2012-08-01 11:35:03

+0

f ()的編碼方式與the_other_f()基本相同。如果你喜歡尖括號,會對你有所幫助。由於局部特化不適用於函數模板,我也認爲應該使用重載而不是顯式的特化 – 2012-08-01 11:49:52

3

如果您堅持將它稱爲f<int>(42),則您聲明函數的方式確實如此。這將找到專業化,但不會超負荷。

如果該呼叫總是看起來像f(42),則可以採用其他方法。

0

函數模板專業化支持函數重載棄用有一個例外:你被允許添加函數模板專門化到std名稱空間,您不允許添加新函數。因此,如果您需要爲std命名空間中的某個東西提供特定版本,則必須使用模板特化。例如,要支持用用戶定義的類創建一個unordered_map作爲鍵,你必須專門爲你的類設置std :: hash。