C++ 的类型系统功能强大且细致入微,提供了(除其他功能外)一套类型推导机制。最广为人知的类型推导工具可能是 auto,用于从初始化器的类型中推导出表达式的类型:
const int n = f();
auto m = n; // m 的类型是 int
auto & r = m; // r 的类型是 int&
const auto & cr0 = m; // cr0 的类型是 const int&
auto & cr1 = n; // cr1 的类型是 const int&
默认情况下,auto 会进行复制(见变量 m 的声明),但如果需要,也可以用 &、&&、const 等限定符来修饰 auto。
有时,希望以更高的精度推导某个表达式的类型,保留它所附带的各种限定符。当需要推导一个算术表达式、lambda 表达式、复杂泛型函数的返回类型等的类型时,这可能会很有用。为此,可以使用 decltype 操作符:
template <class T>
T& pass_thru(T &arg) {
return arg;
}
int main() {
int n = 3;
auto m = pass_thru(n); // m 的类型是 int
++m;
cout << n << ' ' << m << '\n'; // 3 4
decltype(pass_thru(n)) r = pass_thru(n); // r 的类型是 int&
++r;
cout << n << ' ' << r << '\n'; // 4 4
}
在前面的 decltype 示例中,写了两次 pass_thru(n):一次在 decltype 操作符中,另一次在实际的函数调用中。这在一般情况下并不实用,重复了维护工作……而且,本质上只是代码中的“噪音”。
自 C++14 起,可以使用 decltype(auto) 来表示“初始化表达式的完整限定类型”,通常会这样写:
decltype(auto) r = pass_thru(n);
这表示 r 的类型是表达式 pass_thru(n) 的完整限定类型。