一、decltype关键字简介
在C++11中,decltype 是一个操作符,用于查询表达式的数据类型,而不会计算实际执行表达式的值。其语法如下:
decltype(expression) var;
decltype 分析表达式并推导出其类型,它不会执行表达式。甚至函数调用也被视为一种表达式,因此在使用 decltype 时不会触发函数的执行。
二、decltype 推导规则
-
如果 expression 是一个没有使用括号括起来的标识符,那么 var 的类型将与该标识符的类型相同,包括可能存在的 const 等限定符。
int main(){ int a=1; const double b=2; int *pa = &a; int &ra = a; decltype(a) aa=a;//aa的类型是int,因为a的类型是int decltype(b) bb=b;//bb的类型是const double,因为b的类型是const double decltype(pa) paa=pa;//paa的类型是int*,因为pa的类型是int* decltype(ra) raa=ra;//raa的类型是int&,因为ra的类型是int& decltype(add) *padd=add;//padd的类型是int(*)(int,int),因为add的类型是int(int,int) padd(1,2);//等价于add(1,2),输出3 }
-
如果 expression 是一个函数调用,那么 var 的类型将与该函数的返回值类型相同(注意,函数不能返回 void,但可以返回 void*)。
int add(int a,int b){ return a+b; } int main(){ //c返回值是int类型,和add函数返回值类型一致 decltype(add(1,2)) c = add(1,2); }
-
如果 expression 不是一个变量,是一个表达式,则那么 var 的类型将是表达式对应类型,有些表达式向decltype返回一个引用类型,这种情况说明该表达式的结果对象能作为一条赋值语句的左值。
int main(){ int i=1; int *p=&i; int& r= i; decltype(r+1) b;//b是一个int类型,由于r是一个int&引用,为了想让结果类型是r所指向的类型,可以吧r作为表达式的一部分,如r+1 decltype(*p) c=i;//c是一个int&引用类型,如果表达式的内容是解引用操作,则得到引用类型 }
-
expression 是一个使用括号括起来的标识符,那么 var 的类型就是 expression 类型的引用。
int main(){ int i=1; decltype((i)) ii=i;//ii是int&类型 }
总结:要么decltype返回结果要么和表达式类型相同,要么就是表达式类型的引用。
注意:decltype不会执行表达式,auto后面会执行表达式。
三、函数后置返回类型
函数后置返回类型是一种C++11的新特性,它将函数的返回类型放在函数参数列表之后,使用箭头符号(->)来指定返回类型。例如,下面两个函数声明是等价的:
int func(int x,double y);
等同于
auto func(int x,double y) -> int;
其中,auto是一个占位符,为函数返回值占了一个位置。这种语法也可以用于函数定义:
auto func(int x,double y) -> int
{
// 函数体
}
这种好处就是,针对函数模板,计算出来的值,不知道返回值类型的时候,可以得到返回值类型。
template<typename T1,typename T2>
auto fun(T1 a,T2 b) -> decltype(a+b){
decltype(a+b) result = a+b;
return result;
}
int main(){
auto result = fun(3,3.5);
}
C++14 标准对函数返回类型推导规则做了优化,函数的返回值可以用 auto,不必尾随返回类型。
#include <iostream>
using namespace std;
template<typename T1,typename T2>
auto fun(T1 a,T2 b){
decltype(a+b) result = a+b;
return result;
}
int main(){
auto result = fun(3,3.5);
}