Compile-Time Assertions Question submitted by n/a (10 October 2000) |
Return to The Archives |
This entry is not a response to a question. | ||
While working on the next Ask Midnight column entry (an n-dimensional matrix
class that also acts as n-dimensional points and n-dimensional vectors) I
discovered the need for compile-time assertions. So this article is presented as
a preface to the next article.
I don't think anybody out there will disagree with the usefulness of assertions. If you disagree, please locate your elbow and promptly shove it up your nose. :) Presented here is an assertion that looks just like a normal assert, but causes the compiler to produce an error. Hence, it is called the compile-time assert. Compile-time errors are preferred over run-time errors because they notify you of a problem in your code before you even run the application (before you even finish building it, for that matter.) Unfortunately, you can't just replace all of your run-time assertions with compile-time assertions. They do, however, have a very valid use. Consider the following example:
But what if you only wanted 'foo' to be available to instantiations where the template parameter ('I') is an even number, or just a specific range of values? I realize this is a rather esoteric example, but I wanted a simple example to be provided here. In the next Ask Midnight, you'll see a very valid use for these compile-time assertions. Thus, the compile-time assertion was born...
Note that the member function 'tAssert::assert()' only exists for templates created with a Boolean value of 'true' as the template parameter. Here's how it works in practice:
An important difference between normal run-time asserts and compile-time asserts is that compile-time asserts can only be used with constants. Note in the following example, the use of the 'const' keyword:
Though, the ISO C++ specification allows this, many compilers do not (yet) support template instantiation from an expression. But we can fake it, like this:
To clean it up, we'll use a macro.
Unfortunately, we're still not done yet... because of two (ahem) "features" of the Visual C++ 6.0 compiler, our macro doesn't work. Changing the variable names helps, as does the addition of the trinary operator (?:) rather than a (bool) type-cast:
Now we have the compiler's full cooperation. Here is the entire thing reprinted for clarity:
Errors are reported during compile-time, and each brand of compiler will have different error reporting and formatting, but here's what to expect from Visual C++ 6.0. Both of these errors point to the line of code containing 'TAssert()':
Response provided by Paul Nettle |
|||||||||||
This article was originally an entry in flipCode's Ask Midnight, a Question and Answer column with Paul Nettle that's no longer active. |