Reputation: 59
I need some help in writing a macro for 'if-condition' which compiles only when a DEBUG flag is defined by the #define directive.
Here is an example which illustrates what I want. first piece of code shows the usual way of writing an if condition with a #ifdef.
#ifdef DEBUG
if( rv == false )
{
string errorStr = "error in return value" ;
cout << errorStr << endl ;
throw( Exception(errorStr) ) ;
}
I want to write it in a way similar as below:
DEBUG_IF( rv==false )
{
same code as above
}
It seems to be simple but I am having trouble defining a macro which can do this. If someone has experienced this before, kindly help.
Thanks.
Upvotes: 4
Views: 10074
Reputation: 413
Somewhat late here but I was wondering whether simply defining a constant may be more elegant than defining a function:
#ifdef DEBUG
#define IS_IN_DEBUG true
#else
#define IS_IN_DEBUG false
#endif
if ( IS_IN_DEBUG ) {
// do something
}
Isn’t this easier to read? Any thoughts on this?
Upvotes: 0
Reputation: 6797
I don't recommend using a DEBUG_IF kind of macro for the reason Kelly pointed out.
DEBUG_IF(x)
{
// debugging code
}
else
{
// release code (should be executed for both debug and release)
}
See the logical error here? The release code should always be executed unless it's release-only code, yet this would be a fairly easy mistake to make with the DEBUG_IF macro. It might be a nuisance to write this out, but I think it's the clearest and least confusing way. If you do use it, I recommend avoiding else with it completely.
The same is true of the DEBUG_CONDITION macro.
if (DEBUG_CONDITION(x) )
{
// debugging code
}
else
{
// oops, this never gets executed in debug builds
}
Release-only code is very rare in contrast to debug-only code so these kinds of occurrences would generally be logical errors. When I started using C++ I wanted to shorthand everything, but I've learned over the years and especially from working with a team that it's generally better to write it out as intended. Strive to achieve conciseness in logic, but you have to be careful not to cross a line where reducing code steps into obfuscation boundaries.
The idea of debugging a large-scaled system filled with DEBUG_IF/DEBUG_CONDITION macros like these gives me a splitting headache.
Upvotes: 0
Reputation: 3481
Personally I'd go with the #ifdef DEBUG
route instead of the code obfuscating DEBUG_IF
macro approach. Better to write clear code that doesn't hide code behind some macro.
If you really want to go the macro route, I'd leave the if
alone and focus on the condition itself, e.g.
#ifdef DEBUG
# define DEBUG_CONDITION(x) x
#else
# define DEBUG_CONDITION(x) false
#endif /* DEBUG */
if (DEBUG_CONDITION(rv == false))
{
...
}
Some obfuscation still exists with this approach but it is, IMHO, more acceptable than the proposed DEBUG_IF()
macro since it preserves C/C++ syntax.
I believe most, if not all, compilers will simply optimize out the dead code resulting from the if(false)
in the non-DEBUG
case (e.g. equivalent to if(0)
). However, some compilers could conceivably issue a "dead code" warning with this approach as well as the DEBUG_IF()
approach you described.
Upvotes: 0
Reputation: 76690
Try:
#ifdef DEBUG
#define DEBUG_IF(x) if(x)
#else
#define DEBUG_IF(x) if(false)
#endif
Now this won't be exactly the same as what you have right now, because when using this method, the code inside the if
block still gets compiled, although it will never be run when DEBUG
is not defined, and will probably be optimized out. In contrast, with your original example, the code is eliminated by the preprocessor and is never even compiled.
Upvotes: 9
Reputation: 503963
Do you want the if
to be conditional, so that in Release the code runs unconditionally? (As the title suggests.) Or do you want the entire block to be conditional? (So it Release there is no block.) You're missing the #endif in your equivalence code so it's impossible to tell.
For the former, you could use this:
#ifdef DEBUG
#define DEBUG_IF(x) if (x)
#else
#define DEBUG_IF(x) if (false)
#endif
The code in the block will be compiled, but discarded by the compiler, as it's dead code. If you only want the conditional to be changed, do this:
#ifdef DEBUG
#define DEBUG_IF(x) if (x)
#else
#define DEBUG_IF(x)
#endif
Without DEBUG
, the entire conditional ceases to exist. Fix your question to make it clear what you want.
Upvotes: 0
Reputation: 258238
I think this is what you're looking for:
#include <iostream>
#ifdef DEBUG
#define DEBUG_IF(cond) if(cond)
#else
#define DEBUG_IF(cond) if(false)
#endif
int main(int argc, char** argv)
{
DEBUG_IF(argc > 1)
{
std::cout << "In debug mode and at least one argument given" << std::endl;
}
else
{
std::cout << "Not in debug mode or no arguments given" << std::endl;
}
}
Run this at the command line, with or without an argument, with or without being compiled with -DDEBUG
for proof that it works as expected.
Upvotes: 2