std::forward 的工作和参考折叠

Working of std::forward and reference collapsing

我正在尝试熟悉完美转发的概念。 我已阅读 this and this post here. I believe I am also comfortable with the reference collapsing concept. While reading this post。我提出了以下问题

假设我们有下面的例子

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

然后我们像这样传递它

int i= 12;
foo(i);

现在我明白了 i 会被当作 int& 我不明白 就是为什么上面回答的问题 link 提到它会是 被视为 int& && 将崩溃为 int&. 我认为它将被视为 int&& & 将崩溃为 int& 我理解 return 两者的类型相同,但我希望第一部分正确。 我认为是int&& &而不是int& &&的原因如下所述,如有错误请指正

当我传入这样的东西时

int i =12;
foo(i);

那么例1就变成这样了

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

现在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.
}

所以当我们的解决方案应用于它时。变成

return static_cast<int&&>(&param) ; //&param since we passed &t in A

我们得到

int&& & and not `int& &&` please correct me if I am wrong

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

int i = 12;
foo(i);

表达式i有一个左值类别,因此T被推导为int&,所以例子1变成:

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

现在,在 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
}

恢复了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&&`
}

并且当类型模板参数明确指定为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
}