需要引用折叠规则T&;的示例&&&-&燃气轮机;T&&;关于VS2017 给出C++引用折叠规则的几个来源如下: A& & becomes A& A& && becomes A& A&& & becomes A& A&& && becomes A&&
(例如) 我可以给一个&&&成为一个&需要引用折叠规则T&;的示例&&&-&燃气轮机;T&&;关于VS2017 给出C++引用折叠规则的几个来源如下: A& & becomes A& A& && becomes A& A&& & becomes A& A&& && becomes A&&,c++,templates,forwarding-reference,C++,Templates,Forwarding Reference,(例如) 我可以给一个&&&成为一个& template <class T> void f1(T&& param) { // T t = 5; // does not compile because T is T& param++; // param collapses from int&&&& to int&& } void demo() { int x = 8; int &
template <class T> void f1(T&& param) {
// T t = 5; // does not compile because T is T&
param++; // param collapses from int&&&& to int&&
}
void demo()
{
int x = 8;
int &y = x;
f1(y); // OK T will still be int&, param will go to int&&& -> collapses to int&
cout << y; // prints 9
}
模板无效f1(T&¶m){
//T=5;//不编译,因为T是T&
param++;//param从int&&&&折叠为int&&
}
void demo()
{
int x=8;
int&y=x;
f1(y);//OK T仍然是int&,param将转到int&&&->折叠为int&
库特
有人能帮我演示一个类似的例子吗?在这个例子中,T被推导为T&&并且参数从T&&&&折叠为T&&&&
如果我们讨论的是实际的推断,其中模板参数T
没有明确给出或以某种方式默认,那是不可能的。原因是转发不仅依赖于引用折叠
首先,我们必须注意C++中的一个函数(模板)的参数总是某种表达式。表达式从来没有引用类型。
[expr.type]
如果表达式最初的类型为“对T的引用”
([dcl.ref],[dcl.init.ref]),类型在任何
进一步分析。表达式指定对象或函数
由引用表示,表达式是左值或
xvalue,具体取决于表达式
实际上,您不能为引用类型的函数生成参数。因此,在正常情况下,t
不能推断为引用。转发也依赖于模板中引用函数参数的特殊情况
[临时扣减呼叫]
如果p是引用类型,则p引用的类型用于
类型推断。[…]转发引用是对的右值引用
不代表模板的cv非限定模板参数
类模板的参数(在类模板参数期间)
扣减([over.match.class.decreate])。如果P是转发引用
参数是一个左值,类型“levaluereferencetoa”是
用于代替用于类型推断的
如您所见,转发引用是专门围绕作为参数提供的表达式的值类别设计的。只有当表达式是左值时,参数的类型才被视为“对参数的左值引用”。否则,不会进行调整。因此,T
将被推断为所引用的类型
引用折叠规则仅在显式给出类型参数时起作用。在这种情况下,当以某种方式提供int&
时,我们通过引用折叠获得右值引用。但这不是在模板参数推导之后。在注释者和其他答案海报的帮助下,我想出了是演示:
template <class T> void f1() {
int x = 5; // an lvalue
//T t1 = x; // compiles when T is int or int&, fails when T is int&
//T& t2 = x; // always compiles, becomes int&. Can check with ++t2; cout << x;
//T&& t3 = x; // compiles when T is int&, fails when t3 is &&
}
void demo()
{
//f1<int>(); // T becomes int, t1=int, t2=int& t3=int&&
//f1<int&>(); // T becomes int& t1=int& t2=int& t3=int&
f1<int&&>(); // T becomes int&&, t1=int&& t2=int&, t3=int&&
}
template void f1(){
int x=5;//左值
//T t1=x;//当T为int或int&时编译,当T为int时失败&
//t/t2= x;//总是编译,可以用++t2检查;cOUT,你可以称它为<代码> f1(8);< /COD>。我尝试并给出了编译器错误,正如你所期望的,即<代码> T T2= T;< /C> >不会编译。例如,考虑<代码> F1(…))
。这里,T
将是some_type&&
,而param
的类型将从some_type&&&&&
折叠为some_type&&&
。感谢您的详细回复。这里有很多内容。首先,我喜欢通过使用typ显式实例化模板来展示示例的想法e、 我肯定会使用它。至于不能为引用类型的函数生成参数,在某些情况下,我认为您可以。例如,当我的第一个示例中的参数为int&并且参数为T&&时,T变为int&正如我的第一个示例所示。如果我错了,请纠正我。@GonenI-argument从来都不是int&
。当您传递y
时,它是int
类型的id表达式(如第一段所述)。它也是一个左值,这就是转发引用的模板参数推断将类型调整为int&
。但它与y
本身(作为表达式)不同属于int&
类型。这是这里的关键。当参数不是左值时,没有调整。因此我们只剩下值类型。
template <class T> void f1() {
int x = 5; // an lvalue
//T t1 = x; // compiles when T is int or int&, fails when T is int&
//T& t2 = x; // always compiles, becomes int&. Can check with ++t2; cout << x;
//T&& t3 = x; // compiles when T is int&, fails when t3 is &&
}
void demo()
{
//f1<int>(); // T becomes int, t1=int, t2=int& t3=int&&
//f1<int&>(); // T becomes int& t1=int& t2=int& t3=int&
f1<int&&>(); // T becomes int&&, t1=int&& t2=int&, t3=int&&
}