很难总结标题中的问题;所以请允许我澄清这里的情况。
我有一个我设计的课程代表BER TLV structure。在本规范中,"数据" TLV的一部分可以包含原始字节数据或其他嵌套TLV。为了支持这两种形式,我使用相同的结构但有两个向量(实际上只有一个包含某些内容,具体取决于我们在解析TLV数据时发现的内容):
class BerTlv
{
public:
void Parse(std::vector<std::uint8_t> const& bytes_to_parse);
// Assume relevant accessors are provided
private:
// Will be m_data or m_nestedTlvs, but never both
std::vector<std::uint8_t> m_data;
std::vector<BerTlv> m_nestedTlvs;
};
从外部开始,在完全构造此对象(解析所有TLV数据)之后,用户将需要检测他们正在处理的数据类型。基本上,他们必须检查m_data.empty()
,如果是,请使用m_nestedTlvs
。我对这种方法并不满意;它闻起来像缺乏更好的设计。
我想到了某种形式的联合,虽然我不认为真正的联合在这里是合适的,因为矢量数据是堆分配的。所以我想到了std::variant
:
std::vector<std::variant<BerTlv, std::uint8_t>> m_data;
但是,我担心这会对std::uint8_t
案件产生负面影响,因为这只是字节数据。它现在也将变得不连续。该变体仅对嵌套的TLV案例有益,而不是很多。
接下来我考虑在这里使用访问者模式,但我无法直观地看到界面的外观或者如何在两种情况下(原始数据与嵌套TLV)提高可用性。访客是否是正确的解决方案?
到目前为止,我没有想到的任何事情都是正确的,所以我希望能就更好的设计方法提出反馈。这里的一般问题是拥有有时未使用或相互排斥的数据成员。这也是我在其他环境中遇到的问题,因此对这样的问题采用通用设计方法会很棒。
请注意,我可以访问C ++ 14及以下功能。
答案 0 :(得分:3)
基本上,他们必须检查m_data.empty(),如果是,请使用m_nestedTlvs。
如果想法是一个对象要么有一个字节数组,要么有一个其他对象的数组,那么那就是你应该使用的变体:variant<vector<std::uint8_t>, vector<BerTlv>>
。 vector
variant
与您指定的用例不匹配。