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?