實作 max()、copy()、reverse()、sort() 等抽象操作時,若針對每種資料型別 (int, double, complex, date...) 編寫獨立函數,不僅重複勞動、易出錯,還造成維護地獄。即使未使用的版本也會膨脹可執行檔體積 (多數編譯器不會移除未引用函數)。
函數模板 型別無關、按需實例化,完美解決上述問題。編譯器根據實際使用型別自動生成具體函數實體 (模板特化)。
// max.h
#ifndef MAX_INCLUDED
#define MAX_INCLUDED
template <class T>
T max(T t1, T t2) {
return (t1 > t2) ? t1 : t2;
}
#endif
template <class T> 宣告型別參數 T (佔位符)。T 被具體型別取代。int n=10, m=16;
int highest = max(n, m); // 生成 int 版本
std::complex<double> c1, c2;
// ... 賦值 ...
std::complex<double> higher = max(c1, c2); // 生成 complex 版本
內建型別 (int, float) 傳值無妨,但使用者定義型別 (std::string, complex) 傳值會觸發昂貴的拷貝建構。且 max 不修改參數,應加 const:
template <class T>
T max(const T& t1, const T& t2) {
return (t1 > t2) ? t1 : t2;
}
STL <algorithm> 已提供 std::max(),生產代碼請直接使用。下文以更實戰的位元組序反轉為例展示模板威力。
byte_reverseTCP/IP 要求 Big Endian (網路位元組序)。小端序主機 (x86) 需轉換。傳統 Socket API 提供 4 個函數:
unsigned int htonl(unsigned int); // Host-to-Network Long
unsigned short htons(unsigned short); // Host-to-Network Short
unsigned int ntohl(unsigned int); // Network-to-Host Long
unsigned short ntohs(unsigned short); // Network-to-Host Short
本質相同:反轉多位元組值的位元組順序。差別僅在方向與大小。極適合模板化。
#include <algorithm> // std::reverse
template <class T>
T byte_reverse(T val) {
// 將 val 視為位元組流
unsigned char* p = reinterpret_cast<unsigned char*>(&val);
std::reverse(p, p + sizeof(val)); // 反轉位元組
return val;
}
sizeof(val) 自動適應型別大小 (2/4/8/16 位元組)。reinterpret_cast 安全轉型為位元組指標。std::reverse 高效原地反轉。int main() {
int n = 1;
short k = 1;
__int64 j = 2, i;
int m = byte_reverse(n); // 反轉 int (4 bytes)
int z = byte_reverse(k); // 反轉 short (2 bytes) → int
k = byte_reverse(k); // 反轉 short → short (截斷/擴展視賦值型別)
i = byte_reverse(j); // 反轉 __int64 (8 bytes) - 無需修改代碼!
}
優勢:單一模板處理所有現有與未來整數型別 (含 128-bit),零維護成本。
模板濫用會導致代碼膨脹:每個具體型別實例化都生成獨立機器碼。對策:
作者簡介:Danny Kalev,認證系統分析師,C++ 標準委員會前成員 (1997-2000),專攻 C++ 與形式語言理論。定期為 C++ 技術網站撰稿並授課。