C++中decltype的推导规则详解

C++中decltype的推导规则详解

我们先来看看 decltype(exp)的推导规则:
口推导规则 1,exp是标识符、类访问表达式,decltype(exp)和exp的类型一致。
口推导规则 2,exp是函数调用,decltype(exp)和返回值的类型一致。
口推导规则 3,其他情况,若exp是一个左值,则decltype(exp)是exp类型的左值引用,否则和 exp 类型一致。
只看上面的推导规则,很难理解 decltype(exp)到底是一个什么类型。为了更好地讲解这些规则的适用场景,下面根据上面的规则分3种情况依次讨论
1)标识符表达式和类访问表达式。
2)函数调用(非标识符表达式,也非类访问表达式)。
3)带括号的表达式和加法运算表达式(其他情况)。

(1) 标识符表达式和类访问表达式
代码清单1-3是一组简单的例子。

class Foo
{
public :
static const int Number = 0;
int x;
};

int n = 0;
volatile const int & x = n;

decltype(n) a = n; // a -> int
decltype(x) b = n; // b -> const volatile int &

decltype(Foo::Number) c = 0; //c -> const int

Foo foo;
decltype(foo.x) d = 0; //d->int,类访问表达式

变量 a、b、c保留了表达式的所有属性(cv、引用)。这里的结果是很简单的,按照推导规则1,对于标识符表达式而言,decltype 的推导结果就和这个变量的类型定义一致。d是一个类访问表达式,因此也符合推导规则1。
(2)函数调用
如果表达式是一个函数调用(不符合推导规则1),结果会如何呢?
请看代码清单1-4所示的示例。

int& func_int_r(void); //左值(lvalue,可简单理解为可寻址值)
int&& func_int_rr(void); //x值(xvalue,右值引用本身是一个xvalue)
int func_int(void);    // 纯右值(prvalue)

const int& func_cint_r(void);     //左值
const int&& func_cint_rr(void);   //x值
const int func_cint(void);        //纯右值

const Foo func_cfoo(void);    //纯右值

//下面是测试语句
int x = 0;

decltype(func_int_r())   al = x;     // al -> int &
decltype(func_int_rr())  b1 = 0;     // b1 -> int &&
decltype(func_int())     c1 = 0;     // c1 -> int

decltype(func_cint_r())  a2 = x;     // a2 -> const int &
decltype(func_cint_rr()) b2 = 0;     // b2 -> const int &&
decltype(func_cint())    c2 = 0;     // c2 -> int

decltype(func_cfoo())    ff = Foo(); // ff -> const Foo

可以看到,按照推导规则2,decltype的结果和函数的返回值类型保持一致。这里需要注意的是,c2是int而不是constint。这是因为函数返回的int是一个纯右值(prvalue)。对于纯右值而言,只有类类型可以携带cv限定符,此外则一般忽略掉 cy限定。decltype 推导出来的c2是一个int。作为对比,可以看到decltype根据funccfoo()推导出来的f的类型是 const Foo。参见【0voice C++】

(3)带括号的表达式和加法运算表达式
最后,来看看第三种情况:

struct Foo { int x; };
const Foo foo = Foo();

decltype(foo.x)   a = 0;  //a -> int
decltype((foo.x)) b = a;  //b->const int &

int n = 0, m = 0;
decltype(n + m) c = 0;   //c -> int
decltype(n += m) d = c; //d -> int &

a和b的结果:仅仅多加了一对括号,它们得到的类型却是不同的。
a的结果是很直接的,根据推导规则1,a的类型就是foo.x的定义类型。
b的结果并不适用于推导规则1和2。根据fo0.x是一个左值,可知括号表达式也是一个左值。因此可以按照推导规则3,知道 decltype的结果将是一个左值引用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值