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 }

 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM