设为首页收藏本站
网站公告 | 这是第一条公告
     

 找回密码
 立即注册
缓存时间20 现在时间20 缓存数据 和聪明人交流,和靠谱的人恋爱,和进取的人共事,和幽默的人随行。晚安!

和聪明人交流,和靠谱的人恋爱,和进取的人共事,和幽默的人随行。晚安!

查看: 1140|回复: 3

浅析C++模板类型中的原样转发和可变参数的实现

[复制链接]

  离线 

TA的专栏

  • 打卡等级:热心大叔
  • 打卡总天数:229
  • 打卡月天数:0
  • 打卡总奖励:3470
  • 最近打卡:2025-10-09 19:06:38
等级头衔

等級:晓枫资讯-上等兵

在线时间
0 小时

积分成就
威望
0
贡献
385
主题
361
精华
0
金钱
4624
积分
808
注册时间
2023-1-21
最后登录
2025-10-9

发表于 2023-2-13 10:49:50 | 显示全部楼层 |阅读模式
原样转发的意义

前文我们实现了一个my_move函数,用来模拟stl的move操作,实现去引用的功能。其内部的原理就是通过remove_reference实现去引用操作。
有时我们也需要保留原类型的左值或者右值属性,进行原样转发,此时就要用forward实现转发功能。
我们先定义一个模板函数
  1. template <typename F, typename T1, typename T2>
  2. void flip1(F f, T1 t1, T2 t2)
  3. {
  4.     f(t2, t1);
  5. }
复制代码
flip1内部调用了函数f
我们写一个函数测试
  1. void ftemp(int v1, int &v2)
  2. {
  3.     cout << v1 << " " << ++v2 << endl;
  4. }
  5. void use_ftemp(){
  6.     int j = 100;
  7.     int i = 99;
  8.     flip1(ftemp, j, 42);
  9.     cout << "i is " << i << " j is " << j << endl;
  10. }
复制代码
通过打印发现i和j的值没有变化,因为ftemp的v2参数虽然是引用,但是是flip1的形参t1的引用
t1只是形参,修改t1并不能影响外边的实参j。
想要达到修改实参的目的,需要将flip1的参数修改为引用,我们先实现修改后的版本flip2
  1. template <typename F, typename T1, typename T2>
  2. void flip2(F f, T1 &&t1, T2 &&t2)
  3. {
  4.     f(t2, t1);
  5. }
复制代码
我们定义了一个flip2函数,t1和t2分别是右值引用类型。接下来用一个测试函数进行测试
  1. int j = 100;
  2. int i = 99;
  3. flip2(ftemp, j, 42);
  4. cout << "i is " << i << " j is " << j << endl;
复制代码
这次我们发现j被修改了,因为flip2的t1参数类型为T1的右值引用,当把实参j赋值给flip2时,T1变为int&,
t1的类型就是int& &&,通过折叠t1变为int&类型。这样t1就和实参j绑定了,在flip2内部修改t1,就达到了修改j的目的。
但是flip2同样存在一个问题,如果flip2的第一个参数f,如果f是一个接受右值引用参数的函数,会出现编译错误。
为说明这一点,我们实现一个接纳模板参数右值引用类型的函数
  1. void gtemp(int &&i, int &j)
  2. {
  3.     cout << "i is " << i << " j is " << j << endl;
  4. }
复制代码
此时如果我们将gtemp作为参数传递给flip2会报错
  1. int j = 100;
  2. int i = 99;
  3. // flip2(gtemp, j, 42) 会报错
  4. // 因为42作为右值纯递给flip2,t2会被折叠为int&类型
  5. // t2传递给gtemp第一个参数时,int&&无法绑定int&类型
  6. //flip2(gtemp, i, 42);
  7. cout << "i is " << i << " j is " << j << endl;
复制代码
当我们将42传递给flip2第二个参数时,T2被实例化为int类型,t2就变为int && 类型,通过折叠t2变为int&类型。
t2作为参数传递给gtemp的第一个参数时会报错,
  1. cannot bind rvalue reference of type ‘int&&’ to lvalue of type ‘int’
复制代码
因为t2是一个左值,右值无法绑定该左值。
解决的办法就是实现一个flip函数,内部实现对T2,T1类型的原样转发。
  1. template <typename F, typename T1, typename T2>
  2. void flip(F f, T1 &&t1, T2 &&t2)
  3. {
  4.     f(std::forward<T2>(t2), std::forward<T1>(t1));
  5. }
复制代码
通过forward将t2类型转化为和T2类型一样的类型,也就是int的右值类型,接下来的调用就不会出问题了
  1. void use_ftemp()
  2. {
  3.     int j = 100;
  4.     int i = 99;
  5.     flip(gtemp, i, 42);
  6.     cout << "i is " << i << " j is " << j << endl;
  7. }
复制代码
模板的可变参数

模板同样支持可变参数
  1. //可变参数的函数模板
  2. template <typename T>
  3. ostream &print(ostream &os, const T &t)
  4. {
  5.     return os << t; //输出最后一个元素
  6. }
  7. template <typename T, typename... Args>
  8. ostream &print(ostream &os, const T &t, const Args &...rest)
  9. {
  10.     os << t << ", ";
  11.     return print(os, rest...);
  12. }
复制代码
Args是可变的模板参数包, 然后再用Args定义rest变量,这是一个可变参数列表。
我们的模板函数print内部调用stl的print函数,通过对rest…实现展开操作。
调用过程可按如下的方式
  1. void use_printtemp()
  2. {
  3.     int i = 100;
  4.     string s = "hello zack!!!";
  5.     print(cout, i, s, 42);
  6. }
复制代码
第一次调用print实际是调用的可变参数的print,之后才调用没有可变参数的print函数。

总结

本文介绍了模板类型的原样转发,以及多模板参数列表的使用。
视频链接
源码链接
到此这篇关于浅析C++模板类型中的原样转发和可变参数有什么意义的文章就介绍到这了,更多相关C++原样转发和可变参数内容请搜索晓枫资讯以前的文章或继续浏览下面的相关文章希望大家以后多多支持晓枫资讯!

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
晓枫资讯-科技资讯社区-免责声明
免责声明:以上内容为本网站转自其它媒体,相关信息仅为传递更多信息之目的,不代表本网观点,亦不代表本网站赞同其观点或证实其内容的真实性。
      1、注册用户在本社区发表、转载的任何作品仅代表其个人观点,不代表本社区认同其观点。
      2、管理员及版主有权在不事先通知或不经作者准许的情况下删除其在本社区所发表的文章。
      3、本社区的文章部分内容可能来源于网络,仅供大家学习与参考,如有侵权,举报反馈:点击这里给我发消息进行删除处理。
      4、本社区一切资源不代表本站立场,并不代表本站赞同其观点和对其真实性负责。
      5、以上声明内容的最终解释权归《晓枫资讯-科技资讯社区》所有。
http://bbs.yzwlo.com 晓枫资讯--游戏IT新闻资讯~~~

  离线 

TA的专栏

等级头衔

等級:晓枫资讯-列兵

在线时间
0 小时

积分成就
威望
0
贡献
0
主题
0
精华
0
金钱
21
积分
22
注册时间
2022-12-28
最后登录
2022-12-28

发表于 2025-4-12 03:22:49 | 显示全部楼层
感谢楼主分享。
http://bbs.yzwlo.com 晓枫资讯--游戏IT新闻资讯~~~

  离线 

TA的专栏

等级头衔

等級:晓枫资讯-列兵

在线时间
0 小时

积分成就
威望
0
贡献
0
主题
0
精华
0
金钱
14
积分
8
注册时间
2022-12-29
最后登录
2022-12-29

发表于 2025-11-28 19:31:04 | 显示全部楼层
顶顶更健康!!!
http://bbs.yzwlo.com 晓枫资讯--游戏IT新闻资讯~~~

  离线 

TA的专栏

等级头衔

等級:晓枫资讯-列兵

在线时间
0 小时

积分成就
威望
0
贡献
0
主题
0
精华
0
金钱
18
积分
16
注册时间
2022-12-27
最后登录
2022-12-27

发表于 3 天前 | 显示全部楼层
路过,支持一下
http://bbs.yzwlo.com 晓枫资讯--游戏IT新闻资讯~~~
严禁发布广告,淫秽、色情、赌博、暴力、凶杀、恐怖、间谍及其他违反国家法律法规的内容。!晓枫资讯-社区
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

1楼
2楼
3楼
4楼

手机版|晓枫资讯--科技资讯社区 本站已运行

CopyRight © 2022-2025 晓枫资讯--科技资讯社区 ( BBS.yzwlo.com ) . All Rights Reserved .

晓枫资讯--科技资讯社区

本站内容由用户自主分享和转载自互联网,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责。

如有侵权、违反国家法律政策行为,请联系我们,我们会第一时间及时清除和处理! 举报反馈邮箱:点击这里给我发消息

Powered by Discuz! X3.5

快速回复 返回顶部 返回列表