2015-04-21 131 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_使用,但它不能在函数内。这也意味着该函数只能用于文字而不是变量。所以这是非常有限的。 –