且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

类模板如何存储引用或值?

更新时间: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:


  1. 如果 t 绑定到类型为 T2 的左值,然后 T = T2&

  2. 如果 t 绑定到类型为 T2 的右值,则 T = T2

  1. If t is bound to an lvalue of type T2, then T = T2&.
  2. If t is bound to an rvalue of type T2, then T = T2.

std是那些扣除规则: :forward 依靠自己的工作。

上面的意思是您直接用 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.

顺便说一句,因为标记了,我们也可以在您的示例中添加演绎指南。如果我们定义如下(来自 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.