2017-04-05 45 views
0

我想創建一個數據結構來捕獲生產,銷售和庫存數據的時間序列。但是,對於所有情況,我們不需要跟蹤所有數據。需要跟蹤的確切數據(例如銷售和庫存,但不包括生產)是在系列構建/啓動時指定的。C++ Design創建時指定內容首選項的結構

一種方法可能如下。

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的空間。

我正在尋找一種方法,我可以避免這種空間浪費。

兩個選項浮現在腦海中:

  1. 對各種數據創建單獨的時間序列和填充只有那些時間,分別是有必要的。但是,這會多次複製TimePoint數據,並通過將收集的數據分散到多個數據結構中來破壞數據的局部性。

  2. 組織DataEntry指針 s到個人數據條目,像

    struct DataEntryV2 { 
        ProductionDataEntry * pde_{nullptr}; 
        SalesDataEntry  * sde_{nullptr}; 
        InventoryDataEntry * ide_{nullptr}; 
    }; 
    

    ,只有構建這些數據輸入對象是必要的。但是,這會碎片化內存並引入額外的分配和取消分配開銷,如果可能,我想避免這種開銷。

  3. 組織DataEntrystd::optional,像

    struct DataEntryV3 { 
        std::optional<ProductionDataEntry> pde_; 
        std::optional<SalesDataEntry>  sde_; 
        std::optional<InventoryDataEntry> ide_; 
    }; 
    

    我覺得這需要每個條目類型的一個額外的字。它仍然會消耗不必要的數據空間。

我想知道,在設計領域有沒有其他選擇?

(注:DataEntry可能需要被擴展到包括新的類型的數據,例如PreOrderData。)

+0

恕我直言,過於寬泛,並沒有真正明確。您提到的選項都不允許您輕鬆添加新類型的數據。 – user463035818

+0

你有多少這些東西?通常,元數據對象的空間要求與數據的大小(在這種情況下的時間序列)相比是微不足道的,少數未使用的字節實際上並不值得擔心。 – rici

+0

@ tobi303:數據類型在編譯時全部寫入並可用。其中,啓動時指定的內容是什麼(請考慮命令行參數)。 – Arun

回答

0

爲每個類型的數據創建單獨的時間序列和填充僅僅 那些時間序列,其是必要的。但是,這會多次複製TimePoint 數據,並通過將收集的數據分佈在多個數據結構上來破壞數據的局部性。

通過繼承可以實現這一點。例如:

struct DataEntryV1: public ProductionDataEntry, public SalesDataEntry {}; 

您仍然需要定義您要使用的每種數據類型,但它不會「破壞數據的局部性」。作爲獎勵,看看你將通過多態性獲得的所有代碼的重用。

我提出這是一個簡單的選項,你應該閱讀this link關於多繼承之前,你決定這樣做。

+0

不知道我是否正確理解了這個問題,但是如果OP想要動態選擇DataEntry應該包含什麼,那麼繼承並不是一個解決方案 – user463035818

+0

要正確設置繼承,我需要知道哪些數據是需要的我寫代碼的時候,不是嗎?我想推遲這個決定,直到軟件啓動時間。 – Arun

0

如果你知道在編譯的時候,你可以使用模板:

template <typename ... Ts> 
struct TimeSeriesEntry { 
    TimePoint timepoint_; 
    std::tuple<Ts...> entries_; 
}; 

而且

// No Production 
std::deque<TimeSeriesEntry<SalesDataEntry, InventoryDataEntry>> time_series;