模板引數,模板分離編譯

audience_fzn發表於2018-08-08

模板的形參:

1.型別形參:

template<class T>
void h(T a) 
{//……}

  •  型別形參是指:class T/ typename T中的T,型別形參的名字由使用者自己定義,模板的形參(T)表示一個未知的型別。
  • 模板型別形參可以作為型別說明符用在模板中的任何地方,與內建型別/類型別的使用方式完全相同,即可以用於指定返回型別,宣告變數等地方 
  • 不能為同一個的模板型別形參指定兩種不同的型別,比如:
template<class T> 
void h(T a,T b) 
{} 
void test() 
{
     h(1,1.2); 
}

這樣的呼叫方式會出錯,因為該語句給同一模板形參T指定了倆種不同的型別(int,double)

  • 無論時模板函式,還是模板類都不能給同一個模板型別指定倆者不同型別的形參 

2.非型別模板形參:

  • 模板的非型別形參也就是內建型別形參:如:template<class T,int a>class B{},其中int a就是非型別模板形參
  • 非型別模板形參在模板定義的內部是常量值
  • 非型別模板形參只能是整型,指標,引用,不能使用double,string等
  • 呼叫非型別模板形參的實參只能是一個常量表示式,即他必須能在編譯時計算出結果
  • 任何區域性物件,區域性變數,區域性物件地址,區域性變數地址都不是常量表示式,都不能用作非型別模板形參的實參。全域性指標,全域性變數,全域性物件也不是一個常量表示式,不能用作非型別模板形參的實參
  • 全域性變數的地址或引用,全域性物件的地址或引用,const型別變數是常量表示式,可以用作非型別模板形參的實參
  • sizeof表示式的結果是一個常量表示式,也能用作非型別模板形參的實參
  • 當模板的形參是整型時呼叫該函式的實參必須時整型,且在編譯期間是常量。比如int b,AA<int ,b> a1;這時編譯器就會報錯,因為b是一個變數,如果修改為const int b,AA<int ,b> a1;就不會出錯,因為此時b是一個常量

非型別模板形參的形參和實參間所允許的轉換

  1. 允許從陣列到指標,從函式到指標。
template<int *>
class A 
{}; 
void Test() 
{ 
    int b[1]; 
    A<b> a1; 
}

2.const修飾符的轉換

template<const int*a> 
class A {}; 
void Test() 
{ 
    int* b; 
    A<&b> a1;//從int* 到const int* 的轉換 
}

 

3.提升轉換(short——int)

4.整值轉換(int ——unsigned int)

 

模板形參總結:

  1. 型別引數:可以類别範本的型別形參提供預設值,但不能給函式模板的型別形參提供預設值。
  2. 非型別引數:函式模板和類别範本都可以為類别範本的非型別形參提供預設值
  3. 給類别範本的型別形參預設值的方式:
    template<class T1,class T2=int>
    class AA{};

     

  4. 類别範本的型別引數提供預設值的方式與函式預設一樣,要從右向左,不能給T1提供預設值而不給T2。

  5. 在類别範本的外部定義類中的成員時template後的形參表應省略預設的形參型別 

    template <calss T1,class T2 = int>
    class A 
    {
    public:
        void h();
    };
    
    
    viod A<T1,T2>::h()
    
    {}
    
    

     

模板的模板引數:

template<class T>
class Seqlist
{
private:
	int _size;
	int _capacity;
	T* _data;
};

template<class T, template<class>calss Container = Seqlist>
calss Stack
{
public:
	void Push(const T& x);
	void pop();
	const T& Top();

private:
	Container<T> _con;
}

void Test()
{
	Stack<int> s1;
	Stack<int, Seqlist>s2;
}

 

3.模板的分離編譯:

解決方法:

  1. 在模板標頭檔案xxx.h裡面顯示例項化->模板類的定義後面新增template class SeqList<int>;
  2. 一般不推薦這種方法,一方面老編譯器可能不支援,另一方面例項化依賴呼叫者
  3. 將宣告和定義放在同一個檔案“xxx.hpp”裡面,新增使用這種方法 

 

相關文章