C++ decltype用法舉例說明
1.什麼是decltype
decltype是C++11新增的一個關鍵字,和auto的功能一樣,用來在編譯時期進行自動類型推導。引入decltype是因為auto並不適用於所有的自動類型推導場景,在某些特殊情況下auto用起來很不方便,甚至壓根無法使用。
對於內置類型的對象,使用decltype很直觀,但當參數為復合類型的時候就應該註意一些使用細節問題。
auto varName=value; decltype(exp) varName=value;
- auto根據=右邊的初始值推導出變量的類型,decltype根據exp表達式推導出變量的類型,跟=右邊的value沒有關系
- auto要求變量必須初始化,這是因為auto根據變量的初始值來推導變量類型的,如果不初始化,變量的類型也就無法推導
- 而decltype不要求,因此可以寫成如下形式
decltype(exp) varName;
原則上將,exp隻是一個普通的表達式,它可以是任意復雜的形式,但必須保證exp的結果是有類型的,不能是void;如exp為一個返回值為void的函數時,exp的結果也是void類型,此時會導致編譯錯誤
1.1decltype的幾種形式
int x = 0; decltype(x) y = 1; // y -> int decltype(x + y) z = 0; // z -> int const int& i = x; decltype(i) j = y; // j -> const int & const decltype(z) * p = &z; // *p -> const int, p -> const int * decltype(z) * pi = &z; // *pi -> int , pi -> int * decltype(pi)* pp = π // *pp -> int * , pp -> int * *
2.推導規則
decltype的推導規則可以簡單概述如下:
- 如果exp是一個不被括號()包圍的表達式,或者是一個類成員訪問表達式,或者是一個單獨的變量,decltype(exp)的類型和exp一致
- 如果exp是函數調用,則decltype(exp)的類型就和函數返回值的類型一致
- 如果exp是一個左值,或被括號()包圍,decltype(exp)的類型就是exp的引用,假設exp的類型為T,則decltype(exp)的類型為T&
規則1示例:
#include<string> #include<iostream> using namespace std; class A{ public: static int total; string name; int age; float scores; } int A::total=0; int main() { int n=0; const int &r=n; A a; decltype(n) x=n; //n為Int,x被推導為Int decltype(r) y=n; //r為const int &,y被推導為const int & decltype(A::total) z=0; ///total是類A的一個int 類型的成員變量,z被推導為int decltype(A.name) url="www.baidu.com";//url為stringleix return 0; }
規則2示例:
int& func1(int ,char);//返回值為int& int&& func2(void);//返回值為int&& int func3(double);//返回值為int const int& func4(int,int,int);//返回值為const int& const int&& func5(void);//返回值為const int&& int n=50; decltype(func1(100,'A')) a=n;//a的類型為int& decltype(func2()) b=0;//b的類型為int&& decltype(func3(10.5)) c=0;//c的類型為int decltype(func4(1,2,3)) x=n;//x的類型為const int& decltype(func5()) y=0;//y的類型為const int&&
exp中調用函數時需要帶上括號和參數,但這僅僅是形式,並不會真的去執行函數代碼
規則3示例:
class A{ public: int x; } int main() { const A obj; decltype(obj.x) a=0;//a的類型為int decltype((obj.x)) b=a;//b的類型為int& int n=0,m=0; decltype(m+n) c=0;//n+m得到一個右值,c的類型為int decltype(n=n+m) d=c;//n=n+m得到一個左值,d的類型為int & return 0; }
左值:表達式執行結束後依然存在的數據,即持久性數據;右值是指那些在表達式執行結束不再存在的數據,即臨時性數據。一個區分的簡單方法是:對表達式取地址,如果編譯器不報錯就是左值,否則為右值
3.實際應用
類的靜態成員可以使用auto, 對於類的非靜態成員無法使用auto,如果想推導類的非靜態成員的類型,隻能使用decltype。
示例如下:
template<typename T> class A { private : decltype(T.begin()) m_it; //typename T::iterator m_it; //這種用法會出錯 public: void func(T& container) { m_it=container.begin(); } }; int main() { const vector<int> v; A<const vector<int>> obj; obj.func(v); return 0; }
到此這篇關於C++ decltype用法舉例說明的文章就介紹到這瞭,更多相關C++ decltype內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!
推薦閱讀:
- C++ decltype 說明符
- C++11中bind綁定器和function函數對象介紹
- C++泛型編程Generic Programming的使用
- 詳解C++11中模板的優化問題
- C++20中的span容器及用法小結