gcc only
C++11标准前 类似decltype功能的运算符
typeid获取目标操作数类型的运算符 返回的是左值 只会涉及基本类型 不包含CV限定符和引用
auto- 对于变量 从它的初始化器推导出它的类型(Since C++11)
- 对于函数 从它的return语句推导出类型(Since C++14)
- 对于非类型模板形参 指定要从实参推导出它的类型(Since C++20)
可配合cv限定符和&/*(引用/指针)这样的修饰符一起使用
decltype3条推导规则
- 如果实参是没有括号的标识表达式或类成员访问表达式 那么 decltype 产生以该表达式命名的实体的类型
- 如果没有这种实体或该实参指名了一组重载函数 那么程序非良构(即错误的)
- 如果实参是指名某个结构化绑定的没有括号的标识表达式 那么 decltype 产生其被引用类型(Since C++17)
- 如果实参是指名某个非类型模板形参的没有括号的标识表达式 那么 decltype 生成该模板形参的类型(当该模板形参以占位符类型声明时,类型会先进行任何所需的类型推导)(Since C++20)
- 如果实参是其他类型为 T(可以是不完整类型) 的任何表达式
- 如果 表达式 的值类别是亡值 将会 decltype->T&&
- 如果 表达式 的值类别是左值 将会 decltype->T&
- 如果 表达式 的值类别是纯右值 将会 decltype->T
- 如果 表达式 是返回类类型纯右值的函数调用 或是右操作数为这种函数调用的逗号表达式 那么不会对该纯右值引入临时量 (Before C++17)
- 如果 表达式 是~~除了(可带括号的)立即调用以外的 (Since C++20)~~纯右值,那么不会从该纯右值实质化临时对象:即这种纯右值没有结果对象。(Since C++17)
- 如果对象的名字带有括号 那么它会被当做通常的左值表达式 从而decltype(x) 和 decltype((x)) 通常是不同的类型
对于第一条规则
#include#include int main(){ int i = 0; int* j=&i; int n[10]; decltype(i=0); // int& // 但不会赋值(Clang) // rule 1 static_assert(std::is_same_v ); static_assert(std::is_same_v ); static_assert(std::is_same_v ); static_assert(std::is_same_v (i)), int&&>); static_assert(std::is_same_v ); static_assert(std::is_same_v ); // rule 2 static_assert(std::is_same_v ); // xvalue static_assert(std::is_same_v ); // comma/lvalue static_assert(std::is_same_v ); // rvalue static_assert(std::is_same_v ); // lvalue // rule 3 static_assert(std::is_same_v ); }
:::tip cv限定符
通常情况下 decltype 会推导出cv限定符
但当表达式是成员变量时 父对象的限定符会被忽略
struct A {
double x;
};
const A* a = new A();
static_assert(std::is_same_vx),double>);
static_assert(std::is_same_vx)),const double&>);
但多加一层括号会改变结果
:::
Since C++14
- 只能独立使用(不能搭配cv限定 指针/引用)
- 使auto推导使用decltype方式



