C 模板高階

2021-09-13 21:12:09 字數 4136 閱讀 4065

模板引數分為類型別形參和非型別形參。

類型別形參:出現在模板引數列表中,跟在class或者typename之後類的引數型別名稱。

非型別形參:用乙個常量作為類(函式)模板的乙個引數,在類(函式)模板中可將該引數當成常量來使用。

注意:

通常情況下,使用模板可以實現一些與型別無關的**,但一些特殊型別的可能會得到一些錯誤的結果,此時,就需要對模板進行特化。即:在原模板類的基礎上,針對特殊型別所進行特殊化的實現方式。模板特化中分為函式模板特化類模板特化

函式模板特化

函式模板的特化步驟:

1. 必須要先有乙個基礎的函式模板

2. 關鍵字template後面接一對空的尖括號<>

3. 函式名後跟一對尖括號,尖括號中指定需要特化的型別

4. 函式形參表: 必須要和模板函式的基礎引數型別完全相同,如果不同編譯器可能會報錯誤。

//函式模板的特化

templatebool isequal(t& left,t& right)

template<>

bool isequal(char*& left, char*& right)

return false;

}void test()

int main()

類模板特化類模板特化分為全特化和偏特化

全特化:全特化即是將模板引數類表中所有的引數都確定化。例如:

//函式模板的全特化

templateclass data

private:

t1 _d1;

t2 _d2;

};template<>

class data

private:

int _d1;

char _d2;

};void test()

偏特化:任何針對模版引數進一步進行條件限制設計的特化版本。偏特化有兩種表現形式:

templateclass data

private:

t1 _d1;

t2 _d2;

};template//將第二個引數特化為char

class data

private:

t1 _d1;

char _d2;

};

偏特化並不僅僅是指特化部分引數,而是針對模板引數更進一步的條件限制所設計出來的乙個特化版本。

template//兩個引數特化為指標型別

class data

private:

t1 _d1;

t2 _d2;

};//兩個引數特化為引用型別

templateclass data

private:

const t1& _d1;

const t2& _d2;

};void test()

int main()

實現乙個通用的拷貝函式,請看下面的實現有沒有問題?

templatevoid copy(t* dst, const t* src, size_t size)

int main()

; string strarr2[3];

copy(strarr2, strarr1, 3);

return 0;

}

當我們執行程式時會發現程式崩潰,此**雖然對於任意型別的空間都可以進行拷貝,但是如果拷貝自定義型別物件就可能會出錯,因為自定義型別物件有可能會涉及到深拷貝(比如string),而memcpy屬於淺拷貝。如果物件中涉及到資源管理,就只能用賦值的方式進行拷貝。

void copy(t* dst, const t* src, size_t size)

}

用迴圈賦值的方式**的效率比較低,而c/c++程式最大的優勢就是效率高。所以我們就要想乙個辦法,遇到內建型別就用memcpy來拷貝,遇到自定義型別就用迴圈賦值方式。

增加bool型別區分自定義與內建型別

templatevoid copy(t* dst, const t* src, size_t size, bool ispodtype)

else

}

我們可以使用函式區分內建型別和自定義型別

bool ispodtype(const char* strtype)

; for (size_t i = 0; i < sizeof(arrtype)/sizeof(arrtype[0]); ++i)

return false;

}templatevoid copy(t* dst, const t* src, size_t size, bool ispodtype)

else }

//代表內建型別

struct truetype

};//代表自定義型別

struct falsetype

};templatestruct typetraits

;template<>

struct typetraits;

template<>

struct typetraits;

template<> struct typetraits;

template<> struct typetraits;

templatevoid copy(t* dst, const t* src, size_t size)

}int main()

; int a2[10];

copy(a2, a1, 10);

string s1 = ;

string s2[4];

copy(s2, s1, 4);

return 0;

}

當t為int時,typetraits已經特化過,程式執行時就會使用已經特化過的typetraits, 該類中的 ispodtype剛好為類truetype,而truetype中get函式返回true,內建型別使用memcpy方式拷貝  。

當t為string:typetraits沒有特化過,程式執行時使用typetraits類模板, 該類模板中的ispodtype 剛好為類falsetype,而falsetype中get函式返回true,自定義型別使用賦值方式拷貝  。

c/c++程式要執行起來,一般要經歷以下幾個步驟:

1.預處理:展開標頭檔案、進行巨集替換、條件編譯、去掉注釋。生成main.i

2.編譯:檢查語法錯誤,生成彙編**。main.s

3.彙編:將彙編**轉換成二進位制的機器碼。main.o

注意分離編譯可能會導致編譯出錯,例如在下面的情況下:

templatet add(const t& left, const t& right);

// a.cpp

templatet add(const t& left, const t& right)

// main.cpp

#include"a.h"

int main()

編譯器會報以下錯誤:

原因在於:

在a.cpp中,編譯器沒有看到對add模板函式的例項化,因此不會生成具體的加法函式。

模板的優點:

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

2.增強了**的靈活性。

模板的缺點:

1. 模板會導致**膨脹,也會導致編譯時間變長 。

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

C 模板高階

模板引數分為類型別形參和非型別形參。類型別形參 出現在模板引數列表中,跟在class或者typename之類的引數型別名稱。非型別形參 就是用乙個常量作為類 函式 模板的乙個引數,在類 函式 模板中可將該引數當成常量來使用。示例 定義乙個模板型別的靜態陣列。template class t,size...

C 模板高階

模板引數分類型別形參與非型別形參。型別形參即 出現在模板引數列表中,跟在class或者typename之類的引數型別名稱。非型別形參,就是用乙個常量作為類 函式 模板的乙個引數,在類 函式 模板中可將該引數當成常量來使用.定義乙個模板型別的靜態陣列 template10 class array co...

C 模板高階

模板引數分為型別形參與非型別形參。型別形參 出現在模組引數列表中,跟在class或者typename之類的引數型別名稱。非型別形參 用乙個常量作為類 函式 模板的乙個引數,在類 函式 模板中可將該引數當成常量來使用。注意 浮點數 類物件以及字串是不允許作為非型別模板引數的。非型別的模板引數必須在編譯...