Community Pick: Many members of our community have endorsed this article.

Static assertions in C++

evilrixEngineering Manager
CERTIFIED EXPERT
An expert in cross-platform ANSI C/C++ development, specialising in meta-template programming and low latency scalable architecture design.
Published:
Updated:
Errors will happen. It is a fact of life for the programmer. How and when errors are detected have a great impact on quality and cost of a product. It is better to detect errors at compile time, when possible and practical. Errors that make their way to become runtime problems are harder to detect and may go unchecked until such time that the code reaches a customer. The later the defect is identified the more costly it is in terms of time and money.

A static assertion is similar to a runtime assertion, in so far as it allows the programmer to assert that an expression must be true, or an error message must be raised. The difference is that static assertions are triggered at compile time rather than runtime. How is this useful? Well, how about a situation where we've had to make assumptions about the capacity of a specific type, say int?

The C++ Standard makes no specific claims about how big an int will be other than it "has the natural size suggested by the architecture of the execution environment."

What does this actually mean? Well, in reality, it means the size of an int could be any size. The same is true of other types; a long must be as least as big as an int and an int at least s big as a short. Clearly, making an assumption about type size is non-portable and potentially dangerous, and should only be done in controlled cases, such as writing an OS kernel for a particular processor with a particular compiler. As soon as the programmer loses the ability to specify the compiler and the target architecture, type size assumptions go out the window. So, how does a static assertion help? Good question, let's see...

Wouldn't it be nice if we could assert our assumption about the size of a type at compile time so that if this assumption breaks, we are alerted immediately? For example, the code is built by a different compiler than the author used on a platform he did not anticipate. Enter static assertions. The trick is to turn to templates and, specifically, make use of the fact that a template variant, that is not instantiated, will not cause a compile time failure even if it contains erroneous code.

Create a template function that takes a bool template value parameter (not a function parameter). Within the function create a char array and use the value of the bool to determine the size. In the case where the bool template value is true, a char array of one element will be created. Since this will never be used the compiler should happily optimize this away. In the case where the bool template value is false, the compiler will try to generate a template function that creates a char array of zero elements. Since this is invalid C++, a compiler error will ensue. We can now use a simple macro to facilitate the use of this template and then use a sizeof() to assert the sizes of the types we are assuming. Of course, any compile time constant can be asserted with a static assert, this is just one example of usage.
template <bool B>
                      inline void STATIC_ASSERT_IMPL()
                      {
                      	// B will be true or false, which will implictly convert to 1 or 0
                      	char STATIC_ASSERT_FAILURE[B] = {0};
                      }
                       
                      #define STATIC_ASSERT(B) STATIC_ASSERT_IMPL <B>()
                       
                      int main()
                      {
                      	// On a Windows 32 bit platform with Visual Studio 2005 this will not fail
                      	STATIC_ASSERT(sizeof(int) == 4);
                       
                      	// On a Windows 32 bit platform with Visual Studio 2005 this *will* fail
                      	STATIC_ASSERT(sizeof(int) == 3);
                      }

Open in new window

6
8,668 Views
evilrixEngineering Manager
CERTIFIED EXPERT
An expert in cross-platform ANSI C/C++ development, specialising in meta-template programming and low latency scalable architecture design.

Comments (1)

Top Expert 2009

Commented:
Great article. I just used this trick on a current project of mine where I use bitfields and read/write packed structures to/from disk, so I need to know in some cases that my assumptions are true, this saves me some trouble as I don't have to worry about a lot of ifdefs, I just set the assertions and forget about it.

mrjoltcola

Have a question about something in this article? You can receive help directly from the article author. Sign up for a free trial to get started.