#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.
6 comments:
This is a pretty cool trick! Msvc 2010 has straight up static_assert and then some. It's definitely worth the switch over.
Also, the modern c++ design style static assert gives you a full error message (Granted it's a weird hack).
Andy, here is a link to a STATIC_ASSERT implementation of mine in case you're interested
http://stackoverflow.com/questions/1980012/boost-static-assert-without-boost/1980156#1980156
Similar to the one posted above, but in my opinion much cleaner:
template struct CompileTimeAssert;
template<> struct CompileTimeAssert{};
#define STATIC_ASSERT(e) (CompileTimeAssert <(e) != 0>())
sigmel > I got beaten by SFINAE several times: the static assertion was just ignored until I added the sizeof and typedef trickery
hmm also,
what do you mean when you say static_assert is less powerful than __identifier?
Post a Comment