2017-05-07 22 views
1

替代宏在我們公司中的代碼,我們使用64位的標誌枚舉:constexpr無需迴歸

enum Flags : unsigned long long { 
    Flag1 = 1uLL<<0, // 1 
    //... 
    Flag40 = 1uLL<<40 // 1099511627776 
}; 

和添加註釋看,即使我們用文本編輯器讀取的代碼每個標誌十進制值。問題是沒有任何東西可以阻止開發人員在評論中輸入錯誤的數字。

沒有針對此問題的解決方案 - 用static_assert +使用這種方法很容易宏模板 - 無需使用括號並添加:: VAL無處不在:

template <unsigned long long i, unsigned long long j> 
struct SNChecker{ 
    static_assert(i == j, "Numbers not same!"); 
    static const unsigned long long val = i; 
}; 

#define SAMENUM(i, j) SNChecker<(i), (j)>::val 

enum ET : unsigned long long { 
    ET1 =  SAMENUM(1uLL<<2, 4), 
    ET2fail = SAMENUM(1uLL<<3, 4), // compile time error 
    ET4 =  SAMENUM(1uLL<<40, 1099511627776uLL), 
}; 

這一切看起來不錯,但我們並不喜歡宏。

一個問題:我們可以用constexpr函數做同樣的事,但沒有錯誤可讀性迴歸?

我能想到的最接近的解決方案是:

constexpr unsigned long long SameNum(unsigned long long i, unsigned long long j) 
{ 
    return (i == j) ? i : (throw "Numbers not same!"); 
} 

,但它會產生一個編譯時錯誤

error: expression '<throw-expression>' is not a constant-expression 

,而不是無論我在static_assert

編輯寫:

下面的答案几乎是完美的,除了一個小的迴歸:這個調用比使用宏稍微好點。

還有一個方法(仍比使用static_assert差,但在使用「漂亮」)

int NumbersNotSame() { return 0; } 

constexpr unsigned long long SameNum(unsigned long long i, unsigned long long j) 
{ 
    return (i == j) ? i : (NumbersNotSame()); 
} 
+0

這看起來像一個很好的理由不要有評論。你爲什麼在意基數10的值是'1099511627776uLL'?讀取或顯示10位的位標誌看起來像一個可怕的想法。 – Yakk

+0

這是我們公司的具體工作。我們的QA - 測試DB中的標誌 - 讀取我們的.h文件,因此它們更容易具有十進制表示。 – Alek86

+0

您是否考慮過教授您的QA十六進制? – Yakk

回答

6

static_assert在constexpr功能:

template<unsigned long long I, unsigned long long J> 
constexpr unsigned long long SameNum() 
{ 
    static_assert(I == J, "numbers don't match"); 
    return I; 
} 

enum ET : unsigned long long { 
    ET1 =  SameNum<1uLL<<2, 4>(), 
    ET2fail = SameNum<1uLL<<3, 4>(), // compile time error 
    ET4 =  SameNum<1uLL<<40, 1099511627776uLL>(), 
};