函數模板提供了一種泛型函數行為,可接受多種不同型別的呼叫。它代表一個函數家族,函數的具體型別在使用時才由模板參數決定。簡單說,函數模板讓你寫一次邏輯,編譯器自動為不同型別生成對應的函數實例。
template <typename T>
T max(T const& a, T const& b) {
return a < b ? b : a;
}
此模板定義了「回傳兩值中較大者」的函數家族。參數型別由 T 代替,實際型別在呼叫時推導。typename 可用 class 替換,但建議使用 typename 語意更清晰。
#include <iostream>
#include <string>
template <typename T>
T max(T const& a, T const& b) {
return a < b ? b : a;
}
int main() {
int i = 10, j = 20;
std::cout << "max(int): " << ::max(i, j) << std::endl;
double f1 = 3.14, f2 = 2.71;
std::cout << "max(double): " << ::max(f1, f2) << std::endl;
std::string s1 = "apple", s2 = "banana";
std::cout << "max(string): " << ::max(s1, s2) << std::endl;
return 0;
}
編譯器根據實參型別推導模板參數。若呼叫 max(4, 4.2),T 需同時匹配 int 和 double,導致編譯錯誤。解決方法有三種:
max(static_cast<double>(4), 4.2);max<double>(4, 4.2);template <typename T>。max(T const& a, T const& b)。可宣告任意數量模板參數,但函數模板內部無法指定預設參數。
// 兩個輸入型別,一個回傳型別
template <typename T1, typename T2, typename RT>
RT max(T1 const& a, T2 const& b) {
return a < b ? b : a;
}
// 僅顯式指定第一個參數,其餘由推導得出
template <typename RT, typename T1, typename T2>
RT max(T1 const& a, T2 const& b) {
return a < b ? b : a;
}
可針對特定型別提供特化版本,例如指標與 C 風格字串:
#include <iostream>
#include <cstring>
template <typename T>
T const& max(T const& a, T const& b) {
return a < b ? b : a;
}
// 指標版本:比較指向的值
template <typename T>
T const* max(T const* a, T const* b) {
return *a < *b ? b : a;
}
// C-string 版本:使用 strcmp
inline char const* max(char const* a, char const* b) {
return std::strcmp(a, b) < 0 ? b : a;
}
// 三參數版本
template <typename T>
T const& max(T const& a, T const& b, T const& c) {
return max(max(a, b), c);
}
重載時應僅修改必要部分。若 C-string 版本改用傳值而非傳參考:
inline char const* max(char const* a, char const* b) {
return std::strcmp(a, b) < 0 ? b : a;
}
template <typename T>
T max(T a, T b, T c) { // 傳值
return max(max(a, b), c);
}
呼叫 max(s1, s2, s3) 時,內層 max(a, b) 回傳臨時物件,外層以參考接收導致懸空參考。正確做法:保持參考傳遞,或針對指標/字串特化。
typename,參數採 const& 避免不必要拷貝。