模板函数与模板类

前言:通常我们想要比较不同数据类型的时候不得不定义两种不同的函数来表示区分,为了能精简代码和避免强类型的严格性和灵活性的冲突,我们就需要用到模板去改善这种情况。

一、函数模板

//函数模版的隐式实例化
  #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);
 }

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大侠后花园

如果觉得文章不错请给点支持吧

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值