更新时间:2023-12-01 22:10:40
除了为hold_this()赋予左值时,持有人将持有引用,而给与右值时,持有人将进行复制吗?
Except that when hold_this() is given an lvalue the holder will hold a reference, and when given an rvalue the holder will make a copy?
您已经编写了它(减去必需的模板< typename T>
)。 转发参考的扣除规则保留值类别如下:
You already wrote it (minus the required template <typename T>
). The deduction rules for a forwarding reference preserve value category as follows:
t
绑定到类型为 T2
的左值,然后 T = T2&
。 t
绑定到类型为 T2
的右值,则 T = T2
。t
is bound to an lvalue of type T2
, then T = T2&
.t
is bound to an rvalue of type T2
, then T = T2
.
上面的意思是您直接用 holder
实例化 holder
在右值情况下为 T2
。给您您想要的。制作副本。
The above means that you instantiate holder
directly with T2
in the rvalue case. Giving you exactly what you want. A copy is made.
事实上,制作了两个副本。一次创建构造函数自变量 t
,另一个副本是从中初始化 obj_m
。但是我们可以通过巧妙地使用type_traits来摆脱它:
As a matter of fact, two copies are made. Once to create the constructor argument t
, and the other copy is to initialize obj_m
from it. But we can get rid of it with some clever use of type_traits:
template <class T>
class holder {
T obj_m; // should be a reference if possible...
public:
holder(std::add_rvalue_reference_t<T> t) :obj_m { std::forward<T>(t) } {}
};
template<typename T>
auto hold_this(T && t) { return holder<T>(std::forward<T>(t)); }
实时观看。我们使用 add_rvalue_reference_t
在每种情况下,使 t
具有正确的引用类型。然后模拟参数推导,这将使 obj_m {std :: forward< T>(t)}
解析为初始化 obj_m
来自正确的引用类型。
See it live. We use add_rvalue_reference_t
to make t
be of the correct reference type in each case. And "simulate" the argument deduction which would make obj_m { std::forward<T>(t) }
resolve to initializing obj_m
from the correct reference type.
我说模拟是因为了解 holder $ c $的构造函数参数很重要c>不能是转发引用,因为构造函数本身没有模板。
I say "simulate" because it's important to understand the constructor argument for holder
cannot be a forwarding reference because the constructor itself is not templated.
顺便说一句,因为标记了 c ++ 17 ,我们也可以在您的示例中添加演绎指南。如果我们定义如下(来自 TC 的反馈):
By the way, since you tagged c++17, we can also add a deduction guide to your example. If we define it as follows (with the feedback from T.C. incorporated):
template <class T>
class holder {
T obj_m; // should be a reference if possible...
public:
holder(T&& t) :obj_m { std::forward<T>(t) } {}
};
template<typename T>
holder(T&&) -> holder<T>;
然后此实时示例显示了您可以将变量定义为 hold h1 {t};
和 hold h2 {test()};
,其推导类型与函数以前返回的值相同。
Then this live example shows you can define variables as hold h1{t};
and hold h2{test()};
, with the same deduced types as the function return values from before.