Why is template argument deduction disabled with std::forward?(为什么使用 std::forward 禁用模板参数推导?)
问题描述
在 VS2010 中 std::forward 定义如下:
In VS2010 std::forward is defined as such:
template<class _Ty> inline
_Ty&& forward(typename identity<_Ty>::type& _Arg)
{ // forward _Arg, given explicitly specified type parameter
return ((_Ty&&)_Arg);
}
identity
似乎仅用于禁用模板参数推导.在这种情况下故意禁用它有什么意义?
identity
appears to be used solely to disable template argument deduction. What's the point of purposefully disabling it in this case?
推荐答案
如果将 X
类型的对象的右值引用传递给采用 T&& 类型的模板函数
作为其参数,模板参数推导推导出 T
为 X
.因此,参数的类型为 X&&
.如果函数参数是左值或 const 左值,则编译器将其类型推导为该类型的左值引用或 const 左值引用.
If you pass an rvalue reference to an object of type X
to a template function that takes type T&&
as its parameter, template argument deduction deduces T
to be X
. Therefore, the parameter has type X&&
. If the function argument is an lvalue or const lvalue, the compiler deduces its type to be an lvalue reference or const lvalue reference of that type.
如果 std::forward
使用模板参数推导:
If std::forward
used template argument deduction:
由于带有名称的对象是左值
,因此std::forward
唯一一次正确地转换为T&&
参数是一个未命名的右值(如 7
或 func()
).在完美转发的情况下,您传递给 std::forward
的 arg
是一个左值,因为它有一个名称.std::forward
的类型将被推导出为左值引用或常量左值引用.引用折叠规则将导致 std::forward 中 static_cast
T&&
始终解析为左值引用或常量左值引用.
Since objects with names are lvalues
the only time std::forward
would correctly cast to T&&
would be when the input argument was an unnamed rvalue (like 7
or func()
). In the case of perfect forwarding the arg
you pass to std::forward
is an lvalue because it has a name. std::forward
's type would be deduced as an lvalue reference or const lvalue reference. Reference collapsing rules would cause the T&&
in static_cast<T&&>(arg)
in std::forward to always resolve as an lvalue reference or const lvalue reference.
示例:
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));
}
这篇关于为什么使用 std::forward 禁用模板参数推导?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:为什么使用 std::forward 禁用模板参数推导?


基础教程推荐
- 为什么语句不能出现在命名空间范围内? 2021-01-01
- 如何在不破坏 vtbl 的情况下做相当于 memset(this, ...) 的操作? 2022-01-01
- Windows Media Foundation 录制音频 2021-01-01
- 管理共享内存应该分配多少内存?(助推) 2022-12-07
- 使用从字符串中提取的参数调用函数 2022-01-01
- 从 std::cin 读取密码 2021-01-01
- 为 C/C++ 中的项目的 makefile 生成依赖项 2022-01-01
- 如何“在 Finder 中显示"或“在资源管理器中显 2021-01-01
- 在 C++ 中循环遍历所有 Lua 全局变量 2021-01-01
- 如何使图像调整大小以在 Qt 中缩放? 2021-01-01