2012-07-07 114 views
2

我必須在一定條件下生成包含某些字段的數據結構。這通常總是轉換爲類似下面的在編譯時動態生成結構

struct MyStruct { 
    int  alwaysHere; 

#ifdef WHATEVER 
    bool mightBeHere; 
#endif 

    char somethingElse; 

#if SOME_CONSTANT > SOME_VALUE 
    uint8_t alywasHereButDifferentSize; 
#else 
    uint16_t alywasHereButDifferentSize; 
#endif 
... 
}; 

從我的角度來看這很容易變得醜陋來看待,且無法讀取。 甚至沒有談論處理這些字段的代碼,通常在 ifdefs也是如此。

我正在尋找一個優雅的方式來實現相同的結果,而不增加任何開銷,但代碼很多 更具可讀性。模板專業化似乎有點過分,但我認爲 是唯一的選擇。

C++ 11是否添加了任何東西來處理這種情況?

任何建議,將不勝感激。

回答

1

我已經看到這與一個聯合(http://www.cplusplus.com/doc/tutorial/other_data_types/)完成,但我不確定具體細節,因爲我從來沒有自己實現它。代替第二片macrohackery的,你將有:

union { 
    uint8_t alywasHereButDifferentSize; 
    uint16_t alywasHereButDifferentSize; 
} 

和引用時,你將有一個如果提到的一個或另一個變量。

或者,您可以將運行時初始化的void *指針設置爲任一類型的變量。

+0

加上union之外的其他變量,它可以指示正在使用哪個字段。 – 2012-07-07 15:40:31

4

第二種情況可以通過

std::conditional<(SOME_CONSTANT > SOME_VALUE), uint8_t, uint16_t>::type 
alywasHereButDifferentSize; 

首先被替換,我認爲沒有。

+0

我看到大部分注意力集中在第二個案例上,這很好,但我實際上對第一個案例更感興趣。無論如何感謝您的建議。 – emitrax 2012-07-08 17:35:33

0

對於第一:

template <bool> 
struct implement_maybe_here 
{}; 

template <> 
struct implement_maybe_here<true> 
{ 
    int maybe_here; 
}; 

struct my_struct : implement_maybe_here<HAS_MAYBE_HERE> 
{ 
    double always_here; 
}; 

我不以任何方式推薦這個,因爲它是難以維持和maybe_here變量是很難初始化(但與任何辦法,這將是一個爛攤子無論如何)。

請注意,您不能保證implement_maybe_here<false>將佔用零內存,但許多編譯器實現此「empty base optimization」。

第二個使用std::conditional,正如@ForEveR所示。

+0

這很好,但它不是解決方案,因爲HAS_MAYBE_HERE沒有定義 - 代碼不能編譯。所以,我認爲我們根本不能替換#ifdef。 – ForEveR 2012-07-07 16:30:52

+1

@ForEveR:當然。我們必須在某個時候使用一些預處理器,比如'#ifdef WHATEVER #define HAS_MAYBE_HERE 1 #else ...',甚至可能會像'#define HAS_MAYBE_HERE defined(WHATEVER)'那樣工作。但是,這是通過元編程將成員添加到類的標準方法。 – 2012-07-07 16:33:43

+0

是的,所以只有預處理器魔術可以替換結構中的#ifdef。所以,我認爲它比開銷更多,而不是使用一個#ifdef。 – ForEveR 2012-07-07 16:38:01

5

對於第二種情況,我通常喜歡這限制了兩輪牛車到一個地方一個typedef:

#if SOME_CONSTANT > SOME_VALUE 
    typedef uint8_t always_type; 
#else 
    typedef uint16_t always_type; 
#endif 

那麼你的代碼的其餘部分將只使用always_type遍及:

struct MyStruct { 
    // ... 
    always_type always_here_but_different_size; 
    // ... 
}; 

如果你想使用:

typedef std::conditional<(SOME_CONSTANT > VALUE), uint8_t, uint16_t>::type always_type; 

這也很好 - 這裏的觀點不是阿博請使用您用來獲取所需類型的語法,但是您通常需要爲該類型創建一個名稱,以便您可以在需要的地方使用它。

至於存在或不存在的情況,這是一個很難說。通常,這樣的事情將涉及在構建時啓用/禁用某些功能。如果是這樣,看起來這個班級有責任與可以啓用/禁用的功能以及其他功能有關。這聽起來像是可能違反單一責任原則,並且可能不是很有凝聚力。如果是這樣的話,這可能意味着一個問題在整體設計層面得到了更好的解決,而不僅僅是您使用的語法。

警告:我可能從推測的最少證據推測了一點 - 可能比證據確實支持的還要多。