C++泛型编程
1. 基本概念
1.1 泛型编程(Generic Programming)
泛型编程是C++中一种重要的编程范式,它通过 参数化类型 来实现代码的通用性和复用性。
1.2 模板(Templates)
模板 是泛型编程的基础,允许编写与数据类型无关的代码。
模板分类:
-
函数模板:参数化函数的参数类型。
-
类模板:参数化类的成员类型。
-
使用
template
关键字声明模板,typename
或class
声明模板类型,代表一个占位符类型,将在实例化时被具体类型替换。
template<typename T1 , typename T2 , ...>
2. 函数模板
2.1 函数模板语法
template<typename T>
void function( T arg1, T arg2 ) {// ...
}
2.2 函数模板的实例化
函数模板的实例化分为隐式实例化和显示实例化。
-
隐式实例化:编译器根据形参推演模板参数的实际类型。
-
显示实例化:在函数名后<>中指定模板参数的实际类型。
template<typename T>
T add(const T& x , const T& y) {return x + y;
}int main () {add(10 , 20); // 隐式实例化 T为intadd(1.1 , 2.2); // 隐式实例化 T为double// add(10 , 1.1); // 编译不通过,因为无法确定T为 int 还是 double 类型add<int>(10 , 1.1); // 通过显示实例化解决return 0;
}
注意:对于非模板函数和同名函数模板,如果其他条件都相同,会优先调用非模板函数。
3. 类模板
3.1 类模板语法
template<typename T1 , typename T2 , ...>
class ClassName {// ...
};
3.2 类模板的实例化
类模板必须显示实例化。
template<typename T>
class vector {// ...private:T* start = nullptr;T* finish = nullptr;T* end_of_storage = nullptr;
};int main () {// 显示实例化vector<int> v1; vector<double> v1; return 0;
}
4. 非类型模板参数
非类型模板参数是C++模板中一种特殊的参数类型,它允许在编译时传递值而不是类型作为模板参数。
非类型模板参数可以是以下类型之一
-
整型
-
指针或引用类型
-
C++20起支持浮点类型作为模板参数
-
C++20起支持类类型作为模板参数
template<typename T, size_t N = 10>
class Array {// ...T arr[N];
};int main () {Array<> arr1; // 使用缺省值的写法Array<5> arr2;Array<15> arr3; return 0;
}
5. 模板的特化
模板特化是C++中为特定类型提供的模板定制。它允许我们为特定类型提供优化的或不同的实现,同时保留通用模板的灵活性。
5.1 函数模板的特化
函数模板也可以特化,但通常更推荐使用函数重载。
函数模板特化步骤
-
特化必须声明在主模板之后。
-
关键字template后面接一对空的尖括号<>。
-
函数名后跟一对尖括号,尖括号中指定需要特化的类型。
-
特化模板的函数形参必须要和基础模板的函数形参完全相同。
template<typename T>
bool less(T left , T right) {return left < right;
}// 对 int* 特殊化处理
template<>
bool less<int*>(int* left , int* right) {return *left < *right;
}// 更推荐使用函数重载
bool less (int* left , int* right) {return *left < *right;
}
注意:函数模板不能偏特化,但可以通过函数重载实现。
5.2 类模板的特化
类模板特化分为全特化和偏特化两种形式。
-
全特化:为模板的所有参数指定具体类型或值,完全特化整个模板。
-
偏特化:只特化部分模板参数,或者对模板参数施加某种模式或约束。
5.2.1 全特化
// 主模板定义
template <typename T1, typename T2>
class MyClass {// 通用实现
};// 全特化
template <>
class MyClass<int, double> {// 针对<int, double>的特化实现
};
5.2.2 偏特化(特化部分模板参数)
// 主模板定义
template <typename T1, typename T2>
class MyClass {// 通用实现
};// 偏特化/半特化
template <typename T1>
class MyClass<T1, double> {// 针对<T1, double>的特化实现
};
注意:全特化和偏特化都存在时,全特化版本比偏特化版本具有更高的优先级。
5.2.3 偏特化(对模板参数施加某种约束)
// 主模板定义
template <typename T1, typename T2>
class MyClass {// 通用实现
};// 偏特化/半特化
template <typename T1 , typename T2>
class MyClass<T1*, T2*> {// 针对<T1*, T2*>的特化实现
};// 偏特化/半特化
template <typename T1 , typename T2>
class MyClass<T1&, T2&> {// 针对<T1&, T2&>的特化实现
};