我们先来看折叠规则
引用折叠规则
在C++中,引用折叠规则的主要目的是为了保证在模板推导过程中,对于参数 T&&
能够正确地推导出其最终的引用类型,以便进行参数传递时的正确行为。下面是引用折叠规则的总结:
-
左值引用折叠:
T& &
折叠为T&
T& &&
折叠为T&
这意味着如果一个左值引用被再次引用,或者一个左值引用被右值引用引用,最终的结果仍然是左值引用。就是左值怎么引用都是左值。
-
右值引用折叠:
T&& &
折叠为T&
T&& &&
折叠为T&&
这意味着如果一个右值引用被左值引用引用,最终结果是左值引用;如果一个右值引用被右值引用引用,最终结果仍然是右值引用。
了解了折叠规则后,我们来看个demo
template <typename F, typename T1, typename T2>
void flip2(F f, T1 &&t1, T2 &&t2)
{
f(t1, t2);
}
这个函数模板接受三个参数,并将t1和t2作为f的参数进行调用,给出f的实现
void gtemp(int&& v1, int& v2)
{
cout << v1 << " " << v2 << endl;
}
调用
int j = 99;
flip2(gtemp, 42, j);
cout << "j is " << j << endl;
得到报错
error C2664: “void (int &&,int &)”: 无法将参数 1 从“T1”转换为“int &&”
分析:42是一个右值对象,j是左值,在flip2中形参t1通过折叠规则推导知类型为右值引用,t2是左值引用,但是将t1作为f的参数时,它依旧是作为一个左值来用的,因此gtemp也就是f调用明显会出错它的第一个参数类型为右值引用,也就是说flip2函数内部把外部实参42作为其他函数的参数传递时,将其的类型给“修改了”,从右值变为左值,这当然不是我们所希望的,那么怎么解决呢?
std::forward<>()函数就是用来保持类型不变的。
再看修改demo
template <typename F, typename T1, typename T2>
void flip2(F f, T1 &&t1, T2 &&t2)
{
f(std::forward<T1>(t1),std::forward<T2>(t2));
}
forward包含在utility库里,我们使用完美转发函数使t1,t2保持类型与外部实参一致,也就是42(右值),j(int)因此程序正常运行。
标签:右值,t2,左值,C++,t1,详解,引用,&&,转发 From: https://www.cnblogs.com/dwinternet/p/18287426