Welcome to the world of C++ Templates, a powerful but lesser-used feature of the C++ language, which can significantly improve developing clean code in any large or small-scale project. A template is essentially a design of a function or a class using generic data type. It empowers the programmer to write generic code which can work with different data types. This chapter will introduce you to the concept of templates with a brief history to understand where it all started. This chapter will act as the foundation for future chapters and take you gradually to the deeper details about templates.
Brief history of templates
The concept of templates is not new in C++. The consideration to incorporate templates as a feature started in the early ’80s. The first formal proposal for templates came in the mid-’80s. The feature was implemented in the year 1991. Since then, the templates have evolved continuously and become a significant part of the C++ programming paradigm. In the following year (1992), some additional features were added: template instantiation and member template.
Alongside, works were ongoing to develop a standard library since the late ’70s. In 1998, Standard Template Library (STL) was first incorporated into the language. Almost everything in STL is written in templates. Later, C++11 brought in some significant new features such as variadic templates and alias templates. C++14 introduced new features such as variable templates and generic lambdas (related to templates). Then C++17 further introduced features such as “Compile-time if” and Class template argument deduction. With this basic information of templates’ evolution, let us understand the importance of templates in C++ programming in the next section.
Why do we need templates?
Templates are the way to generic programming. What does that mean? For example, let‘s say you want to find a minimum of two numbers. To achieve this, what are the different things coming into your mind? You might possibly be thinking about the following list of things at this point:
- That you will accomplish this by writing a function that takes two numbers as input.
- The types of the data for the two input numbers
- The internal logic to determine the minimum of the two numbers.
If the data types of the input numbers change, you must rewrite the same function. It needs to accommodate the new data types. If there are three different types of data you need to work with (e.g. int, double, char), you need to write three different versions of the same function which is not a very elegant solution.
Let’s say you have written a function that returns a minimum of two integers. Now you realize you have to do the same for two doubles. You need to write a function that would return a minimum of two doubles. The internal logic of these two versions of the functions is identical, but the input data type is different. The possible implementation of the same could be as follows:

The two versions of the min() function we implemented perform the same task. However, they use different data types, namely int and double. This creates redundant code. We can avoid this by using a single, flexible function that works with multiple data types.
This is where generic programming in C++ comes in. It allows programmers to define functions or classes with generic data types. This enables the compiler to determine the appropriate type based on the arguments passed. Essentially, the programmer instructs the compiler:
This function should work with different data types. I’ll specify a generic type in the definition. The compiler will decide which specific type to use based on function calls.
By leveraging C++ templates, developers can write reusable, scalable, and type-safe code, eliminating redundancy while improving maintainability. In the next section, we will explore how to implement a generic version of the min() function using templates.
Template example from STL
Now, coming back to our minimum of two numbers problem. First, we will see how we can write a program using a generic function available in STL. The STL provides a function called std::min(). It takes two input numbers of any type. It returns the minimum of the two. Let’s have a look at the following code snippet:
#include <iostream>
#include <algorithm>
int main()
{
int min_of_two = std::min(100, 200);
std::cout <<"Min of 100 and 200 is " << min_of_two << std::endl;
return 0;
}
The output of this program will look as follows:
Min of 100 and 200 is 100.
The STL library function std::min() takes a pair of integers. As you can see, it returns the minimum of those two. But what’s so special about that? To understand that, let’s expand our program as follows:
#include <iostream>
#include <algorithm>
int main()
{
int min_of_int = std::min(100, 200);
std::cout << "Min of 100 and 200 is " << min_of_int << std::endl;
double min_of_double = std::min(4.5, 2.3);
std::cout << "Min of 4.5 and 2.3 is " << min_of_double << std::endl;
return 0;
}
To compile the previous code, type the following command in a Linux console and press Enter: Here’s how the syntax looks like:
g++ <program-name>.cpp -o <output executable name>
In this case the command will be as shown next:
g++ min_numbers.cpp -o min_numbers
Here the name of the CPP file we are compiling is min_numbers.cpp and the name of the output executable is min_numbers. The name of the output file can be anything you like. if you do not specify an output filename then by default Linux names the binary executable as a.out. So, if you compile it with the following command then you will have an a.out file in the same directory:
$ g++ min_numbers.cpp -o min_numbers
$ ./a.out
The extension of the output file really doesn’t matter. Name it as you like, either keep or skip the extension if you want; Linux doesn’t care. To run the program, type the following command in the Linux console and press the Enter button:
./min_numbers
Output:
Min of 100 and 200 is 100
Min of 4.5 and 2.3 is 2.3
Explanation
We have just added a new line in the second program. You will notice that we passed two doubles to the std::min() function. From the output, it is evident that the STL function std::min() can work both with integers and doubles. std::min() is a template function in the STL library. The header file we have to include is algorithm. The library function std::min() is data type agnostic. It can operate on any kind of data. Therefore, it is a generic function. The internal C++ mechanism which makes it possible to write generic functions is the template.
Looking at a sample template
Just so that you have a flavor of the templates, we will convert our min() function into a template function. Let’s see how it looks. A possible implementation of the min() function using the template is as follows:
template<typename T>
T min(T x, T y)
{
return x > y ? y : x;
}
Please ignore the template function’s implementation details for now. We will discuss all of these in the coming chapters. The above single implementation of the min() function would work for int, double, and char type data. So at the very least, you have saved repeating the same source code two more times. The point here is to give you an idea of how templates can help reduce code redundancy.
Why is that important?
So, by now, you may have got a bit of an idea how by using the C++ template library (STL) can help reduce redundancy in the source code. In any project, the maintainability of source code is a significant issue. The challenge is not only to write the code but also to maintain it for years to come. The readability of the code significantly contributes to source code maintenance.
Templates can immensely improve readability by reducing redundant code. Source code goes through a long life cycle. Some may have written the source code in the first place, whereas someone else may later maintain the source code. The programmer(s) who writes the source code are not always the ones who debug it. Readability means how easy it is for others. It indicates how simply someone who did not write the code can understand it by reading. Templates offer generic and hence compact code, consequently better readability.
Less redundant code means smaller code size. More lines of code also mean the possibility of more bugs. Templates help in writing bug-free code, bugs that creep in due to humanly mistakes. The compiler can automatically generate different versions of classes and functions using different data types using the template’s definition. The chances of accidental errors are less. Using templates would mean more reliable, clean, and maintainable source code. As we progress through the chapters, we will see templates offer much more than just code readability and maintainability. But these are great incentives to start with.
Source code repetition is not advisable due to the following potential issues:
- Writing repeated code is time-consuming.
- Writing the same code in multiple places is tedious and error-prone. The programmer may introduce a bug inadvertently while rewriting the same code. I blame that on the human mistake.
- With repeated code, software maintenance becomes an issue. Every time you fix a bug in one place, you have to replicate that elsewhere as well. This can be very costly in a large project. You have written three versions of a function. These are foo(int, int), foo(double, double), and foo(char, char). Each does the same job with different data types. Now, the company you work for has three different platforms. This is where this code runs. They maintain three different codebases (read Git/SVN branches) for those three platforms. By platform, we mean the underlying hardware. Let’s say for one of its customers, your company uses Broadcom chipset (platform one). For a second customer, it uses the STMicroelectronics chipset (platform two). For the third customer, it uses a Samsung chipset (platform three). You found a bug in foo(int, int), and you fix it. A bug is a programmatic error in a code. A fix is a solution for that error. It essentially involves a change in the source code. You realize that this fix applies to foo(double, double) and foo(char, char) also. So, you need to make changes in those two functions as well. The total number of changes you have to make in the source code is three per platform. As there are three different platforms, you have to port your fix to all those other places. Porting means to replicate the change(s) in all relevant platforms. So, you need to replicate one fix in three different places for one platform. You need to make a total of nine changes considering three different platforms. Using templates, you can reduce that to only three changes instead of nine, just one fix per platform. And that’s a considerable gain. In a large project where there are millions of lines of code, the gain can be considerably significant. By fix we mean a modification in the source code which resolves a problem or bug.
- The compiler does a type check of the arguments you pass while calling the template function. Template argument deduction does the type check while deducing the type of the passed arguments. Don’t be overwhelmed by the template syntax at this point. We will come back to that again in the next chapter. In this section, I brought this up just to explain some of the benefits of using templates. Consider the following code snippet:
#include <iostream>
int add(int x, int y)
{
return x + y;
}
int main()
{
std::cout << add(10, 20) << std::endl;
std::cout << add(10, 20.2) << std::endl;
return 0;
}
Compile the code as follows:
g++ type_conversion.cpp -o type_conversion
Run it using the following code:
./type_conversion
The output will be as follows:
30
30
In the previous program, we have defined the function add(). It takes two integers and returns their sum. In the main() function, we have passed a pair of integers and then deliberately passed an integer and a double. The add() function is returning the result of both the additions, that is, 10 + 20 and 10 + 20.2 as 30. The second result is incorrect as adding 10 and 20.2, you should get 30.2. Alternatively, you might expect an error in the second function call from the compiler. This is because the data types of the argument passed do not match with the function definition. The compiler didn’t complain. However, the program is returning the wrong output. So, what happened here?
This is due to a phenomenon called automatic type conversion by the compiler. The compiler is allowed to convert standard types. This occurs when the types do not match. The parameter types in the definition differ from the argument types of the passed values in the function call. There are rules of implicit conversions. The compiler applies these rules. However, that is out of scope for this book.
The compiler examines the function definition of the add() function in our case. It says, “I have a function that takes two integers. However, the user has passed an integer and a double! So, I convert the double to an integer type so that it fits in the parameter type of the function”. Yes, compilers can do that. If you inadvertently pass the wrong type of data while calling the function, you may get an unexpected result. Now, let’s convert our add() function into a template function as follows:
type_conversion_template_simple.cpp
#include <iostream>
template <typename T>
T add(T x, T y)
{
return x + y;
}
int main()
{
std::cout << add(10, 20) << std::endl;
return 0;
}
Compile and run the code. You will see the output is 30:
30
Now let’s change the code to replace the second argument to add() to a double as follows:
#include <iostream>
template <typename T>
T add(T x, T y)
{
return x + y;
}
int main()
{
std::cout << add(10, 20.5) << std::endl;
return 0;
}
If you try to compile this program, it will fail in the compilation. Let’s have a look why. Look at the following compilation error:
$ g++ type_conversion_template.cpp -o type_conversion_template
type_conversion_template.cpp: In function 'int main()':
type_conversion_template.cpp:10:30: error: no matching function for call to 'add(int, double)'
std::cout << add(10, 20.5) << std::endl;
^
type_conversion_template.cpp:3:3: note: candidate: template<class T> T add(T, T)
T add(T x, T y)
^~~
type_conversion_template.cpp:3:3: note: template argument deduction/substitution failed:
type_conversion_template.cpp:10:30: note: deduced conflicting types for parameter 'T' ('int' and 'double')
std::cout << add(10, 20.5) << std::endl;
^
This error message tells you that the compiler tried to deduce the arguments passed to the add() function. It found conflicting types between the template parameters definition and what have been passed in the function template call. No implicit type conversion is allowed in template argument deduction. Therefore, in this case, you get an error message from the compiler. Even if you pass a wrong argument type while calling the template function, the compiler will catch that error. This benefits the programmer because they learn about the inadvertent mistake during compile time. It is better than experiencing inconsistent behaviour in runtime. This brings us to the next topic: using templates is preferred over function overloading in a similar situation.
Function overloading versus templates
It is easy to study the rules of overloading and templates. However, it is easy to overlook that together they are one of the keys to elegant and efficient type-safe containers.
— Bjarne Stroustrup
Function overloading is a powerful feature in C++ that is not available in C programming. It enables developers to define multiple functions with the same name but different parameter sets. These functions can accept a varying number of arguments or different data types, making code more flexible and readable.
Function overloading shares similarities with C++ templates, raising the question: Why do we need templates if we have function overloading? Function overloading allows defining multiple versions of a function for different data types. Templates provide a more scalable solution by enabling generic programming without writing multiple function versions manually.
Let’s explore this concept further with an example:
#include <iostream>
#include <string.h>
size_t size_of(int x)
{
return sizeof(x);
}
size_t size_of(double x)
{
return sizeof(x);
}
size_t size_of(const char *str)
{
return strlen(str);
}
int main()
{
std::cout << size_of(10) << std::endl;
std::cout << size_of(4.2) << std::endl;
std::cout << size_of("Hello World!") << std::endl;
return 0;
}
Compile and run the previous program as follows:
$ g++ function_overloading.cpp -o function_overloading
$ ./function_overloading
The following will be the output:
4
8
12
In the previous program, we overloaded a function size_of(). It operates on int, double, and string of character type arguments. The function returns the argument’s size. The function’s name remains the same for the application developer, but the argument type varies. If the argument type is int, we return its length using the inbuilt sizeof() operator. Similarly, if the type is double, we use the sizeof() operator to return its length. When the argument type is a pointer (character string), we use the library function strlen(). This function determines its length. In function overloading, we may have different function body (programming logic) for different argument sets but the same function name.
In templates, we have the same function body and name but different argument types. Remember, function overloading is also possible if the function body remains the same. But in that case, to get rid of the repetitive code, you must use the template.
In addition to these points, remember that using templates provides extra type checking which function overloading doesn’t provide. Let’s have a look at the following example:
func_overloading_type_conversion.cpp
#include <iostream>
int foo(int x, int y)
{
return x + y;
}
double foo(double x, double y)
{
return x + y;
}
int main()
{
std::cout << foo(10, 20) << std::endl;
std::cout << foo(10.2, 20.3) << std::endl;
std::cout << foo(10, ‘A’) << std::endl;
return 0;
}
We have overloaded a function foo() with a pair of integers and with a pair of doubles. Now in the main function, we have first passed two integers to foo(). Next, we passed two doubles to foo(). Finally, we have passed an integer and a character to foo(). Now if you compile and run this program, you will see an output like this:
$ g++ func_overloading_type_conversion.cpp -o func_overloading_type_conversion
$ ./func_overloading_type_conversion
30
30.5
75
foo() function has returned 75 as a result of the addition of the characters A and integer 10. Notice that we do not have a version of foo() which accepts an integer and character. However, the compiler didn’t give any error. The input char is implicitly promoted to int. The ASCII value of ‘A’ is 65. This promotion is done by the compiler. However, this may not necessarily be the intention of the programmer. Let’s rewrite our foo() function as a template function:
function_template_type_check.cpp
#include <iostream>
template<typename T>
T foo(T x, T y)
{
return x + y;
}
int main()
{
std::cout << foo(10, 20) << std::endl;
std::cout << foo(10.2, 20.3) << std::endl;
std::cout << foo(10, 'A') << std::endl;
return 0;
}
Now if we compile this program, it will show the following error:
$ g++ function_template_type_check.cpp -o function_template_type_check
function_template_type_check.cpp: In function 'int main()':
function_template_type_check.cpp:13:29: error: no matching function for call to 'foo(int, char)'
std::cout << foo(10, 'A') << std::endl;
^
function_template_type_check.cpp:4:3: note: candidate: template<class T> T foo(T, T)
T foo(T x, T y)
^~~
function_template_type_check.cpp:4:3: note: template argument deduction/substitution failed:
function_template_type_check.cpp:13:29: note: deduced conflicting types for parameter 'T' ('int' and 'char')
std::cout << foo(10, 'A') << std::endl;
^
As you can see, the compiler has spotted the mismatch. There is a discrepancy in data types between the function template definition and the argument types passed in the call. So evidently, template functions guarantee to detect accidental wrong parameter passed to it, but function overloading does not.
Our next candidate, which can come in handy in dealing with different types of argument types, is macro. A macro is a piece of code that is identified by a name. Once defined, the macro name can be used anywhere in the program. We can also pass arguments to macros. Whenever the macro name appears in the program, the pre-processor replaces it with the body of the macro.
Remember, macros are blind code substitution carried out by the pre-processor. The compiler cannot see the macro names. At the beginning of the compilation process, the pre-processor processes the complete source code. It replaces the macro references by their actual body. Once the pre-processor finishes its work, then the pre-processed code is handed over to the compiler. Macros are defined with the keyword define preceded by the # operator. For example, I may like the name PACKT to stand for the string PACKT Publishing in my program. To achieve that I may define a macro like the following in my program:
#define PACKT “PACKT Publishing”
Now when we compile the program first, the pre-processor will process the program. From the above definition of macro, the pre-processor knows about replacing the name PACKT. It is replaced by the string PACKT Publishing. So that is a very brief introduction to macros. We will see more examples of macros in the following section. Macros can take any data type as input. In that sense, macros can be pitted against the templates. In the next section, we will try to find out how fair templates do when pitted against the macros.
Macro versus templates
Macros can be deemed as a mechanism to pass any data type to achieve the same goal as using templates. Let’s look at the following example:
#include <iostream>
#define add(x, y) (x + y)
int main()
{
std::cout << add(10, 20) << std::endl;
std::cout << add(4.2, 5.8) << std::endl;
return 0;
}
Here, we have defined a macro add(). From the main() function, we have called the macro twice. First, with a pair of integers. Then, with a pair of doubles. Now, if you compile and run the program you will see an output like this:
30
10
Our previously defined macro add() worked well with a pair of integers. It also functioned with a pair of doubles. Macros are another way to eliminate repetitive code with different data types.
Note: Macros are processed by the pre-processor and not by the compiler, hence there is no error checking at all.
Then why do we need templates? Firstly, carelessly written macros may have side effects. Let’s have a look at the following piece of code:
#include <iostream>
#define multiply(x, y) (x * y)
int main()
{
std::cout << multiply(10, 20) << std::endl;
std::cout << multiply(10 + 10, 20 + 20) << std::endl;
return 0;
}
In this program, the macro multiply() is intended to take two numbers and return the value of their multiplication. If you compile and run the program you will see the output as follows:
200
230
The output from the first call to multiply() is correct. But in the second call to multiply(), we have passed two arguments, 10 + 10, and 20 + 20. The output of this operation should be 800, but the macro multiply() generated 230, which is incorrect. So, what has just happened here?
Macros work on a text substitution principle. When we pass an argument to the macro, the pre-processor blindly substitutes the arguments into the macro body. When we call our multiply() macro with (10 + 10, 20 + 20), the arguments are substituted into the macro body multiply() as shown in the following pictorial representation:

To avoid this problem, parameters in the macro definition are embraced in brackets. Let’s have a look at the modified version of our multiply macro:
#include <iostream>
#define multiply(x, y) ((x) * (y))
int main()
{
std::cout << multiply(10, 20) << std::endl;
std::cout << multiply(10 + 10, 20 + 20) << std::endl;
return 0;
}
Now, if you compile and run the program, you will see the correct output:
200
800
Here’s a pictorial representation of the effect of this modification is as shown next:

So improper implementation of macros can lead to tricky bugs in the code. The second downside of the macro is that it may lead to a significant increase in the code size. Macros are designed to be substituted by their body wherever they are called. As a result, the whole macro body is inserted into the code by the pre-processor. Because the same macro is pasted multiple times the code size increases significantly. The third problem with macro is that it is processed by the pre-processor and hence there is no type checking. Let us again have a look at the add() the following code:
#include <iostream>
#define add(x, y) (x + y)
int main()
{
std::cout << add(10, 5.2) << std::endl;
return 0;
}
And the following is the output:
15.2
In the previous program, we passed an integer and a double to the macro add(). We got a result of 15.2. This is correct. When we call the macro with the arguments (int and double), that gets substituted in the macro body. The compiler sees we are trying to add an integer with a double. Compiler implicitly converts the integer into a double and performs the addition. And, we get the output of 15.2. This looks benign and correct. However, the programmer may not always intend this. The intention may have been to use the add() macro to add strictly two integers. But if we pass a double accidentally, it will substitute the arguments. The compiler then decides if there is any implicit type conversion required. Because of these issues, macros are not really a substitute for templates. In the next section, we are going to explore some more salient characteristics of function templates.
Important facts about templates
There are aspects of function templates that need further emphasis. Let’s learn about some unique characteristics of function templates in the following sections.
No Template code generated if not used
The compiler doesn’t generate any code for a template if the template hasn’t been used in the program. Templates only represent a design of a function or a class with the generic data type. Templates are defined using generic data types. Therefore, the compiler does not understand how to interpret the data type from the template definition itself. The compiler cannot even compile templates unless an actual instance is created with the actual data type. This process is known as template instantiation. Let’s look at the following example code:
#include <iostream>
template<typename T>
T add(T x, T y)
{
return x + y;
}
int main()
{
std::cout << "Hello World" << std::endl;
return 0;
}
In this program, we have defined a template function called add(). However, we have not called the add() function template anywhere in the main() function. Compile the code and generate the binary executable as shown:
g++ template_code_generation.cpp -o template_code_generation
We have named the binary executable template_code_generation. To check if any code has been generated for the template add(), you can use a Linux tool called strings. Let us have a look:
$ strings template_code_generation | grep add
The tool strings, when operated on a binary file prints all the available strings in the file. Here, we have passed our binary file template_code_generation to the strings tool. We then searched (grep) the string add. However, nothing was returned. That means there is no string named add in template_code_generation binary file. Now, let us search (grep) main as follows:
$ strings template_code_generation | grep main
__libc_start_main
As you can see, the string main, is there in the binary executable but add is not. This means the function main() has been compiled and binary code has been generated by the compiler. However, no binary code has been generated for the template function add(). We have not called it in the program.
Note: No binary or machine language code is produced for function templates. This happens only if the function template has not been called in the program.
However, the same is not true for non-template functions. For example:
#include <iostream>
int add(int x, int y)
{
return x + y;
}
int main()
{
std::cout << "Hello World" << std::endl;
return 0;
}
We have defined a function add in this program but haven’t used it in main(). Now, if compile and search for the function name string add() in the binary executable, we will see the following:
$ g++ function_code_generation.cpp -o function_code_generation
$ strings function_code_generation | grep -i add
_GLOBAL__sub_I__Z3addii
The add() function is present in the binary executable, but its name has been altered due to C++ name mangling. Name mangling is a process where the C++ compiler modifies function names during compilation to support function overloading, allowing multiple functions with the same name to coexist. In this discussion, we primarily focus on function templates because they are simpler and easier to understand. However, the fundamental rules of C++ templates apply to both function templates and class templates. In Chapter 6: Class Templates, we will explore class templates in detail, covering their features and usage.
Template instantiation
Templates are a pattern given to the compiler. They generate multiple functions or classes of the same functionality, but with different data types. Templates do not exist beyond the point where they inform the compiler. They tell the compiler how a particular entity, such as a function or class, will look in the future. When a template is called in the program, the compiler looks at the template definition. Then, it examines the argument types passed. If those arguments agree with the template parameter types, the compiler generates a function or class. This function or class uses that specific argument type. This process is called template instantiation. Instantiated functions or classes are like any manually written function or class, and there is nothing special about them.

The template function add() has been called with two integers, as shown in the previous conceptual model. The compiler has instantiated an instance of add() with two integer type parameters. The programmer could have manually written these parameters. There is no difference between the instance the compiler generates and a manually written function.
No error checking until instantiation
The compiler does not perform error checking of template function code if it has not been called in the program. If you do not call a template function, the compiler will not report any programmatic error. Syntactical errors will be checked and reported by the compiler. Let us have a look at the following program:
#include <iostream>
struct mystruct {
int a;
};
template<typename T>
void foo(T& s)
{
std::cout << s.a << std::endl;
std::cout << s.b << std::endl;
}
int main()
{
struct mystruct s{10};
return 0;
}
In the previous code, we have defined a structure mystruct, which has an integer type member variable a. Then we defined a template function foo. It accepts a reference to a user-defined data type. It then prints two member variables of that input data type, namely a and b. However, in the main program, we have not called the template function. Now, if we try to compile and run the program, there will be no error thrown by the compiler as shown next:
$ g++ error_checking_template.cpp -o error_checking_template
As you might have noticed, the structure does not have any member called b. This is a programmatic error. However, the compiler didn’t throw any error. The reason is that the compiler does not check for errors in the template body. This happens unless the template is called (instantiated) in the program. Now to verify this, add the following line in the main() function body just before the return statement:
foo(s);
And then try compile the program again and you should see the following errors:
$ g++ error_checking_template.cpp -o error_checking_template
error_checking_template.cpp: In instantiation of 'void foo(T&) [with T = mystruct]':
error_checking_template.cpp:18:10: required from here
error_checking_template.cpp:11:20: error: 'struct mystruct' has no member named 'b'
std::cout << s.b << std::endl;
Type checking
The compiler checks the types of arguments we pass while calling a template function. It compares these types against the parameter’s types in the template definition. If the arguments’ type matches, then the compiler instantiates the template into an ordinary function. If the types do not match, then the compiler reports an error. The conceptual model of the same is shown as follows:

Memory usage with templates
It is important to remember that memory usage is not enhanced by using templates. If we define a function template, the compiler generates three different versions. This happens when the template is called by passing three different data types. This is precisely the same if three different versions were written manually. So, the memory required to hold the three copies of the generated functions would be the same in both cases. This occurs if you use a template or write the functions with three different data types manually.
Summary
This chapter introduced the history of templates in C++ and their significance in modern programming. We explored why templates matter, their benefits, and how they improve code reusability and efficiency. We also compared templates with other approaches like function overloading and macros, highlighting key differences. Additionally, we covered some essential features of templates to provide a foundational understanding. By the end of this chapter, you should have a solid grasp of the basic concepts and appreciate the role of templates in C++. In the next chapter, we will delve into function templates, their syntax, and implementation.
Questions
- What is template?
- What are the benefits of using templates?
- What is template instantiation?
- What is type checking of template parameters?
Answers
- Templates are the blueprint of a generic function or class which can work with different types of data.
- Please refer to the summary section for the advantages.
- We pass arguments to the function template. The compiler then generates the actual function definition. It uses the passed arguments’ data type(s). That means an instance of the template function is generated. This is called template instantiation. The same is true for class templates as well.
- When we call a function template with a set of arguments, the compiler checks the arguments’ data types. It also verifies the template function parameters. If there is a mismatch, the compiler throws an error. This is called type checking.

1 Comment