【C++ 筆記】模板(Templates)(下) - part 32
【C++ 筆記】模板(Templates)(下) - part 32
很感謝你點進來這篇文章。
你好,我並不是什麼 C++、程式語言的專家,所以本文若有些錯誤麻煩請各位鞭大力一點,我極需各位的指正及指導!!本系列文章的性質主要以詼諧的口吻,一派輕鬆的態度自學程式語言,如果你喜歡,麻煩留言說聲文章讚讚吧!
模板特製化(Template Specialization)
It is possible in C++ to get a special behavior for a particular data type. This is called template specialization.
From GeeksForGeeks
在 C++ 中,可以為特定資料型態賦予特殊的行為,就稱為模板特製化。
簡單來說,就是可以為特定資料型態去做不一樣的事情,如下範例:
1 |
|
Output:
1 | 一般型態 |
以上範例針對 int 去做模板特製化的事情,除了 int 以外的型態都是按照正常的模板去做一般的執行,只有 int 型態被特別處理。
上述 template <> void print<int>(int value) 的語法就稱為模板特製化語法,除了對函數做模板特製化,也可以對類別做模板特製化:
1 |
|
Output:
1 | Generic template |
當建立 MyContainer <int> 物件時,會呼叫他的特製化版本,接下來再呼叫 print() 函數,會發現 int 的內容與其他型態不一樣。
非型態模板參數(Template Non-Type Arguments)
就是字面上意思,可以傳遞資料型態以外的參數。
但是這個參數必須要是常數,必須在編譯時期可確定(constexpr)。
可接受的型態:
- 整數型態(
int,size_t等) - 列舉型態(
enum) - 指標或參考(對函式、物件或靜態成員)
- C++20 開始支援浮點數型態。
使用限制:
- 傳入的值必須是編譯期常數(constexpr)
- 不能使用非 constexpr 的變數作為非型態模板參數
範例(From GeeksForGeeks):
1 |
|
Output:
1 | 10 |
int max 為非型態模板參數。這支程式主要是找出陣列中的最小值。
模板參數推導(Template Argument Deduction)
Template argument deduction automatically deduces the data type of the argument passed to the templates. This allows us to instantiate the template without explicitly specifying the data type.
From GeeksForGeeks
模板參數推導會自動推導出傳遞給模板的參數的資料型態。這使我們能夠實例化模板而無需明確指定資料型態。
而這種自動推導特性在 C++ 17 之後才出現,如果在這之前的版本上用這個,會 throw 出例外。
而原本我們在創造模板實例的時候,是這樣子寫的:
1 | func <int> (100); |
但是有自動推導的特性時,我們就不用明確指定型態 <int>:
1 | func (100); |
函數模板參數推導(Function Template Arguments Deduction)
這個推導是從 C++98 開始就有的了。
範例:
1 |
|
Output:
1 | 123 |
呼叫 display() 的部分就在做推導了,總之就會根據傳入的參數型態去做調整。
類別模板參數推導(Class Template Arguments Deduction)
該推導是於 C++ 17 後才加入的特性,基本上使用方式與函數模板參數推導相同。
範例:
1 |
|
Output:
1 | 123 |
在建立物件 B1、B2、B3 時,就在做自動推導的動作了,編譯器會推導出每一個值所對應的資料型態是什麼。
可變參數模板(Variadic Templates)
這是 C++ 11 引入的特性,之前建立的模板參數數量只能固定,有了這個特性以後,想加多少就加多少!
大致上有兩個概念需要去理解:
- 模板參數包(template parameter pack):用省略號
...表示的可變長度模板參數列表。
1 | template<typename... Types> |
- 函數參數包(function parameter pack):與模板參數包對應的函數參數列表,也用
...表示,如上範例的Types... params代表零個或多個函數參數。
沒錯,這個語法就是這麼直覺,所以以下是個範例:
1 |
|
Output:
1 | sum(1, 2, 3): 6 |
總結
模板特製化(Template Specialization)
模板特製化就是對特定型態提供不同的實作方式,取代一般模板的預設行為。
分有函數跟類別模板特製化。
函數:
1 | template <typename T> void print(T value) { ... } |
類別:
1 | template<typename T> class MyContainer { ... }; |
特製化語法:template<>,而在後面的函數或類別名稱須加上要特製化的資料型態。
非型態模板參數(Template Non-Type Arguments)
可將常數(非型態)作為模板參數。此參數必須在編譯時期即可確定。
可接受的型態:
- 整數型態(
int,size_t等) - 列舉型態(
enum) - 指標或參考(對函式、物件或靜態成員)
- C++20 開始支援浮點數型態。
使用限制:
- 傳入的值必須是編譯期常數(constexpr)
- 不能使用非 constexpr 的變數作為非型態模板參數
範例:
1 | template <class T, int max> // int max 非型態模板參數 |
模板參數推導(Template Argument Deduction)
讓編譯器自動推斷模板參數型態,可不用手動指定 <T> 型態。
函數模板參數推導(C++98 起)
呼叫函數時自動推導:
1 | template <typename T> T display(T value); |
類別模板參數推導(C++17 起)
建構物件時自動推導:
1 | template <typename T> class Box { ... }; |
可變參數模板(Variadic Templates)
可讓模板接收任意數量的參數。
核心概念:
- 模板參數包:
template<typename... Types> - 函數參數包:
Types... args
1 | template<typename T> T sum(T value) { return value; } // 基本模板 |
一覽表
| 特性名稱 | 語法 | 說明 |
|---|---|---|
| 模板特製化 | template<> | 為特定型態提供特製版本 |
| 非型態模板參數 | template<typename T, int N> | 傳入常數當作模板參數 |
| 函數模板參數推導 | display(123) | 編譯器自動推導型態 |
| 類別模板參數推導 | Box b(123) | 建構時自動推導型態(C++17) |
| 可變參數模板 | template<typename... Args> | 接收任意數量參數 |
參考資料
Template Specialization (C++) | Microsoft Learn
C++ template筆記 (六):樣板特製化 - micky85lu的創作 - 巴哈姆特


