天天看點

記錄一個宏的使用技巧,使用宏生成一定規則的字元串背景宏的使用

記錄一個宏的使用技巧

  • 背景
  • 宏的使用

背景

最近在項目中遇到一個問題,項目中一個字段對外的協定是毫無規律的整形值,内部需要将這個協定映射成友善處理的資料結構,想到的辦法是把協定值先枚舉出來,然後解析枚舉變量。由于枚舉變量本身不能直接解析,是以該為解析枚舉變量的名字。比如

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

非常簡潔,新增值隻要複制一下宏把參數填進去就行了,畢竟我都把複制粘貼模闆給你了,你總不能還不按照這個來吧。

繼續閱讀