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的左值U
,T
则推导为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:不应该转发任意类型转换。