在std :: forward中它如何接受rvalue?

时间:2015-03-13 20:20:02

标签: c++ c++11 perfect-forwarding

查看Scott Meyer的 Effective Modern C ++ 页面200-201,std::forward的建议简化实现可能(确实在其他地方看到了正确的实现):

template <typename T>
T&& forward(std::remove_reference_t<T>& param)
{ return static_cast<T&&>(param); }

当接受右值小部件时,它变为:

Widget&& forward(Widget& param)
{ return static_cast<Widget&&>(param); }

现在,如果您使用替代代码,并执行:

struct Widget { };

Widget&& forward(Widget& param)
{ return static_cast<Widget&&>(param); }

template <typename T>
void G(T&& uref)
{ }

template <typename T>
void F(T&& uref)
{ G(forward(uref)); }

int main()
{
  Widget x;
  F(std::move(x));
}

我无法解决的问题,并且还没有看到关于SO的直接答案,是:<{>} forward参数Widget& param如何管理从F()接受Widget&&?通常gcc-5.0会因为非模板代码而抱怨:

  

错误:从'std :: remove_reference :: type {aka Widget}'类型的右值开始无效初始化'Widget&amp;'类型的非const引用

Question #27501400几乎触及了这个主题,但并不完全。它显示标准同时包含左值和右值以及右值和版本。)

1 个答案:

答案 0 :(得分:0)

  

“命名的右值引用是左值”,

因此,如评论中所述,示例工作正常。

然而,您的代码可以修改为

template <typename T>
void F(T && uref)
{
    G(forward(move(uref)));
}

被另一个重载(比较)接受:

template<typename T>
T && forward(typename std::remove_reference<T>::type & t)
{
    return static_cast<T &&>(t);
}


template<typename T>
T && forward(typename std::remove_reference<T>::type && t)
{
    static_assert(!std::is_lvalue_reference<T>::value, "T is an lvalue reference");
    return static_cast<T &&>(t);
}

第二次重载将用于右值。如果TWidgetWidget &&并且Widget &的断言失败,则此方法有效。