将可选属性表示为 C++ class 成员
Represent an optional attribute as a C++ class member
我正在基于模式生成 C++ 代码。有实体,每个实体都包含属性,每个属性都有相应的数据类型。现在的问题是其中一些属性是 "optional",这意味着它们不必是 class 声明的一部分。但是,在C++中,something要么是class的成员,要么不是class的成员,没有"optional data member"这样的概念。
实体将是 class 名称,属性将是 class 成员。我不确定如何表示标记为 "optional" 现有 C++ 概念的属性。
标准答案是 std::optional
。它是表达模型中可能存在或不存在的值的语义准确方式。
创建此类模型时,对于架构中的每个可选字段,您都会生成相应的 std::optional
包装条目。然后,在反序列化时,可以使用 std::none
标记丢失的条目,并且在访问期间,客户端代码 必须 检查实际值是否存在 1.
但是,如果您的对象很大,并且您想避免不必要地存储空的 space2,下一个选择是 std::unique_ptr
。它具有指针语义的缺点,但在其他方面仍然是这种情况下的有效工具。
如果成员非常动态,例如可能的集合有几十个或几百个,但典型的利用率只会看到几个,键值存储(例如 std::map
)可能是一个更好的主意;那么您只能存储一种类型的值。使用 std::variant
作为映射值类型可能会稍微缓解这种情况,这为您提供了多种可能性之一,或者 std::any
,它可以在失去类型安全性的同时有效地容纳任何东西。
最终将取决于您的确切型号和使用特征。
1 如果客户端代码期望 T
,并且对字段的访问给他们 optional<T>
,则解包步骤 will/shall 检查因为实际价值的存在。这是使用 optional
的主要原因。
2 sizeof(optional<S>)
最常见的是 sizeof(S) + 1
,但由于对齐规则可以变得更大。 Performance&Memory 这篇文章的部分很好地展示了它。
我正在基于模式生成 C++ 代码。有实体,每个实体都包含属性,每个属性都有相应的数据类型。现在的问题是其中一些属性是 "optional",这意味着它们不必是 class 声明的一部分。但是,在C++中,something要么是class的成员,要么不是class的成员,没有"optional data member"这样的概念。
实体将是 class 名称,属性将是 class 成员。我不确定如何表示标记为 "optional" 现有 C++ 概念的属性。
标准答案是 std::optional
。它是表达模型中可能存在或不存在的值的语义准确方式。
创建此类模型时,对于架构中的每个可选字段,您都会生成相应的 std::optional
包装条目。然后,在反序列化时,可以使用 std::none
标记丢失的条目,并且在访问期间,客户端代码 必须 检查实际值是否存在 1.
但是,如果您的对象很大,并且您想避免不必要地存储空的 space2,下一个选择是 std::unique_ptr
。它具有指针语义的缺点,但在其他方面仍然是这种情况下的有效工具。
如果成员非常动态,例如可能的集合有几十个或几百个,但典型的利用率只会看到几个,键值存储(例如 std::map
)可能是一个更好的主意;那么您只能存储一种类型的值。使用 std::variant
作为映射值类型可能会稍微缓解这种情况,这为您提供了多种可能性之一,或者 std::any
,它可以在失去类型安全性的同时有效地容纳任何东西。
最终将取决于您的确切型号和使用特征。
1 如果客户端代码期望 T
,并且对字段的访问给他们 optional<T>
,则解包步骤 will/shall 检查因为实际价值的存在。这是使用 optional
的主要原因。
2 sizeof(optional<S>)
最常见的是 sizeof(S) + 1
,但由于对齐规则可以变得更大。 Performance&Memory 这篇文章的部分很好地展示了它。