C++模板实现printf
2016-02-24 23:29
423 查看
要函数实现接受可变的参数模型,有三种方法。
第一,通过C语言的va_list结构,以及va_start、va_arg、va_end来实现。
如:
第二,通过c++的initializer_list模板,但接受的参数类型必须一致。
如:
调用
第三,通过c++ 模板可变参数实现。
实现printf具体如下(只讨论输出int数据的情况):
【相关知识:模板、函数重载、特例化】
基本思路是通过模板的递归调用,将参数包的参数一个个取出来取代string里的%d输出符号。
图1
图2
第一,通过C语言的va_list结构,以及va_start、va_arg、va_end来实现。
如:
void print(char *msg, ...) { va_list args; va_start(args, msg); ... int a = va_arg(args, int); //这里可以是int/double等等类型,根据msg来判断。 ... va_end(args); }
第二,通过c++的initializer_list模板,但接受的参数类型必须一致。
如:
void func(initializer_list<std::string> sl);
调用
func(str1); func(str1, str2);
第三,通过c++ 模板可变参数实现。
实现printf具体如下(只讨论输出int数据的情况):
【相关知识:模板、函数重载、特例化】
基本思路是通过模板的递归调用,将参数包的参数一个个取出来取代string里的%d输出符号。
#include <iostream> #include <string> using namespace std; /× 函数1. 这个函数要定义,若不定义问题出现如图1. 和模板的实例化有关,在my_printf中sizeof...(args) == 0 的时候依然实例化了if条件的调用,为什么这样?我也不清楚了。 ×/ int pri_print(string &str) { cout << "1 -> "; return 1; } /× 模板2. 此模板比模板3更具特例化,故可打破模板3的无限递归。 ×/ template<typename t2> int pri_print(string &str, const t2 &elem) { cout << "2 -> "; auto index = str.find_first_of("%"); if (index == string::npos) return 0; char num[16]; sprintf(num, "%d", elem); str.replace(index, 2, num); return 1; } /× 模板3. ×/ template<typename t2, typename ... Args> int pri_print(string &str, const t2 &elem, const Args& ... args) { cout << "3 -> "; auto index = str.find_first_of("%"); if (index == string::npos) return 0; char num[16]; sprintf(num, "%d", elem); str.replace(index, 2, num); pri_print(str, args...); return 1; } /× 针对输出函数的第一个语句是const char *的类型,也结合上面三个函数的实现方法,故抽出再定义一个函数,其第一个参数类型为const。 注意:以上函数第一个参数不是const的。 ×/ template<typename ... Args> int my_printf(const string &str, const Args& ... args) { string str_1(str); // ... if (sizeof...(args) != 0) pri_print(str_1, args...); cout << str_1; return 1; } int main(int argc, char *argv[]) { int a = 666; int b = 777; int c = 888; // 输出结果如: 图2 my_printf("I am just a sentence\n"); my_printf("Here a = %d\n", a); my_printf("Here a = %d, b = %d\n", a, b); my_printf("Here a = %d, b = %d, c = %d\n", a, b, c); return 0; }
图1
图2
相关文章推荐
- C++学习笔记48——继承中的构造函数
- 从C++转向java——3、判断与比较
- 关于C++中智能指针与类型推导的说明
- error LNK2019: 无法解析的外部符号 (C++编程出现问题的解决办法)
- 从C++转向java——2、输入与变量
- C/C++知识点整理(1)
- C结构与其他数据形式学习心得
- B样条曲线De Boor 算法/C++
- 【C++】重载二维数组下标 [ ][ ]
- C和指针读书笔记——部分简介
- 《Effective C++》学习笔记——条款38
- 从C++转向java——1、基础篇
- C++计算器项目的初始部分
- C++注意点(第一部分)
- C++多态之虚基类析构函数的作用
- C++调用JAVA方法详解
- C++11之move语义
- g++ -std=c++11 -g -o test emit_log_direct.cpp
- 1040. Longest Symmetric String (25)
- C++面向对象编程<十二>转换函数、explicit、class几种表现形式