C++ Primer Plus(第6版)学习笔记-decltype

为什么要有 decltype

在使用模版编程时,由于模版传入的参数的类型不确定,通过这些参数计算出来结果的类型也不确定。如下示例:

template<class T1, class T2>
void ft(T1 x, T2 y){
    ?type? xpy = x + y;   
}

这里的 xpy 无法直接定义是什么类型。在原先的 C++98 对这种现象无能为力。因此在 C++11 中,增加了类型定义的方式,就是 decltype。

decltype 定义方式

decltype(x + y) xpy; 

这个就是使用 decltype 定义 xpy 的方式。

PS:这里可以理解为用 decltype(x + y) 替换了 int / short / char /...。

编译器确定 decltype 类型的方法

为了表述方便,这里我们可以把 decltype 的定义抽象成:

decltype(expression) var

我们编写了 decltype 之后,编译器在编译过程中就需要确定 decltype(expression) 的具体类型应该是什么。这个时候编译器会按如下优先级来确定 decltype(expression) 中的类型具体应该是什么。一旦匹配到了,后面就不会再去匹配了。

优先级1:expression是没有用括号括起的标识符——完全复刻类型

如果expression是一个没有用括号括起的标识符,则var的类型与该标识符的类型相同,包括const等限定符,下面是几个例子:

double x = 5.5;
double y = 7.9;
double& rx = x;
const double* pd;
decltype(x) w; // w is type double
decltype(rx) u = y; // u is type double&
decltype(pd) v;// v is type const double*

也就是说,在这种情况下, decltype(expression) 的类型完全复刻 expression 的类型。

优先级2:expression 是一个函数——取返回值

如果expression是一个函数调用,则var的类型与函数的返回类型相同:

long indeed(int);
decltype (indeed(3)) m; // m is type in

这个时候是通过函数的原型来查看返回值是什么,而不会真的去执行一遍函数。

PS:如果 decltype 声明的是函数本身应该怎么办?应该直接使用 decltype(indeed) 来表示。但是函数的定义又非常特殊,实际调试猪呢个,不能直接写成:

decltype (indeed) func;

虽然这样定义是成功的,但是没有办法使用(在编译器链接时报错)。实际使用时有两种定义方法

decltype (indeed)& func = indeed;
// 或者
decltype (indeed)* func = indeed;
// 或者
decltype ((indeed)) func = indeed; // 匹配优先级3中的规则

优先级3:expression是一个左值

如果expression是一个左值,则var为指向其类型的引用。

虽然前面例子里面类似 decltype(x) 中的 x 也是左值,但是由于已经符合了优先级1 所以就不会到优先级3 来匹配了。

这里会用另一种方法来表示:

decltype((x)) w;

优先级4:其他情况

如果上述都不满足,则var的类型与expression的类型相同

int j = 3;
int &k = j
int &n = j;
decltype(j +6) i1;   // i1 type int
decltype(100L) i2;   // i2 type long
decltype(k+n) i3;    // i3 type int

使用 decltype 解决函数返回值的不确定问题

前面讲述的都是在函数内部,由于传入参数先做了声明,因此编译器可以通过 decltype 来找到类型。例如:

template<class T1, class T2>
void ft(T1 x, T2 y){
    decltype(x + y) xpy = x + y;   
}

但是如果返回值也不确定,就不能直接用 decltype 了,下面的代码就是错误的:

template<class T1, class T2>
decltype(x + y) ft(T1 x, T2 y){
    return x + y;   
}

这是因为在 decltype(x + y) 时还没有声明 x y 的类型,decltype(x + y) 不在作用域内,所以编译器不知道 decltype(x + y) 的类型是什么。

因此 C++11 提供了声明和定义函数的语法,类似于:

auto func(x + y) -> double

前面的 auto 是占位符,后面的 double 才是返回的类型。用这种方式来声明模版的不确定返回值,就是:

template<class T1, class T2>
auto ft(T1 x, T2 y) -> decltype(x + y) {
    return x + y;   
}

此时的 decltype(x + y) 在 x y 的作用域内,因此是有效的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

攻城狮-小文

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值