C 模板推斷函式型別

2021-10-09 15:19:18 字數 2528 閱讀 6018

借助模板特例化和偏特化可以完成函式返回型別、輸入引數型別的推斷。我們直接步入主題:

首先預熱編譯器對偏特化的型別匹配。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...