C++ 模板參數分為三大類,理解它們的區別是掌握模板元編程與泛型庫設計的基礎。
| 參數類型 | 關鍵字 | 實參形式 | 典型用途 |
|---|---|---|---|
| 類型參數 | typename / class | 類型名:int, MyClass, std::vector | 泛型算法、容器、智能指針 |
| 非類型參數 | auto (C++17) / 具體類型 | 編譯期常量:42, sizeof(int), &global_var, lambda | 固定大小數組、編譯期計算、策略配置 |
| 模板模板參數 | template<...> typename | 模板名:std::vector, MyAllocator | 容器適配器、分配器感知容器 |
// 模板參數列表 (編譯期確定)
template <typename T1, typename T2, typename RT>
// 函數調用參數列表 (運行期傳遞)
inline RT const& max(T1 const& a, T2 const& b)
// 返回類型 RT 是模板參數,但非調用參數!
// 調用時無法從實參推導 RT,必須顯式指定
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
// 強制實例化為 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 (推導)
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 非常量表達式
std::nullptr_t。const char*)。
template
class Buffer { /* ... */ };
Buffer<> b1; // Buffer
Buffer b2; // Buffer
Buffer b3; // Buffer
struct Config 聚合參數。enable_if,提升錯誤信息可讀性。