模板的進階
非類模板參數
類模板的特化
靜態數組:array:template < class T, size_t N > class array; array爲能夠存放N個元素的數組模擬實現:
#include<iostream>
using namespace std;
namespace bit{
template < class T, size_t N > ;
class array{
public:
private:
//T類型參數,N非類型參數
T array[N];
};
}
int main(){
bit::array<int,10> a;
return 0;
}
模板---->任意類型均可以處理
特化---->對模板不能處理或者處理有誤的類型進行特殊化處理(好比對於char *類型,是一個字符串,比較時應該經過字符串的方法進行比較,可是經過這個模板進行比較時直接用大於小於><進行比較,因此須要對模板進行特化)
1.必須提供一個類模板(對於函數模板,通常不進行特化)
template<class T>
T& Max(T& a,T& b){
return a>b?a:b;
}
template<>
char *& Max<char *>(char *& left,char *& right){
//不能加const,不然會出錯,報錯:不是函數模板的專用化
//加了以後對於特化的成本增長了
//若是處理不了,直接給出這種處理的函數便可,不須要特化
if(strcmp(left,right)>0){
return left;
}
retrun right;
}
int main(){
int a=0;
int b=3;
cout<<Max(a,b)<<endl;
char *p1="hello";
char *p2="world";
cout<<Max(p1,p2)<<endl;
return 0;
}
類模板的特化:
1.全特化:類模板實例化期間將類型全給出來好比:class Data<int , double>
2.偏特化(1)部分特化:class Data<int ,T>
(2) 讓模板的參數列表中的類型參數限制更加嚴格class Data<T*,T*>
應用場景:識別被拷貝的元素的類型是內置類型仍是用戶自定義類型?
內置類型:不會涉及資源的管理
自定義類型:會涉及類型的管理
類型萃取:
//實現通用的拷貝函數:
template<>
//內置類型
struct TypeTraits<char>{
typedef TrueType POD_TYPE;
};
template<>
struct TypeTraits<double>{
typedef TrueType POD_TYPE;
};
struct TypeTraits<int>{
typedef TrueType POD_TYPE;
};
template<>
struct TypeTraits<float>{
typedef TrueType POD_TYPE;
};
//是實現的通用的類型,進而判斷是內置類型仍是自定義類型
template<>
struct TypeTraits<T>{
typedef FalseType POD_TYPE;
};
struct TrueType{
static bool Get(){
return true;
}
};//
表明內置類型
struct FalseType{
static bool Get(){
return false;
}
};//
表明自定義類型
template<class T>
void Copy(T* dst,T* src,size_t size){
if(TypeTraits<T>::POD_TYPE::Get()){
memset(dst,src,sizeof(T)*size);
}
else{
for(i=0;i<size;++i){
dst[i]=src[i];
}
}
模板的分離編譯:
預處理階段---->編譯---->彙編---->連接---->可執行程序
1.預處理 宏替換,宏展開,刪除註釋,包含頭文件
2.編譯:語法分析(語法樹—>中序遍歷),語義分析,詞法分析(掃描),代碼優化;編譯器只編譯當前工程的全部源文件,頭文件不參與編譯(?????),頭文件已經展開了。對於當前工程的全部源文件,分別單獨編譯,分別生成目標文件
1.對模板進行簡單的語法檢測
2.生成代碼-->前提(實例化)
未解決的符號表
編譯期間生成未解決的符號表,連接期間進行解決(連接期間到別的已解決的符號表中去找,若是沒找到則報錯:沒法解析的外部符號;若是找到了,則解決了該問題(地址問題))
已解決的符號表
模板的分離編譯:
解決這種問題經過創建全新的"頭文件"「.hpp」,至關於將頭文件和源文件合併到一塊了
推薦方法:
//a.hpp
template<class T,class T>
T& Add(T& left, T& right){
return left+right;
}
//.cpp
#include"a.hpp"
int main(){
Add(1,2);
Add(1.0,3.0);
return 0;
}
另外一種方法(不推薦)
a.cpp:
T& Add(T& left,T& right){
return left+right;
}
void testFun(){
這種方法是經過下面代碼進行模板的實例化,生成相應的函數,若是不給出實例化,因爲每一個源文件是單獨編譯的,所以對於test.cpp源文件中的Add(1,2)會生成未決符號表,在連接期間沒有找到相應的函數,因此會報錯:沒法識別的外部符號
Add(2,1);
Add(2.0,1.0);
}
a.h
template<class T,class T>
T& Add(T& left,T& right);
test.cpp:
#include"a.h"
int main(){
Add(2,1);
Add(2.0,1.0);
return 0;
}