decltype推导表达式类型而非变量声明类型:decltype(x)为int,decltype((x))为int&;它不求值、不支持不完整类型,常与auto、std::declval配合用于泛型编程。

decltype 用来推导表达式的类型,不是变量声明的类型
很多人以为 decltype(x) 就是取变量 x 的声明类型,其实它推导的是“x 这个表达式”在上下文中的类型——包括引用性、const/volatile 限定符,甚至括号是否加了都会影响结果。
- 如果
x是普通变量(如int x = 42;),decltype(x)是int - 如果
x是左值表达式(如(x)或函数返回左值引用),decltype((x))是int& -
decltype不求值表达式,所以decltype(func())即使func()有副作用也不会触发
decltype 和 auto 在模板中配合使用最实用
单独用 decltype 声明变量很啰嗦,它真正发挥作用的地方是和 auto 搭配,尤其在泛型编程里推导复杂返回类型。
- 写回调或适配器时,用
decltype获取 lambda 或函数对象调用结果类型:using result_t = decltype(f(std::declval<t>()))</t> - 配合
std::declval可以在不构造对象的前提下推导成员函数返回类型:decltype(std::declval<myclass>().foo())</myclass> - 注意:不能直接对未定义的类型或未声明的成员用
decltype,编译器会报错,不是 SFINAE 友好型
decltype((x)) 和 decltype(x) 差一个括号,类型完全不同
这是最容易踩的坑。加括号把变量变成表达式,而表达式默认是左值,所以 decltype((x)) 几乎总是带引用。
-
int x = 0;→decltype(x)是int,decltype((x))是int& - 在实现完美转发辅助类型时,常靠这个特性:
decltype((std::forward<t>(t)))</t>保留原值类别 - 如果误写成
decltype((x))却当成非引用用,会导致编译失败或绑定临时对象失败
decltype 无法推导 void 类型,也不能用于不完整类型
decltype 要求表达式类型可确定,void 和前置声明的类都不满足条件。
立即学习“C++免费学习笔记(深入)”;
-
decltype(func_that_returns_void())合法,但结果是void;而void类型不能用于声明变量,只能做函数返回类型或模板参数占位 -
class X;之后写decltype(x.member)(x是X类型)会失败,因为X是不完整类型 - 某些编译器对模板内依赖名的
decltype推导支持不一致,建议在 C++17 及以后版本中使用,并开启-std=c++17
int x = 42;<br>static_assert(std::is_same_v<decltype(x), int>);<br>static_assert(std::is_same_v<decltype((x)), int&>);括号有没有、表达式怎么写,一试便知。


















