c++ - 有纯右值的 std::forward 用例吗?

标签 c++ c++11 move-semantics rvalue-reference

std::forward 最常见的用法是完善转发转发(通用)引用,例如

template<typename T>
void f(T&& param)
{
    g(std::forward<T>(param)); // perfect forward to g
}

这里 param 是一个 lvalue,而 std::forward 最终将其转换为右值或左值,具体取决于参数的内容那是有界的。

definition of std::forward from cppreference.com我看到还有一个 rvalue 重载

template< class T >
T&& forward( typename std::remove_reference<T>::type&& t );

谁能告诉我为什么 rvalue 重载?我看不到任何用例。如果你想传递一个右值给一个函数,你可以直接传递它,不需要在它上面应用 std::forward

这与 std::move 不同,我明白为什么还需要一个 rvalue 重载:您可能会处理您不知道的通用代码您正在传递什么,并且您希望无条件支持 move 语义,请参见例如Why does std::move take a universal reference? .

编辑为了澄清这个问题,我问为什么overload (2) from here是必要的,并且是一个用例。

最佳答案

好的,因为@vsoftco 要求简洁的用例,这里有一个改进的版本(使用他的想法让“my_forward”实际看到调用了重载)。

我通过提供一个代码示例来解释“用例”,如果没有prvalue,它不会编译或行为不同(不管这是否真的有用)。

我们有 2 overloads for std::forward

#include <iostream>

template <class T>
inline T&& my_forward(typename std::remove_reference<T>::type& t) noexcept
{
    std::cout<<"overload 1"<<std::endl;
    return static_cast<T&&>(t);
}

template <class T>
inline T&& my_forward(typename std::remove_reference<T>::type&& t) noexcept
{
    std::cout<<"overload 2"<<std::endl;
    static_assert(!std::is_lvalue_reference<T>::value,
              "Can not forward an rvalue as an lvalue.");
    return static_cast<T&&>(t);
}

我们有 4 个可能的用例

用例 1

#include <vector>
using namespace std;

class Library
{
    vector<int> b;
public:
    // &&
    Library( vector<int>&& a):b(std::move(a)){

    }
};

int main() 
{
    vector<int> v;
    v.push_back(1);
    Library a( my_forward<vector<int>>(v)); // &
    return 0;
}

用例 2

#include <vector>
using namespace std;

class Library
{
    vector<int> b;
public:
    // &&
    Library( vector<int>&& a):b(std::move(a)){

    }
};

int main() 
{
    vector<int> v;
    v.push_back(1);
    Library a( my_forward<vector<int>>(std::move(v))); //&&
    return 0;
}

用例 3

#include <vector>
using namespace std;

class Library
{
    vector<int> b;
public:
    // &
    Library( vector<int> a):b(a){

    }
};

int main() 
{
    vector<int> v;
    v.push_back(1);
    Library a( my_forward<vector<int>>(v)); // &
    return 0;
}

用例 4

#include <vector>
using namespace std;

class Library
{
    vector<int> b;
public:
    // &
    Library( vector<int> a):b(a){

    }
};

int main() 
{
    vector<int> v;
    v.push_back(1);
    Library a( my_forward<vector<int>>(std::move(v))); //&&
    return 0;
}

这是一份简历

  1. 使用了Overload 1,没有它你会得到编译错误
  2. 使用了 Overload 2,没有它会出现编译错误
  3. 使用了Overload 1,没有它你会得到编译错误
  4. 使用了Overload 2,没有它你会得到编译错误

注意,如果我们不使用forward

Library a( std::move(v));
//and
Library a( v);

你得到:

  1. 编译错误
  2. 编译
  3. 编译
  4. 编译

如您所见,如果您只使用两个 forward 重载之一,则基本上导致无法编译 4 种情况中的 2 种,而如果您不使用 forward 4 种情况下你只能编译 3 种。

关于c++ - 有纯右值的 std::forward 用例吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29859696/

相关文章:

c++ - 实现可变类型特征

c++ - 避免在 hpp 文件中暴露私有(private)成员变量

c++ - lambda 是如何 move 的?

c++ - 看不懂std::move的实现

c++ - 将数组设置为包含字符串值会导致错误

c++ - 删除字符串中连续的重复值

c++ - 为什么 visual studio code 告诉我 cout 不是 std 命名空间的成员?

c++ - C++中运算符重载的语法是什么?

c++ - 函数指针的可变函数

rust - 为什么我可以重新分配给 move 的变量?