类模板如何存储引用或值? [英] How can a class template store either reference or value?

查看:110
本文介绍了类模板如何存储引用或值?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

关于通用参考书的阅读导致了我想知道:如何构造一个类模板,以便在可能的情况下按引用存储,或者在必要时按值存储?

Reading about universal references led me to wonder: how can I construct a class template such that it stores by reference if possible, or by value if it must?

也就是说,我可以这样做吗?

That is, can I do something like this

template <class T>
class holder {
    T  obj_m;  // should be a reference if possible...
public:
    holder(T t) :obj_m { t } {}
}

auto 
hold_this(T && t) { return holder<T>(t); }

除了 hold_this()是给定左值的所有者将持有一个引用,当给定 rvalue 的所有者将进行复制吗?

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?

推荐答案


除了为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 不能是转发引用,因为构造函数本身没有模板。

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.

这篇关于类模板如何存储引用或值?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆