函數模,類模板

來源:互聯網
上載者:User

標籤:dfa   版本   重載函數   固定   ios   show   type   有一個   類模板的部分特化   

函數模板特化

函數模板特化:

  1. 關鍵字template後面接一對<>
  2. 再接模板名和一對<>,角括弧中定義這個特華的模板參數
  3. 函數形參表
  4. 函數體
template <typename T>int com(const T &v1,const T &v2) {    return v1>v2?1:0;}template <>int com<const string>(const string &v1,const string &v2){    return strcmp(v1.c_str(),v2.c_str());}

特化的聲明必須與對應的模板相匹配,當調用cmp函數時,傳給他兩個const string類型的參數,編譯器調用特化版本,特化函數參數固定為const string類型,當調用其他類型(包括string)時,調用泛化版本

1.聲明特化模板

函數特化模板可以聲明而無需定義

template <>int com<const string>(const string &v1,const string &v2)

注意:

  1. 模板特化總是包含模板空參說明符(template<>)
  2. 必須包含函數形參列表,如果可以從函數形參推斷模板實參,不必顯示定義模板實參
template <>int com(const string &v1,const string &v2){    return strcmp(v1.c_str(),v2.c_str());}
2.函數重載與模板特化

如果省略template<>,則是函數的重載非模板版本

template <typename T>int com(const T &v1,const T &v2) {    return v1>v2?1:0;}//template <>int com(const string &v1,const string &v2){    return strcmp(v1.c_str(),v2.c_str());}

注意:

  當定義非模板函數的時候,對實參應用常規轉換;特化模板的時候,對應的實參類型不應用轉換。

  模板特化版本的調用中,實參類型必須與特化版本的函數型別參數完全符合,若果不完全符合,編譯器將為實參從模板定義執行個體化一個執行個體。

3.不能總是檢測到重複定義

  應在一個標頭檔中包含模板特化的聲明,每個源檔案包含該標頭檔

完整代碼

#include <iostream>#include <cstring>using namespace std;template <typename T>int com(const T &v1,const T &v2) {    return v1>v2?1:0;}template <>int com(const string &v1,const string &v2){    return strcmp(v1.c_str(),v2.c_str());}int main(){    int a=1,b=2;    string s1="123",s2="1";        cout<<com(s1,s2)<<endl;    return 0;}
類模板特化

  特化可以定義與模板本身不同的成員。如果一個特化無法從模板定義某個成員,該特化類型就不能使用該成員。類模板的定義不會用於顯示建立特化成員的定義。

1.類特化定義

  在類特化外部定義成員時,成員前不加template<>

/* *類特化為 const char*類型,上面的函數特化類似 *此例子只是為了說明類特化模板定義成員  */void queue<const char*>::push(const char *val) {    return real_queue.push(val);}
2.特化成員而不特化類
template<> void queue<const char*>::push(const char *val);

與任何特化函數模板一樣,以空參的形參表開頭,在定義類的標頭檔中

3.類模板的部分特化
template <class T1,class T2>class some_templae{    //}//特化T2為int類型,T1為任何類型 template<T1>class some_template<T1,int>{    //}

注意:

  1. 部分特化像類模板的定義
  2. 部分特化的模板形參是類模板定義的形參表子集
  3. 部分特化形參表只列出未知模板形參的那些實參
#include <iostream>#include <cstring>using namespace std;template <class T1,class T2>class Ship{    public:        Ship(T1 a1,T2 a2):a(a1),b(a2){}        void show()        {            cout<<a<<" "<<b<<endl;        }    private:        T1 a;        T2 b;};//特化T2為int類型,T1為任何類型 template<class T1>class Ship<int,T1>//<T1,int>都可以,int和T1的位置可以交換 {    public:        Ship(T1 a1,int a2):a(a1),b(a2){}        void show()        {            cout<<a<<" "<<b<<endl;        }    private:        T1 a;        int b;};int main(){    Ship<double,int> s(1.222,2);//調用通用版本,也可調用通用版本以為當生命部分特化時,編譯器會選擇最特化的版本,當無部分特化時,選擇通用版本    Ship<double,double> s2(6.66,9.99) ;//調用特化版本         s.show();    s2.show();    return 0;}

注意:

  部分特化的定義與通用模板的定義不衝突,部分特化可以具有與通用模板完全不同的成員集合,類模板成員的通用定義永遠不會用執行個體化模板部分的特化成員

重載與函數模板

(1)為該函數建立候選集合:

   a.與背調函數名相同的任意普通函數

   b.任意模板執行個體化,模板實參發現了與調用中所用函數參數相匹配的模板實參

(2)確定哪些普通函數的的行為是可行的,候選集合中的每個執行個體模板都可行

(3)如果需要轉換來進行調用,根據轉換的種類排列可行函數,模板函數執行個體轉換有限

   a.如果只有一個函數可選,就調用他

   b.有多個可選,具有二義性,去掉所有模板執行個體

(4)重新排列去掉函數模板執行個體的可用函數

   a.有一個則調用

   b.否則具有二義性

  1. 如果只包含一個函數可選,就調用這個函數
  2. 否則具有二義性
//函數模板 template<typename Tint com(const T&,const T&);//普通函數 int com(const char*,const char*);char s1[]="sdfa",s2[]="dfaskf";com(s1,s2);//會調用普通函數,因為函數會將數組轉化為指標,調用普通函數優先於調用模板 
轉換與重載函數模板

  當普通函數與模板函數都同樣匹配,且一樣好時,非模板版本有限

函數模,類模板

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.