首先 注意區分兩個概念:
類模版 和模版類
函式模版 和 模版函式
類/函式模版 是家族 ,模版類/函式 是家族的乙個成員。
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 說明 本系統本次,主要目的是實現功能,系統本身並沒有進行優化,僅僅...