什么是类型推导?
类型推导就是编译器帮助你自动将复杂的类型”猜出来“,从而不需要在代码里写冗长的类型名,主要涉及auto和decltype
类型推导解决了什么问题?
C++ 为了方便使用者,提供了类型推导的功能即auto和decltype,当一个变量带有复杂的修饰,如:
const int& ref = x;
或者是包含容器嵌套的类型:
std::map<std::string, std::vector<int>> myComplexMap;
还有就是从lambda中返回的复杂类型
auto add_lambda = [](int a, int b) -> int { return a + b; };
这种类型根本无法在代码里写出它的名字,因为它是由编译器随机生成的,比如 class <lambda_1d2a3b4c> 这种乱码
当我们需要处理这种类型的时候,就需要引入类型推导了。
auto vs decltype
auto
auto是一种只关心值的类型推导,并不保留引用与const/volatile等修饰符,而decltype精确保留着它们。
上面提到的例子:
int x 5;
const int& ref = x;
如果我们使用auto关键字获取类型,引用和const都被丢弃。
int x = 5;
const int& ref = x;
auto a = ref; // a 的类型是 int,而不是 const int&。
// 因为 auto 丢弃了引用和 const,变成了一个独立的 int 副本。
a = 10; // 合法,因为 a 只是 int,没有 const 限制
decltype
如果用decltype则精确保留了const和&
int x = 5;
const int& ref = x;
decltype(ref) d = x; // d 的类型是 const int&,完全复制了 ref 的类型。
d = 10; // 编译错误!因为 d 是 const 引用,不能修改。
完美转发的情况:同时使用
我们需要原封不动地获取一个函数的返回值时(比如完美转发std::forword的时候),需要保持精确,这样左右值引用才不会出现错配,但是一些参数的类型可能十分复杂,可以同时使用auto和decltype: 声明为decltype(auto)
// 场景:你写了一个转发函数,想原封不动地返回表达式结果(包括引用)
template<typename T>
decltype(auto) forward_example(T&& arg) {
return arg; // 如果 arg 是 int&,返回 int&;如果是 int&&,返回 int&&;完全保留
}
int x = 5;
forward_example(x) = 10; // 合法,因为返回的是 int&





