decltype主要作用就是帮助开发者在不能直接写出变量类型的时候,让编译器自动推导变量的类型。

核心作用是在编译期间推导表达式的类型,并且推导过程中不会执行表达式,仅分析其类型信息
decltype的语法格式:
decltype (表达式) 变量名;	// 括号内的表达式可以是变量、函数调用、运算式等,不能是未定义的标识符

并且其推导结果完全匹配表达式的“原生类型”(包括const、volatile。引用等)

其包括三类典型推导
1、表达式为普通变量或字面量
int a = 10;
const double b = 3.14;
decltype(a) x;		// x类型为int
decltype(b) y = 2.5;	// y类型为const double
// y = 6.6;			// 编译器会报错,assignment of read-only variable ‘y’
decltype(5) z;      // z类型为int (5是int 字面量)
2、表达式为函数调用
// 以下只是函数声明,没有定义,也证明了decltype仅分析返回值类型,并不会执行表达式
int func1();
const int func2();
decltype(func1()) a;	// a类型为int
decltype(func2()) b; 	// b类型为const int
3、表达式为左值/右值

        若表达式是左值(可被取地址的对象,如变量、数组元素、解引用指针等),推导为“该类型的引用”。

        若表达式是右值(临时值,如字面量、运算结果、临时对象等),推导为“该类型本身”。

int a = 10;
int arr[5] = {1, 2, 3, 4, 5};
// 左值:推导为引用
decltype(a) x = a;  // a是左值,但属于“普通变量”,所有类型还是int
decltype((a)) x1 = a;   // (a)为左值表达式,推导为int&(引用)
decltype(arr[0]) x2 = arr[0];    // arr[0]为左值表达式,推导为int&(引用)
decltype(*(int*)0) x3 = a;  // *(int*)a为左值表达式,推导为int&(引用)
    
// 右值:推导为原类型
int foo();
// 函数调用返回临时值,推导为int
decltype(foo()) y;
// 10 + 20 为临时结果,推导为int
decltype(10 + 20) y1;
关键应用场景
1、推导复杂类型(替代typedef和using)

        当类型过于复杂时,decltype可以简化类型定义。这一点与auto相似,不过auto必须结合变量初始化,不能直接推导表达式类型。

// 复杂类型:vector<int> 的迭代器
std::vector<int> vec;
decltype(vec.begin()) it = vec.begin(); // it 类型为 std::vector<int>::iterator
  2、 结合auto定义“返回值后置”的函数
// 函数返回两参数的“共同类型”(依赖 a 和 b 的类型)
template <typename T1, typename T2>
auto add(T1 a, T2 b) -> decltype(a + b) {
    return a + b;
}

// 调用示例:a=1(int),b=2.5(double),返回类型为 double
auto result = add(1, 2.5); 
decltype(add(a, b)) c = add(1, 3.14); // 推导为double
3、模板中推导模板参数类型
template <typename T>
void printSize(T container) {
    // 推导容器元素的类型
    decltype(container[0]) elem = container[0];
    std::cout << "元素类型大小:" << sizeof(elem) << std::endl;
}

// 调用:container 为 vector<double>,elem 类型为 double&
std::vector<double> vec = {1.1, 2.2};
printSize(vec);
另外,看一下decltype和auto的区别

        两者的核心区别在于类型推导依据的不同:auto依据变量的初始化表达式来推导类型,decltype依据给定的表达式本身推导类型,且不执行表达式。

        而且,decltype推导时会完整保留表达式的类型属性(const、volatile),而auto的推导结果会忽略表达式的“引用性和顶层const”

注:顶层const:指const直接修饰变量本身,影响变量的赋值行为(变量值不能被修改)

底层const:const修饰的是变量指向或引用的对象,影响对象的修改行为

比如:const int a = 5 (a是顶层const,a本身不能修改)

const int * p(p指向的是int的const, p本身可以改变指向,这是底层const)

相反,int * const p (p是顶层const)

const int a = 10;
decltype(a) b = a;
auto c = a;
b = 20;   // 会报错,assignment of read-only variable ‘b’
c = 20;   // c 修改成功
总结

decltype 是 C++11 引入的类型推导关键字,核心作用是依据指定表达式本身的类型进行推导,且不执行该表达式,常用于精准获取表达式类型(尤其非变量定义场景)。

更多推荐