写函数的时候,如果功能相同,但是“参数不一样”,“参数数量不一样”,“实现方法不一样”,“参数属性不一样”,我们如何优雅的解决这些问题,template是一个重要的工具。
2.结局这些问题 ①解决实现方法不一样,模板类的半特化看一下这个转换string的例子
#include//将参数变成std::string类型 template std::string logGetString(T t) { return std::to_string(t); } int main() { logGetString(100);//可以,因为std::to_string(int)是合法的 logGetString('c');//不行,因为std::to_string(char)是不合法的 logGetString("str");//不行,因为std::to_string(std::string)是不合法的 return 0; }
那我们如何解决上面的问题呢,这样就可以用到我们的模板的半特化了
#include②解决参数数量不一样//将参数变成std::string类型 template std::string logGetString(T t) { return std::to_string(t); } //转换const char*类型 template<> std::string logGetString(const char* str) { return std::string(str); } //转换char类型 template<> std::string logGetString(char c) { return std::string(1, c); } int main() { logGetString(100);//可以,因为std::to_string(int)是合法的 logGetString('c');//可以,因为std::string(int,char)是合法的 logGetString("str");//可以,因为std::string(const char*)是合法的 return 0; }
#include③解决参数属性不一样template std::string logGetString(T t) { return std::to_string(t); } template<> std::string logGetString(const char* s) { return std::string(s); } template<> std::string logGetString(std::string s) { return s; } template<> std::string logGetString(char c) { return std::string(1, c); } //递归调用的终点 void print() {}; //递归调用print,不断的减少参数数量,让我想起了erlang的循环 template void print(T t, PArgs... args) { std::cout << "t = " << t << std::endl; print(args...); } int main() { print(1,2,3);//允许 print(1,2,2,3,4);//允许 return 0; }
有的时候,为了减少拷贝的消耗,我们会应用到引用符号“&”,但是我们穿的值是右值,我们就会用到右值引用符号"&&",但是我们如何写一个函数左值右值都支持呢,还是要用到template.
#include3.合起来 ①写一个log输出的函数//使用模板,如果传入右值,则T被推导为int 即int&& = 1; //如果传入左值,则T被推到位int&,即int&&& t = a; template void printT(T&& t) { std::cout << "t =" << t << std::endl; } int main() { int a = 2; printT(1);//允许,右值引用 printT(a);//允许,左值引用 return 0; }.
#include②看看效果吧 4.总结#include //-------------------------- //写一个log功能 //使用替代符<>打印后面的参数 //---------------------------- template std::string logGetString(T t) { return std::to_string(t); } template<> std::string logGetString(const char* s) { return std::string(s); } template<> std::string logGetString(std::string s) { return s; } template<> std::string logGetString(char c) { return std::string(1, c); } void insertValue(int index, std::string str) { std::cout << "str = " << str << std::endl; } template void insertValue(int index, std::string str, T t, Args...args) { while (index + 1 < str.size()) { if (str[index] == '<' && str[index + 1] == '>' ) { str = str.substr(0, index) + logGetString(t) + str.substr(index + 2, str.size() - 1); insertValue(index++, str, args...); return; } index++; } insertValue(0, str); } template void print(std::string str, PArgs... args) { std::cout << "print " << str << std::endl; insertValue(0, str, args...); } int main(). { print("aaa<>,<>,<>,<>,<>", 1, 1.3, "sss", 'c',std::string("aaaaaa")); return 0; } ~
模板是c++的一个重要工具,灵活应用模板的话,可以大大的减少代码的冗余,可以让代码变得精炼优雅,后面我将会把这部分东西应用到项目中,写一个XLog类,用于打印日志或者打印输出。



