Intro. I've been long thinking to start my own blog, at least a couple of years now. A common objection
everyone always has is "OK, I feel enthusiastic right now. But can I keep up in the long-term?"
The bad news is I still don't know the answer, though I'll do my best to allocate at least some time on it.
But luckily this question does not stop me anymore. "If you feel like you'd love to write, right now, don't think,
just write!" That's what I said to myself. And here it is: my first blog post!
The topic I've chosen to discuss for the very first post is rather simple, yet nevertheless interesting: compile
time assertion in C++.
Motivation: evaluate a static expression and make sure certain contract is always met.
First of all, one can add a runtime check of course. Second, it's better to document the restrictions anyway to
avoid accidental bugs.
But: explicit assert is better than implicit and the sooner the problem is found, the better. If we have a static
expression, can't we use some magic to assert that at compilation?
So that if for some reason the contract is not met, the compilation would fail and report exactly what happened.
Yes, we can.
Solution: among plenty of features, C++11 finally comes along with
a static assert and allows to use
static_assert
function like this:
And these solutions work just fine, supported by all major compilers. But I'd like to draw attention to the
alternatives some of which I used long before C++0x and it's nice to know they exist.
Boost solution:
BOOST_STATIC_ASSERT
from
Boost library solves the
problem, though it has a limitation: one can't pass a human readable message to the compiler.
And everyone knows compiler errors can be very cryptic.
When the assertion is false, the programmer would see "Illegal use of STATIC_ASSERTION_FAILURE
<false>" error. OK, seems good enough, but what if one does not want a dependency on Boost?
Windows solution: Use
C_ASSERT
macro from Windows.h
. A major drawback is quite obvious, this solution is platform dependent.
But the implementation is so simple, let's try to port it and in addition make a couple of improvements.
Google solution. My favourite one. I call this a Google solution, because I learned it when I worked for
Google back in 2006, though I'm pretty sure it was used even before that. Here's the code:
The compiler now triggers a "error: size of array ‘data_should_be_exactly_64_bytes’ is negative". It's still not
ideal, but it points to the exact line of the assert, and provides at least some reason.
Also note that under the hood the assert is just a
typedef
, so it's not compiled into assembly
instructions and doesn't consume memory.
Real-life usages. Let's repeat that dedicated compiler support
(
static_assert
is not even a macro, but a special directive) is always better and everyone is
encouraged to use it now. Here are a few examples when it might be handy:
No comments:
Post a Comment