-1

Given this sample code:

#define vX(a, ...) ((a)(__VA_ARGS__) ? 1 : 0)

{
    int f();
    vX(f);
}

I get error C2155: '?': invalid left operand, expected arithmetic or pointer type

On the other hand if I provide a second argument to the macro it compiles fin - eg.:

vX(f,1)

is OK. I'm compiling C code with the msvc compiler.

Sorry to bother everyone but the mistake was on my side - the 2 functions that were giving me error not only had no argument but were of void return type also - that was causing my problem and not anything macro related.

AnArrayOfFunctions
  • 3,452
  • 2
  • 29
  • 66
  • If you add `int main()` before the `{`, it compiles fine on my Visual Studio 2017. What versio of VS do you use? – Jabberwocky Oct 02 '18 at 09:46
  • This is a rather complicated issue, discussed here with a gcc non-standard extension as the solution: https://stackoverflow.com/questions/5891221/variadic-macros-with-zero-arguments. Further info and macro trickery: https://gustedt.wordpress.com/2010/06/08/detect-empty-macro-arguments/ – Lundin Oct 02 '18 at 09:49
  • This question is missing something. Filling in minimal correct syntax for a complete program, this compiles just fine in VS 10.0 and VS 12.0. The current answers, while okay (your macro doesn't comply with the standard for the CPP), seem to miss the fact that you're seemingly compiling using MSVS (indicated by the error you're getting). – H Walters Oct 02 '18 at 16:23

2 Answers2

1

From the GCC documentation:

When the macro is invoked, all the tokens in its argument list after the last named argument (this macro has none), including any commas, become the variable argument. This sequence of tokens replaces the identifier __VA_ARGS__ in the macro body wherever it appears.

So, basically the __VA_ARGS__ part cannot be empty, that requires GNU extensions (__VA_OPT__).

unwind
  • 391,730
  • 64
  • 469
  • 606
1

The specification of the preprocessor about this is somewhat verbose, but suffice it to say, that you specified vX must accept at least two arguments.

The reason is that the number of arguments is largely determined by the number of commas in the macro. So for instance vX(f,) would cause your error to go away as well. The reason is that we again provide two arguments, namely f and an empty sequence of tokens after the comma.

One trick to get around it, is to split the macro across two expansions:

#define vX_(a, ...) ((a)(__VA_ARGS__) ? 1 : 0)
#define vX(...) vX_(__VA_ARGS__,)

Note how I added that comma? Now when you write vX(f) it will expand to vX_(f,) which will expand again to give you the expression you wanted. Although, that will not work in the general case, since you'll get a trailing comma. That is why GCC introduced __VA_OPT__ (@unwind's answer), so that the comma could be added conditionally.

StoryTeller - Unslander Monica
  • 165,132
  • 21
  • 377
  • 458