1.参数类型

template <typename T> void f1(T&);//实参必须是左值
f1(i);//对
f1(ci);//对,T的类型是const int
f1();//错
template <typename T> void f2(const T&);//实参可以是左值,const右值
f2(i);//对
f2(ci);//对
f2();//对
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
……
}
//看传入的值
.如果传入值是右值,如字面常量,T为int。此时t的类型也为int,通过val初始化,参数val保持不变
.如果传入值是左值,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(,i)
flip1(f,j,);//没有发挥引用的效果

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

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

还有个问题:

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

解决办法:

template <typename F, typename T1, typename T2> void flip1(F f,T1&& t1,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=; double d=3.14; string s="stringiest ";
foo(i,s,,d);  //参数包有3个参数
foo(s,,"hi"); //参数包有2个参数
foo(d,s);    //参数包有1个参数
foo("hi");   //参数包有0个参数
//实例化版本
void foo(const int&, const string&, const int&, const double&);
void foo(const string&, const int&, const char[]&);
void foo(const double&, const string&);
void foo(const char[]&);

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

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 类模板部分特列化

最新文章

  1. fabric
  2. linux 代码分析工具 gprof - 以wpa_supplicant为例
  3. Jenkins中Jelly基础、超链接、国际化
  4. 深入研究Struts2(一)---Struts2是什么?它的工作原理是什么?
  5. WordPress 主题开发 - (五)WordPress 主题模板及目录结构 待翻译
  6. C# DataTable的詳細使用方法
  7. SSH框架是个怎么回事?
  8. Swift和OC混编时, 关于@objc的作用
  9. Failed to load the JNI shared library &quot;XXXXXXX&quot;
  10. fiddler抓手机报文的配置指南
  11. angularjs ng-if 中的ng-model 值作用域问题
  12. [dart学习]第三篇:dart变量介绍 (二)
  13. Cookie-parser
  14. Flume的四个使用案例
  15. Implementing HTTPS Everywhere in ASP.Net MVC application.
  16. JVM总结-invokedynamic
  17. 单片机CPU
  18. Webpack 配置示例
  19. java从txt文档读写数据
  20. java poi处理新版xlsx后缀的excel

热门文章

  1. h5调用微信支付功能
  2. BPT(Business Process Testing)
  3. 开发 MFC 应用的一般过程
  4. 各种Web服务器与Nginx的对比
  5. 安装Consul服务中心
  6. 【怒转】 idea快捷键说明大全(中英文对照)
  7. Neo4j百万级数据导入只需30s
  8. 七、hibernate的事务使用
  9. JavaScript寻找最长的单词算法
  10. (PASS)JAVA数组去重 三种方法 (不用集合)