c ++ 11:std :: forward的微妙之处:身份真的有必要吗?

Can*_*hiu 12 c++ visual-studio-2010 visual-c++ c++11

我设置了一个测试用例来了解完美转发.

std::string inner(const std::string& str ) {
return "const std::string&";
}
std::string inner(std::string& str ) {
    return "std::string&";
}
std::string inner(const std::string&& str ) {
    return "const std::string&&";
}
std::string inner(std::string&& str ) {
    return "std::string&&";
}

template <typename T> void outer(T&& t) {
  std::cout << "t: " << t << std::endl;
  std::cout << "perfect forward: " << inner(std::forward<T>(t)) << std::endl;
  std::cout << std::endl;
}

void PerfectForwarding()
{
     outer("literal");
     outer(lvalue);
     outer(constlvalue);
     outer(rvalue());
     outer(constrvalue());
}
Run Code Online (Sandbox Code Playgroud)

std::forward按预期工作.当我实现我自己的没有身份的转发函数时,有趣的行为出现了:

template <typename T> T&& MyForward(T& t)
{
   return ((T&&)t);
}
Run Code Online (Sandbox Code Playgroud)

更换std::forwardMyForward外给完全相同的结果!这种行为引出了为什么使用身份的问题?

编译器VS2010

更新1:参考防止类型扣除

AFAIK,特殊类型扣除规则仅在T &&上激活.注意forward的定义forward(typename identity<T>::type& t).参数类型只有一个&.实际上,在我将MyForward更改为使用标识并省略(T &&)转换后,该示例无法编译.从表面上看,从左值到右值的铸造似乎使前进工作.

更新2:在ideone.com上使用GCC 4.5测试,行为相同.

R. *_*des 13

remove_reference<T>(identity在草稿的旧版本中,但更改为remove_reference)用于防止类型推导:std::forward 适用于显式类型参数.否则以下将编译:

std::forward(t)
Run Code Online (Sandbox Code Playgroud)

......但它不会做正确的事情.

关于与左值/右值的问题,请大家注意有两个重载std::forward:一个是左值,另一个是右值.

事实上,MyForward给出的实现更像是std::move:它将左值转换为右值(不同之处在于移动也接受rvalues).