I have been writing a lot of code the last few months, and I’ve had a chance to play with some of the new C++0x features. It’s really the first time in many years that there’s been a significant improvement to the language. I thought I’d take a few blog entries and work through some of the new features, because unless you’ve already had experience with some of them in other languages you might not fully understand the power that is behind some of the features.
The first one I’m going to talk about is called static assertions. I assume you are familiar with the assert macro in debug mode. There’s also the #error preprocessor command. Static assertions on the other hand are compile time tests. They give you the ability to essentially make compile time assertions in your code. One nice feature is that it works with templated expressions as well. If the conditional can be evaluated at compile time then the compiler will immediately evaluate the conditional For a template assertion, the test is performed when a template is instantiated, just like the assert macro, if the condition evaluates to true, nothing is done. If however the condition is false then the compiler will raise an error and post the error message that is part of the static assert. For example;
static_assert ( 1+1 == 3 , "one plus one does not equal three");
For example, you might have code compiles for both 32-bit and 64-bit and you might need to make assertions;
static_assert(8 == sizeof(void*), "Not valid for 32-bit code");
static_assert(4 == sizeof(void*), "64-bit code generation has not been tested");
Or, as I recently have been doing, you’re writing out binary files that have to run on a variety of operating systems and architectures, and you don’t want any nasty surprises when you start running on different systems.
static_assert(4 == sizeof(int) , "ints aren’t 32 bits in size");
A recent post in AltDevBlogADay by Michael Tedder <Trivial Constructors and Destructors in C++> talked about creating POD data (Plain old data – i.e. data that has no virtual function tables, exceptions, etc. that is, data that is just that – data and no dangling functionality hanging off it) If you are creating an allocator for POD objects, it’s possible to check for this at compile time.
#include <type_traits>
template <class TYPE >
class Allocator{
static_assert(std::is_pod>TYPE&rt;::value, "Template argument must be a POD");
};
class pod
{
};
class not_pod
{
virtual ~not_pod(){} ; // the offending non-POD part
};
...
Allocator<int> v1; // works
Allocator<pod> v2; // works
Allocator<not_pod> v3; // static asserts
...
It just takes some creativity to figure out how to assert that what you want, and then it’s in your code forever, tested every time you compile. As you can see, I am a firm believer in letting computers do as much of the work as possible. In this case, it’s possible to let the compiler check my assertions for me. With the rapidly changing pace of both target architecture and operating system that we have today in the games industry an ounce of prevention is worth a whole lot more than a pound of cure.