c++11中的move与forward(三)

2014-11-24 07:44:40 · 作者: · 浏览: 2
PE的构造函数接受的是一个lvalue。
TYPE* ret = new TYPE(forward(arg));
}
复制代码
2. 二个原则
要理解forward()是怎么实现的,先得说说c++11中关于引用的二个原则。
原则(1):
引用折叠原则(reference collapsing rule)
1) T& &(引用的引用) 被转化成 T&.
2)T&& &(rvalue的引用)被传化成 T&.
3) T& &&(引用作rvalue) 被转化成 T&.
4) T&& && 被转化成 T&&.
原则(2):
对于以rvalue reference作为参数的模板函数,它的参数推导也有一个特殊的原则:
假设函数原型为:
template
TYPE* acquire_obj(ARG&& arg);
1)如果我们传递lvalue给acquire_obj(), ARG就会被推导为ARG&,因此
复制代码
ARG arg;
acquire_obj(arg)中acquire_obj被推导为
acquire_obj(ARG& &&)
根据前面说的折叠原则,acquire_obj(ARG& &&)
最后变成
acquire_obj(ARG&)
复制代码
2)如果我们传递rvalue给acquire_obj(),ARG就会被推导为ARG,因此
acquire_obj(get_arg());
则acquire_obj 被推导为 acquire_obj(ARG&&)
3.结论
有了这两个原则,现在我们可以给出最后acquire_obj的原型,以及forward()的原型。
复制代码
template
TYPE&& forward(typename remove_reference::type& arg)
{
return static_cast(arg);
}
template
TYPE* acquire_obj(ARG&& arg)
{
return new TYPE(forward(arg));
}
复制代码
下面我们验证一下,上述函数是否能正常工作,假如我们传给acquire_obj一个lvalue,根据上面说的模板推导原则,ARG会被推导为ARG&,我们得到如下函数:
复制代码
TYPE* acquire_obj(ARG& && arg)
{
return new TYPE(forward(arg));
}
以及相应的forward()函数。
TYPE& &&
forward(typename remove_reference::type& arg)
{
return static_cast(arg);
}
再根据折叠原则,我们得到如下的函数:
TYPE* acquire_obj(ARG& arg)
{
return new TYPE(forward(arg));
}
以及相应的forward()函数。
TYPE&
forward(typename remove_reference::type& arg)
{
return static_cast(arg);
}
复制代码
所以,最后在acquire_obj中,forward返回了一个lvalue, TYPE的构造函数接受了一个lvaue, 这正是我们所想要的。
而假如我们传递给acquire_obj一个rvalue的参数,根据模板推导原则,我们知道ARG会被推导为ARG,于是得到如下函数:
复制代码
TYPE* acquire_obj(ARG&& arg)
{
return new TYPE(forward(arg));
}
以及相应的forward()函数。
TYPE&&
forward(typename remove_reference::type& arg)
{
return static_cast(arg);
}
复制代码
最后acquire_obj中forward()返回了一个rvalue,TYPE的构造函数接受了一个rvalue,也是我们所想要的。
可见,上面的设计完成了我们所想要的功能,这时的acquire_obj函数才是完美的转发函数。
三.move的原型
复制代码
template
typename remove_reference::type&&
std::move(T&& a)
{
typedef typename remove_reference::type&& RvalRef;
return static_cast(a);
}
复制代码
根据rvalue引用的模板推导原则和折叠原则,我们很容易验证,无论是给move传递了一个lvalue还是rvalue,最终返回的,都是一个rvalue reference.
而这正是move的意义,得到一个rvalue的引用。
看到这里有人也许会发现,其实就是一个cast嘛,确实是这样,直接用static_cast也是能达到同样的效果,只是move更具语义罢了。