首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> 關於C++

C++ 模板完整指南:函數/類模板、特化、分離編譯、模板參數與實戰避坑

     編輯:關於C++

泛型編程與模板定位

模板是 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 必須為編譯期常量。

函數模板特化 vs 重載

// 全特化:針對 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> { /* 指針專用邏輯 */ };
  • 類模板不支持實參推演(C++17 CTAD 除外),必須顯式指定 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 一體化鐵律

方案優點缺點
.hpp 全包含(推薦)零配置、跨平台、編譯器可見所有定義編譯時間略增、頭文件大
顯式實例化 .cpp隱藏實現、加快編譯需預知所有類型、舊編譯器不支持
export 關鍵字標準方案幾乎無編譯器實現(已移除 C++11)

進階技巧:SFINAE、Traits、Concepts (C++20)

// 類型萃取:檢測是否有 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) 強制用模板。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved