模板特化详解与示例代码
1. 模板特化时类型模板参数减少
模板特化时,特化版本可以比主模板有更少的模板参数。
cpp
// 主模板 template <typename T, typename U> class MyPair {T first;U second; public:MyPair(T f, U s) : first(f), second(s) {} };// 特化版本 - 减少一个类型参数 template <typename T> class MyPair<T, int> { // 当第二个类型是int时的特化T first;int second; public:MyPair(T f, int s) : first(f), second(s * 2) {} // 对int特殊处理 };int main() {MyPair<double, char> p1(1.1, 'a'); // 使用主模板MyPair<double, int> p2(1.1, 5); // 使用特化版本,second会变成10 }
2. 全特化时类型模板参数消失
全特化是完全指定所有模板参数,不需要任何模板参数了。
cpp
// 主模板 template <typename T, typename U> class Calculator { public:static T add(T a, U b) { return a + b; } };// 全特化 - template<> 没有模板参数 template <> class Calculator<int, int> { public:static int add(int a, int b) { std::cout << "Using int-int specialization\n";return a + b; } };int main() {Calculator<double, int>::add(1.5, 2); // 使用主模板Calculator<int, int>::add(3, 4); // 使用全特化版本 }
3. 偏特化不只是特化某个参数,也可以特化参数类型
偏特化可以特化参数的类型模式,而不仅仅是具体类型。
cpp
// 主模板 template <typename T> class Container { public:void print() { std::cout << "Generic Container\n"; } };// 偏特化 - 针对指针类型的特化 template <typename T> class Container<T*> { public:void print() { std::cout << "Pointer Container\n"; } };// 偏特化 - 针对模板类型的特化 template <typename T> class Container<std::vector<T>> { public:void print() { std::cout << "Vector Container\n"; } };int main() {Container<int> c1; // 使用主模板c1.print(); // 输出: Generic ContainerContainer<int*> c2; // 使用指针特化c2.print(); // 输出: Pointer ContainerContainer<std::vector<double>> c3; // 使用vector特化c3.print(); // 输出: Vector Container }
4. 函数模板特化的参数处理
函数模板特化时,参数可以显式指定、推导或使用缺省值。
cpp
// 主模板 template <typename T, typename U = int> void func(T a, U b = 0) {std::cout << "Primary template: " << a << ", " << b << "\n"; }// 显式特化 - 所有参数显式指定 template <> void func<double, double>(double a, double b) {std::cout << "Specialization for double, double: " << a + b << "\n"; }// 显式特化 - 推导给 template <> void func(char a, int b) {std::cout << "Specialization for char, default int: " << std::string(b, a) << "\n"; }int main() {func(1, 2); // 使用主模板,推导T=int, U=intfunc(1.0, 2.0); // 使用double,double特化func('a', 5); // 使用char特化,U使用缺省intfunc(1.0f, 2); // 使用主模板,T=float, U=int }
5. 类模板特化的参数处理
类模板特化时,参数可以显式指定或使用缺省值。
cpp
// 主模板 template <typename T, typename U = char, int N = 10> class Box { public:void print() {std::cout << "Primary Box: " << typeid(T).name() << ", " << typeid(U).name() << ", " << N << "\n";} };// 全特化 - 所有参数显式指定 template <> class Box<double, float, 20> { public:void print() {std::cout << "Specialized Box for double, float, 20\n";} };// 偏特化 - 部分参数使用缺省值 template <typename T> class Box<T, short> { public:void print() {std::cout << "Partial specialization for " << typeid(T).name() << ", short, 15\n";} };// 偏特化 - 使用缺省参数 template <typename T, int N> class Box<T, char, N> { public:void print() {std::cout << "Partial specialization for " << typeid(T).name() << ", char, " << N << "\n";} };int main() {Box<int, long, 5> b1; // 使用主模板b1.print();Box<double, float, 20> b2; // 使用全特化b2.print();Box<std::string, short, 15> b3; // 使用偏特化b3.print();Box<bool, char, 8> b4; // 使用偏特化 (T=bool, U=char缺省, N=8)b4.print();Box<float> b5; // 使用主模板 (T=float, U=char缺省, N=10缺省)b5.print(); }
总结
-
模板特化可以减少模板参数数量
-
全特化使用
template<>
且没有模板参数 -
偏特化可以特化参数的类型模式(如指针、容器等)
-
函数模板特化参数可以显式指定、推导或使用缺省值
-
类模板特化参数可以显式指定或使用缺省值