So I’ve got a macro that works nicely in GCC, but not in Microsoft’s C++ Compiler. I’m hoping somebody might know of a workaround, or perhaps can explain to me why it behaves this way.
I’m sure this macro isn’t exactly “standard”, but it would really help me out.
Here is a functional example of the macro:
#define VA_NARGS_IMPL(_1, _2, _3, _4, _5, N, ...) N
#define VA_NARGS(...) VA_NARGS_IMPL(__VA_ARGS__, 5, 4, 3, 2, 1)
#define FULLY_EXPANDED(count, ...) \
MAC ## count (__VA_ARGS__)
#define SEMI_EXPANDED(count, ...) FULLY_EXPANDED(count, __VA_ARGS__)
#define EXPAND_THESE(...) SEMI_EXPANDED(VA_NARGS(__VA_ARGS__), __VA_ARGS__)
#define ACTUAL_MACRO(x) parent->GetProperty<x>();
#define MAC1(a) ACTUAL_MACRO(a)
#define MAC2(a,b) MAC1(a) ACTUAL_MACRO(b)
#define MAC3(a,b,c) MAC2(a,b) ACTUAL_MACRO(c)
#define MAC4(a,b,c,d) MAC3(a,b,c) ACTUAL_MACRO(d)
#define MAC5(a,b,c,d,e) MAC4(a,b,c,d) ACTUAL_MACRO(e)
Here is how I might use this macro:
struct MyStructure
{
void Foo()
{
EXPAND_THESE(Property1, Property2, Property3, Property4)
}
Base * parent;
}
Here’s how GCC expands the above:
struct MyStructure
{
void Foo()
{
parent->GetProperty<Property1>();
parent->GetProperty<Property2>();
parent->GetProperty<Property3>();
parent->GetProperty<Property4>();
}
Base * parent;
}
But Microsoft for some reason expands all my __VA_ARGS__ as one argument:
struct MyStructure
{
void Foo()
{
parent->GetProperty<Property1, Property2, Property3, Property4>();
}
Base * parent;
}
Does anybody know why this is? Is there some trick I can pull to get Microsoft to expand this like GCC? Maybe toss in a couple extra pairs of parentheses?
Macros like this could really help me out in replacing a bunch of “glue” code, but because of this problem, I can’t move it into my VS project. Any help would be greatly appreciated!
Thanks.
Coincidentally, I happened to run into this problem just today, and after enough effort I think I’ve found a solution for my own purposes. The bug is MSVC treats
__VA_ARGS__as a single token in argument lists. But you can work around this by not using it directly within a macro call argument list. This comment suggests the start of an answer to your problems:But then I suspect you’ll likely run into the issue of making sure that gets fully expanded to the actual "N" you want, and not to
VA_NARGS_IMPL (arg1, arg2, 5, 4, 3, 2, 1), say. I found that my code (which looked like yours) had to change to expandMAC##codeall as one unit, and then that had to be separately combined with the argument list. Here’s the code that I found worked for me:My mind is too much mush after a few hours solving my own issues to then go and completely solve yours, I’m sorry to say. 🙂 But I think this is enough to get you to something that works, with a little work.