Template Types are an important part of Generic Programming in C++, along with Function overloading. The goal of generic programming is to make your code more flexible, so that it can work with all data types. The goal is to use templates to write code, that can be reused for data of any type without any adjustment.
What is Generic Programming?
Imagine you wanted to add two integers together, so you made a function called add(int, int). Now you also want to add two floats, so you create a function, add(float, float). And then you also want to add two doubles, so you make another function called add(double, double). And so on.
Sounds boring and tedious right? That’s because it is. To counter this repetitiveness and redundancy, C++ introduced the concept of Generic Programming, with Templates types as it’s foundation.
Generic Programming and Templates introduce the idea of type independent code, where we create a blueprint of sorts, and then pass in types to that blueprint. The code then automatically accounts for the types, and the correct operations are applied. Basically what I’m trying to say, we just make a standard blueprint, which works for any type that you pass into it.
Templates Types in C++
Chances are that you’ve already used templates in C++ before. The most common examples are Vectors, and Smart Pointers, both of which are actually templates.
vector<int> vec;
shared_ptr<string> ptr;
As you can see in the example above, we create a vector which holds int values, and a shared pointer which can point to a string. We can actually initialize them with any type, not just int and string. You can even use Custom classes that you have created. This is the essence of Generic programming.
In this tutorial, ,we will focus more on creating templates ourselves. If you are interested in learning more about Vector and Shared Pointers, you can follow the included links to their respective tutorials.
Creating Templates in C++
For our first example, let’s try and solve the problem I mentioned earlier about the add()
functions. Using templates, I have created an add function that will work for any numerical data type, such as Integers, doubles and floats.
template<typename T>
T add(T v1, T v2) {
return v1 + v2;
}
int main() {
cout << add(4,2) << endl;
cout << add(5.5, 4.3) << endl;
}
You can see the correct output being displayed.
6
9.8
Let us now explain the syntax for the function template.
A template definition starts with the keyword template
, followed by a template parameter list. This parameter list contains the templates parameters which are going to be used. There must be atleast one parameter in this list. Similar to how a regular functions parameters represent values, the parameters in the template list represent types.
The reason why we have template<typename T>
, is because we are only using one type throughout the function. Yes, there are two parameters in the function, but both have the same type, T
. If we wanted to use two different types, we would have included two parameters in the list.
Next up is the function definition.
T add(T v1, T v2)
We have T before the function name to define the return type. Furthermore, we use T to define the type of the two function parameters. T basically represent the datatype of the values that will be passed. It will change depending on what data is entered. In the above code, both parameters are of type T, as well as the return type (as we want to return the data as well).
Template Example
Another popular use of the Template function would be for swapping. Using the regular approach, you would have to define a new swap function for every datatype you wish to swap. But with Templates, you just define one that can handle anything.
template <typename T>
void Swap(T &n1, T &n2)
{
T temp = n1;
n1 = n2;
n2 = temp;
}
int main() {
int x = 5;
int y = 10;
Swap(x, y);
cout << "X: " << x << endl;
cout << "Y: " << y << endl;
}
Try running the code for yourself, and try putting in all kinds of things, even objects from custom classes.
Class Templates
We have now covered function templates, so let’s move on to class templates types in C++. Class templates are what Vectors and Smart Pointers are. Just like Function templates, we can use class templates in C++ to create classes with generic types. This way that class/object can work with any type passed into it.
The below example is the best we could do without getting too complicated. It’s also builds on the previous concept of function overloading with the add()
and subtract()
functions.
template<typename T>
class Calculator{
private:
T num1;
T num2;
public:
Calculator(T t1, T t2) {
num1 = t1;
num2 = t2;
}
T add() {
return num1 + num2;
}
T subtract() {
return num1 - num2;
}
};
int main() {
Calculator<int> calc(6, 2);
cout << calc.add() << endl;
cout << calc.subtract() << endl;
}
As you can see, there is little change, except that we declare the template parameter list above the class instead. This allows us to use any of the parameters in the list within the class. You can see that we use T in the example above, as the data type for almost everything in the class.
Try running this code with other numerical types!
Variadic Templates
There is another type of “templates” that we can use called Variadic templates. This a technique which allows you to create functions that can take an arbitrary number of parameters. It basically works by passing in what we call a “Variadic Argument”, which is similar to a dynamic array that stores all the arguments.
Follow the link to our Variadic Templates Tutorial to learn more.
This marks the end of the C++ Template Types Tutorial. Any suggestions or contributions for CodersLegacy are more than welcome. Questions regarding the tutorial content can be asked in the comments section below.