2

In GCC, I have been successfully using the following IS_1 macro for some time. It expands to the value of transmitted macro when the transmitted token is defined, 0 when it is undefined (or explicitly defined to be 0):

// Concatenate two tokens without performing macro expansion.
#define CONCAT(A, B) A##B

// Possibly expand macros in transmitted tokens and concatenate the results.
#define EXPAND_THEN_CONCAT(A, B) CONCAT(A,B)

#define _0_1 0,1
#define IS_X_1_SUB(X,Y,...) Y

// Problem with MSC occurs here: __VA_ARGS__ all end up in sub-macro's first parameter
#define IS_X_1(...) IS_X_1_SUB(__VA_ARGS__, 0)

// This is the useful macro: expands to X's value when defined, 0 otherwise.
#define IS_1(X) IS_X_1(EXPAND_THEN_CONCAT(_0_,X))

Example use case:

#define THIS_IS_TRUE 1
IS_1( THIS_IS_TRUE )
// Expected expansion: 1

IS_1( THIS_IS_FALSE )
// Expected expansion: 0

#define ZERO 0
IS_1( ZERO )
// Expected expansion: 0

Now, I'm hitting a problem trying to use this macro with Visual C++'s compiler, where __VA_ARGS__ in the IS_X_1 macro expansion is apparently transmitted as a single parameter to the IS_X_1_SUB macro, which in turn always expands to 0.

This is visible in the following dumbed-down example:

#define FOO(X, ...) X foo __VA_ARGS___
#define BAR(...) FOO(__VA_ARGS__, bar)
BAR(42, 42)
// expected (and actual result with GCC): 42 foo 42 bar
// output of MSC preprocessor: 42, 42 foo bar
  • Is this a bug?
  • Was it not supposed to work as it did with GCC in the first place?
  • Is there a workaround or an otherwise more portable solution?
Shadocko
  • 1,186
  • 9
  • 27

0 Answers0