基于顯示管理重載集的C++靜態(tài)分派研究_第1頁
基于顯示管理重載集的C++靜態(tài)分派研究_第2頁
基于顯示管理重載集的C++靜態(tài)分派研究_第3頁
基于顯示管理重載集的C++靜態(tài)分派研究_第4頁
基于顯示管理重載集的C++靜態(tài)分派研究_第5頁
已閱讀5頁,還剩12頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

1、 基于顯示管理重載集的C+靜態(tài)分派研究 唐新國(guó)周天宏Summary在C+系統(tǒng)中有靜態(tài)分派編程技術(shù)和動(dòng)態(tài)分派編程技術(shù),將一些執(zhí)行期的分派提前至編譯期,可以減少了編譯后的代碼長(zhǎng)度也提高了程序總體運(yùn)行速度.分析了引入靜態(tài)分派技術(shù)的必要性以及常用的靜態(tài)分派技術(shù),提出了通過使用Boost庫中的enable_if模板族來非侵入地(nonintrusively)顯示管理模板函數(shù)的重載集的方式來實(shí)現(xiàn)C+中靜態(tài)分派編程技術(shù),不但提出了一種新的靜態(tài)分派思路,更為重要的是通過這種方式可以根據(jù)模板函數(shù)的返回值來重載模板函數(shù).Key靜態(tài)分派動(dòng)態(tài)分派模板元編程模板特化TP311A10002537(2015)0500700

2、6A Static Dispatching Technique in C+ withExplicitly Managing the Overload SetTANG Xinguo1*, ZHOU Tianhong2(1.Information Technology School, Hubei Polytechnic Institute, Xiaogan 432100, China;2.Department of Information Engineering, Wuhan Business University, Wuhan 430056, China)AbstractIn C+, there

3、 exists static dispatching technique and dynamic dispatching technique. Moving some dispatching at run time up to compiling time can reduce length of complied code and improve the overall running speed. The necessity of introducing static dispatching technique and those used commonly was analyzed, a

4、nd then a way to realize static dispatching technique was presented by using enable_if template group in Boost library nonintrusively explicitly to manage the overloaded set of template functions. More importantly, in this way, one could overload template functions by their return values.Key wordsst

5、atic dispatching; dynamic dispatching; metaprogramming; template specialization模板元編程(Metaprogramming)指的是高階編程1,它運(yùn)行在編譯期.作為一種高階C+編程技術(shù),C+強(qiáng)大的模板機(jī)制賦予了模板在編譯期的運(yùn)算能力,模板元編程突出了編譯期在整個(gè)程序構(gòu)建和運(yùn)行過程中的地位,努力將計(jì)算從運(yùn)行期提前至編譯期,它既能有效地防止程序錯(cuò)誤被傳播到運(yùn)行期,又能夠?qū)崿F(xiàn)以靜態(tài)代碼控制動(dòng)態(tài)代碼的目標(biāo),使計(jì)算盡可能完成于編譯期的同時(shí)也提高了最終程序的運(yùn)行性能.MPL1(MetaProgramming Library)是由D

6、avid Abrahams和Aleksey Gurtovoy為方便模板元編程而開發(fā)的庫,2003年被Boost吸納為其中的一員,此后又歷經(jīng)一些重大修改,目前已經(jīng)相當(dāng)完善.MPL的出現(xiàn)是C+模板元編程發(fā)展中的一大創(chuàng)舉,它提供了一個(gè)通用、高層次的編程框架,包括了序列、迭代器、算法、元函數(shù)等組件,具有高度的可重用性,提高了模板元編程的效率,使模板元編程的應(yīng)用范圍得到相當(dāng)?shù)臄U(kuò)展.C+模板元編程誕生于十多年前,最初的研究方向是編譯期數(shù)值計(jì)算,后來的實(shí)踐發(fā)展證明,此項(xiàng)技術(shù)在類型計(jì)算領(lǐng)域也可以釋放出巨大能量.現(xiàn)在模板元編程主要用于:數(shù)據(jù)計(jì)算、解開循環(huán)、類型處理和自動(dòng)代碼生成.模板元編程技術(shù)有兩個(gè)強(qiáng)大的優(yōu)勢(shì).

7、首先它使得用其他方法很難或不可能的事情變得容易.第二因?yàn)?template metaprograms(模板元程序)在 C+ 編譯期間執(zhí)行,它們能將工作從運(yùn)行時(shí)轉(zhuǎn)移到編譯時(shí).一個(gè)結(jié)果就是通常在運(yùn)行時(shí)才能被察覺的錯(cuò)誤能夠在編譯期間被發(fā)現(xiàn).另一個(gè)結(jié)果是 C+ 程序使得 TMP 的使用在以下每一個(gè)方面都能更有效率:更小的可執(zhí)行代碼,更短的運(yùn)行時(shí)間,更少的內(nèi)存需求.靜態(tài)分派技術(shù)就是通過一些基于編譯期計(jì)算出來的結(jié)果來選擇不同的運(yùn)行期行為或接口的程序設(shè)計(jì)方式,該技術(shù)能將一些執(zhí)行期的分派提前至編譯期,從而減少了編譯后的代碼長(zhǎng)度,也提高了程序總體運(yùn)行速度.在C+的著名Loki庫中是通過一種將“數(shù)值轉(zhuǎn)換成型別”(

8、Int2Type)2的技術(shù)來實(shí)現(xiàn)的.當(dāng)然在C+中實(shí)現(xiàn)靜態(tài)分派技術(shù)的方法很多,如:模板函數(shù)的重載、類模板特化等等,本文是通過使用Boost庫中的enable_if模板族來非侵入地(nonintrusively)顯示管理模板函數(shù)的重載集的方式來實(shí)現(xiàn)C+中靜態(tài)分派技術(shù),不但提出了一種新的靜態(tài)分派思路,更為重要的是通過這種方式可以根據(jù)模板函數(shù)的返回值來重載模板函數(shù).湖南師范大學(xué)自然科學(xué)學(xué)報(bào)第38卷第5期唐新國(guó)等:基于顯示管理重載集的C+靜態(tài)分派研究1C+的靜態(tài)分派1.1C+的靜態(tài)分派的介紹 在C+中可以通過一些基于編譯期計(jì)算出來的結(jié)果來選擇不同的運(yùn)行期行為或接口的程序設(shè)計(jì)方式稱為靜態(tài)分派(static

9、 dispatching).事實(shí)上在C+程序設(shè)計(jì)中經(jīng)常使用的是執(zhí)行期進(jìn)行分派(dispatching),執(zhí)行期進(jìn)行分派通常是使用ifelse或switch語句來實(shí)現(xiàn)的.大部分情況下其執(zhí)行期的成本是微不足道的,然而有時(shí)還是無法常常這么做,因?yàn)閕felse或switch語句要求每一個(gè)語句分支都要能夠得到編譯成功,即使該條件在編譯期就知道了.例如設(shè)計(jì)一個(gè)泛型容器NiftyContainer,它將元素類型參數(shù)化2:templateclass Tclass NiftyContainer;由于NiftyContainer是泛型容器,那么它即可以包括類型為T的對(duì)象引用,也可以包括指向類型為T的對(duì)象指針.如果

10、要復(fù)制泛型容器NiftyContainer中的某個(gè)元素,可以調(diào)用其copy構(gòu)造函數(shù)(針對(duì)nonpolymorphic類型)或調(diào)用其虛函數(shù)Clone()(針對(duì)polymorphic類型).具體設(shè)計(jì)如下:templateclass T,bool isPolymorphicclass NiftyContainervoid DoSomething()T*pSomeObj=;if(isPolymorphic)T* pNewObj=pSomeObjClone();polymorphic algorithm(多態(tài)算法)elseT* pNewObj=new T(*pSomeObj);/調(diào)用copy構(gòu)造函數(shù)no

11、npolymorphic algorithm(非多態(tài)算法);上述算法表面上看沒有問題,但實(shí)際上任何一款C+編譯器都不會(huì)使之僥幸編譯通過.因?yàn)榫幾g器會(huì)編譯每一個(gè)語句分支,如果多態(tài)算法使用pSomeObjClone(),那么對(duì)任何一個(gè)沒有定義成員函數(shù)Clone()的類型,編譯器都會(huì)停留在語句pSomeObjClone()處告之編譯通不過.當(dāng)然對(duì)nonpolymorphic類型也有可能編譯失敗,因?yàn)橛行╊愋蜁?huì)將copy構(gòu)造函數(shù)置于private區(qū)域.1.2C+的靜態(tài)分派的設(shè)計(jì)方式在上面的執(zhí)行期分派算法中,如果可以讓編譯器不編譯那個(gè)不可能被執(zhí)行的代碼段為好,例如可以將運(yùn)行期測(cè)試換成相應(yīng)的編譯期測(cè)試,C

12、+中靜態(tài)分派的設(shè)計(jì)方式通常是3:template class Tvoid f(T x)if(boost:is_classT:value)implementation 1elseimplementation 2由于測(cè)試條件boost:is_classT:value可以完全地在編譯期決定,所以很多C+編譯器會(huì)對(duì)測(cè)試條件boost:is_classT:value進(jìn)行優(yōu)化,并僅為選擇了的if語句分支生成代碼.這種方式簡(jiǎn)單清晰,只要它能工作,其概念上的開銷就非常小甚至沒有,實(shí)際上這種靜態(tài)分派的設(shè)計(jì)方法也并非普遍適應(yīng).1.3C+靜態(tài)分派的不足考慮上面的函數(shù)模板被實(shí)現(xiàn)為下面的樣子時(shí)會(huì)發(fā)生什么4:templa

13、te class Tvoid f(T x)if(boost:is_classT:value)std:coutx:value;/處理整型常量外覆器elsestd:coutx; /處理非整型常量外覆器這里的意圖是使函數(shù)模板f能夠輸出一個(gè)整數(shù)類型(如int)的值或者一個(gè)整型常量外覆器(如long_5)的值.然而函數(shù)調(diào)用f(42)就會(huì)得到一個(gè)編譯錯(cuò)誤,問題仍然與執(zhí)行期進(jìn)行分派一樣,在于整個(gè)函數(shù)都需要進(jìn)行類型檢查,包括if語句的全部分支,但我們無法訪問整數(shù)類型int的根本不存在的:value成員,這同樣也出現(xiàn)了運(yùn)行期分派的缺點(diǎn).采用模板函數(shù)的重載11、類模板特化12等方法可解決上述問題,關(guān)鍵是將每一個(gè)分

14、支單獨(dú)寫成一個(gè)獨(dú)立的代碼段.采用顯示管理重載集的方法來解決C+的靜態(tài)分派問題.2基于顯式管理重載集對(duì)C+靜態(tài)分派設(shè)計(jì)方式的改進(jìn)2.1顯示管理重載集的原理在C+中,常常使用CRTP13(奇特的遞歸模板模式)來識(shí)別管理重載集,但有時(shí)CRTP對(duì)于限制一般化的函數(shù)模板實(shí)參的范圍是很不夠的.比如我們可能希望通過函數(shù)模板操作內(nèi)建類型(它們沒有基類)或者操作已有的第三方類型(不能修改它們).這時(shí)就可以使用Boost庫中的enable_if模板族14來非侵入地(nonintrusively)顯示管理模板函數(shù)的重載集,在編譯期決定一個(gè)參數(shù)類型的適當(dāng)性.Boost庫中的enable_if模板族的工作原理為:tem

15、platebool,class T=voidstruct enable_if_ctypedef T type;templateclass T struct enable_if_cfalse,T;templateclass Cond,class T=voidstruct enable_if:enable_if_cCond:value,T;注意:當(dāng)C的值為false時(shí),enable_if_cC,T:type不存在,根據(jù)C+標(biāo)準(zhǔn)的重載決議規(guī)則,當(dāng)一個(gè)函數(shù)模板的實(shí)參推導(dǎo)失敗時(shí),它對(duì)被考慮準(zhǔn)備調(diào)用的候選函數(shù)集沒有貢獻(xiàn),并且不會(huì)導(dǎo)致一個(gè)錯(cuò)誤.這個(gè)原則已經(jīng)被David Vandevoorde和Nicolai

16、 Josuttis賦予“替換失敗并非錯(cuò)誤(Substitution Failure Not An Error,SFINAE)”的名號(hào)15.2.2C+靜態(tài)分派設(shè)計(jì)方式的改進(jìn)重載集有時(shí)也能進(jìn)行靜態(tài)分派,如果能在編譯期就能決定一個(gè)參數(shù)類型的適當(dāng)性,則可用Boost的enable_if模板非侵入地(nonintrusively)顯式管理重載集,從而達(dá)到靜態(tài)分派的目的.用C+的顯示管理重載集方式來實(shí)現(xiàn)靜態(tài)分派問題.首先對(duì)模板函數(shù)template class Tvoid f(T x)if(boost:is_classT:value)std:coutx:value;/處理整型常量外覆器elsestd:cou

17、tx; /處理非整型常量外覆器進(jìn)行改進(jìn).重新設(shè)計(jì)后的代碼為:templateclass Ttypename boost:enable_iftypename boost:is_classT:type:typeprint(T x)std:coutT:valuestd:endl;templateclass Ttypename boost:enable_iftypename mpl:not_boost:is_classT :type:typeprint(T x)std:coutxstd:endl;這樣print(42)和print(mpl:int_56()將訪問不同的模板函數(shù),只有匹配的那個(gè)模板函數(shù)才

18、能實(shí)例化且不會(huì)出現(xiàn)編譯錯(cuò)誤.其次應(yīng)用C+的顯示管理重載集方式來重新實(shí)現(xiàn)C+標(biāo)準(zhǔn)程序庫中的advance泛型算法.advance泛型算法5就是一個(gè)使用標(biāo)簽分派的極好例子,advance用來將一個(gè)迭代器i移動(dòng)n個(gè)位置,對(duì)不同類型的迭代器i實(shí)現(xiàn)的策略是不同的.如果i是隨機(jī)迭代器,則可用i+=n來實(shí)現(xiàn).如果i是雙向迭代器,可以在運(yùn)行期決定是否遞增或遞減迭代器;如果i是前向迭代器,則只能是向前步進(jìn)多步.通過編譯期的標(biāo)簽分派也可能達(dá)到靜態(tài)分派,它的基本思想是從運(yùn)行期的泛型編程借用而來.一個(gè)標(biāo)簽(tag)僅僅是一個(gè)空類6(empty class),其唯一的用途就是在編譯期傳達(dá)信息.那么改進(jìn)后的代碼為:tem

19、plateclass Iterator,class Distancetypename boost:enable_iftypename boost:is_samestd:input_iterator_tag,/i是前向迭代器typename std:iterator_traitsIterator:iterator_category:type:typeadvance(Iterator& i,Distance n)while(n-)+i;templateclass Iterator,class Distancetypename boost:enable_iftypename boost:is_sam

20、estd:bidirectional_iterator_tag,/ i是雙向迭代器typename std:iterator_traitsIterator:iterator_category:type:typeadvance(Iterator& i,Distance n)if(n=0)while(n-)+i;elsewhile(n+)-i;templateclass Iterator,class Distancetypename boost:enable_iftypename boost:is_samestd:random_access_iterator_tag,/ i是隨機(jī)迭代器typena

21、me std:iterator_traitsIterator:iterator_category:type:typeadvance(Iterator& i,Distance n)i+=n; 對(duì)于:advance(i,4)調(diào)用,同樣會(huì)根據(jù)迭代器i的類型來選擇一個(gè)合適的模板函數(shù),達(dá)到迭代器i的遞增,其他可能使用一個(gè)給定的迭代器所未實(shí)現(xiàn)的重載則永遠(yuǎn)不會(huì)被實(shí)例化.從以上實(shí)例過程來看:通過C+的顯示管理重載集方式來實(shí)現(xiàn)靜態(tài)分派問題就是將每一個(gè)可能的分支轉(zhuǎn)換成一個(gè)重載的模板函數(shù).2.3應(yīng)用拓展利用Boost庫中的enable_if模板族來非侵入地(nonintrusively)顯示管理模板函數(shù)的重載集實(shí)現(xiàn)

22、C+的靜態(tài)分派問題時(shí),同時(shí)也是根據(jù)模板函數(shù)的返回值來實(shí)現(xiàn)模板函數(shù)重載的過程.下面的函數(shù)模板僅應(yīng)用于算術(shù)類型的迭代器上并將容器中所有元素之和求出,通過元函數(shù)7boost:iterator_value來獲取一個(gè)迭代器的value_type.templateclass Iteratortypename boost:enable_ifboost:is_arithmetic/啟用條件typename boost:iterator_valueIterator:type,typenameboost:iterator_valueIterator:type/返回類型:typesum(Iterator start

23、,Iterator end)typename boost:iterator_valueIterator:type x(0);for(;start!=end;+start)x+=*start;return x;如果啟用條件C的:value為true,enable_ifC,T:type將為T,于是sum將返回一個(gè)“Iterator的value_type”的對(duì)象.否則sum將從重載決議過程中消失8.當(dāng)有模板函數(shù)重載發(fā)揮作用時(shí),這項(xiàng)技術(shù)就變得真正有趣起來.因?yàn)樯鲜瞿0錽um已經(jīng)根據(jù)它返回值被限制為(接收)適當(dāng)?shù)膮?shù),現(xiàn)在可以添加另一個(gè)重載,它允許我們計(jì)算出vectorvectorint的所有算術(shù)元素,

24、以及其他算術(shù)類型的嵌套的容器.templateclass Iteratorstruct inner_value:boost:iterator_valuetypename boost:iterator_valueIterator:type:iterator;templateclass Iteratortypename boost:lazy_disable_ifboost:is_arithmetic/禁用條件typename boost:iterator_valueIterator:type,inner_valueIterator/結(jié)果無函數(shù):typesum(Iterator start,Iter

25、ator end)typename inner_valueIterator:type x(0);for(;start!=end;+start)x+=sum(startbegin(),startend();return x;Lazy_disable_if的“disable”指出當(dāng)條件被滿足時(shí),該函數(shù)被從重載集中移走了,“l(fā)azy”則意味著函數(shù)的結(jié)果:type是以一個(gè)無參元函數(shù)調(diào)用第二個(gè)參數(shù)的結(jié)果9.注意,只有當(dāng)?shù)鞯闹殿愋褪橇硪粋€(gè)迭代器時(shí),inner_valueIterator才能被調(diào)用,這時(shí)sum(Iterator start,Iterator end)會(huì)調(diào)用第二個(gè)模板函數(shù).當(dāng)?shù)鞯闹殿愋?/p>

26、是算術(shù)類型時(shí),sum(Iterator start,Iterator end)會(huì)調(diào)用第一個(gè)模板函數(shù).對(duì)于其他類型的實(shí)參,當(dāng)發(fā)生實(shí)參推導(dǎo)失敗時(shí),那么在重載決議期間它對(duì)考慮準(zhǔn)備調(diào)用的候選函數(shù)集沒有貢獻(xiàn)10,這時(shí)并不會(huì)發(fā)生錯(cuò)誤,這個(gè)過程當(dāng)然也可以看成是根據(jù)模板函數(shù)的返回值來實(shí)現(xiàn)模板函數(shù)重載的過程.3結(jié)束語模板元編程是C+中一種高級(jí)編程技術(shù),它處于編譯期,靜態(tài)分派技術(shù)是基于編譯期計(jì)算出來的結(jié)果來選擇不同的運(yùn)行期行為或接口的程序設(shè)計(jì)方式,這種技術(shù)能將一些執(zhí)行期的分派提前至編譯期,從而減少了編譯后的代碼長(zhǎng)度,也提高了程序總體運(yùn)行速度.這里則是通過使用Boost庫中的enable_if模板族來非侵入地(nonintrusively)顯示管理模板函數(shù)的重載集的方式來實(shí)現(xiàn)C+中靜態(tài)分派技術(shù),提出了一種新的靜態(tài)分派思路,通過這種方式可以根據(jù)

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論