基本語法
decltype(expression)
編譯器不計算表達式的值,僅分析其類型。C++11 引入,主要用於模板元編程與泛型代碼中推導表達式類型。
四大推導規則
| 表達式類別 | decltype 結果 | 說明 |
| 標識符 / 類成員訪問 | 該實體的類型 | 如 decltype(x)、decltype(obj.member) |
| 函數調用 / 重載運算符調用 | 函數返回類型 | 如 decltype(f())、decltype(a+b) |
| 右值 | 表達式類型 | 如 decltype(42) → int |
| 左值 | 左值引用類型 | 如 decltype((x)) → int& |
關鍵區別:括號的影響
int i = 0;
decltype(i) a; // int
decltype((i)) b; // int& —— 加括號變為表達式,表達式是左值,故得引用類型
decltype 與引用
- 若表達式不是變量,結果通常是非引用類型(如
decltype(r+0) → int)。
- 若表達式是解引用,結果是引用(
decltype(*p) → int&),因為解引用可作左值。
decltype vs auto
| 特性 | auto | decltype |
| 頂層 const | 忽略 | 保留 |
| 引用 | 忽略(推導底層類型) | 保留(若表達式為左值) |
| 初始化要求 | 必須初始化 | 無需初始化(僅推導類型) |
| 典型用途 | 變量聲明 | 模板返回類型、類型萃取 |
實戰:模板函數返回類型推導
// C++11 尾置返回類型
template
auto add(T&& t, U&& u) -> decltype(std::forward(t) + std::forward(u)) {
return std::forward(t) + std::forward(u);
}
// C++14 decltype(auto) 簡化
template
decltype(auto) add(T&& t, U&& u) {
return std::forward(t) + std::forward(u);
}
完整示例:自定義類型的運算符重載
#include
#include
#include
#include
using namespace std;
template
auto Plus(T&& t, U&& u) -> decltype(forward(t) + forward(u)) {
return forward(t) + forward(u);
}
class X {
int data;
public:
X(int d): data(d) {}
friend X operator+(const X& a, const X& b) { return X(a.data + b.data); }
int Dump() const { return data; }
};
int main() {
cout << Plus(4, 9) << endl; // 13
cout << Plus(4.0f, 9.5f) << endl; // 13.5
cout << Plus(string("Hello, "), string("world!")) << endl; // Hello, world!
cout << Plus(X(20), X(22)).Dump() << endl; // 42
}
總結
decltype 是編譯期類型推導工具,不求值。
- 核心規則:是變量/成員 → 類型;是表達式/調用 → 返回類型;左值 → 引用;右值 → 非引用。
- 配合
auto 解決模板返回類型依賴參數類型的問題。
- 理解
decltype((x)) vs decltype(x) 的區別是避坑關鍵。