003-EMC 深入解读-理解模板型别推导(三)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/q1007729991/article/details/82912190

上一篇文章我们介绍了 ParamType 是引用或指针的情况,这一节继续第二条规则,也是最复杂的规则。

  • ParamType 是引用或指针,但不是通用引用
  • ParamType 是通用引用
  • ParamType 既非指针也非引用

1. ParamType 是通用引用

首先你得明白,何为通用引用(Universal Reference). 下面是一个比较平易近人的定义:

"函数模板中持有型别形参 T 时,Universal Reference 类型写作 T&&"

注意:不要将通用引用与左值引用相混淆,虽然看上去长的很像。

例如:

// T&& 称为通用引用
template<typename T>
void f(T&& param);

那么通用引用的推导规则是怎样的?

针对于 f(expr) 调用:

  • 如果 expr 是左值,T 会被推导成一个引用(同时保留类型修饰词,比如 const),T&& 也会被推导成引用。(这很奇怪,后面会解释。)
  • 如果 expr 是右值,对 expr 的型别与 T 执行模式匹配,决定 T 的型别。(这也很抽象,后面看例子。)

下面来看示例:

template<typename T>
void f(T&& param);

int x = 27;
const int cx = x;
const int& rx = x;

// x 是左值,T 是 int&, T&& = int&&& = int&
f(x);

// cx 是左值,T 是 const int&, T&& = const int&&& = const int&
f(cx);

// rx 是左值,T 是 const int&, T&& = const int&&& = const int&
f(rx);

// 27 是右值,T 是 int, T&& = int&&
f(27);

比较奇怪的是,当 T 被推导为一个引用时,T&& 也被推导为一个引用,就像:

T = int&
T&& = int&&& = int&

这种变换是什么鬼?到这里,编译器会一声不坑的帮你把 int&&& 处理成 int&,这背后实际上是一种被称为“引用折叠”的东西在搞鬼。你暂时可以理解为下面这几种情况:

T& + & = T&
T&& + & = T&
T& + && = T&
T&& + && = T&&

不过后面,到了 item28 的时候,还会详细描述。

2. 实验

在这个系列的文章中,我准备了大量的代码来验证我们的想法。您可以拉取所有代码进行阅读,欢迎随时留言提问。

所有的验证代码都托管在这里:https://github.com/ivanallen/emc

本节的代码路径:emc/item01/demo04.cpp

在这里插入图片描述

3. 总结

  • 理解通用引用时的推导规则

猜你喜欢

转载自blog.csdn.net/q1007729991/article/details/82912190
EMC
003