EasyC++模板顯式具體化
1.模板顯式具體化
前文當(dāng)中說(shuō)了,模板函數(shù)雖然非常好用,但是也存在一些問(wèn)題。比如有的操作并不是對(duì)所有類型都適用的,針對(duì)這種情況C++提供了一個(gè)解決方案,就是針對(duì)特定類型提供具體化的模板定義。這里的具體可以理解成類型的具體。
我們來(lái)看一個(gè)C++ Primer當(dāng)中的例子,假設(shè)現(xiàn)在我們有一個(gè)結(jié)構(gòu)體叫做job:
struct job {
string name;
double salary;
int floor;
}
對(duì)于結(jié)構(gòu)體是可以整體賦值的,所以之前的Swap函數(shù)對(duì)它一樣適用。
template <typename T>
void Swap(T &a, T &b) {
T temp = a;
a = b;
b = temp;
}
但我們現(xiàn)在希望在交換結(jié)構(gòu)體的時(shí)候,只是交換salary和floor這兩個(gè)字段,把name保持不變。由于我們希望引入邏輯變化,所以直接調(diào)用Swap函數(shù)就不可行了。
當(dāng)然我們可以不用函數(shù)模板,直接重載函數(shù):
void Swap(job &a, job &b) {
// swap為std自帶的交換函數(shù),在algorithm頭文件中
swap(a.salary, b.salary);
swap(a.floor, b.floor);
}
由于C++當(dāng)中規(guī)定,非函數(shù)模板的優(yōu)先級(jí)大于函數(shù)模板,所以我們?cè)趯?duì)job結(jié)構(gòu)體調(diào)用Swap函數(shù)的時(shí)候,會(huì)優(yōu)先使用這個(gè)。
除此之外,我們還可以提供一個(gè)具體化的模板函數(shù):
template <> void Swap<job> (job &a, job &b) {
swap(a.salary, b.salary);
swap(a.floor, b.floor);
}
這個(gè)函數(shù)的寫法看起來(lái)有些特殊,我們?cè)诤瘮?shù)類型之前加上了template <>,在函數(shù)名后面又跟上了<job>。它表示的是這是一個(gè)函數(shù)模板的顯式具體化,也可以理解成為之前的函數(shù)模板提供一個(gè)job類型的版本。C++當(dāng)中規(guī)定顯式模板函數(shù)的優(yōu)先級(jí)高于普通模板函數(shù)。
2.實(shí)例化和具體化
關(guān)于函數(shù)模板,還有一個(gè)很重要的概念,就是實(shí)例化。
我們?cè)诰帉懘a時(shí),如果只是編寫了函數(shù)模板本身,編譯器是不會(huì)為我們生成函數(shù)的定義的。當(dāng)編譯器使用模板為特定的類型生成函數(shù)定義時(shí),就會(huì)得到一個(gè)模板的實(shí)例。這個(gè)概念有點(diǎn)像是Python里的元類,元類的實(shí)例是另外一個(gè)類。
比如我們定義了一個(gè)函數(shù)模板:
template <typename T>
void Swap(T &a, T &b) {
T temp = a;
a = b;
b = temp;
}
當(dāng)我們調(diào)用它,傳入兩個(gè)int類型的時(shí)候,編譯器就會(huì)生成一個(gè)實(shí)例,這個(gè)實(shí)例使用的類型是int。當(dāng)我們使用double類型的參數(shù)又一次調(diào)用的時(shí)候,編譯器會(huì)繼續(xù)生成double類型的實(shí)例。這個(gè)生成實(shí)例的過(guò)程是不可見(jiàn)的,所以被稱為隱式實(shí)例化。
在早年的C++版本當(dāng)中只支持隱式實(shí)例化,但現(xiàn)在C++允許顯示實(shí)例化。也就意味著我們可以手動(dòng)命令編譯器創(chuàng)建特定的實(shí)例,比如Swap<int>() 。語(yǔ)法是通過(guò)<>聲明指定模板類型,并且在聲明之前加上關(guān)鍵字template,如:
template void Swap<int>(int, int);
這個(gè)語(yǔ)法看起來(lái)和顯式具體化非常相似,顯式具體化的寫法是:
template<> void Swap<int>(int &, int &); template<> void Swap(int &, int &);
看起來(lái)非常相似,但是含義是完全不同的。顯式具體化的含義是對(duì)于某特定類型不要使用原模板生成函數(shù),而應(yīng)專門使用指定的函數(shù)定義。而顯式實(shí)例化是使用之前的模板函數(shù)的定義的,只不過(guò)是手動(dòng)觸發(fā)編譯器創(chuàng)建函數(shù)實(shí)例而已。
對(duì)了,我們不能同時(shí)在一個(gè)文件中,使用同一種類型的顯式實(shí)例化和顯式具體化,這會(huì)引起報(bào)錯(cuò)。
我們?nèi)绻烙涳@式實(shí)例化的聲明,的確很容易和具體化混淆。但我們可以在代碼當(dāng)中直接使用,直接使用的形式則要簡(jiǎn)單許多,只需要通過(guò)<>表明類型即可。
例如:
template <typename T>
T Add(T a, T b) {
return a + b;
}
int main() {
int a = 3;
double b = 3.5;
cout << Add<double>(a, b) << endl;
}
在上面這段代碼當(dāng)中,我們通過(guò)給Add函數(shù)加上了<double>來(lái)手動(dòng)創(chuàng)建了一個(gè)接受double類型的函數(shù)。需要注意的是,我們傳入的a是一個(gè)int類型。所以編譯器會(huì)執(zhí)行強(qiáng)制類型轉(zhuǎn)換,將它轉(zhuǎn)換成double傳入。
到此這篇關(guān)于C++模板顯式具體化的文章就介紹到這了,更多相關(guān)C++模板顯式具體化內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
詳解如何配置CLion作為Qt5開(kāi)發(fā)環(huán)境的方法
這篇文章主要介紹了詳解如何配置CLion作為Qt5開(kāi)發(fā)環(huán)境的方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-04-04
Qt5連接并操作PostgreSQL數(shù)據(jù)庫(kù)的實(shí)現(xiàn)示例
本文主要介紹了Qt5連接并操作PostgreSQL數(shù)據(jù)庫(kù)的實(shí)現(xiàn)示例,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-12-12
聊聊C語(yǔ)言中sizeof運(yùn)算符的一個(gè)陷阱
在C語(yǔ)言中,sizeof()是一個(gè)判斷數(shù)據(jù)類型或者表達(dá)式長(zhǎng)度的運(yùn)算符,下面這篇文章主要給大家介紹了關(guān)于C語(yǔ)言中sizeof運(yùn)算符的一個(gè)陷阱的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-11-11
C語(yǔ)言中strcpy()函數(shù)的具體實(shí)現(xiàn)及注意事項(xiàng)
C語(yǔ)言庫(kù)函數(shù)char *strcpy(char *dest, const char *src)把src所指向的字符串復(fù)制到dest,下面這篇文章主要給大家介紹了關(guān)于C語(yǔ)言中strcpy()函數(shù)的具體實(shí)現(xiàn)及注意事項(xiàng)的相關(guān)資料,需要的朋友可以參考下2022-11-11
C++中string轉(zhuǎn)換為char*類型返回后亂碼問(wèn)題解決
這篇文章主要介紹了C++中string轉(zhuǎn)換為char*類型返回后亂碼問(wèn)題解決,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-07-07

