decltype 類型規範
decltype 類型規範會產生指定之運算式的類型。 decltype 類型規範搭配 auto 關鍵字 對於主要是撰寫樣板程式庫的開發人員很有用。 使用 auto 和 decltype 來宣告其傳回類型視樣板引數而定的樣板函式。 或是使用 auto 和 decltype 來宣告包裝對其他函式的呼叫,再傳回所包裝函式之類型的樣板函式。
decltype( expression )
參數
參數 |
說明 |
---|---|
expression |
一個運算式。 如需詳細資訊,請參閱運算式 (C++)。 |
傳回值
expression 參數的類型。
備註
decltype 類型規範在 Visual C++ 2010 (含) 以後版本支援,可以搭配原生或 Managed 程式碼使用。
編譯器會使用下列規則來判斷 expression 參數的類型。
如果 expression 參數是識別項或 類別成員存取,decltype(expression) 是由 expression 命名的實體類型。 如果沒有這種實體或 expression 參數命名了一組多載函式,編譯器會產生錯誤訊息。
如果 expression 參數是對函式或多載運算子函式的呼叫,decltype(expression) 會是函式的傳回類型。 在多載運算子周圍的括號會被忽略。
如果 expression 參數是一個 rvalue,則 decltype(expression) 會是 expression 的類型。 如果 expression 參數是左值,decltype(expression) 會是一個 expression 類型的左值參考。
下列程式碼範例示範 decltype 類型規範的一些用法。 首先,假設您撰寫了下列陳述式。
int var;
const int&& fx();
struct A { double x; }
const A* a = new A();
接著,檢查由下表中四個 decltype 陳述式所傳回的類型。
陳述式 |
類型 |
備註 |
---|---|---|
decltype(fx()); |
const int&& |
對 const int 的右值參考。 |
decltype(var); |
int |
變數 var 的類型。 |
decltype(a->x); |
double |
成員存取的類型。 |
decltype((a->x)); |
const double& |
括號內的陳述式會評估為運算式而不是成員存取。 而且,因為 a 已宣告為 const 指標,所以其類型會是 const double 的參考。 |
Decltype 和 Auto
使用 decltype 類型規範搭配 auto 關鍵字來宣告其傳回類型視樣板引數而定的樣板函式。 例如,請考慮下列程式碼範例,其中樣板函式的傳回類型取決於樣板引數的類型。 在程式碼範例中,UNKNOWN 預留位置表示不能指定傳回類型。
template<typename T, typename U>
UNKNOWNfunc(T&& t, U&& u){ return t + u; };
decltype 類型規範的引入可讓開發人員取得樣板函式傳回的運算式類型。 使用稍後顯示的「替代函式宣告語法」(Alternative Function Declaration Syntax)、auto 關鍵字和 decltype 類型規範來宣告一個「晚期指定」(Late-Specified) 的傳回類型。 晚期指定的傳回類型是在編譯宣告時決定,而不是在撰寫程式時決定。
下列原型說明替代函式宣告的語法。 請注意,const 和 volatile 限定詞,以及 throw 例外狀況規格 是選擇性的。 function_body 預留位置代表指定的函式將進行的是複合陳述式。 基於撰寫程式碼的最佳作法,decltype 陳述式中的 expression 預留位置應該要與 function_body 中 return 陳述式指定的運算式相符 (如果有的話)。
auto function_name(parametersopt) constopt volatileopt −> decltype(expression) throwopt {function_body};
下列程式碼範例中,myFunc 樣板函式的晚期指定傳回類型由 t 和 u 樣板引數的類型決定。 基於撰寫程式碼的最佳作法,程式碼範例也使用右值參考和 forward 函式樣板,其支援「完美轉送」(Perfect Forwarding)。 如需詳細資訊,請參閱右值參考宣告子:&&。
template<typename T, typename U>
auto myFunc(T&& t, U&& u) -> decltype (forward<T>(t) + forward<U>(u))
{ return forward<T>(t) + forward<U>(u); };
decltype 和轉送函式
轉送函式會包裝對其他函式的呼叫。 試想一個轉送其引數,或者包含這些引數的運算式結果到其他函式的函式樣板。 此外,轉送函式會傳回呼叫其他函式的結果。 在這個案例中,轉送函式的傳回類型應該會與包裝函式的傳回類型相同。
在這個案例中,您必須使用 decltype 類型規範才能撰寫適當的類型運算式。 decltype 類型規範可進行泛型轉送函式,因為它不會遺失函式是否傳回參考類型的必要資訊。 如需轉送函式的程式碼範例,請參閱先前的 myFunc 樣板函式範例。
範例
下列程式碼範例會宣告樣板函式 Plus() 的晚期指定傳回類型。 Plus 函式處理其使用 operator+ 多載的兩個運算元。 因此,加號運算子 (+) 的解譯和 Plus 函式的傳回類型取決於函式引數的類型。
// decltype_1.cpp
// compile with: /EHsc
//
#include "stdafx.h"
#include <iostream>
#include <string>
#include <utility>
#include <iomanip>
using namespace std;
template<typename T1, typename T2>
auto Plus(T1&& t1, T2&& t2) ->
decltype(forward<T1>(t1) + forward<T2>(t2))
{
return forward<T1>(t1) + forward<T2>(t2);
}
class X
{
friend X operator+(const X& x1, const X& x2)
{
return X(x1.m_data + x2.m_data);
}
public:
X(int data) : m_data(data) {}
int Dump() const { return m_data;}
private:
int m_data;
};
int main()
{
// Integer
int i = 4;
cout <<
"Plus(i, 9) = " <<
Plus(i, 9) << endl;
// Floating point
float dx = 4.0;
float dy = 9.5;
cout <<
setprecision(3) <<
"Plus(dx, dy) = " <<
Plus(dx, dy) << endl;
// String
string hello = "Hello, ";
string world = "world!";
cout << Plus(hello, world) << endl;
// Custom type
X x1(20);
X x2(22);
X x3 = Plus(x1, x2);
cout <<
"x3.Dump() = " <<
x3.Dump() << endl;
}
輸出
這個程式碼範例會產生下列結果。
13
13.5
Hello, world!
42
需求
Visual C++ 2010 (含) 以後版本。