需要在VS2017上引用折叠规则T &&&&-> T &&的示例

问题描述

C ++参考折叠规则的几个来源如下:

A& & becomes A&
A& && becomes A&
A&& & becomes A&
A&& && becomes A&&

(例如http://thbecker.net/articles/rvalue_references/section_08.html

我可以举一个例子,让A &&&成为A&

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
}

我希望A &&&&&类似的东西变成A &&,但是当我用RValue调用时,T被推导为int,因此这并没有显示我想要的东西。

template <class T> void f1(T&& param) {
    T t = 5;  // compiles since T is int
    T t2 = t; // would not compile if T was int&&
    t2++;
    cout << t; // prints 5 since t2 was not a reference
}

void demo()
{
    f1(8);   // OK T deduced to int,param will go to int&&,no collapsing
}

有人可以帮我显示一个类似的示例,其中T推导为T &&,参数从T &&&&折叠为T &&吗?

解决方法

有人可以帮我显示一个类似的示例,其中T推导为T &&,参数从T &&&&折叠为T &&吗?

如果我们谈论的是实际的推论,而模板参数T并未明确给出或没有默认设置,那是不可能的。原因是转发不仅依赖于参考折叠。

首先,我们必须注意,在C ++中,函数(模板)的参数始终是某种表达式。表达式永远不会具有引用类型。

[expr.type]

1如果表达式最初的类型为“对T的引用” ([dcl.ref],[dcl.init.ref]),将类型调整为T之前的任何 进一步分析。表达式指定对象或功能 由参考表示,并且表达式是左值或 xvalue,取决于表达式。

您实际上不能为引用类型的函数产生参数。因此,在正常情况下,T不能推论为 。转发还依赖于模板中引用功能参数的特殊情况。

[临时扣除电话]

3如果P是引用类型,则P引用的类型用于 类型推演。 [...] 转发参考是一个右值参考 不代表模板的cv不合格模板参数 类模板的参数(在类模板参数期间) 扣除([over.match.class.deduct]))。如果P是转发参考 并且参数是左值,类型“对A的左值引用”是 代替A进行类型推导。

如您所见,转发引用是专门围绕作为参数提供的表达式的值类别而设计的。仅当表达式为左值时,参数的类型才被视为“对A的左值引用”。否则,将无法进行任何调整。因此,将T推导为所引用的类型。

仅当明确给出type参数时,引用折叠规则才起作用。在这种情况下,当以某种方式提供int&&时,我们将通过引用折叠获得右值引用。但这不是在模板参数 deduction 之后。

,

在评论员和其他答案发布者的帮助下,我提出了这个演示:

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&&
}