本文将使用 泛型 实现可变参数。 涉及到的关见函数:  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. 零值初始化&字符串常数作为函数模板参数

    1.在定义一个局部变量时,并希望该局部变量的初始化一个值,可以显示调用其默认构造函数,使其值为0(bool类型默认值为false). template <typename T> void ...

  2. Tostring(); 括号中的参数 格式化字符串

    最近在逛 msdn 发现    查到  getTypeCode 方法  看到里边居然有 tostring("D")这样的写法      运行了一遍 感觉可以显示值      然后就 ...

  3. C语言之可变长参数格式化

    概述 本文演示环境: win10 + Vs2015 可变长参数格式化 两个概念: 1. 参数长度不定, 2. 参数格式化. 使用函数 vsnprintf 结合 va_list. 源码 写好了函数, 照 ...

  4. C++ 11可变参数接口设计在模板编程中应用的一点点总结

    概述 本人对模板编程的应用并非很深,若要用一句话总结我个人对模板编程的理解,我想说的是:模板编程是对类定义的弱化. 如何理解“类定义的弱化”? 一个完整的类有如下几部分组成: 类的名称: 类的成员变量 ...

  5. [二进制漏洞]PWN学习之格式化字符串漏洞 Linux篇

    目录 [二进制漏洞]PWN学习之格式化字符串漏洞 Linux篇 格式化输出函数 printf函数族功能介绍 printf参数 type(类型) flags(标志) number(宽度) precisi ...

  6. Linux下的格式化字符串漏洞利用姿势

    linux最早的漏洞防护机制nx-stack刚刚出现后就有人想出了突破方法.那就是只有栈是不可执行,而除了栈以外的其他地方还是可以执行的,只要把返回地址执行别的地方就可以. 一.格式化字符串漏洞 格式 ...

  7. C++ Templates(1.3 多模板参数 Multiple Template Parameters)

    返回完整目录 目录 1.3 多模板参数 Multiple Template Parameters 1.3.1 为返回类型设置模板参数参数 Template Parameters for Return ...

  8. 《深入实践C++模板编程》之三——模板参数类型详解

    非类型模板参数 和 模板型模板参数 整数以及枚举类型:指向对象或者函数的指针:对对象或函数的引用:指向对象成员的指针.统称为非类型模板参数. 模板型模板参数,是指模板参数还可以是一个模板.   1.整 ...

  9. c(++)可变参数之格式化字符串

    0.序言 使用printf函数,其参数就是可变参数.下面将使用 C语言  的库函数实现可变参数的函数 . 用途(欢迎补充): A.记录日志,可能需要将变量格式化输出到日志文件. B.格式化字符串,显示 ...

随机推荐

  1. Linux系统编程之命名管道与共享内存

    在上一篇博客中,我们已经熟悉并使用了匿名管道,这篇博客我们将讲述进程间通信另外两种常见方式--命名管道与共享内存. 1.命名管道 管道是使用文件的方式,进行进程之间的通信.因此对于管道的操作,实际上还 ...

  2. [R] read.table/read.delim读入数据行数变少?

    以为对read.table/read.delim很熟了,谁知又掉坑里了. 我有个3万多行的数据集,包括样品表达量和注释信息.大概长这样: 本来3万多行,可是读进来的时候变成了1万多行,而且read.d ...

  3. python的包与模块

    win +R d

  4. android Fragment跳转Fragment

    android Fragment跳转Fragment,最新的android studio3 在系统模板建立的BottomNavigationView 中跳转方式 此版本下不能用FragmentMana ...

  5. Mac下source tree 下的安装

    安装时出现了以下错误,解决方法 git -c diff.mnemonicprefix=false -c core.quotepath=false -c credential.helper=source ...

  6. A Child's History of England.25

    It was a September morning, and the sun was rising, when the King was awakened from slumber by the s ...

  7. Hadoop、Hive【LZO压缩配置和使用】

    目录 一.编译 二.相关配置 三.为LZO文件创建索引 四.Hive为LZO文件建立索引 1.hive创建的lzo压缩的分区表 2.给.lzo压缩文件建立索引index 3.读取Lzo文件的注意事项( ...

  8. Android 高级UI组件(一)GridView与ListView

    1.GridView 1.GridView学习 GridView和ListView都是比较常用的多控件布局,而GridView更是实现九宫图的首选 main.xml: <?xml version ...

  9. 【Services】【Web】【Nginx】静态下载页面的安装与配置

    1. 拓扑 F5有自动探活机制,如果一台机器宕机,请求会转发到另外一台,省去了IPVS漂移的麻烦 F5使用轮询算法,向两台服务器转发请求,实现了负载均衡 2. 版本: 2.1 服务器版本:RHEL7. ...

  10. spring中JDBCTemplate的简单应用

    package cn.itcast.datasource.jdbctemplate;import cn.itcast.utils.JDBCUtils;import org.springframewor ...