[原]C++ decltype 关键字学习

陈苏扬 18/10/04 07:40:50

根据我上一片博客的介绍–c++函数模板初探
我们可以用模板实现很多函数,也对c++函数模板有了初步的了解。

但是加入有下面这个情况:

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

在这种情况下xpy应该是什么类型呢?由于不知道ft()将如何使用,因此无法预知这一点。正确的类型可能是T1、T2或者其他类型。假如又出现了重载运算符,这会让问题更加的复杂。

于是为了解决这个问题,c++11新增了关键字 decltype

我们可以这样使用:

int x;
decltype(x) y;//y的类型和x类型一致

除了上述这样写,我们也可以这样写:

decltype(x+y) xpy;
xpy = x+y;

通过这个关键字,我们可以把前面的代码修改成这样:

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

	...
}

decltype比这些实例要复杂些。为了确定类型,编译器必须遍历一个核对表。假设有如下声明:

decltype (expression) var;

1.如果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 *

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

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

这里并不会实际调用函数。编译器通过查看函数的原型来获悉返回类型,而无需实际调用函数。

3.加入expression是用括号括起来的标识符:

double xx = 4.4;
decltype((xx)) r2 = xx ; // r2 is double &
decltype(xx) w = xx; // w is double

括号并不会改变表达式的值和左值性。

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

虽然k和n都是引用,是表达式k+n不是引用。
如果需要多次声明,可以结合使用typdefdecltype:

template <class T1, class T2>
void ft(T1 x, T2 y)
{
	typedef decltype (x+y) xytype;
	xytype xpy = x+y;
	xytype arr[10];
	xytype &rxy = arr[2]; // rxy a reference
}

还有一个问题是decltype没有办法解决的:

template <class T1, class T2>
?type? gt(T1 x, T2 y)
{
	return x+y;	
}

同样无法预知x和y相加得到的类型。看起来我们还可以用decltype,但是很不幸,这个时候还没有声明x和y,它们不在作用域内。**必须在声明参数后使用decltype。**为此,c++新增了一种声明和定义函数的语法。

double h(intx, float y);
可以用新增的语法编写成这个样子:
auto h(int x, float y) -> double;

这将返回类型移到了参数声明后面。->double被称为后置返回类型(trailing return type)。 其中auto是一个占位符,表示后置返回类型提供的类型。这是c++11的新增auto语法。这个语法也可以用于函数定义。

auto h (int x, float y) -> double
{/* function body*/};

通过结合使用这种语法和decltype,便可以给gt()指定返回类型。

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

现在,decltype在参数声明后面,因此x和y位于作用域内,可以使用它们。

作者:helloworld19970916 发表于 2018/10/04 07:40:50 原文链接 https://blog.csdn.net/helloworld19970916/article/details/82935374
阅读:13