C++11 decltype关键字

1.1 decltype语法

在C++11中增加了decltype关键字(表达式:decltype(exp)),用来在编译时推导出一个表达式的类型,并且不会真正计算表达式的值。
int x = 0;
decltype(x) y = 1;			//y->int
decltype(x + y) z = 0;		//z->int


const int& i = x;
decltype(i) j = y;			//j->const int&


const decltype(z) *p = &z;	//*p->const int, p->const int*
decltype(z) *pi = &z;		//*pi->int, pi->int*
decltype(pi) * pp = π	//*pp->int*, pp->int**

1.2 decltype的推导规则

表达式:decltype(exp)
(1)exp是标识符、类访问表达式,decltype(exp)和exp的类型一致

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


int n=0;
volatile const int &x = n;	//volatile:直接存取原始内存地址


decltype(n) a = n;			//a->int
decltype(x) b = n;;			//b->const int&
decltype(Foo::num) c = 0;	//c->const int


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

(2)exp是函数调用,decltype(exp)和返回值的类型一致
int& func_int_r(void);				//左值(可以理解为可寻址值)
int&& func_int_rr(void);			//x值
int func_int(void);					//纯右值


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


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


//test
int x = 0;
decltype(func_int_r()) a1 = x;		//a1->int&
decltype(func_int_rr()) b1 = 0;		//b1->int&&
decltype(func_int()) c1 = 0;		//c1->int,对于纯右值而言,只有类类型可以携带const修饰符,此外的一般忽略掉const属性


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


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

(3)其它情况,若exp是一个左值,则decltype(exp)是exp类型的左值引用,否则和exp类型一致.(左值指的是既能够出现在等号左边也能出现在等号右边的变量(或表达式),右值指的则是只能出现在等号右边的变量(或表达式))
带括号的表达式和加法运算表达式

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(m+n) c = 0;		//c->int
decltype((m+=n)) d = c;		//d->int&
m+n返回一个右值,按照规则3, decltype的结果为int
m+=n返回一个左值,按照规则3,decltype的结果为int&(左值返回引用)

1.3 decltype应用场景

decltype多应用在泛型编程之中,例如如下的代码:
template<typename T> class
{
	typename T::iterator it;
	void func(T t)
	{
		it = t.begin();	//这里取它迭代器的首位置
	}
};

但是需要const迭代器的时候,就需要对代码进行维护了,为代码加入const迭代器
template<typename T> class
{
	typename T::const_iterator it;
	void func(T t)
	{
		it = t.begin();	//这里取它迭代器的首位置
	}
};

但是在使用了decltype之后就不要这样了,上面的代码可以写成
template<typename T> class
{
	decltype(T.begin()) it;
	void func(T t)
	{
		it = t.begin();	//这里取它迭代器的首位置
	}
};

实际上,标准库中有些类型都是通过decltype来定义的:
typedef decltype(nullptr) nullptr_t;
typedef decltype(sizeof(0)) size_t;


  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值