C 11特性 decltype關鍵字

2022-01-21 21:41:26 字數 3113 閱讀 7174

我們之前使用的typeid運算子來查詢乙個變數的型別,這種型別查詢在執行時進行。rtti機制為每乙個型別產生乙個type_info型別的資料,而typeid查詢返回的變數相應type_info資料,通過name成員函式返回型別的名稱。同時在c++11中typeid還提供了hash_code這個成員函式,用於返回型別的唯一雜湊值。rtti會導致執行時效率降低,且在泛型程式設計中,我們更需要的是編譯時就要確定型別,rtti並無法滿足這樣的要求。編譯時型別推導的出現正是為了泛型程式設計,在非泛型程式設計中,我們的型別都是確定的,根本不需要再進行推導。

而編譯時型別推導,除了我們說過的auto關鍵字,還有本文的decltype。

decltype與auto關鍵字一樣,用於進行編譯時型別推導,不過它與auto還是有一些區別的。decltype的型別推導並不是像auto一樣是從變數宣告的初始化表示式獲得變數的型別,而是總是以乙個普通表示式作為引數,返回該表示式的型別,而且decltype並不會對表示式進行求值。

int i = 4;

decltype(i) a; //推導結果為int。a的型別為int。

using size_t = decltype(sizeof(0));//sizeof(a)的返回值為size_t型別

using ptrdiff_t = decltype((int*)0 - (int*)0);

using nullptr_t = decltype(nullptr);

vectorvec;

typedef decltype(vec.begin()) vectype;

for (vectype i = vec.begin; i != vec.end(); i++)

這樣和auto一樣,也提高了**的可讀性。

在c++中,我們有時候會遇上一些匿名型別,如:

struct 

anon_s;

而借助decltype,我們可以重新使用這個匿名的結構體:

decltype(anon_s) as ;//定義了乙個上面匿名的結構體
這也是decltype最大的用途了。

template auto multiply(_tx x, _ty y)->decltype(_tx*_ty)

如果e是乙個沒有帶括號的標記符表示式或者類成員訪問表示式,那麼的decltype(e)就是e所命名的實體的型別。此外,如果e是乙個被過載的函式,則會導致編譯錯誤。

否則 ,假設e的型別是t,如果e是乙個將亡值,那麼decltype(e)為t&&

否則,假設e的型別是t,如果e是乙個左值,那麼decltype(e)為t&。

否則,假設e的型別是t,則decltype(e)為t。

標記符指的是除去關鍵字、字面量等編譯器需要使用的標記之外的程式設計師自己定義的標記,而單個標記符對應的表示式即為標記符表示式。例如:

int arr[4]
則arr為乙個標記符表示式,而arr[3]+0不是。

我們來看下面這段**:

int i=10;

decltype(i) a; //a推導為int

decltype((i))b=i;//b推導為int&,必須為其初始化,否則編譯錯誤

僅僅為i加上了(),就導致型別推導結果的差異。這是因為,i是乙個標記符表示式,根據推導規則1,型別被推導為int。而(i)為乙個左值表示式,所以型別被推導為int&。

通過下面這段**可以對推導四個規則作進一步了解

int i = 4;

int arr[5] = ;

int *ptr = arr;

struct ss ;

void overloaded(int);

void overloaded(char);//過載的函式

int && rvalref();

const bool func(int);

//規則一:推導為其型別

decltype (arr) var1; //int 標記符表示式

decltype (ptr) var2;//int * 標記符表示式

decltype(s.d) var3;//doubel 成員訪問表示式

//decltype(overloaded) var4;//過載函式。編譯錯誤。

//規則二:將亡值。推導為型別的右值引用。

decltype (rvalref()) var5 = 1;

//規則三:左值,推導為型別的引用。

decltype ((i))var6 = i; //int&

decltype (true ? i : i) var7 = i; //int& 條件表示式返回左值。

decltype (++i) var8 = i; //int& ++i返回i的左值。

decltype(arr[5]) var9 = i;//int&. 操作返回左值

decltype(*ptr)var10 = i;//int& *操作返回左值

decltype("hello")var11 = "hello"; //const char(&)[9] 字串字面常量為左值,且為const左值。

//規則四:以上都不是,則推導為本型別

decltype(1) var12;//const int

decltype(func(1)) var13=true;//const bool

decltype(i++) var14 = i;//int i++返回右值

這裡需要提示的是,字串字面值常量是個左值,且是const左值,而非字串字面值常量則是個右值。

這麼多規則,對於我們寫**的來說難免太難記了,特別是規則三。我們可以利用c++11標準庫中新增的模板類is_lvalue_reference來判斷表示式是否為左值:

cout << is_lvalue_reference::value << endl;
結果1表示為左值,結果為0為非右值。

同樣的,也有is_rvalue_reference這樣的模板類來判斷decltype推斷結果是否為右值。

C 11特性 decltype關鍵字

我們之前使用的typeid運算子來查詢乙個變數的型別,這種型別查詢在執行時進行。rtti機制為每乙個型別產生乙個type info型別的資料,而typeid查詢返回的變數相應type info資料,通過name成員函式返回型別的名稱。同時在c 11中typeid還提供了hash code這個成員函式...

C 11基礎 decltype關鍵字

1.decltype關鍵字獲取表示式的型別 int x 0 decltype x y 1 y int2.推導規則decltype exp int n 0 volatile const int x n decltype n a n a int decltype x b n b const volati...

C 11的decltype關鍵字

decltype關鍵字和auto有異曲同工之處 有時我們希望從表示式的型別推斷出要定義的變數型別,但是不想用該表示式的值初始化變數 如果要初始化就用auto了 為了滿足這一需求,c 11新標準引入了decltype型別說明符,它的作用是選擇並返回運算元的資料型別,在此過程中,編譯器分析表示式並得到它...