模板全特化與偏特化的概念
前言
之前我在學習STL的時候,發現STL用到了大量的類模板、函數模板。對于模板而言,我們知道,當用戶傳遞類型后,模板會進行自動類型推演,但是作為一個模板初學者,我有時候并不能確定模板一定會按照我的思路去推導出符合我預期的類型,所以有時候編寫的模板能夠涵蓋的類型過多反而也不是一件好事(如果代碼出現錯誤,很難察覺到),那么為了讓編譯器更加精準了解我們想要的類型,我們就可以對模板進行特化(特例化),讓編譯器更加精確限定我們需要的模板類型,讓模板的泛型不那么“泛”。
本文主要介紹模板的特化(完全特化及偏特化)在類和函數中是什么樣的情況。說白了我其實是想梳理一下C++綁定器和C++11的function機制,為此才寫本篇文章,做一些前置的知識鋪墊。
關于為什么要用模板以及模板的好處在哪?模板實際上就是宏定義的衍生,相比宏,其還可以進行類型檢查,更安全,這里就不再過多贅述,可參考:[??模板特化的概念從何而來]
模板特化
模板為什么要特化,因為編譯器認為,對于特定的類型,如果你能對某一功能更好的實現,那么就該聽你的。
模板分為類模板與函數模板,特化分為全特化與偏特化。全特化就是限定死模板實現的具體類型,偏特化就是如果這個模板有多個類型,那么只限定其中的一部分。
類模板(全特化、偏特化)
類模板的類型傳遞通過<>傳遞,那么類模板配合特化使用后,產生的全特化和偏特化可以看下面的代碼,全特化指的是我要對模板傳遞的所有類型進行明確的指定,即下面代碼的第二部分,同時制定了T1為int,T2為char;偏特化指的是只對模板的部分類型進行明確指定,即下面代碼的第三部分,指定第一個參數為char,第二個參數依舊保持T2,讓模板自動推導。
// 類模板
template<typename T1, typename T2>
class Test {
public:
Test(T1 i, T2 j) : a(i), b(j) { cout << "模板類" << endl; }
private:
T1 a;
T2 b;
};
// 類模板全特化
template<>
class Test<int, char> {
public:
Test(int i, char j) : a(i), b(j) { cout << "全特化" << endl; }
private:
int a;
char b;
};
// 類模板偏特化
template <typename T2>
class Test<char, T2> {
public:
Test(char i, T2 j) : a(i), b(j) { cout << "偏特化" << endl; }
private:
char a;
T2 b;
};
那么下面3句依次調用類模板、全特化與偏特化:
Test<double, double> t1(0.1, 0.2); // 類模板
Test<int, char> t2(1, 'A'); // 模板全特化
Test<char, bool> t3('A', true); // 模板偏特化
函數模板(只有全特化)
而對于函數模板,卻只有全特化,不能偏特化:
//模板函數
template<typename T1, typename T2>
void fun(T1 a , T2 b) {
cout << "模板函數" << endl;
}
//全特化
template<>
void fun<int, char >(int a, char b) {
cout << "全特化" << endl;
}
//函數不存在偏特化:下面的代碼是錯誤的
/*
template<typename T2>
void fun<char, T2>(char a, T2 b) {
cout << "偏特化" << endl;
}
*/
為什么函數不能偏特化呢?似乎不是因為語言實現不了,而是因為偏特化的功能可以通過函數的重載完成。
總結
以上就是對類模板特化和函數模板特化使用方式的介紹,對模板特化有了一個概念上的認識。那么全特化其實也就是一個“披著空空如也的template<>的普通函數或類”。其實模板的使用場景一定是非常復雜的,我所接觸的模板場景也并不多,本篇主要是對模板特化概念層面的總結,哎,C++語法可真多,你問我為什么要學C++,純純是靠情懷硬撐著(因為可以裝逼)。

浙公網安備 33010602011771號