1. 程式人生 > 程式設計 >c++ decltype關鍵字的用法

c++ decltype關鍵字的用法

1. decltype關鍵字的用途是什麼

給定變數的名稱或者表示式,decltype返回變數或者表示式的型別。如下所示:

const int i = 0; // decltype(i) is const int

bool f(const Widget& w); // decltype(w) is const Widget&,decltype(f) is bool(const Widget&)

struct Point {

int x,y; // decltype(Point::x) is int,decltype(Point::y) is int

};

Widget w; // decltype(w) is Widget

if (f(w)) ... // decltype(f(w)) is bool

template<typename T>class vector {

public:

...

T& operator[](std::size_t index);...

};

vector<int> v; // decltype(v) is vector<int>

if (v[0] == 0) ... // decltype(v[0]) is int&

2.decltype主要應用場景是模板函式

decltype在實際的開發中主要用於模板函式中,函式的返回值依賴於模板引數型別的情況。如下authAndAccess函式的返回值型別依賴於Container的元素型別。

template<typename Container,typename Index>
auto authAndAccess(Container& c,Index i) -> decltype(c[i]) {

 authenticateUser();

 return c[i];
}

此處的返回值auto並非型別推導的意思,而是C++ 11中的函式返回型別後置的表達方式,表明函式的返回型別在引數列表之後。函式返回型別後置的優勢在於我們可以用函式的引數來指定返回值。

在c++ 14中auto關鍵字可以獨立用於對函式的返回值進行型別推導,而不必採用c++ 11中的返回返回型別後置的宣告方式:

template<typename Container,Index i) {

 authenticateUser();

 return c[i]; // return type deduced from c[i]
}

但上述寫法在實際應用針對具體case可能存在問題,比如如果operator[]返回T&,auto的推導機制會返回T,下面的就會編譯失敗:

std::deque<int> d;

...

authAndAccess(d,5) = 10; //return d[5],then assign 10 to it; this won't compile!

因為根據auto的推導機制,authAndAccess返回的是右值,所以編譯不通過。authAndAccess函式需要宣告為如下方式才可以保證該示例編譯通過。

template<typename Container,typename Index>
decltype(auto) authAndAccess(Container& c,Index i){

 authenticateUser();

 return c[i];
}

decltype(auto)不僅僅可以用於函式,也可以用於變數,可以完美推導變數的型別。

Widget w;
const Widget& cw = w;
auto myWidget1 = cw; // auto type deduction: myWidget1's type is Widget

decltype(auto) myWidget2 = cw; // decltype type deduction: myWidget2's type is const Widget&

再回到authAndAccess函式

template<typename Container,Index i);

注意到Container是一個非const的左值引用,這意味著使用者可以修改Container內元素的值,同時也意味不能傳遞右值引用給它。

另外右值容器一般是一個臨時物件,會在函式呼叫結束後不久被銷燬,所以當用戶傳入一個右值引用的時候,一般我們要把返回元素拷貝它的一個副本。如何能夠在不過載authAndAccess函式的情況下使它同時支援左值和右值呢?答案是通用引用。

template<typename Container,typename Index>
decltype(auto) authAndAccess(Container&& c,Index i);

為了保證推導結果的正確性,需要在實現中增加完美轉發(std::forward)功能。

template<typename Container,typename Index>
decltype(auto)authAndAccess(Container&& c,Index i){

 authenticateUser();

 return std::forward<Container>(c)[i];
} // c++ 14版本
template<typename Container,typename Index>
auto authAndAccess(Container&& c,Index i)
-> decltype(std::forward<Container>(c)[i])
{
 authenticateUser();

 return std::forward<Container>(c)[i];
} // c++ 11版本

3. decltype使用的極端case

decltype(auto) f1() { // decltype(x) is int,so f1 returns int
 int x = 0;
 ...
 return x;
}

decltype(auto) f2() { // decltype((x)) is int&,so f2 returns int&
 int x = 0;
 ...
 return (x);
}

返回了一個區域性變數的引用。

4. 需要記住的:

1) decltype總是返回與變數或者表示式完全相同的型別;

2) 對於型別T的非名稱的左值表示式,decltype總是返回T&;

以上就是c++ decltype關鍵字的用法的詳細內容,更多關於c++ decltype關鍵字的資料請關注我們其它相關文章!