类型推导之decltype

decltype关键字
跟auto一样,也是用来实现类型推导,但是auto只能根据变量的初始化表达式来推导,即必须初始化。
decltype也是在编译时推导,不会实际计算表达式的值,类似于一元运算符sizeof

如:

	decltype (func()) sum = x;			//sum的类型为函数func的返回值的类型,这里并不调用函数func




推导规则:
1、如果对decltype使用的表达式是一个不加括号的变量,或者是一个类成员变量访问表达式,则推导出的类型为表达式一致,且保留CV限定与引用
如:
		volatile const int& x = 0;
		decltype (x) a ;				//a -> const volatile int&  同时,由于没有对引用进行初始化,此句错误
		
		int *p = &x;
		decltype (p)* pp = &p;		//pp -> int **
		
		class Foo
		{		
		public:
			static const int NUmber = 0;
		int x;
		
		}


		decltype (Foo::NUmber) c = 0;	//c -> const int
		Foo foo;
		decltype (foo.x) d = 0;			//d -> int


		int h = 0;
		decltype (h) i = 0;				//i -> int


2、如果对decltype使用的表达式是函数调用,推导出的类型和返回值一致,如果函数返回的是一个临时变量,推导类型为右值引用,如果函数是重载函数,编译器将报错
如:
		decltype (Foo()) j = 0;			//j -> Foo&&	构造函数返回了临时变量
		
		int&& fun();
		decltype (fun()) K = 0;			//k -> int&&
		
		int func();
		decltype (func()) sum = x;		//sum -> int	普通函数调用
		
		const int func_cint ();
		decltype (func_cint()) l = 0;		//l -> int		函数返回值为右值
		
		const Foo func_cfoo();			
		decltype (func_cfoo()) m = Foo;		//m -> const Foo	返回值为类类型的右值可以带CV限定符


3、如果对decltype使用的表达式结果是左值,推导出的类型为左值引用,表达式结果是右值,则推导出的类型为右值的类型
如:
		//此段代码摘自:http://www.cnblogs.com/QG-whz/p/4952980.html
		int i = 4;
		int arr[5] = { 0 };
		int *ptr = arr;
 
 
		decltype (true ? i : i) var7 = i; //int&  条件表达式返回左值。
 
		decltype (++i) var8 = i; //int&  ++i返回i的左值。
 
		decltype (arr[5]) var9 = i;//int&. []操作返回左值
 
		decltype (*ptr)var10 = i;//int& *操作返回左值
 
		decltype ("hello")var11 = "hello"; //const char(&)[9]  字符串字面常量为左值,且为const左值。


		decltype (1) var12;//const int
		
		decltype (i++) var14 = i;//int i++返回右值
		
		int n = 0, p = 0;
		decltype (n + p) q;			//q ->int
		decltype (n += p) r;		//r ->int&


4、如果对decltype使用的表达式被括号括起来了,类型推导的结果永远是左值引用
如:
		int y = 0;
		decltype ((y)) z;			//z -> int&			同时,由于没有对引用进行初始化,此句错误


5、C++ primer上的一个情况
	int	i = 42, &r = i;
	decltype (r + 0) b;			//b -> int

解释:因为r是一个引用,因此decltype (r)的结果为引用类型,如果想让结果类型时r所指的类型,可以把r作为表达式的一部分,如r + 0,显然这个表达式的结果将是一个具体的值而非一个引用

应用
1.推导出表达式类型
2.与using/typedef合用,用于定义类型。
3.重用匿名类型
4.泛型编程中结合auto,用于追踪函数的返回值类型

参考
C++11特性:decltype关键字 http://www.cnblogs.com/QG-whz/p/4952980.html
C++ Primer
深入应用C++ 11

你可能感兴趣的:(C++,11专题)