記錄一個宏的使用技巧
- 背景
- 宏的使用
背景
最近在項目中遇到一個問題,項目中一個字段對外的協定是毫無規律的整形值,内部需要将這個協定映射成友善處理的資料結構,想到的辦法是把協定值先枚舉出來,然後解析枚舉變量。由于枚舉變量本身不能直接解析,是以該為解析枚舉變量的名字。比如
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
非常簡潔,新增值隻要複制一下宏把參數填進去就行了,畢竟我都把複制粘貼模闆給你了,你總不能還不按照這個來吧。