Hey there, In this brief article, I'll explain the concept and usage of the templated functions in c++. I'll first introduce you to the problem and then how templated functions provide an elegant solution to it. This is not going to be a long-winded article, but if you're a coffee or tea lover, then grab a cup my friend and let's dive right into it. ☕
Introduction to Templates in C++
Template functions and class templates are one of the many superpowers of C++. By using template-based functions and classes you can generalize your code to handle more data types with less code. It also saves you the hassle of refactoring multiple similar functions by allowing you to just refactor the single templated function or class. For this article, we are going to focus on templated functions only.
The Problem
Consider the following example. We are trying to implement a basic add()
function. To handle different cases for different data-types, we have to overload fundamentally the same function for different data-types, as we need them.
#include <iostream>
int add(int a, int b) {
return a + b;
}
float add(float a, float b) {
return a + b;
}
long add(long a, long b) {
return a + b;
}
int main() {
int result_x = add(10, 20);
int result_y = add(9.7f, 20.3f);
std::cin.get();
return 0;
}
Not only it is a lot of redundant code, but it would also be an absolute nightmare to refactor this kind of code in a large codebase.
Templates to the rescue....
How Templated Functions Resolve This Issue
Templates allow you to write a single function, which will be responsible for handling different data-types. What happens behind the scenes is that when you write a templated function, and then later call it with some data-types in your code. The compiler will see it and will generate function definitions tailored to it own its own, at compile time.
So essentially you have automated what you were doing before manually, and letting the compiler handle it implicitly at compile time.
- No Redundant Code ✔
- Easy To Refactor ✔
Defining A Templated Function
We start by prefixing the function definition with a template<class T>
directive, which essentially informs the c++ compiler, that the following function is template-based, please look out for its function calls in the code and generate function definitions accordingly at compile time.
class T
is similar to a data-type and variable name, only this time it's of a general data-type that will be inferred at compile time.
Here Is, How Our Modified Templated Add Function Looks Like
#include <iostream>
template<class T>
T add(T a, T b) {
return a + b;
}
int main() {
int result_x = add(10, 20);
int result_y = add(9.7f, 20.3f);
std::cin.get();
return 0;
}
We are down from three overloaded functions to only one. A clean and simple solution.
Remember, we have to keep this in the back of our minds, that for it to work the definitions for int
based and a float
based add()
function has to be present at runtime, even though we have not explicitly placed the definitions for an int
and float
based function in our code. At compile time, the compiler will notice that we have called a templated function with an int
and float
parameters. It will then generate these specific definitions for us while replacing T
with the actual data type, which in this case will be int
and float
respectively.
It's also pertinent to mention here, currently, in our add function, we are only working with a single Templated parameter, what that means is, in add(T a, T b)
both a
and b
are of a single data-type,
it could be of int
or float
or something else, but not a combination.
Of course, you can have more than one templated parameter, we just have to update our template definition. So let's say you want to have two different types of parameters. The function definition for this scenario would look something like the following.
#include <iostream>
//consider class T as data-type 1, and class P as data-type 2
template<class T, class P>
//Please note, We could have returned a different datatype, it's up to the programmer
//In the following case we have returned a generic data-type, but we can also return other data types such as int, float, etc
//Its the choice of the programmer to decide what they want to return.
P add(T a, P b) {
return a + b;
}
int main() {
float result_x = add(10, 20.5);
float result_y = add(9.7f, 20.3f);
std::cin.get();
return 0;
}
If you are still not really convinced by the beauty and power of templates, then I highly encourage you to have a look at any of the c++ collections. Like std::vector, you could have a vector of ints or a vector of floats, all thanks to templates.
Final Words
The concept of generics or what c++ calls templates
is very popular in many programming languages. Being a developer you will have to work with generics/templates almost every day. So it's a good idea to learn about it early on with hands-on practice.
Aamir, Out
Do not go gentle into that good night,
Old age should burn and rave at close of day;
Rage, rage against the dying of the light.
Dylan Thomas.
Top comments (0)