为什么 std::forward 返回 static_cast<T&&> 而不是 static_cast<T>?
Why does std::forward return static_cast<T&&> and not static_cast<T>?
让我们有一个名为Y的函数来重载:
void Y(int& lvalue)
{ cout << "lvalue!" << endl; }
void Y(int&& rvalue)
{ cout << "rvalue!" << endl; }
现在,让我们定义一个类似于 std::forward 的模板函数
template<class T>
void f(T&& x)
{
Y( static_cast<T&&>(x) ); // Using static_cast<T&&>(x) like in std::forward
}
现在看看 main()
int main()
{
int i = 10;
f(i); // lvalue >> T = int&
f(10); // rvalue >> T = int&&
}
正如预期的那样,输出为
lvalue!
rvalue!
现在回到模板函数f()
,static_cast<T&&>(x)
替换为 static_cast<T>(x)
。让我们看看输出:
lvalue!
rvalue!
是一样的!为什么?如果它们是相同的,那么为什么std::forward<>
将演员表从x
返回到T&&
?
左值与右值分类保持不变,但效果完全不同(并且值类别确实发生了变化 - 尽管在您的示例中不是以可观察的方式)。让我们回顾一下这四种情况:
template<class T>
void f(T&& x)
{
Y(static_cast<T&&>(x));
}
template<class T>
void g(T&& x)
{
Y(static_cast<T>(x));
}
如果我们用左值调用f
,T
会推导出为一些X&
,所以强制转换引用X& && ==> X&
折叠,所以我们最终得到相同的左值,没有任何变化。
如果我们用右值调用f
,T
会推断为某种X
所以强制转换只是将x
转换为右值引用x
,所以它变成了右值(特别是x值)。
如果我们用左值称呼g
,所有同样的事情都会发生。没有必要折叠引用,因为我们只是使用 T == X&
,但演员表仍然是一个无操作,我们最终仍然得到相同的值。
但是,如果我们用右值调用g
,我们将static_cast<T>(x)
复制x
.该副本是一个右值(正如您的测试所验证的那样 - 除了现在它是一个 prvalue 而不是 xvalue),但它充其量是一个额外的、不必要的副本,并且在最坏的情况下将是编译失败(如果T
是可移动但不可复制的)。对于 static_cast<T&&>(x)
,我们强制转换为不调用副本的引用。
所以这就是为什么我们做T&&
.
相关文章:
- 请解释这句话(cout<<1+int((a<b)^((b-a)&1) )<<endl
- 呼叫运营商<<临时
- 如何防止clang格式在流运算符调用之间添加换行符<<
- <<操作员在下面的行中工作
- EASTL矢量<向量<int>>连续的
- C - 创建矢量&lt; vector&lt; double&gt;&gt;矩阵具有分配而不是inizializ
- 为什么将此对向量&lt; map&lt; int,int&gt;&gt;中的地图进行更新.失败
- C :对矢量进行排序&lt; struct&gt;(结构有2个整数)基于结构的整数之一
- 明确的专业化“ CheckIntmap&lt;&gt;”实例化
- 什么是模板&lt;&gt;inline bla bla
- 编辑C Qlist&lt; object*&gt; gt;QML代码和一些QML警告中的模型
- eigen :: llt&lt;eigen :: matrixxd&gt;具有不完整的类型
- 错误,包括&lt; ctype&gt;在原子上使用C 11
- std::vector<;uint8_t>;当C++11/14启用时,手动复制而不是调用memcpy
- 如何加入向量&lt; int&gt;到C 中的单个INT
- 是std :: set&lt; std :: future&gt;不可能存在
- 是numeric_limits&lt; int&gt; :: is_modulo从逻辑上矛盾
- opencv 2.4.7在iOS错误背景_segm.hpp #include&lt; list&gt;未找到
- 在修改列表后,std :: list&lt; t&gt; :: end()的值是否会更改
- ///<评论></评论>在Visual Studio中