前言:通常我们想要比较不同数据类型的时候不得不定义两种不同的函数来表示区分,为了能精简代码和避免强类型的严格性和灵活性的冲突,我们就需要用到模板去改善这种情况。
一、函数模板
//函数模版的隐式实例化
#include <iostream>
using namespace std;
template <class T>
T Max(T x, T y); //函数模版的申明
int main()
{
int intX = 1, intY = 2;
double dblX = 3.9, dblY = 2.9;
cout << Max(intX, intY) << endl; //实参为int型,生成int型模板函数,并对第二个参数进行检查
//或者cout << Max<int>(intX, intY) << endl;
cout << Max(dblX, dblY) << endl; //实参为double型,生成double型模板函数,并对第二个参数进行检查
//或者cout << Max<double>(dblX, dblY) << endl;
cout << Max(dblY,intX) << endl; //模板函数做不到两个参数类型不一致还可以比较
return 0;
}
template <class T>
T Max(T x, T y) //函数模版的实现
{
return (x > y ? x : y);
}、
正常函数模板:
template <typename T1, typename T2, Typename T3>
T1 sum(T2, T3)
{
T1 nres;
cout<<"执行相应de"的操作"<<endl;
retuen nres;
}
显示调用:auto val= sum<long long>(i, lng); //返回值类型:long long,形参类型:T2=decltype(i) , T3=decltype(lng)
或者:auto val1= sum<long long, int, long>(i, lng); //返回值类型:long long,形参类型:T2=int , T3=long
尾置函数模板:返回序列中元素类型的引用
template <typename It>
auto fcn (It beg, It end)->decltype(*beg)
{
return *beg;//返回序列中元素类型的引用
}
调用:vector<int > ci={1,2,3,4,5};
Blob<string> ca={"hi","bye"};
auto &i=fcn(vi.begin(),vi.end()); //fcn返回int&
auto &s=fcn(ca.begin(),ca.end()); //fcn返回string&
尾置函数模板:返回序列中一个函数的引用
template <typename It>
auto fcn (It beg, It end)->typename remove_referance<decltype(*beg)>::type
{
return *beg;//返回序列中元素的拷贝
}
函数指针和实参的推断:
template <typename T> int compare(const T&, const T&);
void func(int(*)(const string&, const string&));
调用:func(compare <int>);//指定实参类型
从右值引用推断类型
template <typename T> void f3(T&&);
f3(43);
引用折叠:创建一个引用的引用,这些引用形成了“折叠”,引用因此会折叠为左值引用类型
规则:
1.如果一个函数的参数是一个指向函数模板类型参数的右值引用,则它可以被绑定为一个左值
2.如果一个函数的参数是一个指向函数模板类型参数的左值引用,则它可以被绑定为一个左值
void f(int v1, int &v2)
{
cout << "" << ++v2 << endl;
}
template <typename F, typename T1, typename T2>
void flip1(F f, T1 &&t1, T2 &&t2)//引用折叠,保留原参数t1的左值类型
{
f(t2, t1);//t1是左值
}
调用:flip1(f, j, 42);
std::move语义:可传递给move一个左值或者右值,最终都会得到一个右值
完美转发:保留原数据类型
void f1(int &&v1, int &v2)
{
cout << v1 << "" << ++v2 << endl;
}
template <typename F, typename T1, typename T2>
void flip2(F f, T1 &&t1, T2 &&t2)//引用折叠
{
f1(std::forward<T2>(t2), std::forward<T1>(t1));//保留t1,t2的右值类型
}
调用:flip2(f, j, 42);
可变参数模板:
template <typename T, typename ...args> void foo(const T &t, const args&... res)
{
cout << sizeof...(args) << endl;// sizeof...(args)获取包中有多少个可变参数
}
调用:foo(i,j,13,4213,44);
利用可变参数模板来打印值
template <typename T> ostream & _print(ostream &os, const T &t)
{
return os << t;//打印最后一个元素
}
template <typename T, typename ...args> ostream &_print(ostream &os,const T &t, const args&... res)
{
os << t << ",";
return _print(os, res...);//递归调用打印值
}
调用:
_print(cout, i, j, 132);
_print(cout, i, j, 132, 42, 34);
模板特例化:
原始模板函数
template <typename T>
int compare(const T &v1, const T &v2)
{
if (less<T>()(v1, v2))
{
return -1;
}
if (less<T>()(v2, v1))
{
return 1;
}
return 0;
}
特例化函数
template<>
int compare(const char* const &v1, const char* const&v2)
{
return strcmp(v1, v2);
}
调用:
const char *p1 = "hi";
const char *p2 = "mom";
compare(p1, p2);
二、模板类
#include <iostream>
using namespace std;
#define MaxSize 10
template <class T>
class CStack
{
private:
T data[MaxSize];
int top;
public:
CStack():top(-1)
{
}
void Push(void);
void Pop(void);
bool ifEmpty()
{
if(top == -1)
return true;
else
return false;
}
bool ifFull()
{
if(top == MaxSize-1)
return true;
else
return false;
}
T getTop(void)
{
if(ifEmpty())
{
cout<<"栈为空,不能取栈顶!"<<endl;
return -1;
}
return this->data[top];
}
};
template <class T>
void CStack<T>::Push(void)
{
if(ifFull())
{
cout<<"栈已满,不能入栈!"<<endl;
return ;
}
T a;
cin>>a;
this->data[++top] = a;
cout<<"元素"<<a<<"入栈!"<<endl;
}
template <class T>
void CStack<T>::Pop(void)
{
if(ifEmpty())
{
cout<<"栈为空,不能出栈!"<<endl;
return ;
}
T temp = this->data[top--];
cout<<"元素"<<temp<<"出栈!"<<endl;
}
int main()
{
CStack<int> s1; //可以自己更换数据类型int
int i;
do
{
cout<<"\t===============================\n";
cout<<"\t*********顺序栈类模板**********\n";
cout<<"\t 1.入栈 \n";
cout<<"\t 2.出栈 \n";
cout<<"\t 3.取栈顶 \n";
cout<<"\t 0.退出 \n";
cout<<"\t*******************************\n";
cout<<"\t===============================\n";
do
{
cout<<"\tplease input your operator:";
cin>>i;
system("cls");
}while(i!=1 && i!=2 && i!=3 && i!=0);
switch(i)
{
case 1:
s1.Push();
system("pause");
system("cls");
break;
case 2:
s1.Pop();
system("pause");
system("cls");
break;
case 3:
if(-1 == s1.getTop())
{
system("pause");
system("cls");
break;
}
else
cout<<"栈顶元素为:"<<s1.getTop()<<endl;
system("pause");
system("cls");
break;
}
}while(i != 0);
}