#define COMPILE_ASSERT(x) extern int __dummy[(int)x]
Which is typically used as
COMPILE_ASSERT(sizeof(int) == sizeof(unsigned));
COMPILE_ASSERT(sizeof(int) == sizeof(char));
the second example if obviously wrong and provides the output.
error C2466: cannot allocate an array of constant size 0
Which is not very useful other than as a signal that something bad occurred.
Now consider the form
#pragma warning (disable: 4483)
typedef char __identifier("compile assert:");
#define COMPILE_STRING_ASSERT(condition, name) \
typedef __identifier("compile assert:") __identifier(name)[1]; \
typedef __identifier("compile assert:") __identifier(name)[(condition) ? 1 : 0];
define COMPILE_ASSERT(condition) COMPILE_STRING_ASSERT(condition, #condition)
The above uses the identifier keyword which is technically an error however the pragma warning disables the error (yes it doesn't make sense). This keyword allows the user to define ANY identifier, valid C++ or not.
COMPILE_ASSERT(sizeof(int) == sizeof(char));
Now provides the output
'compile assert: sizeof(int) == sizeof(char)[1]'
which is a much more palatable message esp when considering automatic build systems.
Note2
- __identifier is specific to Visual Studio and may not be supported by other compilers.
- VC++ 2010 introduces static_assert for all targets, tho it is less powerful than using __identifier.
- SNC may support both, i will try to confirm.