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

C++ 模板參數詳解:類型參數、非類型參數、模板參數與調用參數區別

     編輯:C++ 入門

模板參數分類總覽

C++ 模板參數分為三大類,理解它們的區別是掌握模板元編程與泛型庫設計的基礎。

參數類型關鍵字實參形式典型用途
類型參數typename / class類型名:int, MyClass, std::vector泛型算法、容器、智能指針
非類型參數auto (C++17) / 具體類型編譯期常量:42, sizeof(int), &global_var, lambda固定大小數組、編譯期計算、策略配置
模板模板參數template<...> typename模板名:std::vector, MyAllocator容器適配器、分配器感知容器

模板參數 vs 調用參數:關鍵區別


// 模板參數列表 (編譯期確定)
template <typename T1, typename T2, typename RT>

// 函數調用參數列表 (運行期傳遞)
inline RT const& max(T1 const& a, T2 const& b)

// 返回類型 RT 是模板參數,但非調用參數!
// 調用時無法從實參推導 RT,必須顯式指定

參數推導與顯式實例化

1. 隱式推導 (最常用)


template
T max(T a, T b) { return a < b ? b : a; }

int i = max(3, 5);        // T 推導為 int
double d = max(3.14, 2.7); // T 推導為 double
// max(3, 3.14);         // 錯誤:T 無法同時推導為 int 和 double

2. 顯式指定模板參數


// 強制實例化為 double 版本,實參隱式轉換
double d = max(3, 3.14); // 3 -> 3.0

// 部分顯式指定 (從左到右,C++17 允許模板參數默認值配合)
template
RT max(T1 a, T2 b);

max(3, 4); // RT=double, T1=int, T2=int (推導)

3. 非類型參數實戰:固定大小棧數組


template // N 為非類型參數 (編譯期常量)
class StackArray {
    T data_[N];
    size_t top_ = 0;
public:
    void push(const T& v) { 
        // 可選:靜態斷言防止溢出
        static_assert(N > 0, "Size must be > 0");
        data_[top_++] = v; 
    }
    T pop() { return data_[--top_]; }
};

StackArray s1; // 100 元素棧
StackArray s2; // 50 元素棧
// StackArray s3; // 錯誤:n 非常量表達式

非類型參數限制 (C++20 前)

  • 允許:整型 (含枚舉)、指針/引用 (指向靜態存儲期對象)、std::nullptr_t。
  • 禁止:浮點數、類類型對象、字符串字面量 (指針可傳地址但類型為 const char*)。
  • C++20 重大突破:允許結構體類型作為非類型參數 (需滿足字面類型、強結構相等)。

模板參數默認值


template
class Buffer { /* ... */ };

Buffer<> b1;       // Buffer
Buffer b2; // Buffer
Buffer b3; // Buffer

實戰建議

  1. 優先用類型參數 實現泛型。
  2. 非類型參數 用於編譯期常數配置 (如緩衝區大小、對齊值、策略標誌)。
  3. 返回類型無法推導時 (如工廠函數、轉換函數),設計為模板參數並顯式指定。
  4. 避免過度參數化:參數過多導致代碼膨脹、編譯緩慢、報錯難讀。考慮 struct Config 聚合參數。
  5. C++20 Concepts 約束模板參數,替代 enable_if,提升錯誤信息可讀性。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved