C 之 模板元程式設計(一)

2021-07-10 12:38:59 字數 4175 閱讀 1256

利用模板特化機制實現編譯期條件選擇結構,利用遞迴模板實現編譯期迴圈結構,模板元程式則由編譯器在編譯期解釋執行。

模板是c++支援引數化多型的工具,使用模板可以使使用者為類或者函式宣告一種一般模式,使得類中的某些資料成員或者成員函式的引數、返回值取得任意型別。

模板是一種對型別進行引數化的工具;

通常有兩種形式:函式模板類模板

函式模板針對僅引數型別不同的函式

類模板針對僅資料成員成員函式型別不同的類。

使用模板的目的就是能夠讓程式設計師編寫與型別無關的**。比如編寫了乙個交換兩個整型int 型別的swap函式,這個函式就只能實現int 型,對double,字元這些型別無法實現,要實現這些型別的交換就要重新編寫另乙個swap函式。使用模板的目的就是要讓這程式的實現與型別無關,比如乙個swap模板函式,即可以實現int 型,又可以實現double型的交換。模板可以應用於函式和類。下面分別介紹。

注意:模板的宣告或定義只能在全域性,命名空間或類範圍內進行。即不能在區域性範圍,函式內進行,比如不能在main函式中宣告或定義乙個模板。

template ...> 返回型別 函式名(引數列表)

其中template和class是關鍵字,class可以用typename 關鍵字代替,在這裡typename 和class沒區別。

<>括號中的引數叫模板形參,模板形參和函式形參很相像,模板形參不能為空。一但宣告了模板函式就可以在該函式中使用內建型別的地方都可以使用模板形參名。模板形參需要呼叫該模板函式時提供的模板實參來初始化模板形參,一旦編譯器確定了實際的模板實參型別就稱他例項化了函式模板的乙個例項。比如swap的模板函式形式為

template

void swap(t& a, t& b){}

當呼叫這樣的模板函式時型別t就會被被呼叫時的型別所代替,比如swap(a,b)其中a和b是int 型,這時模板函式swap中的形參t就會被int 所代替,模板函式就變為swap(int &a, int &b)。而當swap(c,d)其中c和d是double型別時,模板函式會被替換為swap(double &a, double &b),這樣就實現了函式的實現與型別無關的**。

注意:

對於函式模板而言不存在 h(int,int) 這樣的呼叫,不能在函式呼叫的引數中指定模板形參的型別,對函式模板的呼叫應使用實參推演來進行,即只能進行 h(2,3) 這樣的呼叫,或者int a, b; h(a,b)。

template

class 類名{

// 類定義...

};

類模板和函式模板都是以template開始後接模板形參列表組成,模板形參不能為空,一但宣告了類模板就可以用類模板的形參名宣告類中的成員變數和成員函式,即可以在類中使用內建型別的地方都可以使用模板形參名來宣告。比如

templatet> class a;
在類a中宣告了兩個型別為t的成員變數a和b,還宣告了乙個返回型別為t帶兩個引數型別為t的函式hy。

對於類模板,模板形參的型別必須在類名後的尖括號中明確指定。比如a<2> m;用這種方法把模板形參設定為int是錯誤的(編譯錯誤:error c2079: 'a' uses undefined class 'a'),類模板形參不存在實參推演的問題。也就是說不能把整型值2推演為int 型傳遞給模板形參。要把類模板形參調置為int 型必須這樣指定am

在類模板外部定義成員函式的方法為:

template《模板形參列表》 函式返回型別 類名《模板形參名》::函式名(引數列表)
比如有兩個模板形參t1,t2的類a中含有乙個void h()函式,則定義該函式的語法為:

templatet1,class

t2> void

a,t2>::h(){}

注意:當在類外面定義類的成員時template後面的模板形參應與要定義的類的模板形參一致。

其中,template 是宣告類模板的關鍵字,表示宣告乙個模板,模板引數可以是乙個,也可以是多個,可以是型別引數 ,也可以是非型別引數。型別引數由關鍵字 class或typename及其後面的識別符號構成。非型別引數由乙個普通引數構成,代表模板定義中的乙個常量。例:

template

type,int width>

//type為型別引數,width為非型別引數

class

graphics;

注意:

(1)如果在全域性域中宣告了與模板引數同名的變數,則該變數被隱藏掉。

(2)模板引數名不能被當作類模板定義中類成員的名字。

(3)同乙個模板引數名在模板參數列中只能出現一次。

(4)在不同的類模板或宣告中,模板引數名可以被重複使用。

通過將計算從執行期轉移至編譯期,在結果程式啟動之前做盡可能多的工作,最終獲得速度更快的程式。也就是說模板元程式設計的優勢在於:

1.以編譯耗時為代價換來卓越的執行期效能(一般用於為效能要求嚴格的數值計算換取更高的效能)。通常來說,乙個有意義的程式的執行次數(或服役時間)總是遠遠超過編譯次數(或編譯時間)。

2.提供編譯期型別計算,通常這才是模板元程式設計大放異彩的地方。

模板元程式設計技術並非都是優點:

1.**可讀性差,以類模板的方式描述演算法也許有點抽象。

2.除錯困難,元程式執行於編譯期,沒有用於單步跟蹤元程式執行的偵錯程式(用於設定斷點、察看資料等)。程式設計師可做的只能是等待編譯過程失敗,然後人工破譯編譯器傾瀉到螢幕上的錯誤資訊。

3.編譯時間長,通常帶有模板元程式的程式生成的**尺寸要比普通程式的大,

4.可移植性較差,對於模板元程式設計使用的高階模板特性,不同的編譯器的支援度不同。

模板元程式設計使用靜態c++語言成分,程式設計風格類似於函式式程式設計,在模板元程式設計中,主要操作整型(包括布林型別、字元型別、整數型別)常量和型別,不可以使用變數、賦值語句和迭代結構等。被操縱的實體也稱為元資料(metadata),所有元資料均可作為模板引數。

由於在模板元程式設計中不可以使用變數,我們只能使用typedef名字和整型常量。它們分別採用乙個型別和整數值進行初始化,之後不能再賦予新的型別或數值。如果需要新的型別或數值,必須引入新的typedef名字或常量。

// 主模板

template

struct fib;};

// 完全特化版

template <>

struct fib<1>;};

// 完全特化版

template <>

struct fib<0>;};

int main()

// 僅宣告

struct nil;

// 主模板

template

struct ispointer

; typedef nil valuetype;

};// 區域性特化

template

struct ispointer;

typedef t valuetype;

};// 示例

int main()

//主模板

template

struct staticassert;

// 完全特化

template

<>

struct staticassert

{};// 輔助巨集

#define static_assert(exp)\

int main()

[1]

[2]

[3]

C 之模板元程式設計

關於模板原程式設計知識強烈推薦 非常好!首先複述一下模板元程式設計,以下標紅或者加粗的地方是模板元程式設計的精髓 從程式設計范型 programming paradigm 上來說,c 模板是 函式式程式設計 functional programming 它的主要特點是 函式呼叫不產生任何 沒有可變的...

C 模板元程式設計

原理 模板元程式由編譯器在編譯期解釋執行,利用模板特化機制實現編譯期條件選擇結構,利用遞迴模板實現編譯期迴圈結構。模板元程式設計 metaprogramming 意思是,程式設計系統將會執行我們所寫的 來生成新的 而這些新 才真正實現了我們所期望的功能。元程式設計最大的特點在於 某些使用者自定義的計...

C 模板元程式設計

昨天wl發給我一段我覺得很 奇怪 的c 當時沒看太懂,後來問了才知道是叫做模板元程式設計。template struct binary template specialization struct binary 0 terminates recursion 覺得很新奇,於是乎索要了一本電子書,名為 ...