3 min to read
按照不同參數數目展開不同的宏
有了上一篇 選取第 n 項參數和判斷參數數目 的宏之後
我們可以來做 按照不同參數數目展開不同的宏 的宏
▌回顧:
上一篇提到一個 選取第 n 項參數 的宏:
#define get1th(a1, ...) a1
#define get2th(a1, a2, ...) a2
#define get3th(a1, a2, a3, ...) a3
#define get4th(a1, a2, a3, a4, ...) a4
#define get5th(a1, a2, a3, a4, a5, ...) a5
// ... getnth(a1, a2, a3, ... , an, ...) an
和判斷參數數目的宏:
#define parameterNum(...) get5thVS(__VA_ARGS__, 4, 3, 2, 1)
然後針對 分辨 0 和 1 個參數數目,出現的最後版本:
#define parameterNum(...) get5th( __VA_ARGS__ __VA_OPT__(,) 4, 3, 2, 1, 0)
用法:
parameterNum() // 0
parameterNum(?) // 1
parameterNum(?, ?) // 2
parameterNum(?, ?, ?) // 3
parameterNum(?, ?, ?, ?) // 4
▌按照不同參數數目展開不同的宏
我們察覺到 parameterNum
會按照不同參數數目展開不同的 數字
那我們可不可以擴展成 按照參數數目展開不同的 宏 呢?當然可以
顯然,模仿 parameterNum
的做法:
#define foo(...) get5th( __VA_ARGS__ __VA_OPT__(,) e, d, c, b, a)
現在 foo
的行為會是這樣:
foo() // a
foo(?) // b
foo(?, ?) // c
foo(?, ?, ?) // d
foo(?, ?, ?, ?) // e
我們可以想像到,每一次都要按這種格式編寫是多麼的麻煩
後面需要展開的部分甚至需要倒序編寫,以及有一堆讓人迷糊的東西
作為一個合格的程式員,我們來簡單地封裝一次:
#define select0_4(m0, m1, m2, m3, m4, ...) \
get5th( __VA_ARGS__ __VA_OPT__(,) m4, m3, m2, m1, m0 )
現在可以方便一點:
#define foo(...) select0_4(a, b, c, d, e, __VA_ARGS__)
同樣道理,parameterNum
也可以換成用這個實現:
#define parameterNum(...) select0_9(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, __VA_ARGS__)
▌代碼:
#define get1th(a1, ...) a1
#define get2th(a1, a2, ...) a2
#define get3th(a1, a2, a3, ...) a3
#define get4th(a1, a2, a3, a4, ...) a4
#define get5th(a1, a2, a3, a4, a5, ...) a5
#define get6th(a1, a2, a3, a4, a5, a6, ...) a6
#define get7th(a1, a2, a3, a4, a5, a6, a7, ...) a7
#define get8th(a1, a2, a3, a4, a5, a6, a7, a8, ...) a8
#define get9th(a1, a2, a3, a4, a5, a6, a7, a8, a9, ...) a9
#define get10th(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, ...) a10
#define parameterNum(...) select0_9(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, __VA_ARGS__)
#define select0_1(m0, m1, ...) get2th( __VA_ARGS__ __VA_OPT__(,) m1, m0 )
#define select0_2(m0, m1, m2, ...) get3th( __VA_ARGS__ __VA_OPT__(,) m2, m1, m0 )
#define select0_3(m0, m1, m2, m3, ...) get4th( __VA_ARGS__ __VA_OPT__(,) m3, m2, m1, m0 )
#define select0_4(m0, m1, m2, m3, m4, ...) get5th( __VA_ARGS__ __VA_OPT__(,) m4, m3, m2, m1, m0 )
#define select0_5(m0, m1, m2, m3, m4, m5, ...) get6th( __VA_ARGS__ __VA_OPT__(,) m5, m4, m3, m2, m1, m0 )
#define select0_6(m0, m1, m2, m3, m4, m5, m6, ...) get7th( __VA_ARGS__ __VA_OPT__(,) m6, m5, m4, m3, m2, m1, m0 )
#define select0_7(m0, m1, m2, m3, m4, m5, m6, m7, ...) get8th( __VA_ARGS__ __VA_OPT__(,) m7, m6, m5, m4, m3, m2, m1, m0 )
#define select0_8(m0, m1, m2, m3, m4, m5, m6, m7, m8, ...) get9th( __VA_ARGS__ __VA_OPT__(,) m8, m7, m6, m5, m4, m3, m2, m1, m0 )
#define select0_9(m0, m1, m2, m3, m4, m5, m6, m7, m8, m9, ...) get10th( __VA_ARGS__ __VA_OPT__(,) m9, m8, m7, m6, m5, m4, m3, m2, m1, m0 )
有興趣可以去 GitHub:
CWKSC/MyLib_Cpp_Macro: Marco Lib for C++20 and new preprocessor in Visual Studio 2019