std :: forward和reference折叠的工作

Jam*_*nco 3 c++ perfect-forwarding c++11

我试图熟悉完美转发的概念.我已阅读张贴在这里.我相信我对参考折叠概念感到满意.在阅读这篇其他 职位.我提出了以下问题

假设我们有以下示例

Example-1
template <class T>
void foo(T &&t)
{
  bar(std::forward<T>(t));
}
Run Code Online (Sandbox Code Playgroud)

我们传递这样的东西

int i= 12;
foo(i);
Run Code Online (Sandbox Code Playgroud)

现在我明白这i将被视为一个int&我不明白的是为什么上面链接中的回答问题提到它将被视为int& &&会崩溃,因为int&.我认为它会被视为int&& &会崩溃以int& 我的理解这两者的返回类型是相同的,但我想获得第一部分的权利.我之所以认为它int&& &不是int& &&下面提到的原因,请纠正我,如果我错了

当我传递这样的东西

int i =12;
foo(i);
Run Code Online (Sandbox Code Playgroud)

然后示例1变成这样的东西

void foo(int &&t)
{
  bar(std::forward<int>(&t)); // t is a reference now ------>A
}
Run Code Online (Sandbox Code Playgroud)

现在std :: forward实现就是这个

template<typename T>                // For lvalues (T is T&),
T&& std::forward(T&& param)         // take/return lvalue refs.
{                                   // For rvalues (T is T),
    return static_cast<T&&>(param); // take/return rvalue refs.
}
Run Code Online (Sandbox Code Playgroud)

所以当我们的解决方案适用于它.它成为了

return static_cast<int&&>(&param) ; //&param since we passed &t in A
Run Code Online (Sandbox Code Playgroud)

我们得到

int&& & and not `int& &&` please correct me if I am wrong
Run Code Online (Sandbox Code Playgroud)

Pio*_*cki 5

当您i作为参数传递给foo:

int i = 12;
foo(i);
Run Code Online (Sandbox Code Playgroud)

表达式i具有左值类别,因此T推导为int&,因此示例1变为:

void foo<int&>(int& && t) // `int& t` due to reference collapsing
//         |   \ /
//         +--> T  = int&
{//                   V
    bar(std::forward<int&>(t));
}
Run Code Online (Sandbox Code Playgroud)

现在,在std::forward,param显式指定的类型是int&,所以:

int& && std::forward<int&>(typename std::remove_reference<int&>::type& param)
//                    ^~~+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^
//                       |
{//                      V          
    return static_cast<int& &&>(param); // `int&` due to reference collapsing
}
Run Code Online (Sandbox Code Playgroud)

它恢复了左值类别i.


为了说清楚,当参数表达式的值类别是右值时会发生这种情况:

foo(12); // -> foo<int>(12);
//                  |
//        v~~~~~~~~~+
void foo<int>(int && t) // `int&& t`
//        |   \ /
//        +--> T  =  int
{//                   V
    bar(std::forward<int>(t));
}//                   |
//                    V 
int && std::forward<int>(typename std::remove_reference<int>::type& param)
//                    ^~~+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^
//                       |
{//                      V          
    return static_cast<int &&>(param); // `int&&`
}
Run Code Online (Sandbox Code Playgroud)

当type模板参数int&&明确指定时:

foo<int&&>(12);
//     ^~~~+
//         V
void foo<int&&>(int&& && t) // `int&& t` due to reference collapsing
//         |    \   /
//         |     \ /
//         +----> T = int&&
{//                    V
    bar(std::forward<int&&>(t));
}//                    |
//                     V 
int&& && std::forward<int&&>(typename std::remove_reference<int&&>::type& param)
//                     ^~~+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^
//                        |
{//                       V          
    return static_cast<int&& &&>(param); // `int&&` due to reference collapsing
}
Run Code Online (Sandbox Code Playgroud)