借助模板特例化和偏特化可以完成函式返回型別、輸入引數型別的推斷。我們直接步入主題:
首先預熱編譯器對偏特化的型別匹配。c++模板庫中,std::is_same可判斷兩個型別是否相同,這裡我們可以借助偏特化自己實現乙個is_same模板:
templateclass is_same
;template//偏特化
class is_same;
利用編譯器對模板型別匹配的特點,如果兩個模板引數的型別相同,則例項化偏特化模板,其value成員為true;反之例項化一般模板,其value成員為false。
下面是另乙個模板型別匹配的例子:
templateclass gg
;template//偏特化
class gg;
int main()
這裡使用了兩個型別t和u構建了函式型別t(u),以此作為模板gg的偏特化型別。編譯器例項化gg後,可以得到t和u的型別。
c++模板可表示三種可執行型別,其依次為:
1. t (*)(u...) 函式指標;
2. t(&)(u...) 函式引用;
3. t(u...) 函式型別。表示函式,常用於tr1::function、bind等模板的型別表示。
通過上述形式的偏特化模板,我們可以推斷函式指標的返回型別:
templateclass gg
;template//偏特化
class gg
typedef t return_type; //函式返回型別
pfunc g;
};typedef int(*p)(int,int);
int getcs(int s, int f)
;templateclass getarg;
template//設定遞迴結束
class getarg<0,t,u...>
;templateclass gg
;template//偏特化型別匹配
class gg;
};gg::arg<0>::type //is int
gg::arg<1>::type //is double
如需獲得可變型別引數的個數,利用模板例項化遞迴可以完成:
1. 傳統實現方式,使用static常量或enum型別:
templateclass getnum
;templateclass getnum;
templateclass num
;
這種方式占用記憶體可能較大(與編譯優化有關),每遞迴一層都要生成乙個getnum型別,每個型別都存在乙個static常量。
2. 改進的實現方式,減少static常量個數:
templateclass getnum : public getnum;
templateclass getnum;
templateclass num
;
通過繼承的方式完成遞迴例項化,getnum只存在乙個static常量。
題外話:
c++模板編譯時進行的two-phase name lookup過程(第一次匹配模板內部非dependent 名稱,在模板例項化後再匹配dependent 名稱),要求第一次檢查模板即劃分dependent名稱和非dependent 名稱,再確定所有非dependent名稱的使用是否合法。經驗而言,第一次模板檢查,必須確定所有涉及的名稱是否為指標、引用、函式、class物件;如果編譯器在檢查名稱時無法推斷是否為指標、引用、函式、class物件,則需手工新增typename、template標識,否則模板檢查出錯。dependent types依賴模板引數t可能產生多種形式(指標、引用、函式、class物件),阻礙名稱檢查;非dependent types根據模板引數t只能產生固定的形式,不阻礙名稱檢查。
函式型別作為模板引數時,模板內只能間接使用該型別,如進行函式宣告、作為函式指標或函式引用,不能用作建立函式物件。函式宣告需注意dependent types的影響:
templateclass hh
};int get(int a)
{ cout
//或如下表示
typedef int(func)(int); //表示函式型別,等同於模板型別int(int)
func get; //宣告get函式
func *p = get;
func &q = get;
t foo錯誤原因是c++標準的如下規定:
取自《information technology — programming languages — c++》iso/iec 14882:2011,c++14大體沒有變化。
也可參考stackoverflow上關於dependent 名稱的深入討論:
C 函式模板的實參推斷
在使用類模板建立物件時,程式設計師需要顯式的指明實參 也就是具體的型別 例如對於下面的 point 類 templateclass point 我們可以在棧上建立物件,也可以在堆上建立物件 pointp1 10,20 在棧上建立物件 point p new point 東京180度 北緯210度 在...
C 變數 型別推斷
宣告變數的語法有些變化 使用var關鍵字代替實際的型別。編譯器可以根據變數的初始化值 推斷 出變數的型別。例如 var score 0 編譯器會將它變成 int score 0 即使 score 從來沒有宣告 int,編譯器也可以確定。編譯後上面的2個語句是等價的。static void main ...
型別推斷 var
型別推斷 type inference 使用 var 關鍵字。編譯器可以根據變數的初始化值 推斷 變數的型別。例如 int number 0 就可以寫成 var number 0 編譯器可以 推斷 出變數number為int型別。上面兩個語句是等價的。var name bu iancai var a...