隨著C++語言的發(fā)展,越來越多的C++類庫都使用模板庫提供給大家使用。模板庫通常使用基于對象的設(shè)計,相比傳統(tǒng)的面向?qū)ο蟮脑O(shè)計而言,前者的每個模塊可以單獨使用,而不依賴框架。整個模板庫的框架,只是一個膠水層,讓各個組件之間按照某種協(xié)議,組合到一起,形散而神不散,發(fā)揮出強大的功能。而且模板庫非常好擴展。模板庫的擴展通常有以下三種模式:
由于前兩種方式比較簡單,還要就是沒有找到比較好的素材,鄙文暫時主要討論第三種擴展方式。在實現(xiàn)iguana的過程中,我們發(fā)現(xiàn)模板特化和宏的結(jié)合,在碰到命名空間的時候,我們一籌莫展。案例如下,
REFELCTION宏實質(zhì)上生成了一個在全局命名空間下的類模板的特化的代碼。但是由于宏是預(yù)處理階段,生成的代碼在client命名空間下。C++的語言規(guī)范不允許在一個命名空間中特化另一個命名空間的類模板,也不允許在一個命名空間下特化全局命名空間的類模板(全局的情況MSVC能編過,我是服氣的)。這里是一個參考鏈接。
那么我們庫中遇到的問題,用下列簡化的代碼給出,有興趣的讀者可以到各個編譯環(huán)境下測試。
其實這個限制并不是無解,只要你保證REFLEACTION宏在全局命名空間下,就不會出錯。例如BOOST_FUSION_ADAPT_STRUCT宏,也是用相同的方法規(guī)避的。但是你會發(fā)現(xiàn)這樣對使用來說非常不便,你偶爾不得不把一個完整的命名空間的代碼block拆成兩個。我們得找另外一種方法來擴展我們的模板庫,而不受限于命名空間。
什么樣的擴展方法,可以跨越命名空間的限制?仔細(xì)閱讀過template C++的讀者應(yīng)該不難發(fā)現(xiàn),就是函數(shù)的ADL查找。我們用如下代碼來說明,如何利用函數(shù)的ADL查找
簡單解釋一下,下面的代碼是如何工作的。首先,函數(shù)的ADL查找,是apply函數(shù)嘗試調(diào)用to_extend的時候,不僅會查找lib命名空間下的符號,也會去查找T類型所在命名空間的符號。我們定義的to_extend函數(shù)在client命名空間下,foo類型也在client命名空間下。那么ADL查找肯定可以找到to_extend函數(shù)的符號。然后,我們沒有選擇類模板的特化,而是選擇了使用to_extend函數(shù),返回一個它內(nèi)部定義的類型作為policy的功能。這個思想有點類似Andrei Alexandrescu大神的MDC中第11章節(jié)的Multimethod的蹦床函數(shù),trampoline funciton. 有了這些,我們就可以在任意命名空間下來擴展我們的模板庫,當(dāng)然配合宏使用也沒有問題了。在iguana中具體實現(xiàn)的小細(xì)節(jié),可以參考reflection.hpp里面的實現(xiàn)。
本站文章版權(quán)歸原作者及原出處所有 。內(nèi)容為作者個人觀點, 并不代表本站贊同其觀點和對其真實性負(fù)責(zé),本站只提供參考并不構(gòu)成任何投資及應(yīng)用建議。本站是一個個人學(xué)習(xí)交流的平臺,網(wǎng)站上部分文章為轉(zhuǎn)載,并不用于任何商業(yè)目的,我們已經(jīng)盡可能的對作者和來源進(jìn)行了通告,但是能力有限或疏忽,造成漏登,請及時聯(lián)系我們,我們將根據(jù)著作權(quán)人的要求,立即更正或者刪除有關(guān)內(nèi)容。本站擁有對此聲明的最終解釋權(quán)。