我正在尝试完美转发,我发现
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/