Template specialization
Template specialization allows you to customize the behavior of a template for specific data types. This is useful when you need to provide different implementations for certain types or when you want to optimize your code for specific cases.
Function Template Specialization
First, let's start with a generic function template:
template <typename T>
T maxFunc(T a, T b) {
cout << "function template, <T>: ";
return (a > b) ? a : b;
}
We can specialize this function template for the int type to have a different behavior:
template <>
int maxFunc(int a, int b) {
cout << "function template specialization, <int>: ";
return a + b; // This is not the typical behavior of max(), but it illustrates the difference
}
Class Template Specialization
Next, let's define a generic class template:
template <typename T>
class MaxClass {
T a;
T b;
public:
MaxClass(T a, T b) : a(a), b(b) {}
T maxFunc() {
cout << "class template, <T>: ";
return (a > b) ? a : b;
}
};
We can specialize this class template for the int type:
template <>
class MaxClass {
int a;
int b;
public:
MaxClass(int a, int b) : a(a), b(b) {}
int maxFunc() {
cout << "class template specialization, <int>: ";
return a + b;
}
}
Full and Partial Specialization of Class Templates with Multiple Types
When a class template has more than one generic type, you can fully or partially specialize the template. For function templates, only full specialization is supported.
Here is a generic function template with two types:
template <typename T1, typename T2>
void combine(T1 a, T2 b) {
cout << "function template, two types, <T1, T2>: " << a << ", " << b << endl;
}
Function templates can only be fully specialized:
template <>
void combine(int a, int b) {
cout << "function template, two types, full specialization <int, int>: " << a + b << endl;
}
Class templates with multiple types can be partially or fully specialized. Here is a generic class template:
template <typename T1, typename T2>
class MyClass2 {
T1 a;
T2 b;
public:
MyClass2(T1 a, T2 b) : a(a), b(b) {}
void combine() {
cout << "class template, two types, <T1, T2>: " << a << ", " << b << endl;
}
};
Partial specialization for a class template:
template <typename T2>
class MyClass2<int, T2> {
int a;
T2 b;
public:
MyClass2(int a, T2 b) : a(a), b(b) {}
void combine() {
cout << "class template, two types, partial specialization, <int, T2>: " << a * 10 << ", " << b << endl;
}
}
Full specialization for a class template:
template <>
class MyClass2 {
int a;
int b;
public:
MyClass2(int a, int b) : a(a), b(b) {}
void combine() {
cout << "class template, two types, full specialization, <int, int>: " << a + b << endl;
}
}