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

. This is ok with me, I can even check the correct values ​​dynamically, but I would like to check statically when someone feeds in the wrong values. If I were to define x and y as unsigned, they would silently go from negative values ​​to huge positive values ​​that could lead to erroneous results, so I don't want that. I want compilation to fail when someone tries to feed negative values ​​like in div_round_up(variable, -7)

. What should I do?

+3


source to share


3 answers


To check for a number at compile time (what it does static_assert

), it must be known at compile time. To understand why this is necessary, think something like div_round_up(read_integer_from_file(), read_keyboard_character())

. The obvious downside to this is that you have to know the numbers at compile time.

The easiest way is to make it template parameters, which allows you to leave the function implementation (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 named as div_round_up<3, 4>()

, but it compiles when triggeredstatic_assert

.

+3


source


If you are using gcc or clang you can enable the macro

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

      



and two different functions that drus

contain a static statement for b, but drud

not.

+2


source


Yeap you can do it with some magic (one unloved 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 even in this case there is one limit. The compiler needs to know the result of this value. In any other case, it is incomprehensible (IMHO).

0


source







All Articles