模板的進階 非類模板參數 類模板的特化

模板的進階
非類模板參數
類模板的特化
靜態數組: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;
}
相關文章
相關標籤/搜索