读书笔记
decltype的关注点
两种场景
decltype
有两种推导场景: 标识符的类型和表达式的类型. 区别是带不带括号. 如果不带括号, 表示要推导标识符的类型. 如果带了括号, 表示要推导表达式的类型. 我们通常看得不仔细, 往往会忽略后面一点.
当要推导表达式时, 遵循下面的规则:
- 若表达式的值为左值, 则推导出
T&
- 若表达式的值为纯右值, 则推导出
T
- 若表达式的值类别为将亡值, 则推导出
T&&
例如, 考虑下面的声明:
1 2 3 4 5
| QPoint pt; QPoint* pPt = &pt; const QPoint* cpPt = & pt; QPoint& lrPt = pt; QPoint&& rrPt = {};
|
则表达式推导结果:
1 2 3 4 5 6 7 8 9 10 11 12 13
| using T1 = decltype((pt)); using T2 = decltype((pPt)); using T3 = decltype((pt.x)); using T4 = decltype((++pt.x));
using T11 = decltype((pt.x++)); using T12 = decltype((QPoint(1,1))); using T13 = decltype((5));
using T21 = decltype((QPoint(10,10).x)) using T22 = decltype((std::move(pt))); using T23 = decltype((static_cast<QPoint&&>(pt)));
|
decltype(auto)的处理
在这里面, auto
是一个占位符, 代表了等号右边的表达式. 因此, 我们可以按照这个规则进行理解, 同样存在标识符和表达式的两种场景.
从这个角度看, 它类似于std::forward
, 可以保留值语义和引用语义.
变量的推导:
1 2
| decltype(auto) v1 = pt; decltype(auto) v1 = (pt);
|
函数返回值的推导:
1 2 3 4 5 6 7
| string fun1(); string& fun1();
decltype(auto) test_1() { return fun1(); } decltype(auto) test_2() { return fun2(); } decltype(auto) test_3() { auto str = fun1(); return str; } decltype(auto) test_4() { auto str = fun2(); return (str); }
|
注意test_4()
, 它返回的是一个局部变量的引用!