经过一番研究和大量的讨论,我已经想出了这个:
#include <stdio.h>
// Variadic Function Overloading:
#define VOID "__variadic_VOID__"
#define variadic_count(...) variadic_count_(__VA_ARGS__, 6, 5, 4, 3, 2, 1, 0)
#define variadic_count_(_6, _5, _4, _3, _2, _1, count, ...) count
#define variadic_token(func, ...) variadic_token_(func, variadic_count(__VA_ARGS__))
#define variadic_token_(func, count) variadic_token__(func, count)
#define variadic_token__(func, count) func ## _ ## count
#define variadic(func, ...)\
do {\
if (#__VA_ARGS__ == "\"__variadic_VOID__\"")\
{\
variadic_token__(func, 0)();\
}\
else\
{\
variadic_token(func, __VA_ARGS__)(__VA_ARGS__);\
}\
} while (0)
// Usage:
#define somefunction(...) variadic(somefunction, __VA_ARGS__)
#define somefunction_0()\
do {\
printf("somefunction_0(VOID)\n\n");\
} while (0)
#define somefunction_1(x)\
do {\
printf("somefunction_1(x = %i)\n\n", (x));\
} while (0)
#define somefunction_2(x, y)\
do {\
printf("somefunction_2(x = %i, y = %i)\n\n", (x), (y));\
} while (0)
int main(int argc, char* argv[])
{
//somefunction(); ERROR
somefunction(VOID);
somefunction(1);
somefunction(11);
somefunction(2, 3);
//somefunction(1, 2, 3); ERROR
printf("\n\n");
return 0;
}
基本上,它允许通过特殊令牌VOID区分零和一个参数。除非将可变参数函数/宏传递给由VOID定义的字符串文字作为唯一参数,否则它是有效的。在这种情况下,只有somefunction("__variadic_VOID__");
的调用才会导致意外行为;传递与字符串文字值相同的变量不会导致意外行为。
虽然提供的代码仅适用于0-6个参数,但可以修改它以使用更多的参数。
然而,我很好奇,if ("blah" == "blah") {doSomething();}
是否被编译器(Pelles C)优化为doSomething();
?或者指针比较是否在运行时发生?如果它被优化掉了,那么我认为这段代码片段允许简单有效的函数/宏的可变重载...是吗?
答案 0 :(得分:0)
更好的方案是:
#define variadic(func, ...)\
do {\
if (0 == *#__VA_ARGS__)\
{\
variadic_token__(func, 0)();\
}\
else\
{\
variadic_token(func, __VA_ARGS__)(__VA_ARGS__);\
}\
} while (0)
然后,somefunction()
之类的通话将扩展为somefunction_0()
的通话,并且不需要魔法VOID
令牌。它也更安全,更有可能被编译器优化掉。