1. 程式人生 > >C++模板之實例化和具體化

C++模板之實例化和具體化

++ ati UC AR 情況 增加 .com 定義 存在

模板聲明 template<typename/class T>, typename比class最近後添加到C++標準。

常規模板,具體化模板,非模板函數的優先調用順序。

非模板函數(普通函數)> 具體化模板函數 > 常規模板

顯示具體化:

具體化表示為某一特定的類型重寫函數模板,聲明的含義是使用獨立的,專門的函數定義顯示地為 特定類型生成函數定義。

為什麽要有顯示具體化?處理模板函數所不能處理的特殊情況。顯式具體化顯式具體化也是基於函數模板的,只不過在函數模板的基礎上,添加一個專門針對特定類型的、實現方式不同的具體化函數。

顯示具體化聲明在關鍵字template後包含<>.

如:

  1. template<> void swap<job>(job &j1, job &j2);

vs2013不支持:

  1. void swap(Any &a, Any &b);
  2. struct job
  3. {
  4. char name[40];
  5. double salary;
  6. int floor;
  7. };
  8. template<> void swap<job>(job &j1, job &j2);
  9. void Show(job &j);
  10. int main(){
  11. using namespace std;
  12. template void swap<job>(job &, job &);
  13. int i = 10, j = 20;
  14. swap(i, j);
  15. return 0;
  16. }
  17. template<typename Any>
  18. void swap(Any &a, Any &b){
  19. Any temp;
  20. temp = a;
  21. a = b;
  22. b = temp;
  23. }
  24. template<> void swap<job>(job &j1, job &j2){
  25. double temp_sal;
  26. temp_sal = j1.salary;
  27. j1.salary = j2.salary;
  28. j2.salary = temp_sal;
  29. }

顯示實例化:

實例:如函數調用swap(i,j)會導致編譯器生成swap()的一個實例,該實例使用 int 類型。

句法:聲明所需的種類用<>符號指示類型,並在聲明前加上關鍵字template:

為什麽要有顯示實例化?事實上,編譯器只在要調用函數的時候才使用到函數,如果不使用顯示實例化,每次調用函數時,模板都會消耗性能去推導使用的是哪個類型的函數,增加了程序運行時的負擔;使用了顯示實例化,則在編譯時就已經處理了函數選擇。

實例化示例:

    1. template void swap<int>(int, int);

註意:試圖在同一個文件(或轉換單元)中使用同一種類型的顯示實例化和顯示具體化聲明,會出錯。

推薦:可以用在函數調用時,直接顯示實例化,而不使用顯示實例化聲明。

  如:

template <typename T>
T add(T x,T y)
{
      return x+y;      
}
int main()
{
     int i1=2,i2=3;
     add<int>(i1,i2);
     template int add<int>(i1,i2);//盡量用上面一行的寫法代替本行
     return 0;    
}

  

模範代碼:

 ///**********************************************
 /// @file    templetAdd.cc
 /// @author  alex([email protected])
 /// @date    2018-06-19 21:42:20
 ///**********************************************/

#include <string.h>
#include <iostream>
using std::cout;
using std::endl;
//模板-->類型參數化-->代碼生成器

//	  實例化(模板參數推導)
//函數模板    -->    模板函數


//< >  模板參數列表
//1、使用class 或者typename設置類型參數
//2、非類型參數、常量表達式(整型數據)
template <class T>
T add(T x,T y)
{
    return x + y;
}
#if 0
template int add<int>(int x,int y)//
{
    cout<<"template 顯示實例化"<<endl;
    return x+y;
}
#endif
template<> int add<int>(int x,int y)//等價於template<>int add(int x,int y)
{
    cout<<"template 顯示具體化"<<endl;
    return x+y;
}
//模板的特化版本,不能獨立用於通用版本
//針對特殊情形,但一定要在通用版本存在時才能用
template<>//把這行註釋掉也是可以的,那表明下面的這個方法是重載了模板函數
const char* add(const char*lhs,const char* rhs)
{
    char*tmp = new char[strlen(lhs)+strlen(rhs)+1]();
    strcpy(tmp,lhs);
    strcat(tmp,rhs);
    return tmp;
}
#if 0
//普通函數與函數模板可以重載
//普通函數優先級高於模板函數
int add(int x,int y)//可以重載,因為形參類型不一樣
{
    return x + y;
}
#endif
//函數模板與函數模板之間也可以重載
//函數模板的聲明
template <typename T>
T add(T x,T y,T z);

//c++11的特性
//c++11以前的版本對於函數模板而言,非類型參數不能設置默認值
//非類型參數必須是整形類數據(bool、char、int、long、long long)
template <typename T,int num=10>
int func(T x,T y)
{
    return x*y*num;
}
int main()
{
    int a=3,b=4;
    double c1=1.2,c2=2.3,c3=4.9;
    char ch1=‘a‘,ch2=2;
    //template char add<char>(char x,char y);//試圖在同一個文件(或轉換單元)中使用同一種類型的顯示實例化和顯示具體化聲明,會出錯
    func(ch1,ch2);
    const char *p1="hello";
    const char *p2="good";

    cout << "int + int = " << add(a,b) << endl;//隱式實例化
    cout << "double + double = " << add<int>(c1,c2) << endl;//顯示實例化
    cout << "char + char = " << add(ch1,ch2) << endl;
    cout << "double + double = " << add(c1,c2,c3) << endl;
    cout << "int + int = " << func<double,8>(a,b) << endl;//常量傳遞的方式
    //cout << "a+d1=" << add(a,c1) << endl;//error,模板參數必須嚴格一致
 
    cout << add(p1,p2) << endl;
    return 0;
}
//函數模板的實現
template <class T>
T add(T x,T y,T z)
{
    return x +y + z;
}

  

總結:

隱式實例化指的是:在使用模板之前,編譯器不生成模板的聲明和定義實例。只有當使用模板時,編譯器才根據模板定義生成相應類型的實例。如:int i=0, j=1;swap(i, j); //編譯器根據參數i,j的類型隱式地生成swap<int>(int &a, int &b)的函數定義。Array<int> arVal;//編譯器根據類型參數隱式地生成Array<int>類聲明和類函數定義。

顯式實例化:當顯式實例化模板時,在使用模板之前,編譯器根據顯式實例化指定的類型生成模板實例。如前面顯示實例化(explicit instantiation)模板函數和模板類。其格式為:template typename function<typename>(argulist);template class classname<typename>;顯式實例化只需聲明,不需要重新定義。編譯器根據模板實現實例聲明和實例定義。

顯示具體化:對於某些特殊類型,可能不適合模板實現,需要重新定義實現,此時可以使用顯示具體化(explicite specialization)。顯示實例化需重新定義。格式為:template<> typename function<typename>(argu_list){...};template<> class classname<typename>{...};

C++模板之實例化和具體化