There're two widely used implementations of static assert for versions of C++ that don't have built-in static_assert
.
The first one is used in Boost and uses a template and a specialization of that template:
template <bool> struct static_assert;
template <> struct static_assert<true> {}; // only true is defined
#define STATIC_ASSERT(x) static_assert<(x)>()
Here once a condition to check is false the compiler is unable to find a generic version of template and compilation fails.
the second uses a typedef
:
#define STATIC_ASSERT( x ) typedef char __STATIC_ASSERT__[( x )?1:-1]
Here once a condition to check is violated the compiler attempts to typedef
an array of size -1 and that's illegal hence a compile-time error.
To me the latter is better since it is guaranteed to emit no code and also it can be used like this (from here):
template<int Shift> class BinaryFlag {
STATIC_ASSERT( 0 <= Shift && Shift < sizeof( DWORD) * CHAR_BIT );
public:
static const DWORD FlagValue = static_cast<DWORD>( 1 << Shift );
};
#define BINARY_FLAG( n ) CBinaryFlag<n>::FlagValue
while the former can't be used like that.
Is there any reason to prefer the former implementation of static assert over the latter one?
Second version of STATIC_ASSERT
you cannot use one after another in the same block.
template<int N, int M>
void foo ()
{
STATIC_ASSERT(N<M), STATIC_ASSERT(M<0); // error
};
Demo.
On the other hand, in the example you posted, you cannot use first version (because it deals with temporary constructions). So both the version has their own audience. 1st version I can say is kind of mix of compile and runtime. However 2nd version is purely compile time.
Edit: sometimes for readability you may want to put all asserts in single line with comman operator (where only last instruction will effective in this case). I know that they can be put with ;
too. But just for sake of having an example, this is one use case.
Similarly there will be situations where object construction will be ok but putting a typedef
will not be ok syntactically. So all those will fall into same place.
I've generally used the second, or some variant of it, in my own code. In practice, the Boost variant has the advantage that it can be used anywhere an expression may appear, and not just at statement level. It has the disadvantage that it can only be used where an expression may appear, and thus not at namespace scope.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With