c++之可变参数格式化字符串(c++11可变模板参数)
本文将使用 泛型 实现可变参数。 涉及到的关见函数: std::snprintf
1、一个例子
函数声明及定义
1 // 泛型
2 template <typename... Args>
3 std::string show_str(const char *pformat, Args... args)
4 {
5 // 计算字符串长度
6 int len_str = std::snprintf(nullptr, 0, pformat, args...);
7
8 if (0 >= len_str)
9 return std::string("");
10
11 len_str++;
12 char *pstr_out = nullptr;
13 pstr_out = new(std::nothrow) char[len_str];
14 // 申请失败
15 if (NULL == pstr_out || nullptr == pstr_out)
16 return std::string("");
17
18 // 构造字符串
19 std::snprintf(pstr_out, len_str, pformat, args...);
20
21 // 保存构造结果
22 std::string str(pstr_out);
23
24 // 释放空间
25 delete pstr_out;
26 pstr_out = nullptr;
27
28 return str;
29 }
2、一个调用例子
1 std::cout << "str = " << show_str("1-%s, 2-%.2f, 3-%d", "ABC", 12.3456, 100).c_str() << "\n";
3、输出结果
演示环境为: VS2015 up3

4、完整代码
1 #include <iostream>
2
3 // 泛型
4 template <typename... Args>
5 std::string show_str(const char *pformat, Args... args)
6 {
7 // 计算字符串长度
8 int len_str = std::snprintf(nullptr, 0, pformat, args...);
9
10 if (0 >= len_str)
11 return std::string("");
12
13 len_str++;
14 char *pstr_out = nullptr;
15 pstr_out = new(std::nothrow) char[len_str];
16 // 申请失败
17 if (NULL == pstr_out || nullptr == pstr_out)
18 return std::string("");
19
20 // 构造字符串
21 std::snprintf(pstr_out, len_str, pformat, args...);
22
23 // 保存构造结果
24 std::string str(pstr_out);
25
26 // 释放空间
27 delete pstr_out;
28 pstr_out = nullptr;
29
30 return str;
31 }
32
33 // 入口函数
34 int main(int argc, char *argv[])
35 {
36 std::cout << "str = " << show_str("1-%s, 2-%.2f, 3-%d", "ABC", 12.3456, 100).c_str() << "\n";
37
38 system("pause");
39 return 0;
40 }
5、总结
A、 new 和 delete 需要配对使用
B、可自定义日志输出格式 和 构造c++格式化字符串。 更加方便输出日志.
6、扩展 (c++11)
A、可变参数模板函数
C++11的新特性--可变模版参数是C++11新增的特性之一,它对参数进行了高度泛化,能表示0到任意个数
一个例子,其定义如下
1 // 可变参数模板函数
2 template <typename ... Args>
3 void vp_func(Args ... args)
4 {
5 // 计算参数个数
6 int count_param = sizeof...(args);
7 std::cout << "参数个数=" << count_param << std::endl;
8 }
其中,计算参数个数的方式:
int count_param = sizeof...(args);
B、调用
1 // 入口函数
2 int main(int argc, char *argv[])
3 {
4 vp_func(1);
5 vp_func("-=+", 1.23456f);
6 vp_func(1, 2.2f, "ABC");
7
8 system("pause");
9 return 0;
10 }
C、输出结果:
演示环境: VS2015 up3

D、解包(包展开)
有两种方式
1)、递归
2)、非递归
递归,好用,但是要考虑爆栈的情况,不推荐。这里就不介绍了。
下面介绍非递归的方式展开
2.1)、定义展开函数
1 // 参数包展开
2 template<typename T>
3 void expand(const T t)
4 {
5 std::cout << t << std::endl;
6 }
再调用展开函数
1 // 可变参数模板函数
2 template <typename ... Args>
3 void vp_func(Args ... args)
4 {
5 // 计算参数个数
6 // int count_param = sizeof...(args);
7 // std::cout << "参数个数=" << count_param << std::endl;
8
9 std::initializer_list<int>{(expand(args), 0)...};
10 // std::initializer_list<int>{([&] {std::cout << args << std::endl; }(), 0)...};
11 }
2.2)、使用lambda 展开
1 // 可变参数模板函数
2 template <typename ... Args>
3 void vp_func(Args ... args)
4 {
5 // 计算参数个数
6 // int count_param = sizeof...(args);
7 // std::cout << "参数个数=" << count_param << std::endl;
8
9 // std::initializer_list<int>{(expand(args), 0)...};
10 std::initializer_list<int>{([&] {std::cout << args << std::endl; }(), 0)...};
11 }
非lambda 完整展开代码:
1 // 参数包展开
2 template<typename T>
3 void expand(const T t)
4 {
5 std::cout << t << std::endl;
6 }
7
8
9 // 可变参数模板函数
10 template <typename ... Args>
11 void vp_func(Args ... args)
12 {
13 // 计算参数个数
14 // int count_param = sizeof...(args);
15 // std::cout << "参数个数=" << count_param << std::endl;
16
17 std::initializer_list<int>{(expand(args), 0)...};
18 // std::initializer_list<int>{([&] {std::cout << args << std::endl; }(), 0)...};
19 }
c++之可变参数格式化字符串(c++11可变模板参数)的更多相关文章
- 零值初始化&字符串常数作为函数模板参数
1.在定义一个局部变量时,并希望该局部变量的初始化一个值,可以显示调用其默认构造函数,使其值为0(bool类型默认值为false). template <typename T> void ...
- Tostring(); 括号中的参数 格式化字符串
最近在逛 msdn 发现 查到 getTypeCode 方法 看到里边居然有 tostring("D")这样的写法 运行了一遍 感觉可以显示值 然后就 ...
- C语言之可变长参数格式化
概述 本文演示环境: win10 + Vs2015 可变长参数格式化 两个概念: 1. 参数长度不定, 2. 参数格式化. 使用函数 vsnprintf 结合 va_list. 源码 写好了函数, 照 ...
- C++ 11可变参数接口设计在模板编程中应用的一点点总结
概述 本人对模板编程的应用并非很深,若要用一句话总结我个人对模板编程的理解,我想说的是:模板编程是对类定义的弱化. 如何理解“类定义的弱化”? 一个完整的类有如下几部分组成: 类的名称: 类的成员变量 ...
- [二进制漏洞]PWN学习之格式化字符串漏洞 Linux篇
目录 [二进制漏洞]PWN学习之格式化字符串漏洞 Linux篇 格式化输出函数 printf函数族功能介绍 printf参数 type(类型) flags(标志) number(宽度) precisi ...
- Linux下的格式化字符串漏洞利用姿势
linux最早的漏洞防护机制nx-stack刚刚出现后就有人想出了突破方法.那就是只有栈是不可执行,而除了栈以外的其他地方还是可以执行的,只要把返回地址执行别的地方就可以. 一.格式化字符串漏洞 格式 ...
- C++ Templates(1.3 多模板参数 Multiple Template Parameters)
返回完整目录 目录 1.3 多模板参数 Multiple Template Parameters 1.3.1 为返回类型设置模板参数参数 Template Parameters for Return ...
- 《深入实践C++模板编程》之三——模板参数类型详解
非类型模板参数 和 模板型模板参数 整数以及枚举类型:指向对象或者函数的指针:对对象或函数的引用:指向对象成员的指针.统称为非类型模板参数. 模板型模板参数,是指模板参数还可以是一个模板. 1.整 ...
- c(++)可变参数之格式化字符串
0.序言 使用printf函数,其参数就是可变参数.下面将使用 C语言 的库函数实现可变参数的函数 . 用途(欢迎补充): A.记录日志,可能需要将变量格式化输出到日志文件. B.格式化字符串,显示 ...
随机推荐
- windows和linux文本的编码格式不一样所出的错
windows下编写的python脚本上传的linux下执行会出现错误: usr/bin/python^M: bad interpreter: No such file or directory 原因 ...
- shell 除法和格式化输出printf
相关知识的补充: printf命令模仿C程序库里的printf()程序.printf由POSIX标准所定义,因此使用printf的脚本比使用echo有着更好的移植性. printf使用引用文本或者空格 ...
- rabbit mq的一个实例,异步功能
简单的使用场景:消息队列的场景有:解耦,异步,削峰. 此例用的场景,异步 有时候会有请求消耗时间过长,不能老让用户等待返回结果,可以用消息队列来做异步实现,之前用过workmain等类似的异步,但不如 ...
- Python序列化,json&pickle&shelve模块
1. 序列化说明 序列化可将非字符串的数据类型的数据进行存档,如字典.列表甚至是函数等等 反序列化,将通过序列化保存的文件内容反序列化即可得到数据原本的样子,可直接使用 2. Python中常用的序列 ...
- QQ空间技术架构之深刻揭秘
QQ空间技术架构之深刻揭秘 来源: 腾讯大讲堂 发布时间: 2012-05-17 17:24 阅读: 7822 次 推荐: 4 [收藏] QQ 空间作为腾讯海量互联网服务产品,经过近七年 ...
- Python中的随机采样和概率分布(二)
在上一篇博文<Python中的随机采样和概率分布(一)>(链接:https://www.cnblogs.com/orion-orion/p/15647408.html)中,我们介绍了Pyt ...
- Azure Key Vault(二)- 入门简介
一,引言 在介绍 Azure Key Vault 之前,先简单介绍一下 HSM(硬件安全模块). -------------------- 我是分割线 -------------------- 1,什 ...
- C++ 继续(3n+1)猜想
1005 继续(3n+1)猜想 (25分) 卡拉兹(Callatz)猜想已经在1001中给出了描述.在这个题目里,情况稍微有些复杂. 当我们验证卡拉兹猜想的时候,为了避免重复计算,可以记录下递推过 ...
- mysql触发器实例说明
触发器是一类特殊的事务 ,可以监视某种数据操作(insert/update/delete),并触发相关操作(insert/update/delete). 看以下事件: 完成下单与减少库存的逻辑 Ins ...
- navigationItem的leftBarButtonItem和rightBarButtonItem隐藏
- (void)showEdit { if (不符合显示条件) { self.navigationItem.rightBarButtonItem.customView.hidden = YES; // ...