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

C++ 模板階段性總結:從實例化機制到元編程核心技法

     編輯:關於C++

核心認知:模板非類別/函式,而是「模具」

template 
class AutoList { ... }; // AutoList 是模板,非類型

AutoList myList; // 錯誤:缺少模板參數
AutoList intList;   // 正確:實例化為具體類型 AutoList
AutoList longList; // 另一個獨立類型

編譯器根據模板參數實例化生成具體代碼。每組參數生成一份代碼——代碼膨脹風險需注意。

模板函式與 inline

template  inline T test(const T&); // 正確
inline template  T test(const T&); // 錯誤:inline 必須在 template 之後

模板實參推演與隱式轉換

  • 推演過程不進行隱式類型轉換匹配現有實例,而是生成新實例。
  • 陣列參數加引用(T (&)[N])可保留大小資訊,避免退化為指標導致類型不匹配。
  • const 轉換規則:非 const 實參可傳給 const 引用/指標參數(安全);傳值參數忽略 const。

編譯模型:包含模型

  • 僅在使用模板時實例化。
  • 編譯器需可見模板定義源碼(通常放在頭文件)。
  • 分離編譯模型(export)已被 C++ 標準移除。

非類型模板參數

template 
class Test { ... };
Test<80, 60> obj; // 實參必須為編譯期常數表達式

模板特化與進階技巧

1. 模板參數本身為模板

template  class Container = vector>
class MyStack { ... };

2. 顯式實例化:分離聲明與定義

// .h
template  class Test { void setData(const T&); T getData(); };
// .cpp
template  void Test::setData(const T& v) { ... }
template  T Test::getData() { ... }
template class Test; // 顯式實例化 int 版本

模板元編程:編譯期計算

template 
struct Factorial { enum { value = N * Factorial::value }; };
template <> struct Factorial<0> { enum { value = 1 }; };

Factorial<5>::value; // 編譯期得到 120

將運算從執行期遷移至編譯期,提前發現錯誤,提升執行效能(代價:編譯時間變長)。

隱式介面與編譯期多態

// 顯式介面 + 執行期多態
void doProcessing(Widget& w) { if (w.size() > 10) { Widget tmp(w); tmp.normalize(); tmp.swap(w); } }

// 隱式介面 + 編譯期多態
template 
void doProcessing(T& w) { if (w.size() > 10) { T tmp(w); tmp.normalize(); tmp.swap(w); } }
  • 顯式介面基於函式簽名;隱式介面基於有效表達式。
  • 隱式介面更靈活:w != nasty 不要求 T 有 operator!=,只要存在可轉換的比較運算子即可。

typename 雙重含義

  • 模板參數列表中 class 與 typename 等價。
  • 嵌套從屬類型名稱前必須加 typename 告訴編譯器這是型別:
template 
void print2nd(const C& container) {
    typename C::const_iterator* x; // 必須加 typename
    // ...
}

例外:基類列表、成員初始化列表中的基類修飾符不可加 typename。

SFINAE:替換失敗非錯誤

模板函式多載解析時,若模板實參替換導致無效型別/運算式,編譯器不報錯,直接從多載集移除該候選,嘗試其他多載。核心技術:

typedef char TrueType;
struct FalseType { char a[2]; };

template  static TrueType TestIsClass(int C::*); // 類型有成員指標
template  static FalseType TestIsClass(...);     // 通配

template 
struct IsClass {
    enum { OK = (sizeof(TestIsClass(0)) == sizeof(TrueType)) };
};

編譯期判斷 T 是否為類類型。SFINAE 讓「非類型」匹配通配版本,避免硬錯誤。

結語

模板揭示了 C++ 泛型編程的博大精深。從實例化機制、推演規則、元編程到 SFINAE,每一層都值得深入探索。泛型編程與面向對象並重,構成現代 C++ 的雙輪驅動。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved