问题描述
我设置了一个测试用例来了解完美转发.
I set up a test case to learn about perfect forwarding.
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
按预期工作.当我在没有身份的情况下实现自己的前向函数时,有趣的行为出现了:
std::forward
works as expected. The interesting behavior emerges when I implement my own forward function without identity:
template <typename T> T&& MyForward(T& t)
{
return ((T&&)t);
}
在外部用 MyForward
替换 std::forward
给出完全相同的结果!这种行为引出了一个问题,为什么要使用身份?
Replacing std::forward
with MyForward
in outer gives the exact same result! The behavior begs the question why identity is used?
编译器VS2010
更新 1:关于防止类型推导
Update 1: In reference to preventing type deduction
AFAIK,特殊类型扣除规则仅在 T&& 上激活.注意forward的定义,forward(typename identity::type&t)
.参数类型只有一个 &.事实上,在我将 MyForward 更改为使用身份并省略 (T&&) 转换后,该示例无法编译.从表面上看,从左值到右值的转换似乎使向前工作.
AFAIK, the special type deduction rule is only activated on T&&. Note the definition of forward, forward(typename identity<T>::type& t)
. The argument type has only one &. In fact, after I changed MyForward to use identity, and leave out the (T&&) casting, the example does not compile. On the surface, the casting from lvalue to rvalue seems to make the forward work.
更新 2:在 ideone.com 上使用 GCC 4.5 进行测试,行为相同.
Update 2: tested on ideone.com with GCC 4.5, same behavior.
推荐答案
remove_reference(
identity
在旧版的草稿中,但改为remove_reference
) 用于防止类型推导:std::forward
仅 使用显式类型参数.否则将编译以下内容:
remove_reference<T>
(identity
was in an old version of the draft, but was changed to remove_reference
) is used to prevent type deduction: std::forward
only works with an explicit type parameter. Otherwise the following would compile:
std::forward(t)
...但它不会做正确的事情.
... but it would not do the right thing.
关于左值/右值的问题,请注意有两个std::forward
的重载:一个用于左值,另一个用于右值.
Regarding the issue with lvalues/rvalues, please do notice that there are two overloads of std::forward
: one for lvalues, another for rvalues.
事实上,给出的 MyForward
实现更像是 std::move
:它将左值转换为右值(不同的是,move 也接受右值).
In fact, the MyForward
implementation given is more like std::move
: it turns lvalues into rvalues (the difference is that move accepts rvalues as well).
这篇关于c++11:std::forward的微妙之处:身份真的有必要吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!