将可选属性表示为C++类成员

nmd*_*_07 2 c++ schema code-generation class

我正在基于模式生成C++代码.存在实体,每个实体包含具有相应数据类型的每个属性的属性.现在问题是这些属性中的一些是"可选的",这意味着它们不必是类声明的一部分.但是,在C++中,某些东西要么是类的成员,要么不是类的成员,没有诸如"可选数据成员"之类的概念.

实体将是类名,属性将是类成员.我不确定如何表示标记为"可选"现有C++概念的属性.

Bar*_*icz 9

规范的答案是std::optional.它是一种语义上准确的方式来表达模型中可能存在或可能不存在的值.

创建此类模型时,对于模式中的每个可选字段,都会生成相应的已std::optional包含条目.然后,在反序列化时,您可以使用std::none标记缺失的条目,并且在访问期间,客户端代码必须检查是否存在实际值1.

但是,如果您的对象很大,并且您希望避免不必要地存储空白空间2,则下一个选择是std::unique_ptr.它具有指针语义的缺点,但在其他方面仍然是这种情况的有效工具.

如果成员非常动态,例如可能的集合数十或数百,但典型的利用率只会看到几个,键值存储(如std::map)可能是一个更好的主意; 那么你只能存储一种类型的值.这可以通过std::variant用作地图值类型来减轻一些,这可以为您提供多种可能性之一,或者std::any可以在失去类型安全性的同时有效地保留任何内容.

决定最终取决于您的确切型号和使用特性.


1如果客户端代码需要T,并且字段的访问权限给予它们optional<T>,则展开步骤将/将检查是否存在实际值.这是使用的主要原因optional.

2 sizeof(optional<S>)最常见sizeof(S) + 1,但由于对齐规则可能会变大.本文的性能和内存部分很好地展示了它.

  • @ user463035818 - 使用`std :: vector`可能是一个很好的黑客,但它是错误的抽象.它最终迫使维护者跟踪哪些向量是真实向量,哪些只是"可选"字段.这不是一个很好的代码库.唯一指针更接近可选作为抽象. (3认同)
  • @ user463035818你也可以包装`std :: unique_ptr`,它也是C++ 11. (3认同)
  • @Eljay - 只表明你永远不会真正杀死一个坏主意 (3认同)