Assuming some_code() is actually code
This can be tricky: if id is expanded from another token, it could be something like (0) instead of 0, or 0x10 instead of 16. Also, run-time values.
If you have a modern enough compiler, however, you can make use of dead code elimination:
#define M(id, ...) do { \
if (id) { \
some_code(__VA_ARGS__); \
} \
} while (/* CONSTCOND */ 0)
This will do the trick, even in a setting such as…
void
foo(int bar, int baz) {
M(bar, baz);
}
… and, since id is supposed to be a constant in all other cases, the if will be optimised away (even GCC 3.4.6 without any optimisation flags does that, for both zero and nōn-zero values, I just checked; LLVM will also do that, and many commercial Unix vendor compilers are likely to do so; PCC probably won’t, but is unlikely to be encountered by you).
So, this is not a pure-cpp solution, but one that’s likely to work in the wild, and it doesn’t invoke Undefined Behaviour or similar… fun… either.
The /* CONSTCOND */ is for lint, and the whole do { … } while (0) block is commonly used around macros that contain control constructs, so they can be used universally.
If some_code is not code but an arithmetic expression
In this case, the same solution becomes even shorter:
#define M(id, ...) ((id) ? some_code(__VA_ARGS__) : void)
Instead of void at the end, substitute anything you wish to return if id was zero. (I don’t believe the question warrants this, as writing some_code(__VA_ARGS__) pretty much looks like a function taking arguments, but some commenting person insists on this.)