c++ - std::forward() 的右值引用重载的目的是什么?
问题描述
我正在尝试完美转发,我发现
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
取决于传递给它的参数是左值还是右值。如果它是 type 的左值U
,T
则推导为U&
。如果是右值,T
则推导为U
.
wrapper()
在任何情况下 - 在-的范围内e
都是一个左值,因此它总是使用 的第一个重载std::forward()
。
现在我的问题:
使用(并且需要)第二次重载的有效场景是什么?
解决方案
N2951forward
中详细讨论了其设计原理。
本文档列出了 6 个用例:
A.应该将左值作为左值转发。所有实现都通过了这个测试。但这不是经典的完美转发模式。此测试的目的是表明实现 2 未能实现其既定目标,即阻止除完美转发之外的所有用例。
B.应该将右值作为右值转发。与用例 A 一样,这是一个身份转换,这提供了一个需要身份转换的激励示例。
C.不应将右值作为左值转发。此用例演示了意外创建悬空引用的危险情况。
D. 应该将较少的 cv 限定表达式转发到更多 cv 限定的表达式。一个鼓舞人心的用例,涉及在转发期间添加 const。
E.应该将派生类型的表达式转发到可访问的、明确的基类型。一个涉及将派生类型转发到基本类型的激励用例。
F. 不应转发任意类型转换。此用例演示了正向中的任意转换如何导致悬空引用运行时错误。
第二个重载启用情况 B 和 C。
本文继续提供每个用例的示例,这些示例太长,无法在此重复。
更新
我刚刚通过这 6 个用例运行了第一个重载的“解决方案”,这个练习表明第二个重载也启用了用例 F:不应该转发任意类型转换。
推荐阅读
- c++ - 启动时调用其他 C++ 程序的 C++ 系统调用不起作用
- c# - 如何从 DatePicker 计算年龄?
- python - 如何在函数式编程中使用循环?
- node.js - 如何只显示最新的文档?
- python - 如何绘制弹丸在重力、浮力和空气阻力作用下的运动?
- python - 使用 selenium 转到亚马逊上的下一页
- android - Android WorkManager 使用调试版本但不使用发布 APK
- python-2.7 - 将 \x1d\xe3Gi%a\x00\x00\x00\x00 转换为 1de347692561
- testing - 使用 Mocha 插件测试无服务器
- python - 如何使用Python中的函数返回算术运算的结果