我设置了一个测试用例来了解完美转发。
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
按预期工作。当我实现我自己的没有身份的转发函数时,会出现有趣的行为:
template <typename T> T&& MyForward(T& t)
{
return ((T&&)t);
}
在外部用std::forward
替换MyForward
会得到完全相同的结果!这种行为引出了为什么要使用身份的问题?
编译器VS2010
更新1:参考防止类型扣除
AFAIK,特殊类型扣除规则仅在T&amp;&amp;上激活。请注意forward forward(typename identity<T>::type& t)
的定义。参数类型只有一个&amp ;.实际上,在我将MyForward更改为使用标识并省略(T&amp;&amp;)转换后,该示例无法编译。从表面上看,从左值到右值的铸造似乎是向前发展的。
更新2:使用GCC 4.5在ideone.com上测试,行为相同。
答案 0 :(得分:13)
remove_reference<T>
(identity
在草稿的旧版本中,但已更改为remove_reference
)用于防止类型扣除:std::forward
仅< / em>使用显式类型参数。否则将编译以下内容:
std::forward(t)
......但它不会做正确的事。
关于左值/右值的问题,请注意two overloads of std::forward
:一个用于左值,另一个用于右值。
实际上,给出的MyForward
实现更像std::move
:它将左值变为右值(不同之处在于移动也接受rvalues)。
答案 1 :(得分:0)
我在VS 2010中检查了forward
和identity
的定义。MyForward
与forward
之间的唯一区别是您使用T&
参数,他们使用typename identity<T>::type&
参数。而identity<T>::type
只是T
。
这种差异最重要(也许也是唯一)的影响是,要使用他们的forward
,必须明确指定模板参数,同时可以从调用中推导出MyForward
的模板参数。