模版的實現原理

2021-10-05 02:10:47 字數 1826 閱讀 7717

首先 注意區分兩個概念:

類模版 和模版類

函式模版 和 模版函式

類/函式模版 是家族 ,模版類/函式 是家族的乙個成員。

c++中類模板的宣告格式為template<模板形參表宣告><類宣告>,並且類模板的成員函式都是模板函式

什麼是非型別模版引數:就是傳來的引數 可以當作實參使用。

注意:浮點數、類物件以及字串是不允許作為非型別模板引數的。

非型別的模板引數必須在編譯期就能確認結果。

首先來看乙個例子:

template int func1()

int func2(int n)

你能看出這兩個函式的區別在**嗎?

它們的區別就在於,func1的引數是編譯期指定,如func1<0>() ;而func2的引數則是執行期指定。

特性一:: 這正體現了模板的特性或者說是它的技術核心,就是編譯期的動態機制,這種機制使程式在執行期具有更大的效率優勢。

到此你是不是對本文開頭那段**有了更深入的理解了呢?

特劃分為 : 全特化 、半特化

半特化可以只是簡單的特化 ,也可以說對型別的限制。 外部傳t 等,內部用 *t & t 等。

特性 二:如果乙個模板沒有被特化,那麼編譯器根本不會去理會它,也就是說模板內的**被隱藏了

------後邊跟著乙個具體的函式
這是乙個函式模板:template func(t param) {}

函式模板的模板引數是隱式的,編譯器會自動根據傳入值的型別來確定模板引數的型別。因此函式模板的模板引數不能有預設值

這是乙個類模板:template class myclass {};

------後邊跟著乙個具體的類
類模版的模板引數是顯式的,**使用乙個模板類時必須指明其模板引數,**因此類模板的模板引數可以有預設值。

我們還可以做更多的事情,比如myclass可以派生自t(xtp介面庫就是這麼做的),在myclass內部可以使用關於t的enum、typedef等等。這些將在下文一一談到。

(我在這裡提出乙個建議,建立乙個類模板,請記得第一件事就是對模板引數進行typedef定義。)

模板最有價值的地方就是它的部分特化,也是應用最廣泛的特性。

所謂「部分特化」也就是說,乙個模板有多個引數,但我們只對其中一部分引數進行特化,或者是只針對常量模板引數的某種情況進行特化。

編譯期assert

這是對bool型模板引數部分特化的乙個例子。最簡單的實現:

template struct compiletimeassert;

template<> struct compiletimeassert {};

當我們將乙個表示式作為模板引數,而這個表示式的值為false時,編譯器就找不到合適的實現,便會報錯了

事實是編譯期可用的表示式或函式(如sizeof)數量上並不多。

【優點】

模板復用了**,節省資源,更快的迭代開發,c++的標準模板庫(stl)因此而產生

增強了**的靈活性

【缺陷】

3. 模板會導致**膨脹問題,也會導致編譯時間變長

4. 出現模板編譯錯誤時,錯誤資訊非常凌亂,不易定位錯誤

容斥原理的二進位制實現模版

最近學習容斥原理,實現容斥原理大致有三種方法 dfs,佇列陣列,二進位制。今天主要講下二進位制實現容斥原理 有乙個集合,求集合的子集?很顯然答案為 也就是2 n個,也就是每乙個子集有唯一標誌符 i 0 看下面的 1 include2 include3 include4 include5 includ...

康托展開的公式(模版原理)

康托展開的公式是 x an n 1 an 1 n 2 ai i 1 a2 1 a1 0 其中,ai為當前未出現的元素中是排在第幾個 從0開始 這個公式可能看著讓人頭大,最好舉個例子來說明一下。例如,有乙個陣列 s a b c d 它的乙個排列 s1 d b a c 現在要把 s1 對映成 x。n 指...

通用後台模版的實現

最近溫故了部分j aweb的知識,加之好久不寫 就想利用本次機會,做過乙個通用的後台管理 系統簡介 前端,基於bootstrap的免費後台框架cloud admin 資料庫 mysql 技術 jsp spring hibernate 說明 本系統本次,主要目的是實現功能,系統本身並沒有進行優化,僅僅...