23.5.2.1 Reference Deduction[Q]----The C++ Programming Language 4th Edition

It can be useful to have different actions taken for lvalues and rvalues. Consider a class for holding
an {integer,pointer} pair:
template<typename T>
class Xref {
public:
Xref(int i, T∗ p) // store a pointer: Xref is the owner
:index{i}, elem{p}, owner{true}
{ }
Xref(int i, T& r) // store a pointer to r, owned by someone else
:index{i}, elem{&r}, owner{false}
{ }
Xref(int i, T&& r) // move r into Xref, Xref is the owner
:index{i}, elem{new T{move(r)}}, owner{true}
{ }
˜Xref()
{
if(owned) delete elem;
}
// ...
private:
int index;
T∗ elem;
bool owned;
};
So:
string x {"There and back again"};
Xref<string> r1 {7,"Here"}; // r1 owns a copy of str ing{"Here"}
Xref<string> r2 {9,x}; // r2 just refers to x
Xref<string> r3 {3,new string{"There"}}; // r3 owns the string{"There"}
Here, r1 picks Xref(int,string&&) because x is an rvalue. Similarly, r2 picks Xref(int,string&) because x
is an lvalue.
Lvalues and rvalues are distinguished by template argument deduction: an lvalue of type X is
deduced as an X& and an rvalue as X. This differs from the binding of values to non-template argument
rvalue references (§12.2.1) but is especially useful for argument forwarding (§35.5.1). Consider
writing a factory function that make Xrefs on the free store and returns unique_ptrs to them:
template<typename T>
T&& std::forward(typename remove_reference<T>::type& t) noexcept; // §35.5.1
template<typename T>
T&& std::forward(typename remove_reference<T>::type&& t) noexcept;

template<typename TT, typename A>
unique_ptr<TT> make_unique(int i, A&& a) // simple var iant of make_shared (§34.3.2)
{
return unique_ptr<TT>{new TT{i,forward<A>(a)}};
}
We want make_unique<T>(arg) to construct a T from an arg without making any spurious copies. To
do that, it is essential that the lvalue/rvalue distinction is maintained. Consider:
auto p1 = make_unique<Xref<string>>(7,"Here");
"Here" is an rvalue, so forward(string&&) is called, passing along an rvalue, so that Xref(int,string&&)
is called to move from the string holding "Here".
The more interesting (subtle) case is:
auto p2 = make_unique<Xref<string>>(9,x);
Here, x is an lvalue, so forward(string&) is called, passing along an lvalue: forward()’s T is deduced to
string& so that the return value becomes string& &&, which means string& (§7.7.3). Thus,
Xref(int,string&) is called for the lvalue x, so that x is copied.
Unfortunately, make_unique() is not part of the standard library, but it is widely supported nevertheless.
Defining a make_unique() that can take arbitrary arguments is relatively easy using a variadic
template for forwarding (§28.6.3).

转载于:https://www.cnblogs.com/fbwang2011/p/3780284.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值