user1687327
user1687327

Reputation: 176

Combining static assert and assert?

I have a function that looks like this:

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;
}

It won't work with y <= 0 or x < 0. That's ok with me, I can even dynamically check for right values, but I would like to check statically, when someone feeds it wrong values. If I defined x and y as unsigned, they would get silently converted from negative values to huge positive values which would produce erroneous result, so I don't want that. I would like to make compilation fail when someone attempts to feed it negative values like in div_round_up(variable, -7). What should I do?

Upvotes: 3

Views: 226

Answers (3)

POTEMKINDX
POTEMKINDX

Reputation: 395

Yeap you can do it with some magic(one nonamed russian code guru told me this trick)

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

but also in this case there is one limit. Compiler should know result of this value. In any another case it`s imossible(IMHO).

Upvotes: 0

Pixelchemist
Pixelchemist

Reputation: 24926

If you're using gcc or clang you can include a macro

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

and two different function where drus includes a static assertion for b while drud does not.

Upvotes: 2

danielschemmel
danielschemmel

Reputation: 11116

To verify a number at compile time (which is what static_assert does), it has to be known at compile time. To see why this is needed, consider that something like div_round_up(read_integer_from_file(), read_keyboard_character()). The obvious drawback of doing that is that you have to know the numbers at compile time.

The easiest way is to make them template parameters, which allows you to leave the implementation of the function (almost) the same:

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;
}

It can be called as div_round_up<3, 4>() and will fail the compilation when the static_assert fires.

Upvotes: 3

Related Questions