结合静态断言和断言?

Combining static assert and 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) 那样向它提供负值时,我想让编译失败。我该怎么办?

要在编译时验证数字(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

如果您使用的是 gcc 或 clang,您可以包含一个宏

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

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

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

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

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