【问题标题】:How can a class template store either reference or value?类模板如何存储引用或值?
【发布时间】:2018-07-29 11:15:23
【问题描述】:

阅读universal references 让我想知道:我如何构造一个类模板,使其尽可能通过引用存储,或者如果必须通过值存储?

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

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()被赋予一个左值时,持有者将持有一个引用,而当给定一个右值时,持有者将复制一份?

【问题讨论】:

    标签: c++ templates c++17


    【解决方案1】:

    除了当hold_this()被赋予一个左值时持有者将持有一个引用,而当给定一个右值时持有者将进行复制?

    你已经写好了(减去所需的template &lt;typename T&gt;)。 转发引用保留值类别的扣除规则如下:

    1. 如果t 绑定到T2 类型的左值,则T = T2&amp;
    2. 如果t 绑定到T2 类型的右值,则T = T2

    std::forward 依靠这些推理规则来完成工作。以及为什么我们还需要将类型传递给它。

    上面的意思是你在右值的情况下直接用T2实例化holder。给你你想要的。已制作副本。

    事实上,制作了两份副本。一次创建构造函数参数t,另一个副本是从它初始化obj_m。但是我们可以通过巧妙地使用 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)); }
    

    See it live。我们使用add_rvalue_reference_t 使t 在每种情况下都具有正确的引用类型。并“模拟”使obj_m { std::forward&lt;T&gt;(t) } 解析为从正确的引用类型初始化obj_m 的参数推导。

    我说“模拟”是因为理解 holder 的构造函数参数不能是转发引用很重要,因为构造函数本身没有模板化。


    顺便说一句,既然你标记了,我们还可以在你的例子中添加一个演绎指南。如果我们将其定义如下(并入feedback from T.C.):

    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>;
    

    然后this live example 显示您可以将变量定义为hold h1{t};hold h2{test()};,其推导类型与之前的函数返回值相同。

    【讨论】:

    • 除非您处理的是不可引用的类型,否则add_rvalue_reference_t&lt;T&gt; 完全等同于T&amp;&amp;
    • @T.C. - 我不怀疑有人会尝试传递其中一个,所以T&amp;&amp; 作为编辑示例中的替代方案。不过我必须说,我发现 add_rvalue_reference_t 对于那些认为 t 将是转发参考的人来说不太容易混淆。
    猜你喜欢
    • 1970-01-01
    • 2011-12-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多