std::nullptr_t。float/double)、類類型對象 (含自定義結構體)、字符串字面量 (可傳 const char* 但受限)。
// 錯誤示例
template class A; // 浮點數非法
template class B; // C++17 非法,C++20 合法 (若符合條件)
// 正確示例
template class Buffer; // 整型常量
template class Msg; // 字符串地址 (需外部鏈接)
模板實例化需見到定義。編譯器不支持 export 關鍵字 (僅 EDG 前端實現,已從 C++11 標準移除)。
// MyTemplate.h
#ifndef MYTEMPLATE_H
#define MYTEMPLATE_H
template
class MyClass {
public:
void foo(); // 聲明
};
// 定義在頭文件內 (或包含 .inl/.tcc 文件)
template
void MyClass::foo() { /* 實現 */ }
#endif
// MyTemplate.h
template class MyClass; // 聲明
extern template class MyClass; // 告訴編譯器:int 版本在別處實例化
// MyTemplate.cpp
#include "MyTemplate.h"
template class MyClass; // 顯式實例化定義 (僅此處生成代碼)
// 其他類型用戶仍需見到定義 (頭文件含實現) 或自行顯式實例化
// test.h
template class Test { void print(); };
// test.cpp
template void Test::print() { std::cout << "OK"; }
// main.cpp
#include "test.h"
#include "test.cpp" // 直接包含實現文件!極不規範,破壞編譯單元獨立性
int main() { Test t; t.print(); }
缺點:破壞封裝、導致重複編譯、依賴管理混亂、**嚴禁用於生產項目**。
每個模板實例化生成獨立代碼。濫用模板導致二進制體積膨脹。對策:將與類型無關的代碼提取到非模板基類/輔助函數 (Type Erasure / SCARY Iterator 技術)。
inline 變量/函數允許在頭文件定義非模板靜態成員/函數,配合模板使用,減少 .cpp 文件。
// mymodule.ixx (模塊接口單元)
export module mymodule;
export template
class MyClass {
public:
void foo(); // 定義可在模塊內部實現文件,不暴露於頭文件
};
// mymodule_impl.cpp (模塊實現單元)
module mymodule;
template
void MyClass::foo() { /* 實現 */ }
// 用戶端
import mymodule;
MyClass obj; // 直接使用,無需見到定義!
優勢:真正分離接口與實現、編譯極快、無宏/頭文件保護符、無 ODR 違規風險。MSVC/GCC/Clang 已全面支持。
#include <concepts>
template
concept Integral = std::is_integral_v;
template // 僅接受整型
class IntContainer { /* ... */ };
// IntContainer c; // 編譯錯誤:概念檢查失敗,錯誤信息清晰
#include 進頭文件。extern template。enable_if 约束參數。