背景
最近在项目中遇到一个问题,项目中一个字段对外的协议是毫无规律的整形值,内部需要将这个协议映射成方便处理的数据结构,想到的办法是把协议值先枚举出来,然后解析枚举变量。由于枚举变量本身不能直接解析,所以该为解析枚举变量的名字。比如
enum
{
ONLY_TYPE1 = 1,
ONLY_TYPE2 = 2,
ONLY_TYPE3 = 3,
ONLY_TYPE4 = 4,
TYPE1_AND_TYPE2 = 5,
TYPE1_AND_TYPE2_AND_TYPE3 = 6,
TYPE1_AND_TYPE2_AND_TYPE3_AND_TYPE3 = 7,
};
只要保证枚举变量名字按照这种规律去命名,就可以去解析它。但是嘛,写代码吗,你就算在这里注释要这么写,也还是会出现就不看你注释来的情况,毕竟这种命名规则不能算是规范。所以呢,想通过自动生成变量名的方式强制约束,你不要自己去命名,按照我给的接口传参数就行了。
宏的使用
基本还是依靠宏连接符号##,因为参数数量是可变的,还要解析参数数量,这部分参考了这位大佬的代码,
https://blog.csdn.net/10km/article/details/80760533
基本思路是把各个参数数量的宏先定义出来,然后定义一个入口宏,根据参数数量再替换成相应的宏。
上代码,
//这个宏用来获取参数列表数量
#define ARG_COUNT(...) _ARG_COUNT_PRIVATE(0, ##__VA_ARGS__,\
9, 8, 7, 6, 5, 4, 3, 2, 1, 0)
#define _ARG_COUNT_PRIVATE(\
_0, _1, _2, _3, _4, _5, \
_6, _7, _8, _9, N, ...) N
//嵌套的宏不能展开,需要再定义一层
#define _CAT(x, y) x##y
#define _NAME(TYPE) #TYPE
#define _JOIN(A, B) A##_##B
#define CAT(x, y) _CAT(x, y)
#define NAME(TYPE) _NAME(TYPE)
#define JOIN(A, B) _JOIN(A, B)
//这些宏用来连接字符形成统一规范的命名
#define METHOD_CREATE(COMBINE, OLDMETHOD, NEWTYPE) JOIN(OLDMETHOD, JOIN(COMBINE, NEWTYPE))
#define METHOD1(TYPE) TYPE
#define METHOD2(COMBINE, TYPE) JOIN(COMBINE, TYPE)
#define METHOD3(COMBINE, TYPE1, TYPE2) METHOD_CREATE(COMBINE, METHOD1(TYPE1), TYPE2)
#define METHOD4(COMBINE, TYPE1, TYPE2, TYPE3) METHOD_CREATE(COMBINE, METHOD3(COMBINE, TYPE1, TYPE2), TYPE3)
#define METHOD5(COMBINE, TYPE1, TYPE2, TYPE3, TYPE4) METHOD_CREATE(COMBINE, METHOD4(COMBINE, TYPE1, TYPE2, TYPE3), TYPE4)
#define METHOD6(COMBINE, TYPE1, TYPE2, TYPE3, TYPE4, TYPE5) METHOD_CREATE(COMBINE, METHOD5(COMBINE, TYPE1, TYPE2, TYPE3, TYPE4), TYPE5)
//这个宏会根据参数数量去替换成上面的其中一个METHOND
#define METHOD(...) CAT(METHOD, ARG_COUNT(__VA_ARGS__))(__VA_ARGS__)
using namespace std;
enum
{
METHOD(ONLY, TYPE1) = 1,
METHOD(AND, TYPE1, TYPE2) = 5,
METHOD(AND, TYPE1, TYPE2, TYPE3) = 6,
METHOD(AND, TYPE1, TYPE2, TYPE3, TYPE4) = 7,
};
int main()
{
cout << NAME(METHOD(ONLY, TYPE1)) << endl;
cout << NAME(METHOD(AND, TYPE1, TYPE2)) << endl;
cout << NAME(METHOD(AND, TYPE1, TYPE2, TYPE3)) << endl;
cout << NAME(METHOD(AND, TYPE1, TYPE2, TYPE3, TYPE4)) << endl;
}
out>>>>
ONLY_TYPE1
TYPE1_AND_TYPE2
TYPE1_AND_TYPE2_AND_TYPE3
TYPE1_AND_TYPE2_AND_TYPE3_AND_TYPE4
非常简洁,新增值只要复制一下宏把参数填进去就行了,毕竟我都把复制粘贴模板给你了,你总不能还不按照这个来吧。