Saturday, 21 May 2011

With C++0x we now have proper static asserts. Hurrah! Except I don't like them. Their syntax is:

static_assert(sizeof(int) < 5, "Integers too big");
To me, the second argument is extra fluff that should be optional, but isn't. Perhaps we can get around it with preprocessor macros:STATIC_ASSERT(sizeof(int) < 5, "Integers too big");STATIC_ASSERT(sizeof(int) < 5);
But how do we overload preprocessor macros? With the help of variadic macros it is (just about) possible to overload based on the number of arguments. Ironically, this is much easier with the C99 preprocessor than with the current C++ one; all the solutions for C++ that I've seen need tweaking for different compilers. The code below works for Microsoft C++ 2010.

As an aside, Jens Gustedt has produced an amazing (and instructive) set of C99 preprocessor macros called P99. Well worth a look.

But for our C++ case, we want to construct something along the lines of:

How this actually works is left as an exercise for the reader, but the bottom line is that "CHILLIANT_VA_EMPTY(...)" called with no arguments resolves to the token "1", whilst one or more arguments causes it to resolve to "0". The above code snippet only works for up to nine arguments, but it is trivial to expand to a greater number.

For completeness, here's the macro to return the count of the number of arguments:

The second problem, generating the if-then-else semantic, is made difficult because we want it to resolve during the preprocessor phase, not during compilation. However, if we assume the condition is only ever the token "0" or "1" (which it is) the problem can be solved with careful identifier concatenation:

This does seem to be a lot of trouble to go to just to make the second argument of a static assert optional, but now you also have some of the basic building blocks to really go to town with the preprocessor.