“宏”這個(gè)玩意兒可能會(huì)觸動(dòng)很多人抵觸的情緒,我也一樣:很討厭它。通常我不會(huì)用它進(jìn)行計(jì)算,只有在合適的時(shí)候(比如能讓我少打一些字,或者能增 強(qiáng)代碼的可讀)才會(huì)請(qǐng)出它來(lái)。好了,言歸正轉(zhuǎn),現(xiàn)在我要將一個(gè)代碼片段有規(guī)律地重復(fù)N次,更具體點(diǎn),就是在定義一個(gè)模板的時(shí)候,參數(shù)列表會(huì)很長(zhǎng),但是這些 參數(shù)的名字是很有規(guī)律地:依次為typename T1,typename T2,....typename TN:
在C++還沒(méi)有支持模板的List參數(shù)(《C++ template》第13章)之前,我們可以利用宏來(lái)減少我們的工作量。
想一下吧,如果問(wèn)題變了,現(xiàn)在的問(wèn)題是要你寫(xiě)一個(gè)函數(shù)打印出上面的模板參數(shù)列表,你會(huì)怎么干?拿到這個(gè)需求時(shí),我寫(xiě)下了兩個(gè)函數(shù):
-
printMetaExpr: 接收一個(gè)參數(shù)i,打印出
typename
Ti,
- print:接收一個(gè)參數(shù)N,作為需要打印的參數(shù)個(gè)數(shù),然后在一個(gè)for循環(huán)中調(diào)用printMetaExprN次.
如下:
|
|
宏其實(shí)也和stream差不多,只不過(guò)宏不是把這些東西輸出到控制臺(tái)或者文件中,而是輸出給編譯器看的,本質(zhì)上沒(méi)什么區(qū)別,所以我們可以這樣來(lái)設(shè)計(jì)我們的宏:
- 定義宏DEFINE_TEMPLATE_PARAM(N),來(lái)展開(kāi)typename TN,這個(gè)比較簡(jiǎn)單:#define DEFINE_TEMPLATE_PARAM(N) typename T##N
- 定義一個(gè)可以調(diào)用DEFINE_TEMPLATE_PARAM的宏CALL_MACRO(N,callee,sep):這個(gè)宏會(huì)調(diào)用callee N次,并且每一次調(diào)用后都會(huì)加上一個(gè)分隔sep.
難點(diǎn)就在每二步了,如何來(lái)循環(huán)調(diào)用宏呢?搔頭了吧,其實(shí)也不是十分地難,還是拿上面打印到控制臺(tái)的程序來(lái)說(shuō)吧,如果你將print寫(xiě)了成遞歸的形式,一切就真相大白啦:
按照這個(gè)思路,如果說(shuō)我們要支持最多可以調(diào)用5次,我們就可以寫(xiě)出下面的遞歸宏啦:
最后用下面的宏封裝一下上面的宏
#define CALL_MACRO(N,callee) CALL_MACRO##N(callee)
為了驗(yàn)證上述宏的正確性,我向大家隆重介紹一個(gè)可以調(diào)試宏的宏:
1
|
|
2
|
|
3
|
|
4
|
|
5
|
|
6
|
好了,現(xiàn)在可以寫(xiě)一個(gè)簡(jiǎn)單地程序來(lái)測(cè)試一下成果啦:
運(yùn)行后輸出:
下面給出我使用宏的一點(diǎn)心得:
宏的性質(zhì):
- #可以將傳入的參數(shù)變?yōu)樽址琍RINT_MACRO使用了這個(gè)思想,##用以連接宏參數(shù)和其他的字符,例如如果有宏
1
|
#defineMEMBER(name) m_##name;
|
調(diào)用 MEMBER(Num) 你會(huì)得到 m_Num;
- 宏不能實(shí)現(xiàn)真正意義上的遞歸調(diào)用,例如:
1
|
#define Add(n) Add(n – 1) + n
|
調(diào)用Add(3),你將得到:Add(3 – 1) + 3,這恐怕不是你想要的。為了實(shí)現(xiàn)宏的遞歸調(diào)用必須像上面定義CALL_MACRO一樣一步步地遞歸。
- 我將宏分成了兩類:
(1)值宏,例如: #define __COMMA__ ,
(2)函數(shù)宏,例如CALL_MACRO。函數(shù)宏又分為兩種
I. 可調(diào)用宏,也就是可以作為其他宏的參數(shù)被調(diào)用,例如DEFINE_TEMPLATE_PARAM
II.不可調(diào)用宏,由于#和##的存在。例如: CALL_MACRO
- 定義一個(gè)宏時(shí)要注意的是:
(1).只將宏用在展開(kāi)代碼的時(shí)候。其他的功能用inline函數(shù)和模板代替吧。
(2).如果你在寫(xiě)一個(gè)可調(diào)用宏,對(duì)于傳入的函數(shù)宏,要讓它可以展開(kāi),值宏只能在最下層展開(kāi).比如逗號(hào),為了讓它只在最底層展開(kāi),你可以這樣來(lái)定義它:
.傳參時(shí),傳入_COMMA_,在最底層調(diào)用時(shí),用_COMMA_(1)
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號(hào)聯(lián)系: 360901061
您的支持是博主寫(xiě)作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對(duì)您有幫助就好】元
