c/c++:基于for each pair 遍历 __VA_ARGS__ 中的元素,实现定义struct的宏

在上一篇博客《c/c++:for each遍历 __VA_ARGS__ 中的每一个元素》,我们具备了遍历__VA_ARGS__中元素的能力,那么具备这个能力有啥用呢? 在上篇博客中的例子中,可以利用这个遍历功能定义枚举(enum)类型。
进一步延伸思考,还可以利用这个能力定义结构体(struct)呀。当然定义结构体与枚举类似是有区别的,结构体的每个成员不光需要成员名还需要指定数据类型。所以不能简单的使用上篇文章中的FL_FOREACH宏来实现。我们需要能遍历成对参数的能力,这就是下面的宏FL_VA_FOREACH_PAIR,这个函数宏对__VA_ARGS__(必须是偶数个)中的参数以两个一组为单位进行遍历。

#define FL_DOPAIR0(s,f,a,O)
#define FL_DOPAIR2(s,f,a,t,v) f(a,t,v)
#define FL_DOPAIR4(s,f,a,t,v,...) FL_DOPAIR2(s,f,a,t,v) s FL_DOPAIR2(s,f,a,__VA_ARGS__)
#define FL_DOPAIR6(s,f,a,t,v,...) FL_DOPAIR2(s,f,a,t,v) s FL_DOPAIR4(s,f,a,__VA_ARGS__)
#define FL_DOPAIR8(s,f,a,t,v,...) FL_DOPAIR2(s,f,a,t,v) s FL_DOPAIR6(s,f,a,__VA_ARGS__)
#define FL_DOPAIR10(s,f,a,t,v,...) FL_DOPAIR2(s,f,a,t,v) s FL_DOPAIR8(s,f,a,__VA_ARGS__)
#define FL_DOPAIR12(s,f,a,t,v,...) FL_DOPAIR2(s,f,a,t,v) s FL_DOPAIR10(s,f,a,__VA_ARGS__)
#define FL_DOPAIR14(s,f,a,t,v,...) FL_DOPAIR2(s,f,a,t,v) s FL_DOPAIR12(s,f,a,__VA_ARGS__)
#define FL_DOPAIR16(s,f,a,t,v,...) FL_DOPAIR2(s,f,a,t,v) s FL_DOPAIR14(s,f,a,__VA_ARGS__)
#define FL_DOPAIR18(s,f,a,t,v,...) FL_DOPAIR2(s,f,a,t,v) s FL_DOPAIR16(s,f,a,__VA_ARGS__)
#define FL_DOPAIR20(s,f,a,t,v,...) FL_DOPAIR2(s,f,a,t,v) s FL_DOPAIR18(s,f,a,__VA_ARGS__)
#define FL_DOPAIR22(s,f,a,t,v,...) FL_DOPAIR2(s,f,a,t,v) s FL_DOPAIR20(s,f,a,__VA_ARGS__)
#define FL_DOPAIR24(s,f,a,t,v,...) FL_DOPAIR2(s,f,a,t,v) s FL_DOPAIR22(s,f,a,__VA_ARGS__)
#define FL_DOPAIR26(s,f,a,t,v,...) FL_DOPAIR2(s,f,a,t,v) s FL_DOPAIR24(s,f,a,__VA_ARGS__)
#define FL_DOPAIR28(s,f,a,t,v,...) FL_DOPAIR2(s,f,a,t,v) s FL_DOPAIR26(s,f,a,__VA_ARGS__)
#define FL_DOPAIR30(s,f,a,t,v,...) FL_DOPAIR2(s,f,a,t,v) s FL_DOPAIR28(s,f,a,__VA_ARGS__)
#define FL_DOPAIR32(s,f,a,t,v,...) FL_DOPAIR2(s,f,a,t,v) s FL_DOPAIR30(s,f,a,__VA_ARGS__)
#define FL_DOPAIR34(s,f,a,t,v,...) FL_DOPAIR2(s,f,a,t,v) s FL_DOPAIR32(s,f,a,__VA_ARGS__)
#define FL_DOPAIR36(s,f,a,t,v,...) FL_DOPAIR2(s,f,a,t,v) s FL_DOPAIR34(s,f,a,__VA_ARGS__)
#define FL_DOPAIR38(s,f,a,t,v,...) FL_DOPAIR2(s,f,a,t,v) s FL_DOPAIR36(s,f,a,__VA_ARGS__)
#define FL_DOPAIR40(s,f,a,t,v,...) FL_DOPAIR2(s,f,a,t,v) s FL_DOPAIR38(s,f,a,__VA_ARGS__)
#define FL_DOPAIR42(s,f,a,t,v,...) FL_DOPAIR2(s,f,a,t,v) s FL_DOPAIR40(s,f,a,__VA_ARGS__)
#define FL_DOPAIR44(s,f,a,t,v,...) FL_DOPAIR2(s,f,a,t,v) s FL_DOPAIR42(s,f,a,__VA_ARGS__)
#define FL_DOPAIR46(s,f,a,t,v,...) FL_DOPAIR2(s,f,a,t,v) s FL_DOPAIR44(s,f,a,__VA_ARGS__)
#define FL_DOPAIR48(s,f,a,t,v,...) FL_DOPAIR2(s,f,a,t,v) s FL_DOPAIR46(s,f,a,__VA_ARGS__)
#define FL_DOPAIR50(s,f,a,t,v,...) FL_DOPAIR2(s,f,a,t,v) s FL_DOPAIR48(s,f,a,__VA_ARGS__)
#define FL_DOPAIR52(s,f,a,t,v,...) FL_DOPAIR2(s,f,a,t,v) s FL_DOPAIR50(s,f,a,__VA_ARGS__)
#define FL_DOPAIR54(s,f,a,t,v,...) FL_DOPAIR2(s,f,a,t,v) s FL_DOPAIR52(s,f,a,__VA_ARGS__)
#define FL_DOPAIR56(s,f,a,t,v,...) FL_DOPAIR2(s,f,a,t,v) s FL_DOPAIR54(s,f,a,__VA_ARGS__)
#define FL_DOPAIR58(s,f,a,t,v,...) FL_DOPAIR2(s,f,a,t,v) s FL_DOPAIR56(s,f,a,__VA_ARGS__)
#define FL_DOPAIR60(s,f,a,t,v,...) FL_DOPAIR2(s,f,a,t,v) s FL_DOPAIR58(s,f,a,__VA_ARGS__)
#define FL_DOPAIR62(s,f,a,t,v,...) FL_DOPAIR2(s,f,a,t,v) s FL_DOPAIR60(s,f,a,__VA_ARGS__)
#define FL_DOPAIR64(s,f,a,t,v,...) FL_DOPAIR2(s,f,a,t,v) s FL_DOPAIR62(s,f,a,__VA_ARGS__)

// 为动态参数 __VA_ARGS__ 每两个值(一对值)执行 调用 fun 宏,最大支持64个参数,参数个数必须是偶数
// sepatator 分隔符
// fun 函数宏
// funarg 函数宏的附加参数
#define FL_VA_FOREACH_PAIR_(sepatator,fun,funarg,...) \
        FL_CONCAT(FL_DOPAIR,FL_ARG_COUNT(__VA_ARGS__))(sepatator,fun,funarg,__VA_ARGS__)
#define FL_VA_FOREACH_PAIR(sepatator,fun,funarg,...) \
        FL_VA_FOREACH_PAIR_(sepatator,fun,funarg,__VA_ARGS__)

利用上面的FL_VA_FOREACH_PAIR我们可以创建一个定义struct的宏FL_DEF_STRUCT


#define fl_def_struct_field_def(t,v) t v
#define fl_def_struct_field(a,t,v) fl_def_struct_field_def(t,v);

// 定义一个名为clsName的结构,动态参数提成员的类型和名字,最多支持32个成员
// clsName##_为元素名前缀
// 对__VA_ARGS__参数成对遍历,对每一对参数执行fl_def_struct_field函数
// fl_def_struct_field函数用于定义每一个成员变量。
#define FL_DEF_STRUCT(clsName, ...)\
typedef struct _##clsName {\
    FL_VA_FOREACH_PAIR(,fl_def_struct_field, , __VA_ARGS__)\
}clsName,* clsName##_ptr;

调用示例:

// 定义具有三个成员变量的Struct
FL_DEF_STRUCT(test_struct10,char, m1,long, m2,char*, m3)

展开代码(eclipse显示编译器花了18步完成宏展开,so艰难):
这里写图片描述

这里写图片描述

发挥你的想象力,你会发现你可以顺着这个思路用macro干很多事儿。

猜你喜欢

转载自blog.csdn.net/10km/article/details/80798072