CWKSC's blog | 博客 (已棄用)

按照不同參數數目展開不同的宏

Featured image

有了上一篇 選取第 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

CWKSC

Author 作者

CWKSC

喜歡編程,會一點點鋼琴,會一點點畫畫,喜歡使用顏文字 About me 關於我

For any comments or discussions on my blog post, you can open an issue here

對於我博客文章的任何評論或討論,可以在這裏開一個 issue

Feel free to give your comments. OW<