2.1.6 Compile-Time Assertions

What was the problem

Compile-time assertions, declared with a static_assert, are a way to verify a property at compile time.

For example, the code below declares a type with an array whose size, with respect to the type’s name, must be even:

template<typename T, unsigned N> 
struct even_sized_array 
{ 
  typedef T type[N]; 
};

How can we ensure that N is always even? Before C++11 a solution to that would have been to enter some template dance such that passing an odd value would instantiate an incomplete type.

// The third template argument is expected to receive a flag 
// telling if N is even (i.e. valid). 
template<typename T, unsigned N, bool IsEven> 
struct even_sized_array_impl; 
 
// And we implement this type only if the flag is true. 
template<typename T, unsigned N> 
struct even_sized_array_impl<T, N, true> 
{ 
  typedef T type[N]; 
}; 
 
template<typename T, unsigned N> 
struct even_sized_array 
{ 
  // Now we trigger the check by actually instantiating the 
  // helper type, hoping that the flag will be true. 
  typedef 
  typename even_sized_array_impl<T, N, N % 2 == 0>::type 
  type; 
}; 
 
void test() 
{ 
  even_sized_array<int, 8>::type ok; 
  even_sized_array<int, 9>::type nok; 
}

Not only this is verbose, but these kind of template instantiation errors are well known for producing kilometer-long unbearable error messages.

How the Problem is Solved

Enters static_assert in C++11. Just like the good old assert(condition) would check that the given condition is true at run time, static_assert(condition, message) will check the condition during the compilation.

template<typename T, unsigned N> 
struct even_sized_array 
{ 
  // We can also put a message to repeat the condition, like 
  // professionals. Don’t forget the exclamation mark to 
  // show it is serious. 
  static_assert(N % 2 == 0, "The size must be even!"); 
  typedef T type[N]; 
}; 
 
// So much less code <3 
void test() 
{ 
  even_sized_array<int, 8>::type ok; 
  even_sized_array<int, 9>::type nok; 
}

This is very less verbose than previously and it actually carries the intent. The error message is also clearer, as it is just something like “static assertion failed: the message”.