我想设计一个可以存储值或引用的类,但在模板声明中具有相同的参数。我不知道如何编写模板类。谁能给我一些建议吗
tempalte <typename T>
class Holder {
// ......
Holder(T &value);
Holder(T value);
}
class CannotCopy {
CannotCopy(CannotCopy const&) = delete;
};
Holder<CannotCopy> holder1(CannotCopy())
CannotCopy cannot_copy;
Holder<CannotCopy> holder2(cannot_copy) // passed by reference
因此,如果我理解正确的话,您有时希望该类拥有您传递给它的元素的所有权(当就地构造时),有时您希望将其用作对存储在其他地方的所有权的引用。
不幸的是,当我告诉你这是一个坏主意时,我是根据经验说话的。乍一看,这看起来是个好主意,但是,经过几个抽象层之后,您最终会得到无法推理所有权的代码。
一种方法是在参数的右值/左值上重载构造函数:
template <typename T>
class Holder {
public:
Holder(T &&value)
: m_ownership{std::make_unique<T>(std::move(value))},
m_value{*m_ownership} {}
Holder(T &value) : m_value{value} {}
private:
std::unique_ptr<T> m_ownership;
T &m_value;
};
如您所见,现在有一个带有
T &&
的构造函数,它允许您将右值传递给它并移动它。 (假设移动构造函数可用,这通常是不可复制的情况)
这将知道它需要所有权并将该值存储为 unique_ptr,然后在 m_value 中传递 unique_ptr 内部值的引用。
如果您使用左值调用构造函数,它只是将其放入 m_value 中,而不使用 unique_ptr 作为所有权。
这样,您的班级就有该值的有条件所有权。如果您不喜欢 unique_ptr 占用空间,您可以(如果对齐允许 -> 您可以强制执行一些位操作)进行一些位操作来编码(无论您是否拥有所有权)并编写一堆自定义代码。
用户定义的推导指南似乎可以解决问题。
template<class T>
struct Holder{
T value;
};
template<class T>
Holder(T&&) -> Holder<T>;
请注意,您应该在不明确指定
CannotCopy
的情况下初始化变量,以便让推导指南完成其工作。
Holder holder1{CannotCopy()};
CannotCopy cannot_copy;
Holder holder2{cannot_copy}; // passed by reference
另请参阅构造函数调用的 godbolt 演示。