想要學好c++的話,或是想要真正了解c++中的精髓和本質的話,c++中的stl, template ,演算法都是必須要精通的。
從今天來開始學習c++中的模板,參考和摘錄的書籍是《c++ template 中文版》 和 《boost 程式庫探秘——深度解析c++標準庫》(作者很喜歡笑,新技能get....)(笑)
1.基本概念
1.1 模板元程式設計(template meta-programing ):通常稱之為元程式設計,是c++在發展的過程中從泛型程式設計衍生出的最複雜、最強大和最具威力的一種。
1.2元程式:遠程式 metaprogram , 本質上是 a program about a program , 與普通程式所不同的是, 是用來規定、描述普通程式編寫方式, 一種位於普通程式之上超越普通程式的程式,是一種可以操控、產生程式的程式。並且可以這麼說模板程式設計本質上是泛型程式設計的乙個子集,也可以這麼說在**的編寫方式中,所有使用template 的泛型**都可以統稱為元程式,因為泛型**不是真正可以編譯直接生成可執行程式的**; 泛型**僅僅定義了普通**(可以生成可執行程式完成相應功能的**)的產生規則;泛型**是用來生成**的「模板」 。
1.3 模板元程式設計與泛型程式設計的不同之處:模板程式設計是一種「函式式程式設計」 ,< 所謂的函式式程式設計是一種程式設計的典範,是將電腦視為函式的計算。函式程式語言中最終要的是λ 演算(lambda calculus) ,而且 演算的函式可以接受函式當做輸入(引數) 和輸出(返回值)也可以函式的規定。 與函式式程式設計相對應的是 命令式程式設計,和過程化程式設計, 與命令式程式設計相比較,函式式程式設計更加強調的是計算比指令的執行更加的重要。 而與過程化程式設計相比較,在函式式的程式設計裡面, 函式的計算是可以隨時呼叫的。>
並且這種「函式式程式設計」已經被證明是圖靈完備的《什麼是圖靈完備的呢? 所謂的圖靈完備的,指的就是一切可計算的問題都能夠計算,這樣的虛擬機器或者是程式語言就叫做圖靈完備的》。
1.4 模板元程式設計執行時期:模板元程式設計的執行是在編譯期,模板元會將編譯器變成元程式的直譯器。 《什麼叫做編譯期? 所謂的編譯期所指的就是: 利用編譯程式即編譯器從源語言編寫的源程式中來生成目標程式的過程,後續的操作就是將目標程式通過連線的方式對其進行連線生成可執行的程式。> 也可以這麼說,模板元程式設計產生的元程式是在編譯期執行的程式,元程式所操縱的物件也不是普通的變數,因此在元程式中是不能夠使用執行時的c++中的關鍵字的( 比如說 if ,else , for ), 可用的語法元素也是十分有限的。
1.5 模板元程式設計中最常用的關鍵字有:
enum, static ,這兩個關鍵字是用來定義編譯期的整數常量的
typedef , 這個關鍵字是用來定義元資料的,是元程式設計中最為重要的關鍵字
template , 這個事模板元程式設計的「起點」 , 主要用於定義元函式;
"::" , 這個是域運算子,用於解析型別作用域獲取計算結果(元資料) 。
1.6 元資料 :所謂的元資料指的就是元程式設計中可以操作的資料物件就是「元資料」 (meta data ) , 有因為模板元程式設計的執行時期是在系統的編譯期,所以對元資料操作的時期就是編譯時期,也就是c++編譯期在編譯時期來對元資料進行操控的,元資料是元程式設計的基礎。元資料都是不可變的。在模板元程式設計中的元資料更多的是以型別(type)的面目來出現的。 這些元資料並不是普通的執行時期的變數, 而是如 int , double . class(非模板類)這樣的抽象資料型別----這是模板元程式設計與普通執行時期程式設計的最根本的乙個不同點。
元資料還可以對其進行進一步的分類: 整數元資料, 值型元資料,函式元資料,類元資料(class 、struct等使用者自定義型別)。
1.7 元函式 :所謂的元函式指的是模板元程式設計中用於操作處理元資料的「構件」,元函式的呼叫是在編譯時期,因為其功能和形式類似執行時的的函式而得名, 元函式是元程式設計中最為重要的構件。
下面是元函式中乙個簡單的小例子:
template struct meta_function
;
編寫元函式就像是編寫乙個普通的執行時的函式,但是它的形式上確實乙個模板類:
函式引數列表從普通函式的圓括號程式設計了對應的尖括號<> , 函式的形參變成了模板引數(即上面我們所討論的元資料) ;因為在元程式設計的時候是不能夠使用執行時的關鍵字的,所以元函式不能像普通函式那樣來使用 return 來返回相應的結果,那麼應該如何定義可以返回數值的模板函式呢? 可以在元函式(模板類)的內部使用typedef 來定義乙個名為type 型別(type 也是元資料)或者是名為value 的數值作為返回值。
當然還需要注意的是,元函式在定義之後要通過分號來結束,因為元函式在本質上(即對於編譯器來說)是c++ 中的乙個類。
2. 元函式例子
#include templatestruct meta_func1
;
上面的**是乙個使用boost的最一般的元函式**,它的作用是計算兩個整數的和,在這裡需要注意的就是元函式 meta_func1<> 的執行過程,它的計算在編譯期的時候就已經計算結束了,(在這裡涉及到了模板例項化的知識),這樣的話實際程式在執行的時候並沒有計算動作而是直接得到接過來,就像是離線計算或是通常使用的打表的計算方法,將計算移動到了編譯時期而不是執行時期來執行,這樣的話就會節省執行時期所占用的時間。如果在乙個大型的工程中,編譯時期節約的計算的工作量就會相當可觀。
同樣,因為元程式是執行在編譯時期的,所以下述的**會引發錯誤。
int i = 10 , j = 10 ;
meta_func1::value ;
下面的**例子的是另乙個元函式,它會返回元函式引數中的第乙個元資料:
templatestruct select1st
;
返回值的規定是通過 type 來修飾的t1 來實現的。
3. 元函式的**
模板元程式設計中的元函式的**相當於執行時期的函式**呼叫,但是在模板元程式設計過程中需要通過public 對應的派生來實現,模板引數傳遞給父類完成元函式的呼叫這樣子類會獲得父類的::type的定義,也就通過這種方式來完成了元函式的返回,就像是下面的例子所示,將元資料進行位置互換之後**給之前定義的select1st<> , 就相當於下面select2nd<> 這段**的功能:
templatestruct forward
;
C 中的模板學習筆記2
繼續昨天的學習,今天將要介紹的是,自己實現乙個stack的模板,然後在程式中例項化該模板,呼叫這個模板,以及使用模板函式優越性能的原因 1.乙個stack 模板的例子 include include template class stack template void stack push t co...
「模板」學習筆記(1) 引出模板
c 中引出模板的原因 我們大家都知道,c 給我們提供了眾多的資料型別,比如說整型 浮點型 雙精度型 布林型等等。而且c 還為我們提供了一種函式過載的方式,即函式名相同,但是型別不同,那麼也可以被c 編譯器所認識到,進而可以輸出不同的結果。下面,我們以乙個程式為例來說明 include using n...
C 學習筆記(8) 模板
模板主要是提供一種處理方式,相當於加強版的函式處理,裡面的引數型別,處理方式都能夠被模板化,傳統的函式處理是不能夠針對多種處理方式的,所以會出現函式的過載問題。模板主要包括兩個方面 針對函式的模板,格式 template 函式返回值 函式名稱 函式引數 例如template void swap t ...