在 VS2010 中,std::forward 定义如下:
template<class _Ty> inline
_Ty&& forward(typename identity<_Ty>::type& _Arg)
{ // forward _Arg, given explicitly specified type parameter
return ((_Ty&&)_Arg);
}
identity
似乎仅用于禁用模板参数推导。在这种情况下有意禁用它有什么意义?
最佳答案
如果将右值引用传递给 X
类型的对象到采用类型 T&&
的模板函数作为其参数,模板参数推导推导 T
成为X
.因此,该参数的类型为 X&&
.如果函数参数是左值或 const 左值,则编译器将其类型推断为该类型的左值引用或 const 左值引用。
如果std::forward
使用的模板参数推导:
自 objects with names are lvalues
唯一一次std::forward
会正确转换为 T&&
当输入参数是一个未命名的右值时(如 7
或 func()
)。在完美转发的情况下arg
你传递给std::forward
是一个左值,因为它有一个名字。 std::forward
的类型将被推断为左值引用或 const 左值引用。引用折叠规则会导致 T&&
在 static_cast<T&&>(arg)
在 std::forward 中始终解析为左值引用或 const 左值引用。
示例:
template<typename T>
T&& forward_with_deduction(T&& obj)
{
return static_cast<T&&>(obj);
}
void test(int&){}
void test(const int&){}
void test(int&&){}
template<typename T>
void perfect_forwarder(T&& obj)
{
test(forward_with_deduction(obj));
}
int main()
{
int x;
const int& y(x);
int&& z = std::move(x);
test(forward_with_deduction(7)); // 7 is an int&&, correctly calls test(int&&)
test(forward_with_deduction(z)); // z is treated as an int&, calls test(int&)
// All the below call test(int&) or test(const int&) because in perfect_forwarder 'obj' is treated as
// an int& or const int& (because it is named) so T in forward_with_deduction is deduced as int&
// or const int&. The T&& in static_cast<T&&>(obj) then collapses to int& or const int& - which is not what
// we want in the bottom two cases.
perfect_forwarder(x);
perfect_forwarder(y);
perfect_forwarder(std::move(x));
perfect_forwarder(std::move(y));
}
关于c++ - 为什么使用 std::forward 禁用模板参数推导?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24936441/