One in a while there's a need for a no-op statement in C++. For example when implementing assert()
which is disabled in non-debug configuration (also see this question):
#ifdef _DEBUG
#define assert(x) if( !x ) { \
ThrowExcepion(__FILE__, __LINE__);\
} else {\
//noop here \
}
#else
#define assert(x) //noop here
#endif
So far I'm under impression that the right way is to use (void)0;
for a no-op:
(void)0;
however I suspect that it might trigger warnings on some compilers - something like C4555: expression has no effect; expected expression with side-effect
Visual C++ warning that is not emitted for this particular case but is emitted when there's no cast to void
.
Is it universally portable? Is there a better way?
;
should do it,(void)0;
(your macro should not contain the;
, that should be up to the caller to add) – Southeastwards#define assert(x) //noop here
– Sarcomatosis#define assert(x) if(x); else ThrowException(__FILE__, __LINE__)
, which will require the semicolon to compile properly and will look/act like a statement. Leaving in the brackets allow that to be omitted, which can be a problem (particularly if your release macro definition requires the semicolon, and you forgot to use it somewhere). – Eolithicassert
s are enabled in release mode, and we dump a small diagnostics and core file so that we can try and diagnose what went wrong out in the field. – Southeastwardsif (cond) assert(cond2);
- you'll get anif(cond) ; if(cond2) ; else (....);
which is ambiguous. Better place the whole thing in a block on its own. – Reminisceelse
binds with the innermostif
. It looks ambiguous if you add incorrect indentation, but it isn't. (A compiler with sufficiently high warnings settings may claim it to be ambiguous, but in that case the best solution is to adjust your compiler warnings to the code you want to write, or usedo { if(!x) ThrowException(__FILE__, __LINE__); } while(0)
.) – Eolithic