2015-04-21 128 views
3

我有一個功能,看起來像這樣:結合靜態斷言和斷言?

int div_round_up(int x, int y) { 
    /** 
    * This function only works for positive divisor and non-negative dividend!! 
    */ 
    assert(y > 0 && x >= 0); 
    if (x == 0) 
     return 0; 
    return (x - 1)/y + 1; 
} 

它不會與y <= 0x < 0工作。沒關係,我甚至可以動態檢查正確的值,但是我想靜態檢查,當有人給它錯誤的值時。如果我將x和y定義爲無符號的,他們會默默地從負值轉換爲巨大的正值,這會產生錯誤的結果,所以我不希望這樣。如果有人試圖提供負值(如div_round_up(variable, -7)),我想編譯失敗。我該怎麼辦?

+0

嗯......你可能會遇到一些麻煩。你意識到'7'和'-7'具有相同的類型,對吧? – Brian

+0

除非ISO'C++'委員會決定變得更聰明,否則你不能這樣做。最終你可以嘗試向他們寫一個提案。我已經勾勒出了基礎知識,但真的不想再費心了。你可以在這裏查看 - https://groups.google.com/a/isocpp.org/forum/#!topic/std-proposals/6qGR67u-Z9I。或者嘗試使用一些不同的語言,例如「D」。或者,你可以編寫另一個你的函數的模板版本,並且在使用編譯常量時以不同的方式實例化它。 – AnArrayOfFunctions

+0

我很確定你不能這麼做 - static_assert不能這樣工作。 –

回答

3

要在編譯時驗證一個數字(這是static_assert的作用),它必須在編譯時知道。要明白爲什麼這是必要的,請考慮類似div_round_up(read_integer_from_file(), read_keyboard_character())。這樣做的明顯缺點是你必須在編譯時知道這些數字。

最簡單的方法是讓他們的模板參數,它允許您離開此功能(幾乎)相同的實現:

template<int x, int y> 
int div_round_up() { 
    static_assert(y > 0 && x >= 0, "This function only works for positive divisor and non-negative dividend"); 
    if (x == 0) 
     return 0; 
    return (x - 1)/y + 1; 
} 

它可以被稱爲div_round_up<3, 4>()will fail the compilation when the static_assert fires

2

如果你正在使用gcc或鐺可以包括宏

#define div_round_up(a, b) (__builtin_constant_p(b) ? drus(a, b) : drud(a, b)) 

和兩個不同的功能,其中包括:drus對於B靜態斷言,而drud沒有。

0

葉氏你可以用一些神奇的做到這一點(一個nonamed俄羅斯碼大師告訴我,這招)

#define check2(x) typedef char checkVal[(x)?1:-1]; 
int main() { 
    check2(3<4); 
    check2(5<4); 
    return 0; 
} 

而且在這種情況下,有一個極限。編譯器應該知道這個值的結果。在任何其他情況下,這是不可能的(恕我直言)。

+0

它不是隻是混淆/奇怪的便攜式static_assert等效? – user1687327

+0

yeap這是等同於static_assert,但有一個區別,它可以使用沒有C + + 11(我記得static_assert介紹)。它使用了一個有趣的typedef理念,我們可以重新定義一個別名。 – POTEMKINDX

+0

@ user1687327:它必須由_caller_使用,但它不能在函數內。這也意味着該函數只能用於文字而不是變量。所以這是非常有限的。 –