Similar to function templates, C++ allows us to create template for class types such as struct, classes and array. Consider the following program where a struct Collection can contain values of type int, double or any other type. We can’t define Collection for different types. We can use class template.
template <typename T>
struct Collection
{
T a;
T b;
};We can create instance of Collection like below.
Collection<int> c {1, 2};
Collection<double> d {4.34, 2.21};Similar to function templates, compiler will instantiate concrete structs from the template by replacing T when it comes to the use case. So, it creates definition for Collection<int> and Collection<double>.
What eventually compiler compiles after the instantiation is done, is:
// declaration Collection template.
// does not require definition.
template <typename T>
struct Collection;
// tells compiler that it is a template type with no template params
template <>
struct Collection<int>
{
int a;
int b;
};
template <>
struct Collection<double>
{
double a;
double b;
};
int main(int argc, char const *argv[])
{
Collection<int> c {1, 2}; // instantiate Collection<int> and create object c
Collection<double> d {4.34, 2.21}; // instantiate Collection<double> and create object d
return 0;
}Passing class template as parameter to function
Let’s say we want to print Collection<int> and Collection<float>, we can overload the function as shown below.
void printCollection(Collection<int> p)
{
std::cout << "{" << p.a << ", " << p.b << "}" << "\n";
}
void printCollection(Collection<double> p)
{
std::cout << "{" << p.a << ", " << p.b << "}" << "\n";
}If we want to create Collection of other types, we need to define their functions as well, which would be redundant. We can use function template to solve this issue.
template <typename T>
void printCollection(Collection<T> p)
{
std::cout << "{" << p.a << ", " << p.b << "}" << "\n";
}We can call the function the usual way as shown below,
printCollection<double>(Collection<double>{3.5, 4.2});
printCollection(Collection<int>{1, 2}); // let the compiler do the template type argument deductionClass templates with multiple template types
Class templates can also have multiple template types. We can modify Collectiontemplate to support it to store values of two types as shown below.
template <typename T, typename U>
struct Collection
{
T a;
U b;
};
Collection<int, double> c{1, 2.3};We can also update function template to support this as shown below,
template <typename T, typename U>
void printCollection(Collection<T, U> p)
{
std::cout << "{" << p.a << ", " << p.b << "}" << "\n";
}
printCollection(Collection<int, double>{1, 2.3});
printCollection<double, int>(Collection<double, int>{3.5, 4});