C++11 函數模板的默認模板參數


類模板:通用的類描述(使用泛型來定義類),進行實例化時,其中的泛型再用具體的類型替換。

函數模板:通用的函數描述(使用泛型來定義函數),進行實例化時,其中的泛型再用具體的類型替換。

【1】C++98標准中兩者的區別

函數模板和類模板在C++98標准中一起被引入,兩者區別主要在於:

在類模板聲明時,標准允許其有默認模板參數。而函數模板卻不支持。

默認模板參數的作用如同函數的默認形參。不過在C++11中,這一限制已經被解除了,如下例所示:

1 void DefParm(int m = 3) {} // c++98編譯通過,c++11編譯通過
2 
3 template <typename T = int>
4 class DefClass {};        // c++98編譯通過,c++11編譯通過
5 
6 template <typename T = int>
7 void DefTempParm() {};    // c++98編譯失敗,c++11編譯通過

可以看到,DefTempParm函數模板擁有一個默認模板參數(類型int)。

使用僅支持C++98的編譯器編譯,DefTempParm的編譯會失敗,而支持C++11的編譯器則無問題。

【2】C++11標准中兩者的區別

盡管C++11支持了函數模板的默認模板參數,不過在語法上,兩者還是存在區別:

類模板在為多個默認模板參數聲明指定默認值時,必須遵照“從右往左”的規則進行指定。

而這個規則對函數模板來說並不是必須的。示例如下:

 1 template <typename T1, typename T2 = int>
 2 class DefClass1 {};
 3 
 4 template <typename T1 = int, typename T2>
 5 class DefClass2 {};  // ERROR: 無法通過編譯:因為模板參數的默認值沒有遵循“由右往左”的規則
 6 
 7 template <typename T, int i = 0>
 8 class DefClass3 {};
 9 
10 template <int i = 0, typename T>
11 class DefClass4 {};  // ERROR: 無法通過編譯:因為模板參數的默認值沒有遵循“由右往左”的規則
12 
13 template <typename T1 = int, typename T2>
14 void DefFunc1(T1 a, T2 b) {}; // OK 函數模板不用遵循“由右往左”的規則
15 
16 template <int i = 0, typename T>
17 void DefFunc2(T a) {};  // OK 函數模板不用遵循“由右往左”的規則

可以看到,不按照從右往左定義默認類模板參數的模板類DefClass2和DefClass4都無法通過編譯。

而對於函數模板來說,默認模板參數的位置則比較隨意。

DefFunc1和DefFunc2都為第一個模板參數定義了默認參數,而第二個模板參數的默認值並沒有定義,C++11編譯器卻認為沒有問題。

函數模板的參數推導規則也並不復雜。簡單地講:如果能夠從函數實參中推導出類型的話,那么默認模板參數就不會被使用,反之,默認模板參數則可能會被使用。

如下示例:

 1 template <class T, class U = double>
 2 void f(T t = 0, U u = 0) {};
 3 void g() 
 4 {
 5     f(1, 'c'); // f<int, char>(1, 'c') 
 6     f(1);      // f<int, double>(1, 0), 使用了默認模板參數double
 7     f();       // 錯誤: T無法被推導出來
 8     f<int>();  // f<int, double>(0, 0), 使用了默認模板參數double
 9     f<int, char>(); // f<int, char>(0, 0)
10 }

定義了一個函數模板f,f同時使用了默認模板參數和默認函數參數。

可以看到,由於函數的模板參數可以由函數的實參推導而出:

在f(1)這個函數調用中,實例化出了模板函數的調用應該為f<int, double>(1, 0),其中,第二個類型參數U使用了默認的模板類型參數double,而函數實參則為默認值0。

類似地,f<int>()實例化出的模板函數第二參數類型為double,值為0。

而表達式f()由於第一類型參數T的無法推導,從而導致了編譯的失敗。

而通過這個例子也可以看到,默認模板參數通常是需要跟默認函數參數一起使用的。

還有一點應該注意:模板函數的默認形參值不是模板參數推導的依據。函數模板參數的選擇,終究是由函數的實參推導而來的。

 

good good study, day day up.

順序 選擇 循環 總結


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM