2. 函数模板二
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. 函数模板与函数包装器:
#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; }
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; }
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; }
//模板自带引用,无论是 & 还是 && //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; }
//不是函数模板,需要严格地类型匹配 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; }
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; }
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; }
//节约输入参数的作用,类型参数可以有的指定有的不指定,填充是从左到右,必须覆盖类型参数 //函数参数,默认的都要统一在右边,至少要把不默认的填充了才能调用 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; }
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; }
文章写来不易,转载请标注。。。欢迎关注!