对c++11模板函数的理解——神奇的template

1.前言

写函数的时候,如果功能相同,但是“参数不一样”,“参数数量不一样”,“实现方法不一样”,“参数属性不一样”,我们如何优雅的解决这些问题,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.

#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;
}.

3.合起来

①写一个log输出的函数

#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++11模板函数的理解——神奇的template_第1张图片

4.总结

     模板是c++的一个重要工具,灵活应用模板的话,可以大大的减少代码的冗余,可以让代码变得精炼优雅,后面我将会把这部分东西应用到项目中,写一个XLog类,用于打印日志或者打印输出。

你可能感兴趣的:(开发一个服务器,c++,后端,vim)