C++——模板

C++——模板,第1张

概述1.参数类型 template <typename T> void f1(T&);//实参必须是左值f1(i);//对f1(ci);//对,T的类型是const intf1(5);//错template <typename T> void f2(const T&);//实参可以是左值,const右值f2(i);//对f2(ci);//对f2(5);//对templa

1.参数类型

template <typename T> voID f1(T&);//实参必须是左值f1(i);//f1(ci);//对,T的类型是const intf1(5);//template <typename T> voID f2(const T&);//实参可以是左值,const右值f2(i);//f2(ci);//f2(5);//template <typename T> voID f3(T&&);//实参只能是非const右值

 2.右值引用参数的模版函数

template <typename T> voID f3(T&& val){    T t=val;//拷贝还是绑定一个引用?    t=fcn(t);//赋值只改变t还是t和val都变?    if (val == t)//若t是引用类型,则一直为true    ……}//看传入的值1.如果传入值是右值,如字面常量,T为int。此时t的类型也为int,通过val初始化,参数val保持不变2.如果传入值是左值,T为int&???此时t的类型也为int&,则变t也变val

 

3.标准库的move

template <typename T> typename remove_reference<T>::type&& move(T&& t){    return static_cast<typename remove_reference<T>::type&&>(t);}

std::move (string("bye!"))执行过程:

推断T的类型为string remove_reference用string实例化 remove_reference<string>的type成员是string move的返回类型是string&& move的函数参数t的类型为string&&

 

4.转发的类型保持

template <typename F,typename T1,typename T2> voID flip1(F f,T1 t1,T2 t2){    f(t2,t1);}voID f(int v1,int &v2){}//f(42,i)flip1(f,j,42);//没有发挥引用的效果

解决办法:模版类型参数是右值引用,对应实参的const属性和左右值属性得到保持。为什么?引用折叠。

template <typename F,typename T2> voID flip1(F f,T1&& t1,T2&& t2){    f(t2,t1);}

还有个问题:

flip(g,i,42);//不能从一个左值实例化int &&

解决办法:

template <typename F,T2&& t2){    f(std::forward<T2>(t2),std::forward<T1>(t1));//显式模版实参类型}

 

4.模版重载

//1.template <typename T> string deBUG_rep(const T& t){  stream ret;  ret<<t;  return ret.str();      }//2.template <typename T> string deBUG_rep(T* p){  stream ret;  ret<<"pointer is: "<<p;  if (p)      ret<<" "<<deBUG_rep(*p);  else      ret<<" null ptr"<<;  return ret.str();      }//调用string s("hi");cout<<deBUG_rep(s)<<endl;//只有第一个版本可行cout<<deBUG_rep(&s)<<endl;//第一个版本实例化为:deBUG_rep(const string*&),T类型为string*                          //第二个版本实例化为:deBUG_rep(string*),T类型为string  更精确,编译器选择第二个const string *sp=&s;cout<<deBUG_rep(sp)<<endl;//第一个版本实例化为:deBUG_rep(const string*&),T类型为string*                          //第二个版本实例化为:deBUG_rep(const string*),T类型为const string,更特列化,选择第二个

一个非函数模版和一个函数模版都能提供同样的匹配时,编译器选择非函数模版。

多个函数模版提供同样的匹配时,编译器选择最特例化的那个。

 

5.可变函数模版

template <typename T,typename ... Args> viod foo(const T& t,const Args& ... rest)
{
  cout<<sizeof...(Args)<<endl;//类型参数的数目
  cout<<sizeof...(rest)<<endl;//函数参数的数目
}
//int i=0; double d=3.14; string s="stringIEst ";foo(i,s,42,d);  //参数包有3个参数foo(s,42,"hi"); //参数包有2个参数foo(d,s);    //参数包有1个参数foo("hi");   //参数包有0个参数//实例化版本voID foo(const int&,const string&,const int&,const double&);voID foo(const string&,const char[3]&);voID foo(const double&,const string&);voID foo(const char[3]&);

递归调用:必须声明一个非可变参数版本,否则无限递归

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&... rest){    os<<t<<",";    return print(os,rest ...);//递归调用}

 

5.1 扩展

5.2 转发(forward)

 

6.模版特例化:本质上实例化一个模板,而不是重载,不影响函数匹配

template <typename T> int compare(const T&,const T&);template <size_t N,size_t M> int compare(const char (&)[N],const char (&)[M]);const char* p1="hi",*p2="mom";compare(p1,p2);//调用第一个版本compare("hi","mom");//调用两个版本template <> int compare(const char* const &p1,const char* const &p2){    return strcmp(p1,p2);}//此特例化,是为了处理字符指针,而不是数组

模版及其特例化版本应声明在同一个头文件中,同名模版的声明应放在前面,然后是这些模版的特例化版本。

6.1 类模板特列化

6.2 类模板部分特列化

总结

以上是内存溢出为你收集整理的C++——模板全部内容,希望文章能够帮你解决C++——模板所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/1210443.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-04
下一篇 2022-06-04

发表评论

登录后才能评论

评论列表(0条)

保存