泛型编程即以一种独立于任何特定类型的方式编写代码。
模板类型
一,模板参数
指定形式参数类型和返回参数类型, 模板参数不允许自动类型转换
template<typename T1, typename T2, typename RT>
inline RT max(const T1& a, const T2& b)
{
    return a > b? a:b;
}
int main()
{
    int a, b;
    a = 1;
    b = 2;
    max<int, int, double>(a,b);
}
二,模板函数
#include <iostream>
#include <string>
//typename 意义时说明,T 是一个数据类型,不是一个类或者成员变量, 或者成员函数。并非强制使用typename, class同样可以替换wq
template <typename T>
inline T func(T& t) {
    return  t;
}
using namespace std;
int main() {
    string  hello = "hello";
    //编译器猜测类型
    cout << func(hello) << endl;
    //指明类型
    cout << func<string>(hello) << endl;
    return  0;
}
1.隐式指定
template <typedef T>
const T& max(const T& a, const T& n)
{
    retun a > b ? a :b;
}
int main()
{
    int a, b;
    a = 1;
    b = 4;
    //隐式转换
    max(a, b);
    return 0;
}
2.显式转换
template <typedef T>
const T& max(const T& a, const T& n)
{
    retun a > b ? a :b;
}
int main()
{
    int a, b;
    a = 1;
    b = 4;
    //显式转换
    max<int>(a, b);
    return 0;
}
3.数据类型强制转换
template <typedef T>
const T& max(const T& a, const T& n)
{
    retun a > b ? a :b;
}
int main()
{
    int a;
    double b;
    a = 1;
    b = 4.0;
    //隐式转换
    max<double>(static_cast<double>a, b);
    return 0;
}
三, 模板重载函数
inline const int& max(const int& a, const int& b)
{
    return a > b ? a : b;
}
template<typename T>
inline const T& max(const T& a, const T& b)
{
    return a > b? a: b;
}
template<typename T>
inline const T& max(const T& a, const T& b, const T& c)
{
    return max(max(a, b), c);
}
int main()
{
    max(1, 7); //调用int 类型的重载函数
    max(1, 2, 3); //调用三个参数䣌模板
    return 0;
}
三,类模板
#include <iostream>
#include <string>
using namespace std;
template <class T>
class Hello {
    public:
        void say(const T& t) {
            cout << t << endl;
        }
};
int main() {
    Hello<string>* hello = new Hello<string>();
    hello->say("hello");
    return  0;
}
模版定义和实现分离时
//test.h
template <class T>
class Test
{
public:
    void print(T& t);
}
//test.cpp, 需要再次声明T
template <class T>
void Test<T>::print(T&t)
{
    std::cout << t << std::endl;
}
高级
二次定义模版
template <class T, class NewT = std::queue<T>>
模板元编程
1.用于编译开关部分代码使用
//一个支持透明色的32bit blit函数
template<const bool useMask>
void blit(int& dst, const int* src, int mask, size_t size)
{
    for(size_t = 0; i < size; i++, dst++, src++)
    {
        if(!useMask || *src != mask) 
        {
            *dst = *src;
        }
    }
}
void main()
{
   //关闭或开启, 编译时期确定
    blit<true>(....)
}
- 递归算法优化
将指数级运算,降低到常数级运算
//被优化算法
unsigned int fib(unsigned int n)
{
    if (n == 0 || n == 1) {
        return 1;
    } 
    else
    {
        return fib(n -1) + fib(n-2);
    }
}
//优化后算法
template<unsigned int N>
struct FibR
{
    enum
    {
        Val = FibR<N-1>::Val + FibR<N-2>::Val
    };
    
}
//定义模板确定常量时,的格式
template <>
struct FibR<0>
{
    enum
    {
        Val = 1;
    }
}
template <>
struct FibR<1>
{
    enum
    {
        Val = 0;
    }
}
//定义为一个函数,记得传递n
#define fib(n) FibR<n>::Val
可变参数模板
#include <iostream>
void showall()
{
    return;
}
template <typename R1, typename... Args>
void showall(R1 var, Args... args)
{
    std::cout << var << std::endl;
    showall(args...);
}
int main(int argc, char* args[])
{
    //传递参数数字
    showall(1 ,2 ,3, 4);
    
    //传递字符
    showall("a", "b", "c");
    
    //混合传递
    showall(1 ,"abc", 2);
    return 0;
}
仿函数中的应用
#include <iostream>
#include <functional>
template <typename R1, typename R2>
struct Calc
{
    void add(R1 a)
    {
        std::cout << a <<std::endl;
    }
    void add_1(R1 a, R2 b)
    {
        std::cout << a + b << std::endl;
    }
};
int main(int argc, char* args[])
{
    void (Calc<int, double>::* fc)(int) = &Calc<int, double>::add;
    //实际上不能用
    //fc(25);
    Calc<int, double > calc;
    auto fun = std::bind(&Calc<int, double>::add, &calc, std::placeholders::_1);
    std::function<void(int, double)> fun2 = std::bind(&Calc<int,  double>::add_1, &calc, std::placeholders::_1, std::placeholders::_2);
    fun(25);
    fun2(1, 25);
    return 0;
}
使用using, 函数指针, typedef来实现函数调用
#include <iostream>
#include <stdlib.h>
int calc()
{
    return 0;
}
template <typename R1, typename... Args>
int calc(R1 a, Args... args)
{
    return  a + calc(args...);
}
int main(int argc, char* args[])
{
    int(* fun)(int, int, int) = calc;
    std::cout << fun(1, 1, 1) << std::endl;
    system("echo 使用函数指针");
    typedef int(*Add)(int, int, int);
    Add Gadd = calc;
    std::cout << Gadd(2, 2, 2) << std::endl;
    system("echo 使用typedef实现");
    using Func = int(*)(int, int, int);
    Func func = calc;
    std::cout << func(3, 3, 3) << std::endl;
    system("echo 使用using实现");
    return 0;
}