本文将使用 泛型 实现可变参数。 涉及到的关见函数:  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. ubuntu 常用指令

    1.进入到root权限的指令 sudo su,效果同su,只是不需要root的密码,而需要当前用户的密码.(亲测有效) 2.从root权限里面退出到 普通用户模式 exit---指令亲测有效 3.下载 ...

  2. Linux——基础命令用法(下)

    一.linux用户 1.什么是用户 用户是用来运行某一些进程.拥有某一些文件或目录. 在Linux里面,用户分成三大类:root用户.系统用户.普通用户. 用户是用UID来唯一标识身份的,且root用 ...

  3. MybatisPlus的CRUD及拓展

    创建一个简单的MybatisPlus项目在上一篇博客:MybatisPlus入门程序 一.CRUD 1. select 1.1 查找全部用户 //查 @Test public void select( ...

  4. Mysql索引数据结构详解(1)

    慢查询解决:使用索引  索引是帮助Mysql高效获取数据的排好序的数据结构 常见的存储数据结构: 二叉树    二叉树不适合单边增长的数据 红黑树(又称二叉平衡树)    红黑树会自动平衡父节点两边的 ...

  5. 【分布式】ZooKeeper权限控制之ACL(Access Control List)访问控制列表

    zk做为分布式架构中的重要中间件,通常会在上面以节点的方式存储一些关键信息,默认情况下,所有应用都可以读写任何节点,在复杂的应用中,这不太安全,ZK通过ACL机制来解决访问权限问题,详见官网文档:ht ...

  6. java中的collection小结

    Collection 来源于Java.util包,是非常实用常用的数据结构!!!!!字面意思就是容器.具体的继承实现关系如下图,先整体有个印象,再依次介绍各个部分的方法,注意事项,以及应用场景.   ...

  7. Output of C++ Program | Set 3

    Predict the output of below C++ programs. Question 1 1 #include<iostream> 2 using namespace st ...

  8. my38_MySQL事务知识点零记

    从innodb中查看事务信息 show engine innodb status\G; ------------ TRANSACTIONS------------Trx id counter 3153 ...

  9. 关于Mysql java.sql.SQLException: Access denied for user 'root'@'localhost' (using password: YES)的问题

    问题所在: 1.连接数据库一个是密码是否正确, 2.driver是否对, 3.有么有jar包冲突,

  10. Mysql一致性效验_pt工具

    目录 一.简介 二.原理介绍 三.选项 四.环境 五.部署 一.简介 pt工具可以随机抽取主从的数据进行对比,用于测试主从数据一致性.也可以对不一致数据进行修复.这个工具在主或者从上安装均可 二.原理 ...