我设置了一个测试用例来学习完美转发。
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());
}
std::forward
的功能符合预期。当我实现自己的 forward 函数时,没有使用 identity 时会出现有趣的行为:
template <typename T> T&& MyForward(T& t)
{
return ((T&&)t);
}
在外部使用
MyForward
代替std::forward
会得到完全相同的结果!这种行为引发了一个问题,为什么要使用identity?编译器为VS2010。关于防止类型推断,据我所知,特殊的类型推断规则只在T&&上被激活。注意forward的定义,forward(typename identity<T>::type& t)
。参数类型只有一个&。事实上,当我改用identity,并省略(T&&)强制转换时,示例无法编译。表面上,从左值到右值的强制转换似乎使forward起作用。在ideone.com上测试GCC 4.5,结果相同。
std::forward
的两个重载还是remove_reference<T>::type
? - kennytmT&& forward(typename remove_reference<T>::type& t)
(还有一个接受&&
的重载)。 - kennytmstd::identity<>
;最终的C++11标准是基于N3290的,已经将其删除。 - ildjarn