3

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?

8
  • Hmm... you might have some trouble there. You realize 7 and -7 have the same type, right? Commented Apr 21, 2015 at 20:46
  • You can't - unless ISO 'C++' committee decides to get smarter. Eventually you could try writing a proposal to them. I already sketched the basics but really don't want to bother with anything more. You can check it here - groups.google.com/a/isocpp.org/forum/#!topic/std-proposals/… . Or try using some different language like 'D' for example. Alternatively you can write another templated version of your function and instance it differently when compile-constants are used. Commented Apr 21, 2015 at 20:46
  • I'm pretty sure that you can't do that - static_assert don't work that way. Commented Apr 21, 2015 at 20:47
  • However, if you're ok with compiler specific directives, there's SAL. Something akin to _Ret_range_(0, INT_MAX) int div_round_up(_In_range_(0, INT_MAX) int x, _In_range_(1, INT_MAX) int y). msdn.microsoft.com/en-us/library/hh916382.aspx Commented Apr 21, 2015 at 20:50
  • @Brian I do realize that. I know that I can't solve this via some kind of type checking, I would like to know if there is some kind of compile time value checking I can apply. Commented Apr 21, 2015 at 20:51

3 Answers 3

3

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.

Sign up to request clarification or add additional context in comments.

Comments

2

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.

Comments

0

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).

3 Comments

Isn't it just obfuscated/weirdly portable static_assert equivalent?
yeap this is eq to static_assert, but have one difference it can be used without C++11(as I remember static_assert introducing in it). it using one intresting idea of typedef, that we can redefine an alias.
@user1687327: It has to be used by the caller though, it can't be inside the function. It also means the function can only be used with literals and not variables. So this is highly limiting.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.