2. 函数模板二

时间:2020-12-25 05:33:37

1. 引用包装器

#include <iostream>
using namespace std;

void change(int &num)    //引用作为参数
{
    num = 3;
}

int main1001()
{
    int data = 100;
    //change(data);
    //cout << data << endl;    //3

    int &rdata(data);
    change(rdata);
    cout << data << endl;    //3

    system("pause");
    return 0;
}

template<class T>
void show(T t)        //函数模板    法一:将函数模板改为引用 void show(T & t)
{
    cout << t << endl;
    t += 10;
}

int main()
{
    double db(1.0);
    double &rdb(db);
    //show(db);                //1
    //show(rdb);            //1    若想改为11,有两种办法
    show(ref(rdb));            //法二:引用包装器,ref声明为引用
    cout << "db:" << db << endl;
    
    system("pause");
    return 0;
}

    2. 函数模板二

2. 函数模板与函数包装器:

#include <iostream>
#include <functional>    //函数包装器的头文件
using namespace std;
using std::function;

int add(int a, int b)
{
    return a + b;
}

template<class T,class F>
T run(T t1, T t2, F f)        //作为通用的接口,任何数据类型,任何函数都可以
{
    return f(t1, t2);
}

int main()
{
    function<int(int, int)> fun1 = add;    //包装函数
    function<int(int, int)> fun2 = [](int a, int b)->int {return a - b; };

    cout << fun1(10, 19) << endl;
    cout << run(10, 19, fun1) << endl;        //默认推导,原生函数优先
    cout << run<int>(10, 19, fun1) << endl;    //指定为int类型
    cout << run<int, function<int(int, int)>>(10, 19, fun1) << endl;    //强行指定类型,前面是T的类型,后面是F的类型
    cout << fun2(10, 19) << endl;


    system("pause");
    return 0;
}

    2. 函数模板二

3. 模板的嵌套:

#include <iostream>
#include <vector>
#include <list>
using namespace std;

template<class T>
void showallA(vector<T> v)
{
    for (auto i:v)
    {
        cout << i << " ";
    }
    cout << endl;
}

template<class T1,class T2>
void showallB(vector<T1> v,list<T2> l)    //模板的嵌套
{
    for (auto i : v)
    {
        cout << i << " ";
    }
    cout << endl;
    for (auto i:l)
    {
        cout << i << " ";
    }
    cout << endl;
}

int main()
{
    vector<int> myint1{ 1,2,3,4,5 };
    vector<char> mych1{ 'A','B','C','D','E' };
    list<int> myint2{ 1,2,3,4,5 };
    list<char> mych2{ 'A','B','C','D','E' };

    showallA(myint1);
    showallA(mych1);
    showallB(myint1, myint2);
    showallB(mych1, mych2);

    system("pause");
    return 0;
}

    2. 函数模板二

4. 函数模板与引用:

#include <iostream>
using namespace std;

//变量、左值引用、右值引用,原则上不能冲突
//ref:    变量->左值引用
//move:    左值引用->右值引用
template<class T>
void print1(T t)        //数据
{
    cout << "print(T t):";
    t += 1;
    cout << t << endl;
}

template<class T>
void print2(T & t)    //左值引用
{
    cout << "print(T & t):";
    t += 1;
    cout << t << endl;
}

template<class T>
void print3(T && t)    //右值引用
{
    cout << "print(T && t):";
    t += 1;
    cout << t << endl;
}

int main()
{
    int data = 100;            //数据
    int & rdata(data);         //左值引用,4字节
    int && rrdata(data + 1);  //右值引用,4字节

    //print1(data);                         //101    副本
    //cout << "data=" << data << endl;      //100

    //print1(ref(data));                    //101    原本    引用包装器,包装变量或引用
    //cout << "data=" << data << endl;      //101

    //print1(rdata);                        //101    副本
    //cout << "data=" << data << endl;      //100

    //print1(rrdata);                       //102    副本    右值引用内存保存的临时值
    //cout << "data=" << data << endl;      //100
    //cout << "rdata=" << rdata << endl;    //100
    //cout << "rrdata=" << rrdata << endl;  //101

    print1(ref(rrdata));                    //102    原本    右值引用内存保存的临时值
    cout << "data=" << data << endl;        //100
    cout << "rdata=" << rdata << endl;      //100
    cout << "rrdata=" << rrdata << endl;    //102

    system("pause");
    return 0;
}

    2. 函数模板二

//模板自带引用,无论是 & 还是 &&
//T t,带有ref都是原本,否则都是副本
int main()
{
    int data = 100;            //数据
    int & rdata(data);        //左值引用,4字节
    int && rrdata(data + 1);//右值引用,4字节

    /*
    print2(data);                           //101    模板自带引用,都是原本
    cout << "data=" << data << endl;        //101
    cout << "rdata=" << rdata << endl;      //101
    cout << "rrdata=" << rrdata << endl;    //101

    print2(rdata);                          //101    
    cout << "data=" << data << endl;        //101
    cout << "rdata=" << rdata << endl;      //101
    cout << "rrdata=" << rrdata << endl;    //101

    print2(rrdata);                         //102    
    cout << "data=" << data << endl;        //101
    cout << "rdata=" << rdata << endl;      //101
    cout << "rrdata=" << rrdata << endl;    //102
    
    print3(data);                           //101    
    cout << "data=" << data << endl;        //101
    cout << "rdata=" << rdata << endl;      //101
    cout << "rrdata=" << rrdata << endl;    //101
    
    print3(rdata);                          //101    
    cout << "data=" << data << endl;        //101
    cout << "rdata=" << rdata << endl;      //101
    cout << "rrdata=" << rrdata << endl;    //101
    */

    print3(rrdata);                         //102    
    cout << "data=" << data << endl;        //100
    cout << "rdata=" << rdata << endl;      //100
    cout << "rrdata=" << rrdata << endl;    //102

    system("pause");
    return 0;
}

    2. 函数模板二

//不是函数模板,需要严格地类型匹配
void printInt(int && t)
{
    cout << t << endl;
}

int main()
{
    int num = 10;
    int & rnum(num);

    //printInt(num);        //无法将参数 1 从“int”转换为“int &&”
    //printInt(rnum);       //无法将参数 1 从“int”转换为“int &&”
    printInt(rnum+1);       //11
    printInt(move(num));    //10    移动语义,数据或者左值 转换为右值
    printInt(move(rnum));   //10

    system("pause");
    return 0;
}

    2. 函数模板二

5. 函数模板的重载:

#include <iostream>
using namespace std;

//函数模板的重载:参数的个数不一样、类型不一样、顺序不一样(与返回值无关)
//有指针要优先匹配指针
template<class T>
void go(T t1)
{
    cout << "T:";
    cout << t1 << endl;
}

template<class T>
void go(T * t1)
{
    cout << "T * :";
    cout << t1 << endl;
}

int main()
{
    int *p = new int[5]{ 1,2,3,4,5 };
    go(p[0]);
    go(p);
    go(&p);        //地址趋向地址

    system("pause");
    return 0;
}

    2. 函数模板二

6. 模板的默认参数:

#include <iostream>
using namespace std;

template<class T = int>    //模板参数可以有默认值
void BoBo(T t)
{
    cout << t << endl;
}

template<class T = int, int n = 10>    //模板参数可以有默认值
void bobo(T t)
{
    cout << "n:" << n << endl;
    cout << "t:" << t << endl;
}

int main()
{
    BoBo(25);            //25
    BoBo(25.52);         //25.52    自动推理
    BoBo<>(25.52);       //25.52    自动推理
    BoBo<int>(25.52);    //25

    bobo<int>(25.52);        //n:10    t:25
    bobo<int,250>(25.52);    //n:250    t:25

    system("pause");
    return 0;
}

    2. 函数模板二

//节约输入参数的作用,类型参数可以有的指定有的不指定,填充是从左到右,必须覆盖类型参数
//函数参数,默认的都要统一在右边,至少要把不默认的填充了才能调用
template<class T1 = int, class T2 , class T3 = double, class T4 = double>   //参数类型同样可以设置默认
void BoDa(T1 t1=250.1,T2 t2=250.11,T3 t3=250.111,T4 t4=250.1111)            //参数值可以设置为默认值
{
    cout << t1 << " " << t2 << " " << t3 << " " << t4 << endl;
}

int main()
{
    BoDa<int,int>();            //250 250 250.111 250.1111
    BoDa(1, 2, 3, 4);           //1 2 3 4

    system("pause");
    return 0;
}

    2. 函数模板二

7. 函数模板类型匹配:

#include <iostream>
using namespace std;

//模板会自动匹配*号多的函数
template<class T>
void com(T *p)
{
    cout << "*:";
    cout << typeid(T).name() << endl;
}

template<class T>
void com(T **p)
{
    cout << "**:";
    cout << typeid(T).name() << endl;
}

int main()
{
    int *p = nullptr;
    int **pp = nullptr;
    int ***ppp = nullptr;

    com(p);
    com(pp);
    com(ppp);

    system("pause");
    return 0;
}

    2. 函数模板二