问题
I'm trying to overload a macro by the number of parameter.
Of course I can't actually overload the macro.
I've tried using variadic macros to choose the right macro (using the fact that if __VA_ARGS__
doesn't exist it's supposed to delete the last coma before it - GCC Reference):
#define TEST1() printf("TEST1");
#define TEST2() printf("TEST2");
#define CHOOSER(x, y,FUNC,...) FUNC()
#define MANIMACRO(...) CHOOSER(,__VA_ARGS__,TEST1,TEST2)
int main(void)
{
MANIMACRO(1);
MANIMACRO();
}
The idea was that if __VA_ARGS__
exists it should pass 4 arguments to CHOOSER, where the third one should have been "disappeared" with the unused args. so TEST1 would be chosen.
If there is no parameter the __VA_ARGS__
would be null, and should have removed the coma, so TEST2 would be chosen and used.
So, i guess that doesn't work because the __VA_ARGS__
probably gets removed only at the end of the preprocessing stage, after the whole thing was already expanded.
So, how can I do such a thing? (in vs2010)
回答1:
Based on this answer:
#define TEST1(expr) printf("test1")
#define TEST2(expr, explain) printf("test2")
#define N_ARGS_IMPL2(_1, _2, count, ...) \
count
#define N_ARGS_IMPL(args) \
N_ARGS_IMPL2 args
#define N_ARGS(...) N_ARGS_IMPL((__VA_ARGS__, 2, 1, 0))
/* Pick the right helper macro to invoke. */
#define CHOOSER2(count) TEST##count
#define CHOOSER1(count) CHOOSER2(count)
#define CHOOSER(count) CHOOSER1(count)
/* The actual macro. */
#define TEST_GLUE(x, y) x y
#define TEST(...) \
TEST_GLUE(CHOOSER(N_ARGS(__VA_ARGS__)), \
(__VA_ARGS__))
int main() {
TEST(one); // singleArgumentExpansion(one)
TEST(two, "foopy"); // twoArgumentExpansion(two, "foopy")
return 0;
}
回答2:
First, the page you link explains it is a GCC extension. If you are using visual studio 2010 as your tag implies, I'm not surprised it doesn't work.
Then you aren't using it correctly: you need ##
between the coma and __VA_ARGS__
. If I do this and fix the typo which makes both TESTx macros print TEST1, I get the behaviour you expect with gcc 4.4
#include <stdio.h>
#define TEST1() printf("TEST1\n");
#define TEST2() printf("TEST2\n");
#define CHOOSER(x, y, FUNC,...) FUNC()
#define MANIMACRO(...) CHOOSER(,##__VA_ARGS__,TEST1,TEST2)
int main(void)
{
MANIMACRO(1);
MANIMACRO();
}
来源:https://stackoverflow.com/questions/11974170/overloading-a-macro