tags:

views:

775

answers:

3

I have the following preprocessor divective:

#ifndef NDEBUG
#define TRACE printf
#else
#define TRACE(...)
#endif

and example of usage is:

TRACE("TRACE: some parameter = %i\n", param);

In C all works perfectly well when I build both debug and release versions, but in C++ compiler emits the following:

warning: invalid character in macro parameter name

error: badly punctuated parameter list in `#define'

and points these warning and error to the 'TRACE(...)' directive.

How to write this in C++ correctly?

+1  A: 

You could do:

inline void TRACE(...) {}
Greg Hewgill
Problem is compiler always has to evaluate the arguments. If they are expensive you want them turned off. Hence TRACE type macros should generally evaluate to empty code in release mode.
Martin York
A: 

What compiler? For what it's worth, G++ 4.3.1 does not have any problem with that code.

Ted Percival
QXN Netrino QCC compiler, gcc_ntox86 version 2.95.3. As far as I understand this is GCC with externsions for QNX version for x86.
Nikita Borodulin
+3  A: 

#define TRACE false ||

This turns TRACE(x,y,z) into false || (x,y,z). Since x,y and z will be expressions, (x,y,z) evaluates to z (comma operator). z must be a built-in type (to be legally passed to a printf-style function) so it should be valid on the right side of ||. It won't be evaluated, but it must be a legal expression (e.g. you can't reference class members which only exist in DEBUG builds)

Vararg macros are a C99 invention, they're not in C++98 but might very well be in C++0x

[edit] - Using || to guarantee non-evaluation

MSalters
Problem is compiler always has to evaluate x,y and z. If they are expensive you want them turned off.
Martin York