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

ope*_*ind 16 c++ perfect-forwarding c++11 c++14 c++17

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

过载 1:

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

重载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);
}
Run Code Online (Sandbox Code Playgroud)

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

template <typename T>
void wrapper(T&& e)
{
    wrapped(forward<T>(e));
}
Run Code Online (Sandbox Code Playgroud)

当然,您知道何时wrapper()实例化T取决于传递给它的参数是左值还是右值。如果它是type的左值UT则推导为U&。如果是右值,T则推导为U

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

现在我的问题是:

使用(需要)第二重载的有效方案是什么?

How*_*ant 14

N2951forward中详细讨论了其设计原理。

本文档列出了6个用例:

应该转发一个左值作为左值。所有实现均通过此测试。但这不是经典的完美转发模式。该测试的目的是表明实现2未能实现其既定目标,即无法阻止除完美转发之外的所有用例。

B. 应该转发一个右值作为右值。像用例A一样,这是一个身份转换,这是一个需要身份转换的激励示例。

C. 是否应转发一个右值作为左值。该用例演示了意外创建悬挂参考的危险情况。

D. 应该将较少的cv限定的表达式转发到更多的cv限定的表达式。一个积极的用例,涉及在向前过程中添加const。

E. 应该将派生类型的表达式转发到可访问的,明确的基本类型。一个激动人心的用例,涉及将派生类型转发到基本类型。

F. 是否应转发任意类型转换。该用例演示了正向内的任意转换如何导致悬空的参考运行时错误。

第二次过载启用情况B和C。

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

更新资料

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

  • 大声笑在输入与本文链接的答案时中途完成-很高兴您在这里:-) (5认同)