【发布时间】:2014-04-06 01:24:38
【问题描述】:
我正在尝试用 C(不是 C++,所以我不能使用 Boost)编写一个可变参数宏,它允许分配函数指针,如下所示:
#define INIT_METHODS(name,...)
typedef struct{
void (*method1)();
}data1_t;
typedef struct{
void (*method1)();
void (*method2)();
}data2_t;
void function1(){}
void function2(){}
data1_t ptr1 = calloc(sizeof(data1,1));
data2_t ptr2 = calloc(sizeof(data2,1));
INIT_METHODS(ptr1, method1, function1);
INIT_MEGHODS(ptr2, method1,function1, method2, function2);
我希望宏会生成以下代码(变量参数列表的大小应该始终是偶数)
ptr1->method1 = function1;
ptr2->method1 = function1;ptr2->method2 = function2;
很遗憾,我没能做到。以下是我的尝试。
#define VA_NARGS_IMPL(_1,_2,_3,_4,_5,_6,_7,_8,N,...) N
#define VA_NARGS(...) VA_NARGS_IMPL(__VA_ARGS__, 8, 7, 6, 5, 4, 3, 2, 1, 0)
#define setfunc1 (name,a8) a8
#define setfunc2 (name, a7, a8) name->a7=setfunc1(name,a8)
#define setfunc3 (name, a6, a7, a8) a6;setfunc2(name,a7,a8)
#define setfunc4 (name, a5, a6, a7, a8) name->a5=setfunc3(name,a6,a7,a8)
#define setfunc5 (name, a4, a5, a6, a7, a8) a4;setfun4(name,a5,a6,a7,a8)
#define setfunc6 (name, a3, a4, a5, a6, a7, a8) name->a3=setfunc5(name,a4,a5,a6,a7,a8)
#define setfunc7 (name, a2, a3, a4, a5, a6, a7, a8) a2;setfunc6(name,a3,a4,a5,a6,a7,a8)
#define setfunc8 (name, a1, a2, a3, a4, a5, a6, a7, a8) \
name->a1=setfunc7(name,a2,a3,a4,a5,a6,a7,a8)
#define INIT_METHODSP(name, count, ...) setfunc##count(name, __VA_ARGS__)
#define INIT_METHODS (name, ...) INIT_METHODSP(name, VA_NARGS(__VA_ARGS__), __VA_ARGS__))
【问题讨论】:
-
你的工作保障有问题
-
使用宏有什么好处?没有宏的代码将更容易维护。通过使用此类宏 AFAICS,您不会使代码更具可移植性。 (我认为带有 G 的
INIT_MEGHODS是一个错字。) -
您可能还注意到
setfunc1和左括号之间的空格意味着名称setfunc1是类对象宏,而不是类函数宏。如果您希望(name, a8)成为类似函数的宏的参数,那么定义宏时 的宏名称后,左括号不能有任何空格(或注释)。使用宏时,宏名与其参数列表之间可以有任意数量的空格(包括 cmets),但在定义宏时不能。 -
您的宏链也很可疑,因为您应该使用成对的参数。
#define setfunc1(pointer, member, function) pointer->member = function;然后可能是#define setfunc2(pointer, member1, function1, member2, function2) setfunc1(pointer, member1, function1) setfunc1(pointer, member2, function2)或类似的东西。