我想创建一个数据结构来捕获生产,销售和库存数据的时间序列。但是,对于所有情况,我们不需要跟踪所有数据。在构建/启动系列时指定要跟踪的确切数据(例如销售和库存但不生产)。
一种方法可能如下。
struct ProductionDataEntry { ... };
struct SalesDataEntry { ... };
struct InventoryDataEntry { ... };
// Each of the above struct could be arbitrarily large
struct DataEntryV1 {
ProductionDataEntry pde_;
SalesDataEntry sde_;
InventoryDataEntry ide_;
};
typedef std::chrono::system_clock::time_point TimePoint;
struct TimeSeriesEntry {
TimePoint timepoint_;
DataEntry entry_;
};
std::deque<TimeSeriesEntry> time_series;
以上方法的缺点如下。在用例中,销售和库存数据是必需的,而不是生产,数据结构仍然会占用ProductionDataEntry
的空间。
我正在寻找一种可以避免这种空间浪费的方法。
有两种选择:
为每种数据创建单独的时间序列,并仅填充必要的时间序列。但是,这会多次复制TimePoint
数据,并通过将收集的数据分布在多个数据结构上来破坏数据的位置。
将DataEntry
作为指针组织到各个数据条目,例如
struct DataEntryV2 {
ProductionDataEntry * pde_{nullptr};
SalesDataEntry * sde_{nullptr};
InventoryDataEntry * ide_{nullptr};
};
并仅构造必要的数据输入对象。但是,这会破坏内存并引入额外的分配和释放开销,如果可能的话我希望避免这种开销。
使用DataEntry
组织std::optional
,例如
struct DataEntryV3 {
std::optional<ProductionDataEntry> pde_;
std::optional<SalesDataEntry> sde_;
std::optional<InventoryDataEntry> ide_;
};
我认为每个条目类型需要一个额外的单词。它仍然会消耗不必要数据的空间。
我想知道,设计领域还有其他选择吗?
(注意:DataEntry
可能需要扩展才能包含新类型的数据,例如PreOrderData
。)
答案 0 :(得分:0)
为每种数据创建单独的时间序列并仅填充 那些必要的时间序列。但是,这会复制TimePoint 数据多次通过传播来破坏数据的位置 通过多种数据结构收集数据。
可以通过继承来实现这一点。例如:
struct DataEntryV1: public ProductionDataEntry, public SalesDataEntry {};
您仍然需要定义要使用的每种数据类型,但它不会“破坏数据的局部性”。作为奖励,请查看通过多态性获得的所有代码重用。
我将此作为一个简单的选项,您应该在决定执行此操作之前阅读this link有关多重继承的内容。
答案 1 :(得分:0)
如果您在编译时知道,可以使用模板:
template <typename ... Ts>
struct TimeSeriesEntry {
TimePoint timepoint_;
std::tuple<Ts...> entries_;
};
和
// No Production
std::deque<TimeSeriesEntry<SalesDataEntry, InventoryDataEntry>> time_series;