写函数的时候,如果功能相同,但是“参数不一样”,“参数数量不一样”,“实现方法不一样”,“参数属性不一样”,我们如何优雅的解决这些问题,template是一个重要的工具。
看一下这个转换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.
#include
//使用模板,如果传入右值,则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
#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类,用于打印日志或者打印输出。