在C++开发中,我们经常遇到需要为不同类型实现相同逻辑的情况。比如交换两个变量的值,无论是int、double还是自定义类,算法逻辑完全一致。传统C语言中常见的两种实现方式各有明显缺陷:
宏代码块方案:
cpp复制#define SWAP(a, b) { typeof(a) temp = a; a = b; b = temp; }
注意:虽然typeof是GCC扩展,但这里展示了宏的典型问题——缺乏类型安全检查,且调试困难
函数重载方案:
cpp复制void swap(int& a, int& b) { /*...*/ }
void swap(double& a, double& b) { /*...*/ }
// 需要为每种类型重复编写
函数模板的诞生正是为了解决这种困境。通过template关键字定义的模板函数,本质上是一个"函数生成器",编译器会根据调用时的具体类型实例化出对应的函数版本。这种机制实现了:
当编译器遇到模板函数调用时,会执行两步关键操作:
cpp复制template <typename T>
void swap(T& a, T& b) {
T temp = a;
a = b;
b = temp;
}
int main() {
int x = 1, y = 2;
double m = 1.1, n = 2.2;
swap(x, y); // 生成swap<int>版本
swap(m, n); // 生成swap<double>版本
}
编译器通过以下规则确定模板参数类型:
swap<int>(a,b)语法可强制使用模板重要限制:函数模板不支持隐式类型转换。例如
swap(1, 2.0)会导致编译错误,因为无法确定T是int还是double
模板可以接受多个类型参数,实现更灵活的泛型编程:
cpp复制template <typename Ret, typename T1, typename T2>
Ret add(T1 a, T2 b) {
return static_cast<Ret>(a + b);
}
// 使用示例
double result = add<double, int, float>(5, 3.2f);
模板函数可以像普通函数一样被重载,形成更强大的多态体系:
cpp复制// 基础版本
template <typename T>
void print(T value) {
cout << value << endl;
}
// 数组特化版本
template <typename T, size_t N>
void print(T (&arr)[N]) {
for(auto& item : arr) {
cout << item << " ";
}
cout << endl;
}
// 指针特化版本
template <typename T>
void print(T* ptr, size_t size) {
for(size_t i=0; i<size; ++i) {
cout << ptr[i] << " ";
}
cout << endl;
}
结合type_traits可以实现编译期类型判断:
cpp复制template <typename T>
void process(T value) {
if constexpr (std::is_integral_v<T>) {
// 整数类型特有处理
} else if constexpr (std::is_floating_point_v<T>) {
// 浮点类型特有处理
} else {
// 其他类型处理
}
}
让我们实现一个完整的类型无关排序方案:
cpp复制template <typename T>
void bubbleSort(T arr[], size_t size) {
for(size_t i=0; i<size-1; ++i) {
for(size_t j=0; j<size-i-1; ++j) {
if(arr[j] > arr[j+1]) {
swap(arr[j], arr[j+1]);
}
}
}
}
// 支持自定义比较器
template <typename T, typename Compare>
void bubbleSort(T arr[], size_t size, Compare comp) {
for(size_t i=0; i<size-1; ++i) {
for(size_t j=0; j<size-i-1; ++j) {
if(comp(arr[j], arr[j+1])) {
swap(arr[j], arr[j+1]);
}
}
}
}
使用示例:
cpp复制// 内置类型排序
int intArr[] = {5,2,9,1,5};
bubbleSort(intArr, 5);
// 自定义类型排序
struct Person {
string name;
int age;
bool operator>(const Person& other) const {
return age > other.age;
}
};
Person people[3] = {{"Alice",30}, {"Bob",25}, {"Charlie",35}};
bubbleSort(people, 3);
// 使用自定义比较器
bubbleSort(people, 3, [](const Person& a, const Person& b) {
return a.name > b.name;
});
cpp复制template void swap<int>(int&, int&);
C++17引入的if constexpr和C++20的概念(concept)大大改善了模板编程体验:
cpp复制// C++20概念示例
template <typename T>
concept Addable = requires(T a, T b) {
{ a + b } -> std::same_as<T>;
};
template <Addable T>
T sum(T a, T b) {
return a + b;
}
在实际工程中,函数模板最常见的应用场景包括:
掌握函数模板不仅能让代码更简洁高效,更是理解STL设计思想的基础。建议从简单工具函数开始实践,逐步过渡到更复杂的模板元编程技术。