C++新标准——decltype 关键字
decltype 是 C++11 新增的一个关键字,它和 auto 一样,都用来在编译期进行类型推导。它不需要对表达求职即可获得表达式类型。C++ 文档给出的介绍是:decltype 检查实体的声明类型或表达式的类型和值类别。实际应用这些场景:标记符的类型推导、函数模板的返回值类型推导、 Lambda 表达式中 auto&& 类型的形参类型推导、函数模板的函数参数的类型推导等。
一、语法
decltype(entity) | 如果实参是未加括号的标识符表达式或未加括号的类成员访问表达式,则 decltype 产生该表达式所命名实体的类型。若不存在此实体,或实参指代一组重载函数,则程序非良构(编译出错)。 C++17、C++20 暂略 |
decltype(expression) | 若实参是其他类型为 a> 若 expression 的值类别是将亡值,则 b> 若 expression 的值类别是左值, 则 c> 若 expression 的值类别是纯右值,则 C++17、C++20 暂略 |
上述表格对语法的表述可能略显晦涩,其实它们表达的核心是如下前两种情况:
- 表达式是一个变量,则 decltype 返回变量的类型(包含顶层 const 和引用在内),如下代码片段传给 decltype 的实参都是变量(名):
int main(int argc, char *argv[]) {const int ci = 9, &cj = ci;decltype(ci) x = 0;decltype(cj) y = x; }
- 表达式不是一个变量(而是其他类型为
T
的任何表达式),则 decltype 返回表达式结果的类型。此时还需要考虑表达式的 value category:int main(int argc, char* argv[]) {int j = 88, i = 9, k = 68, *p = &i, &r = i;decltype(r + 0) b = 66;decltype(*p) c = j;decltype(6) pv = 8;decltype(std::move(k)) xv;return 0; }
- 实参是加括号的标识符表达式,简单说“标识符表达式”就是定义变量名、函数名等。如果给变量加一层或多层括号,编译器就会把它当作表达式;变量可以作为赋值语句的左值,结合这两种特征,decltype 会返回相应的引用类型:
int main(int argc, char* argv[]) {int t = 99, s = 9;decltype((t)) ref = s;return 0; }
实参是函数调用时,decltype 会返回与函数调用时返回值一致的类型:
static int foo() { return 2; }static int&& xv_foo() {int i = 9;return std::move(i); }int main(int argc, char* argv[]) {decltype(foo()) foo_v;decltype(xv_foo()) foo_xv = 999; }
二、decltype 使用场景