C++模板顯式具體化

1.模板顯式具體化

前文當中說瞭,模板函數雖然非常好用,但是也存在一些問題。比如有的操作並不是對所有類型都適用的,針對這種情況C++提供瞭一個解決方案,就是針對特定類型提供具體化的模板定義。這裡的具體可以理解成類型的具體。

我們來看一個C++ Primer當中的例子,假設現在我們有一個結構體叫做job:

struct job {
    string name;
    double salary;
    int floor;
}


對於結構體是可以整體賦值的,所以之前的Swap函數對它一樣適用。

template <typename T>
void Swap(T &a, T &b) {
    T temp = a;
    a = b;
    b = temp;
}


但我們現在希望在交換結構體的時候,隻是交換salaryfloor這兩個字段,把name保持不變。由於我們希望引入邏輯變化,所以直接調用Swap函數就不可行瞭。

當然我們可以不用函數模板,直接重載函數:

void Swap(job &a, job &b) {
    // swap為std自帶的交換函數,在algorithm頭文件中
    swap(a.salary, b.salary);
    swap(a.floor, b.floor);
}


由於C++當中規定,非函數模板的優先級大於函數模板,所以我們在對job結構體調用Swap函數的時候,會優先使用這個。

除此之外,我們還可以提供一個具體化的模板函數:

template <> void Swap<job> (job &a, job &b) {
    swap(a.salary, b.salary);
    swap(a.floor, b.floor);
}

這個函數的寫法看起來有些特殊,我們在函數類型之前加上瞭template <>,在函數名後面又跟上瞭<job>。它表示的是這是一個函數模板的顯式具體化,也可以理解成為之前的函數模板提供一個job類型的版本。C++當中規定顯式模板函數的優先級高於普通模板函數。

2.實例化和具體化

關於函數模板,還有一個很重要的概念,就是實例化。

我們在編寫代碼時,如果隻是編寫瞭函數模板本身,編譯器是不會為我們生成函數的定義的。當編譯器使用模板為特定的類型生成函數定義時,就會得到一個模板的實例。這個概念有點像是Python裡的元類,元類的實例是另外一個類。

比如我們定義瞭一個函數模板:

template <typename T>
void Swap(T &a, T &b) {
    T temp = a;
    a = b;
    b = temp;
}


當我們調用它,傳入兩個int類型的時候,編譯器就會生成一個實例,這個實例使用的類型是int。當我們使用double類型的參數又一次調用的時候,編譯器會繼續生成double類型的實例。這個生成實例的過程是不可見的,所以被稱為隱式實例化。

在早年的C++版本當中隻支持隱式實例化,但現在C++允許顯示實例化。也就意味著我們可以手動命令編譯器創建特定的實例,比如Swap<int>() 。語法是通過<>聲明指定模板類型,並且在聲明之前加上關鍵字template,如:

template void Swap<int>(int, int);


這個語法看起來和顯式具體化非常相似,顯式具體化的寫法是:

template<> void Swap<int>(int &, int &);
template<> void Swap(int &, int &);


看起來非常相似,但是含義是完全不同的。顯式具體化的含義是對於某特定類型不要使用原模板生成函數,而應專門使用指定的函數定義。而顯式實例化是使用之前的模板函數的定義的,隻不過是手動觸發編譯器創建函數實例而已。

對瞭,我們不能同時在一個文件中,使用同一種類型的顯式實例化和顯式具體化,這會引起報錯。

我們如果死記顯式實例化的聲明,的確很容易和具體化混淆。但我們可以在代碼當中直接使用,直接使用的形式則要簡單許多,隻需要通過<>表明類型即可。

例如:

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;
}   


在上面這段代碼當中,我們通過給Add函數加上瞭<double>來手動創建瞭一個接受double類型的函數。需要註意的是,我們傳入的a是一個int類型。所以編譯器會執行強制類型轉換,將它轉換成double傳入。

到此這篇關於C++模板顯式具體化的文章就介紹到這瞭,更多相關C++模板顯式具體化內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!

推薦閱讀: