c++ - std::forward() 的右值引用重载的目的是什么?

标签 c++ c++11 c++14 c++17 perfect-forwarding

我正在尝试完美转发,我发现 std::forward()需要两个重载:

重载nr。 1:

template <typename T>
inline T&& forward(typename 
std::remove_reference<T>::type& t) noexcept
{
    return static_cast<T&&>(t);
}

重载 nr.2:

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

现在完美转发的典型场景是这样的

template <typename T>
void wrapper(T&& e)
{
    wrapped(forward<T>(e));
}

当然你知道当 wrapper() 被实例化时,T 取决于传递给它的参数是左值还是右值。如果它是 U 类型的左值,则将 T 推导出为 U&。如果是右值,则将 T 推导出为 U

无论如何 - 在 wrapper() 的范围内 - e 是一个左值,因此它总是使用 std::forward( ).

现在我的问题:

使用(并且需要)第二个重载的有效场景是什么?

最佳答案

forward 的设计原理在 N2951 中有详细讨论。 .

本文档列出了 6 个用例:

A. Should forward an lvalue as an lvalue. All implementations pass this test. But this is not the classic perfect forwarding pattern. The purpose of this test is to show that implementation 2 fails in its stated goal of preventing all use cases except perfect forwarding.

B. Should forward an rvalue as an rvalue. Like use case A, this is an identity transformation and this presents a motivating example where the identity transformation is needed.

C. Should not forward an rvalue as an lvalue. This use case demonstrates a dangerous situation of accidentally creating a dangling reference.

D. Should forward less cv-qualified expressions to more cv-qualified expressions. A motivating use case involving the addition of const during the forward.

E. Should forward expressions of derived type to an accessible, unambiguous base type. A motivating use case involving forwarding a derived type to a base type.

F. Should not forward arbitrary type conversions. This use case demonstrates how arbitrary conversions within a forward lead to dangling reference run time errors.

第二个重载启用情况 B 和 C。

本文继续提供每个用例的示例,篇幅太长,无法在此重复。

更新

我刚刚通过这 6 个用例运行了第一个重载的“解决方案”,这个练习表明第二个重载也启用了用例 F:不应该转发任意类型转换。

关于c++ - std::forward() 的右值引用重载的目的是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56361755/

相关文章:

c++ - 函数使用对象,对象使用函数

c++ - 将 rng 的列表存储在 std::array 中以进行多线程处理

c++ - 允许运行时和编译时多态性的灵活方式?

c++ - 成对函数评估算法(C++、STL)

c++ - DrawText VS TextOut Win32

c++ - 如何在 Visual C++ 中跟踪到外部编译的库

c++ - 为什么这个程序输出相同的结果 4 次?

c++ - 工厂类实现问题

c++ - 字符串文字,让编译器计算 string_view 构造函数的长度

c++ - 保留 std::initializer_list 的拷贝是否安全?这是什么道理?