模板是 C++ 靜態多態的核心,實現編譯期代碼生成,兼具泛型復用性與零抽象開銷。STL 即建立在模板之上。
template <typename T> // typename 推薦於 class
T max(T a, T b) { return a > b ? a : b; }
max(3,5) → 推演 T=int,實例化 int max(int,int)。max<double>(3,5) 強制實例化 double 版本。template <typename T, size_t N> class Array,N 必須為編譯期常量。// 全特化:針對 const char* 比較內容而非地址
template <>
const char* max<const char*>(const char* a, const char* b) {
return strcmp(a,b) > 0 ? a : b;
}
// 重載:普通函數優先於模板
const char* max(const char* a, const char* b) { ... }
規則:同名普通函數優先;模板特化不參與重載解析,僅在模板被選中後匹配。建議:優先用重載,少寫特化。
template <typename T, size_t CAP = 100>
class Stack {
T data[CAP]; size_t top = 0;
public:
void push(const T& x) { data[top++] = x; }
T pop() { return data[--top]; }
};
// 全特化:針對 bool 壓縮存儲
template <size_t CAP>
class Stack<bool, CAP> { /* bitset 實現 */ };
// 偏特化:指針類型
template <typename T, size_t CAP>
class Stack<T*, CAP> { /* 指針專用邏輯 */ };
Stack<int>。template<typename T,size_t CAP> void Stack<T,CAP>::push(...)。template <typename T,
template <typename> class Container = std::vector>
class Stack {
Container<T> c;
public:
void push(const T& x) { c.push_back(x); }
// ...
};
Container 接受單一類型參數,可傳 vector、deque、list 甚至自定義 SeqList。
| 方案 | 優點 | 缺點 |
|---|---|---|
| .hpp 全包含(推薦) | 零配置、跨平台、編譯器可見所有定義 | 編譯時間略增、頭文件大 |
顯式實例化 .cpp | 隱藏實現、加快編譯 | 需預知所有類型、舊編譯器不支持 |
export 關鍵字 | 標準方案 | 幾乎無編譯器實現(已移除 C++11) |
// 類型萃取:檢測是否有 push_back
template <typename T, typename = void>
struct has_push_back : false_type {};
template <typename T>
struct has_push_back<T, void_t<decltype(declval<T>().push_back(1))>> : true_type {};
// C++20 Concept 寫法
template <typename T>>
concept PushBackable = requires(T c, int x) { c.push_back(x); };
template <PushBackable Container>
void foo(Container& c) { c.push_back(42); }
undefined reference to `Stack<int>::push(int)' → 模板定義未在頭文件。template argument 2 is invalid → 非類型參數傳了非常量。ambiguous overload → 普通函數與模板同時匹配,加 max<>(a,b) 強制用模板。