C++11新增的关键字decltype(auto)
一、函數(shù)模板存在的類型問題
template<class T1,class T2> void fun(T1 a, T2 b) {(T1 or T2?)y = a + b; }語句y = a+b,其實我們并不知道y應該為什么類型,我們可以寫成T1或者T2甚至可能是其類型。但是具體準確的寫成哪一個呢?我們并不確定,因為用函數(shù)模板產(chǎn)生函數(shù)實體跟傳入實參的類型有關,如果我們調(diào)用的時候是fun(int, double)那么按道理來說,結果應該是double,當然,如果我們用T1(在這里即int)也可以接收,只不過降低了結果的精確度。如果調(diào)用的時候是fun(short, int)那么結果準確類型的話,就是int類型的。甚至如果我們調(diào)用函數(shù)時fun(char , short),那么結果準確類型應該是int類型(在這里加法運算會導致自動整數(shù)提升),這個時候既不是T1類型,也不是T2類型。除此之外,我們可能重載結構體或者類的"+"運算符,這會導致結果的類型更復雜多變。
C++11提出decltype關鍵字來解決這個問題。
二、decltype關鍵字
1.decltype基本用法和作用
int main() {int x = 10;decltype(x) y1;//int類型short a = 2;char b = 1;decltype(a + b) y2;//int類型double c = 1;decltype(x + c) y3;//double類型return 0; }相當于decltype會自動推演類型,這一點我覺得和auto挺相像的。
那么我們的模板類就可以寫成下面這樣。
這樣y類型就是精確的類型了。
即decltype的使用格式是:decltype (expression) y;即定義一個變量y,類型和expression類型相同。expression可以是變量也可以是表達式。
編譯器為了確定類型,會遍歷一個核對表。
(1)如果expression是一個沒有用括號括起來的標識符,則y與這個標識符類型相同。
舉例:
int a;
decltype(a) y;
那么y就是和a類型相同,是int類型,包括const限定符。
舉例:
const int a = 10;
decltype(a) y = 20;
decltype(a) y2(20);
注意上面decltype兩種用法都可,但是一定得給初始值,因為y和y2也是const int類型,所以一定得給初始值。
(2)如果expression是一個左值并且用括號括起來了,那么y是這個標識符類型的引用。
舉例:
int a;
decltype ((a)) y1(x1);
const int b = 10;
decltype((b)) y2(x2);
注意在這里y1就是類型為int& 類型的變量,x1是給y1初始化的,x1一定是個左值,且肯定不能是const。y2是類型為const int& 類型的變量,x2是給y2初始化的。
總結來說,expression再加個括號,那么decltype定義的變量類型就是expression類型的引用。引用我們都知道,一定需要初始化,初始化規(guī)則和我們平常使用引用初始化規(guī)則都一樣。
(3)如果expression是一個函數(shù)調(diào)用,那么y與函數(shù)返回值類型相同,注意在這里并沒有實施調(diào)用函數(shù),只是編譯器根據(jù)函數(shù)返回值類型推出來變量y應該的類型。
舉例:
int fun(){return 0;}
decltype(fun()) y1;
decltype((fun())) y2;
注意y1和y2都是與fun函數(shù)返回類型相同的類型,即int。并不會因為多加了括號而變成int&。也就是上面的第二點對于函數(shù)并不適用。
(4)如果上面的都不符合,那么y和表達式expression類型相同。
舉例:
int a = 10;
int& b = a;
int& c = a;
float d = 10;
decltype(a+b) y1;
decltype(b+c) y2;
decltype(a+d) y3;
a+b為int類型,所以y1是int類型。
b+c也是int類型,所以y2是int類型。
a+d是float類型,所以y3是float類型。
模板函數(shù)內(nèi)部的變量類型用C++11新增的關鍵字decltype解決了。但是函數(shù)返回類型呢?
比如:
函數(shù)返回值類型是什么?我們并不確定,剛才講了decltype,難道可以這樣寫?:
template<class T1,class T2> decltype(x+y) fun(T1 a,T2 b) {return a + b; }答案是不行!因為此時還沒有執(zhí)行函數(shù)體,還不知道x和y變量,編譯器看不見x和y,沒辦法使用。我們可以用auto。在這里auto是一個占位符,表示后置返回類型提供的類型。編譯器會在編譯期間將auto替換為正確類型。而decltype是關鍵字。這也是它們倆的不同點。
template<class T1,class T2> auto fun(T1 a,T2 b)->decleype(x+y) {return a + b; }這種寫法是我在書上看的,但是我們其實不用這么麻煩,可以直接這樣寫:
template<class T1,class T2> auto fun(T1 a,T2 b) {return a + b; }因為auto是占位符,沒有什么其他特殊作用,是編譯器編譯期間推導出來類型,將auto替換為了正確推導出來的類型。auto除了占位這個作用,其他事情都是編譯器做的。
其實我們前面說的decltype做的事情,我們可以用auto占位,讓編譯器編譯期間將auto替換掉。
比如:
int a = 10;
float b = 20;
auto x1 = a;
auto x2(a+b);
auto x2 = (a+b);
發(fā)現(xiàn)auto可以基本替代掉decltype的作用。只不過定義變量使用auto占位時,必須給出變量的初始值或者表達式,這樣編譯器才會有推導變量類型的依據(jù),才能用正確類型替換掉占位符auto。
總結
以上是生活随笔為你收集整理的C++11新增的关键字decltype(auto)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 函数默认形参与占位参数
- 下一篇: 类的使用注意事项