decltype
是 C++11 引入的关键字,用于推导表达式的类型。它可以在编译时获取变量或表达式的静态类型(保留引用和 const
等修饰符),常用于泛型编程、模板元编程和自动类型推导场景。
基本用法
int x = 10;
decltype(x) y = x; // y 的类型为 int
const int& rx = x;
decltype(rx) ry = x; // ry 的类型为 const int&
核心规则
变量或表达式
- 若
decltype(e)
中的e
是一个变量(无括号)或类成员访问,结果与该变量的声明类型一致(包括引用和const
)。
int a = 0; decltype(a) b = a; // b: int
- 若
带括号的表达式
- 若
e
是带括号的表达式(如(x)
),则结果会根据表达式的值类别决定:
- 左值 →
T&
- 右值 →
T
int x = 0; decltype((x)) y = x; // y: int& (因为 (x) 是左值) decltype(42) z = 1; // z: int (因为 42 是右值)
- 左值 →
- 若
函数调用
decltype(func())
返回函数返回值的实际类型(包括引用)。
std::string func(); decltype(func()) s; // s: std::string
典型应用场景
模板中依赖表达式的返回类型
template <typename T, typename U> auto add(T t, U u) -> decltype(t + u) { return t + u; }
在 C++14+ 中可简化为
auto add(T t, U u) { return t + u; }
。保存 lambda 表达式的类型
auto lambda = [](int x) { return x * 2; }; decltype(lambda) copy_lambda = lambda; // 复制同类型的 lambda
与 SFINAE(模板元编程)结合
通过decltype
检测成员函数或操作的存在性:template <typename T> auto has_begin(T&& t) -> decltype(t.begin(), std::true_type{});
替代后置返回类型(C++11)
在需要推导复杂表达式类型的场景:template <typename Container> auto getValue(Container& c, size_t i) -> decltype(c[i]) { return c[i]; }
与 auto
/std::declval
的区别
auto
: 忽略顶层引用和const
,仅推导基础类型。- **
std::declval<T>()
: 在编译时模拟一个未构造的T
类型的对象,常与decltype
配合使用:
using Type = decltype(std::declval<T>().member());
注意事项
decltype(auto)
(C++14): 完全保留表达式的所有类型信息(包括引用)。- 避免冗余:
简单场景优先用
auto
,复杂类型推导再用decltype
.
如果需要进一步探讨具体用例或底层机制,可以继续提问!
内容由零声教学AI助手提供,问题来源于学员提问