Cur*_*ous 13 c++ reference rvalue perfect-forwarding c++11
鉴于以下参考折叠规则
T& & - > T&T&& & - > T&T& && - > T&T&& && - > T&&第三和第四条规则意味着T(ref qualifer) &&身份转变,即T&停留在T&并T&&保持在T&&.为什么我们有两个重载std::forward?以下定义无法满足所有目的吗?
template <typename T, typename = std::enable_if_t<!std::is_const<T>::value>>
T&& forward(const typename std::remove_reference<T>::type& val) {
return static_cast<T&&>(const_cast<T&&>(val));
}
Run Code Online (Sandbox Code Playgroud)
这里服务的唯一目的const std::remove_reference<T>&是不复制.并且enable_if有助于确保仅在非const值上调用该函数.我不完全确定是否const_cast需要它,因为它不是引用本身的const.
由于forward总是使用显式模板参数调用,因此我们需要考虑两种情况:
forward<Type&>(val)这里Tin 的类型forward将是T&,因此返回类型将是身份转换T&forward<Type&&>(val)这里Tin 的类型forward将是T&&,因此返回类型将是身份转换T&&那么为什么我们需要两个重载,如http://en.cppreference.com/w/cpp/utility/forward中所述?
注意:我不确定是否std::forward曾使用过const类型,但forward在这种情况下我禁用了,因为我从未见过像这样使用它.在这种情况下,移动语义也没有意义.
一个良好的开端将是霍华德Hinnant(欣南特)的答案和论文上std::forward().
你的实现处理所有正常正确的用例(T& --> T&,T const& --> T const&,和T&& --> T&&).它无法处理的是常见且容易出错的错误,这些错误在您的实现中很难调试但无法编译std::forward().
鉴于这些定义:
struct Object { };
template <typename T, typename = std::enable_if_t<!std::is_const<T>::value>>
T&& my_forward(const typename std::remove_reference<T>::type& val) {
return static_cast<T&&>(const_cast<T&&>(val));
}
template <class T>
void foo(T&& ) { }
Run Code Online (Sandbox Code Playgroud)
我可以将非const引用传递给const对象,这两个都是左值的:
const Object o{};
foo(my_forward<Object&>(o)); // ok?? calls foo<Object&>
foo(std::forward<Object&>(o)); // error
Run Code Online (Sandbox Code Playgroud)
和右值品种:
const Object o{};
foo(my_forward<Object>(o)); // ok?? calls foo<Object>
foo(std::forward<Object>(o)); // error
Run Code Online (Sandbox Code Playgroud)
我可以将左值引用传递给rvalues:
foo(my_forward<Object&>(Object{})); // ok?? calls foo<Object&>
foo(std::forward<Object&>(Object{})); // error
Run Code Online (Sandbox Code Playgroud)
前两种情况导致可能修改预期的对象const(如果构造它们可能是UB const),最后一种情况是传递悬空左值引用.
| 归档时间: |
|
| 查看次数: |
772 次 |
| 最近记录: |