當前位置:編程學習大全網 - 源碼下載 - C++ 模板元編程系列專題 2:模板特化的概念從何而來

C++ 模板元編程系列專題 2:模板特化的概念從何而來

如果元編程中所有的變量(或者說元編程的參數),都是類型,那麽這樣的編程,我們有個特定的稱呼,叫“泛型”。

模板的發明,僅僅是為了做和 宏 幾乎壹樣的替換工作嗎?可以說是,也可以說不是。

壹方面, 模板 可以用來替換類型,這點和宏沒什麽區別。只是宏在編譯階段基於文本做純粹替換,被替換的文本本身沒有任何語義。而模板會在分析模板時以及實例化模板的時候都會進行檢查,而且源代碼中也能與調試符號壹壹對應,所以無論是編譯時還是運行時,排錯都相對簡單。

另壹方面,模板和宏也有很大的不同,模板最大的不同在於它是 “可以運算” 的。我們來看壹個例子:

上述函數實現了壹個 uint8_t 和 uint8_t 類型的加法運算,如果現在要實現 int16 和 int16 類型的加法運算,該怎麽辦呢?簡單點的方法如下:

但是這裏有兩個難點:

有人說, 重載 虛函數 也能解決如上問題:

甚至在 C 語言中定義新的 結構體 Variant 或使用 void* 也能解決該問題:

沒錯,但是如果我還有 uint9_t、uint10_t 等各種類型的加法運算呢?Anyway,不 管是哪種方法都很難避免 if/else 的存在。

模板與上述這些方法最大的區別在於:模板無論其參數或者是類型,它都是壹個編譯期分派的方法。編譯期就能確定的東西既可以做類型檢查,編譯器也能進行優化,砍掉任何不必要的代碼執行路徑。

我們先來看看壹個模板的例子:

那麽當傳入兩個不同類型的變量,或者不是 in t 和 float 變量,編譯器就會提示錯誤。

從能力上來看,模板能做的事情都是編譯期完成的。編譯期完成的意思就是,當妳編譯壹個程序的時候,所有的量就都已經確定了。比如下面的例子:

從 上述代碼中我們可以看到:aVar 和 bVar 都壹定會是整數。所以 如果有合適的機制,編譯器就能知道此處的 AddFloatOrMulInt 中只需要執行 int 路徑上的代碼,而且編譯器在此處也能單獨為 int 路徑生成代碼,從而去掉那個不必要的 if 。在模板代碼中,這個“合適的機制”就是指“特化”和“部分特化(Partial Specialization)”,後者也叫“偏特化”。

1.0 版本 - 偽代碼

2.0 版本 - 函數重載

3.0 版本 - 純模板

好吧,問題來了!如何要讓兩個內容不同,但是模板參數形式相同的類進行區分呢?特化!特化(specialization)是根據壹個或多個特殊的整數或類型,給出模板實例化時的壹個指定內容

4.0 版本 - 模板特化

解釋:

至此,第壹個模板特化的代碼已經寫完了。這裏的 AddFloatOrMulInt 如同是壹個函數,卻只能在編譯期間執行。如果妳體味到了這壹點,那麽恭喜妳,妳的模板元編程已經開悟了。

本文核心只講了兩個問題:壹是為什麽需要泛型編程,重點介紹了宏、模板和元編程的關系;二是模板類的特化代碼如何編寫。關於特化,還有很多細節知識,在之後的文章中我們繼續探究,另外將還介紹偏特化等知識點,敬請期待。

  • 上一篇:做壹個微信小程序商城開發大概多少錢(多少費用)?
  • 下一篇:每個區塊只能由壹個礦工確認記賬嗎
  • copyright 2024編程學習大全網