C++模板的偏特化與全特化(轉)


模板機制為C++提供了泛型編程的方式,在減少代碼冗余的同時仍然可以提供類型安全。 特化必須在同一命名空間下進行,可以特化類模板也可以特化函數模板,但類模板可以偏特化和全特化,而函數模板只能全特化。 模板實例化時會優先匹配”模板參數”最相符的那個特化版本。

模板的聲明

類模板和函數模板的聲明方式是一樣的,在類定義/模板定義之前聲明模板參數列表。例如:

// 類模板
template <class T1, class T2>
class A{
    T1 data1;
    T2 data2;
};

// 函數模板
template <class T>
T max(const T lhs, const T rhs){   
    return lhs > rhs ? lhs : rhs;
}

 

全特化

通過全特化一個模板,可以對一個特定參數集合自定義當前模板,類模板和函數模板都可以全特化。 全特化的模板參數列表應當是空的,並且應當給出”模板實參”列表:

// 全特化類模板
template <>
class A<int, double>{
    int data1;
    double data2;
};

// 函數模板
template <>
int max(const int lhs, const int rhs){   
    return lhs > rhs ? lhs : rhs;
}

 

注意類模板的全特化時在類名后給出了”模板實參”,但函數模板的函數名后沒有給出”模板實參”。 這是因為編譯器根據int max(const int, const int)的函數簽名可以推導出來它是T max(const T, const T)的特化。

特化的歧義

上述函數模板不需指定”模板實參”是因為編譯器可以通過函數簽名來推導,但有時這一過程是有歧義的:

template <class T>
void f(){ T d; }

template <>
void f(){ int d; }

 

此時編譯器不知道f()是從f<T>()特化來的,編譯時會有錯誤:

error: no function template matches function template specialization 'f'

 

這時我們便需要顯式指定”模板實參”:

template <class T>
void f(){ T d; }

template <>
void f<int>(){ int d; }

 

偏特化

類似於全特化,偏特化也是為了給自定義一個參數集合的模板,但偏特化后的模板需要進一步的實例化才能形成確定的簽名。 值得注意的是函數模板不允許偏特化,這一點在Effective C++: Item 25中有更詳細的討論。 偏特化也是以template來聲明的,需要給出剩余的”模板形參”和必要的”模板實參”。例如:

template <class T2>
class A<int, T2>{
    ...
};

 

函數模板是不允許偏特化的,下面的聲明會編譯錯:

template <class T1, class T2>
void f(){}

template <class T2>
void f<int, T2>(){}

 

但函數允許重載,聲明另一個函數模板即可替代偏特化的需要:

template <class T2>
void f(){}              // 注意:這里沒有"模板實參"

 

多數情況下函數模板重載就可以完成函數偏特化的需要,一個例外便是std命名空間。 std是一個特殊的命名空間,用戶可以特化其中的模板,但不允許添加模板(其實任何內容都是禁止添加的)。 因此在std中添加重載函數是不允許的,在Effective C++: Item 25中給出了一個更詳細的案例。

 

轉自:https://harttle.land/2015/10/03/cpp-template.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM