结合静态断言和断言?

时间:2015-04-21 20:43:09

标签: c++ assert static-assert

我有一个看起来像这样的函数:

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)那样尝试提供负值时,我想让编译失败。我该怎么办?

3 个答案:

答案 0 :(得分: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

答案 1 :(得分:2)

如果您正在使用gcc或clang,则可以包含宏

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

和两个不同的函数,其中drus包含b的静态断言,而drud则不包含。{/ p>

答案 2 :(得分:0)

你可以用一些魔法做到这一点(一位非法的俄罗斯代码大师告诉我这个技巧)

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

但在这种情况下还有一个限制。编译器应该知道该值的结果。在任何其他情况下它都是不可能的(恕我直言)。