當模板函數與非模板函數、或多個模板函數重載時,C++ 編譯器遵循嚴格的決議順序:
<> 強制選模板:繞過非模板優先規則。
// 非模板版本
int max(int a, int b) { return a < b ? b : a; }
// 模板版本
template
T max(T a, T b) { return a < b ? b : a; }
int main() {
max(3, 5); // 調用非模板 int max(int,int)
max<>(3, 5); // 顯式空模板參數列表 -> 強制調用模板 max(int,int)
max(3, 5); // 顯式指定 double -> 調用模板 max(double,double)
}
設計啟示:為基本類型提供非模板重載可獲得更好性能/行為控制,但需警惕「隱藏模板」導致泛型代碼調用非預期版本。
template
T max(T a, T b) { return a < b ? b : a; }
int max(int a, int b) { return a < b ? b : a; }
max('c', 42.2);
// 實參類型: char, double
// 模板推導: T 需同時為 char 和 double -> 失敗 -> 模板不參與
// 非模板: char->int 提升, double->int 收窄 -> 匹配 int max(int,int) -> 調用非模板
強制調用模板:max<>('c', 42.2) → 編譯錯誤 (T 無法推導統一類型)。
// 通用模板
template
T const& max(T const& a, T const& b) { return a < b ? b : a; }
// 指針特化模板 (比較指向的值)
template
T const& max(T* const& a, T* const& b) { return *a < *b ? *b : *a; }
// C 風格字符串專用非模板 (比較字典序)
char const* const& max(char const* const& a, char const* const& b) {
return std::strcmp(a, b) < 0 ? b : a;
}
int main() {
int a=7, b=42;
max(a, b); // 通用模板 T=int
std::string s="hey", t="you";
max(s, t); // 通用模板 T=string
int *p1=&a, *p2=&b;
max(p1, p2); // 指針特化模板 T=int (參數類型 int* const&)
char const* s1="David", *s2="Nico";
max(s1, s2); // 非模板 char const* 版本 (精確匹配,優於指針模板)
}
決議細節:max(p1,p2) 同時匹配通用模板 T=int* 和指針模板 T=int。指針模板更特化 (參數類型含 *),勝出。max(s1,s2) 精確匹配非模板 char const*,非模板優先勝出。
max_val, max_ptr) 或命名空間隔離。func<>(args) (空模板參數列表)。std::less<> (透明比較器 C++14) 或自定義比較器,避免重載迷宮。