标签:执行 oid 改变 初始化 bsp 影响 拷贝 div ring
1.参数类型
template void f1(T&);//实参必须是左值
f1(i);//对
f1(ci);//对,T的类型是const int
f1(5);//错
template void f2(const T&);//实参可以是左值,const右值
f2(i);//对
f2(ci);//对
f2(5);//对
template void f3(T&&);//实参只能是非const右值
2.右值引用参数的模版函数
template 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 remove_reference::type&& move(T&& t)
{
return static_cast::type&&>(t);
}
std::move (string("bye!"))执行过程:
- 推断T的类型为string
- remove_reference用string实例化
- remove_reference的type成员是string
- move的返回类型是string&&
- move的函数参数t的类型为string&&
4.转发的类型保持
template 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 void flip1(F f,T1&& t1,T2&& t2)
{
f(t2,t1);
}
还有个问题:
flip(g,i,42);//不能从一个左值实例化int &&
解决办法:
template void flip1(F f,T1&& t1,T2&& t2)
{
f(std::forward(t2),std::forward(t1));//显式模版实参类型
}
4.模版重载
//1.
template string debug_rep(const T& t)
{
stream ret;
rett;
return ret.str();
}
//2.
template string debug_rep(T* p)
{
stream ret;
ret"pointer is: "p;
if (p)
ret" "p);
else
ret" null ptr";
return ret.str();
}
//调用
string s("hi");
cout//只有第一个版本可行
cout//第一个版本实例化为:debug_rep(const string*&), T类型为string*
//第二个版本实例化为:debug_rep(string*),T类型为string 更精确,编译器选择第二个
const string *sp=&s;
cout//第一个版本实例化为:debug_rep(const string*&), T类型为string*
//第二个版本实例化为:debug_rep(const string*),T类型为const string,更特列化,选择第二个
一个非函数模版和一个函数模版都能提供同样的匹配时,编译器选择非函数模版。
多个函数模版提供同样的匹配时,编译器选择最特例化的那个。
5.可变函数模版
template viod foo(const T& t, const Args& ... rest)
{
cout cout}
//
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 int&, const char[3]&);
void foo(const double&, const string&);
void foo(const char[3]&);
递归调用:必须声明一个非可变参数版本,否则无限递归
template ostream &print(ostream &os, const T& t)//打印最后一个元素
{
return ost;
}
template ostream &print(ostream& os, const T& t, const Args&... rest)
{
os",";
return print(os, rest ...);//递归调用
}
5.1 扩展
5.2 转发(forward)
6.模版特例化:本质上实例化一个模板,而不是重载,不影响函数匹配
template int compare(const T&, const T&);
template 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++——模板
标签:执行 oid 改变 初始化 bsp 影响 拷贝 div ring
原文地址:https://www.cnblogs.com/yrm1160029237/p/11621878.html