C++ 变长参数解包
source link: http://pkxpp.github.io/2021/01/09/C -变长参数解包/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
[TOC]
最近,看C++11相关的东西,看到模板变长参数的时候,关于变长参数的代码都看不懂了~
变长参数模板
解包的正确姿势
参考[1][3]中说变长参数模板如何解包的问题,其中一种方法是用逗号表达式+初始化列表的方式,参考[3]
template <class T> void printarg(T t) { cout << t << endl; } template <class ...Args> void expand(Args... args) { int arr[] = {(printarg(args), 0)...}; } expand(1,2,3,4);
其中 {(printarg(args), 0)…} 展开为 (printarg(arg1), 0), (printarg(arg2), 0), (printarg(arg3), 0), (printarg(arg4), 0) 。 如果,我把调用改成 expand(1, 2.987, 3, “abc”); ,结果为
1 2.987 3 abc
解包的错误姿势
参考[2]代码
template <typename T> T func(T value) { return value; } template <typename T, typename ... U> void g(T value, U ...u) { func(u)...; // error C3520: “u”: 必须在此上下文中扩展参数包 } g(1.2, 3.4, 5.6);
可以看到,用法 func(u)… 显示的编译错误
error C3520: “u”: 必须在此上下文中扩展参数包
参考[2]中的有网友给出了一些解决办法
int a[] = {0, (func(u), 0)...};
小结
这里我不懂的地方都是属于变长参数范围,总的来说是这个点自己不清楚。所以,看代码就很疑惑。关于我不懂的地方,现在清楚了一点
- 1.这里的(args)…,就是一个 模式 后面跟着冒号的表达式,表示对这个 模式 进行解包
- 2.解包这个语法使用有限定环境,如果不在限定环境内使用,就会报错 必须在此上下文中扩展参数包
变长参数解包
参考[4][5],这篇非常值得拜读!还有些地方虽然没看懂,但是收获颇丰,基本上我的疑惑都是从这里得到解答了。 列两个模板变长参数解包相关的环境 1. Lambda captures
template<class ...Args> void f(Args... args) { auto lm = [&, args...] { return g(args...); }; lm(); }
2. Brace-enclosed initializers 。 解包的正确姿势 中就是属于这种情况 参考[1]中的代码也属于这种情况。开始以为是lambda那种情况,细细分析一下觉得还是属于初始化列表环境。下面是逐行解析:
template<typename T, typename... Ts> auto printf3(T value, Ts... args) { std::cout << value << std::endl; (void) std::initializer_list<T>{([&args] { std::cout << args << std::endl; }(), value)...}; }
(1)保证环境正确:在*std::initializer_list *后面的花括号环境中,可以使用包展开。 (2)包展开语法:模式...,这里的模式是小括号中的部分。一个lambda表达式和value组成的逗号表达式
([&args] { std::cout << args << std::endl; }(), value)
(3)假设三个参数展开为: ([&arg1] {std::cout « arg1 « std::endl;}(), value), ([&arg2] {std::cout « arg2 « std::endl;}(), value), ([&arg3] {std::cout « arg3 « std::endl;}(), value) 。 这也就是我最终认为,这个例子里面用到的是初始化列表展开,不是属于lambda环境展开。因为初始化列表展开之后到lambda捕获的时候已经不是一个pack了,而是展开之后逐个的元数了。
参考
[1] modern-cpp-tutorial [2] C++可变参数模板展开 [3] 泛化之美–C++11可变模版参数的妙用 [4] Parameter pack [5] 形参包
Recommend
-
42
导读:本文总结了 Python 解包操作的方方面面,文章略长,看本文前,首先确保身边有多个不同版本 Python 解释器的电脑(公众号回复 conda ,了解如何安装多个环境),以便随时验证代码。看完记得收藏,方便查阅) 解包在英文里叫做...
-
52
标题想了很久,最终还是直接表述了。O(∩_∩)O Python 3的可迭代解包 在 PEP 3132 - Extended Iterable Unpacking 里面描述了一种对可迭代对象的解包用法,Pyt...
-
6
使用C++11变长参数模板 处理任意长度、类型之参数实例 变长模板...
-
6
对接C++socket打包发送与解析,打包解包一律使用网络字节序(大端)java该怎么实现? ...
-
4
22 变长参数函数的妙用-慕课专栏 ...
-
4
16 理解包导入路径的含义-慕课专栏 ...
-
4
威联通(QNAP)在2021年9月发布了全新的QTS 5.0系统,笔者最近收到了官方更新通知,于是将自己的TS-551升级到最新版,却发现无论是系统流畅度还是稳定性都与他们宣传的差距甚远,不得不降级到QTS 4.5.4。然而由于QTS 5.0将FTP作为可选软件包(QuFTP)...
-
8
【点滴记录】公主联结自走棋解包记录 - 赵苦瓜のBlog 欢迎食用『【点滴记录】公主联结自走棋解包记录』~,这里是赵苦瓜的看板娘desu~ ...
-
2
WebSocket传输数据服务端的封包解包原理 客户端和服务端传输数据时,需要对数据进行【封包】和【解包】。客户端的JavaScript类库已经封装【封包】和【解包】过程,但Socket服务端需要手动实现。 获取客户端发送的数据【解包】
-
5
如何解包 Python 恶意可执行文件-51CTO.COM 如何解包 Python 恶意可执行文件 作者:Avenger 2022-05-11 14:50:34 使用 Python 编写的程序通常以源码的形式发布,也可以将所有依赖都打...
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK