根据我上一片博客的介绍–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不是引用。
如果需要多次声明,可以结合使用typdef和decltype:
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位于作用域内,可以使用它们。