c 模板元程式設計的一點體會

2022-07-06 23:30:24 字數 2628 閱讀 9719

趁著國慶長假快速翻了一遍傳說中的、大名鼎鼎的 modern c++ design,鈦合金狗眼頓時不保,已深深被其中各種模板奇技淫巧傷了身。。。論語言方面的深度,我看過的 c++ 書裡大概只有 insight c++ object model 能與之一戰吧?難怪 herb 老喜歡調侃 andrei 在模板方面是個可怕的傢伙,就從這本書的質量來看,andrei 當之無愧。

c++ 模板元程式設計的能量遠比第一眼印象裡所能想像得要強大,當然,這個結論並不明顯,很多時候人們也就拿模板當作減少重複**的工具簡單使用,很少有人會像寫 stl, boost, loki 那樣子正兒八經完全以模板為根基進行創作,個中原因是多樣的,乙個結果就是,模板的威力即使在很多 c++ 熟手的手下也不容易充分展現出來,當然,從工程的角度來講,這並非就是壞事,並不見得非得窮盡語言的高階特性,寫出讓人驚嘆的**才是好**,實戰中更多時候講究的是簡潔,易讀,好上手好維護這些基本原則,特別是當團隊中人員在語言水平上參差不齊時更是如此,杜甫的詩也許更工整嚴謹,但白居易的詩則顯然更老少皆宜,這個體會我是在閱讀 boost.proto 的**時得來的,好奇的讀者可以自行去了解一下,注意做好安全措施。

從語言特性上來說,模板元程式設計具備了乙個完備的程式語言所必需的一些基本結構,比如說,迴圈,分支,判斷等,當然,這些結構在模板中可能也不太明顯,例如迴圈,它的實現的關鍵在於使用遞迴,出口點在特化,typedef 和 enum 則可以當成是編譯時的變數,它們都能在編譯時遞迴式地依賴於別的模板,尤其是 enum, 甚至可以通過使用三元操作符(:?)實現編譯時判斷,而至於分支(if/else),它們的實現顯然就在於特化了。

以上的說辭可能有些虛無,下面以 loki 中光彩奪目的 typelist 為例簡單展示一下模板都能做些什麼。

typelist 是這樣乙個好東西,你可以把它看成是乙個鍊錶,該煉表中放的是型別,具體結構定義如下:

template struct typelist

;

head 是 typelist 中當前節點所儲存的 type, tail 是 typelist 中該節點之後的其它部分,可以看成是一般鍊錶中的 next 指標,怎麼判斷哪個節點是 typelist 的最後乙個節點呢?在一般鍊錶中,next 為空的節點是最後乙個節點,同理,在 typelist 中我們可以定義乙個空的結點:

struct nulltype

;

有了如上的定義,於是我們可以按如下樣子來使用 typelist 了:

typedef typelist>
但是上面的寫法怎麼看都很難用很彆扭,而且極端不美觀,在這個看臉的時代這樣怎麼行,所以 loki 定義了一大堆巨集來減輕使用者的負擔,看這裡,因為當時 c++ 的標準還不支援 variadic template parameter,這些巨集事實上是相當死板噁心的,但這也是沒法的事,不看它的實現就好了。

就這麼乙個簡單的結構,現在我們要讓它支援查詢,定位,插入,刪除等常規操作,是不是覺得有些為難甚至覺得不可能? 答案是這些操作都是可行的,比如說查詢,現在給定乙個如上定義的 typelist,怎麼判斷該 typelist 中是否存在某乙個特定型別呢?答案如下,其它的操作本質上差不多,有興趣的讀者可自行挑戰一下,這裡就不在囉嗦:

templatestruct indexof;

// 當搜尋空的 typelist 時,結果為 -1.

template<>

struct indexof;

};// 當前節點的型別為所想要搜尋的型別時

templatestruct indexof, t>;};

// 當前節點不是所查詢的型別時,遞迴地在 tail 中進行查詢。

templatestruct indexof, t>;

// 使用三元操作符進行判斷,t 是否在 tail 中存在。

enum ;

};

從上面的例子我們可以看到,因為 c++ 支援對模板遞迴式的解析(也就是乙個模板依賴於另乙個模板時,先解釋被依賴的模板),尤其是 template template parameter,使得模板事實上有了很強的編譯時執行的能力,這種能力表面上看起來可能不容易操控,但卻顯然是潛力無窮的,不過它的缺點也比較明顯:

編譯時**與執行時**攪在一起,在處理複雜問題時,程式的邏輯可能不容易讀懂。

編譯時除錯現階段的支援還不夠好,錯誤資訊異常地冗餘而且不精確。

網路上關於 c++ 模板元程式設計的討論有很多,模板的各種能力技巧也漸漸被越來越多的人所發現所挖掘,但是在實際的工作中,對很多人來說模板元程式設計卻仍一直處於比較保守的階段,說到底過分依賴模板元程式設計所帶來的缺點還是太明顯,就我粗陋的見聞來說,完全基於模板元程式設計做出來的比較出名的工具型的東西,主要有幾個(都來自 boost):boost spirit,boost proto 及 boost mpl,東西都非常非常棒,但使用的體驗嘛,老實說都不是很好。。。特別是 spirit。而至於它們的實現,對有興趣練習深入這方面技能的程式猿來說,這兩者倒確實是不可多得好素材,尤其是 proto, 代表了乙個高峰。

好訊息是,伴隨著 c++11 的到來,好些眾人期盼以久的新特性終於從理想照進現實,尤其是 variadic parameter 的加入,可以預見將再度大大提公升模板的能力,c++ 標準沉寂近10年後迎來了乙個新時期,甚至還有人曾經提議要加入 static_if,concept 等概念也在醞釀中了,變化是唯一永恆不變的東西,你,作好準備了嗎?

c語言的一點體會

最近在寫乙個windows平台的客戶段通訊程式。在我們領導的指導下寫的。我們領導是乙個有著20多年c語言經驗的老手。經他指點獲益良多。記錄一下,免得忘記。1.字元函式 strcpy 一般禁用。strncpy 驗證可用 sprintf 等同printf 2.記憶體函式 memcpy memcmp me...

一點小體會

最近一段時間3個工作周的封閉開發。比較累,也從原來的按時間工作改變為按量工作。工作量完不成得加班完成。在 這一塊體會比較多的 1 寫好注釋,不要太多,能表達清楚意思就行。2 在動手寫 之前,花時間想清楚自己的思路,以及自己準備在什麼地方做改動。要考慮周全,嚴謹,簡單。如果改動步數過多,該思考一下是否...

Session的一點體會

一直以來,沒有怎麼去好好研究session。只是大概知道用session來記錄會話狀態,知道瀏覽器關閉後session會丟失,知道伺服器端會記錄session,知道伺服器重啟有時會引起session丟失。僅此而以!後來發現的問題 一是如果用乙個瀏覽器不同的標籤卡來進行登入操作,那麼最後一次登入的會話...