Why we need the functions/classes template and how/why this concept created by C++ compiler engineers? In this medium post, I want to go through the steps which made c++ experts think about the template concept and auto deduction in the modern days of software development.
As you know, when we write programs with C language, our software is nothing more than tons of functions and structures. With C language, we should implement various functions for every task. For example, consider we want to implement a calculator with C language.
We should implement multiple variants of the add or mul or div or … function for different data types such as int, float, double and etc. It is completely a nightmare to repeat the same code implementation and also choose unique names for each function.
For example, in the above program, we implement three different add functions for work with different inputs like integer, float and double correctly.
If you notice carefully, the add function has the same implementation for even different data types. These three Add functions just have different names and get different data types, but their internal implementation is the same as each other completely.
The above photo represents the disassembled output of the add program that is generated by IDA pro. With the observation of the disassembled output, you can understand why we need a unique name for every function because if they have not a unique name we can not call them in our program correctly but however, as you may be understood, choose a unique name for every function can be a tedious task and if we choose a name carelessly, name conflict can ruin our program.
So if we could implement a compile-time feature in order to name the different variants of the Add functions in the background automatically, our pain will be reduced significantly.
C++ with function overloading feature solved this problem of C completely. For example, in CPP we can use the following pattern to implement the add program with less than pain as C.
You can see the difference between the program which is written by C and C++? With overloading features, C++ gives this chance to us, we use just one name for all different implementation of the add function but how the compiler suite can manage this overloading in the background and how the linker can resolve these overloaded functions at runtime?
If you disassemble the add program which is written by C++, you will find out the C++ compiler gave a unique name to the add function in the machine/assembly level, although we use one name to implement add function in the source code level.
For example, in the above photo, you can see Add function which gets integer input has been decorated with j__?Add@YAHH@Z name. This naming convention and also decoration make functions distinguishable from each other at the linking phase.
As a result, when the linker encounter with add function which has been decorated like j__?Add@YAHH@z, it gives the opportunity to the linker to resolve the address of this function correctly without making any conflict with other variants of add function.
I should mention this note here: Functions, data, and objects in C++ programs are represented internally by their decorated names. A decorated name is an encoded string created by the compiler during the compilation of an object, data, or function definition. It records calling conventions, types, function parameters and other information together with the name. This name decoration, also known as name mangling, helps the linker find the correct functions and objects when linking an executable.
The decorated naming conventions have changed in various versions of Visual Studio, and can also be different on different target architectures. To link correctly with source files created by using Visual Studio, C and C++ DLLs and libraries should be compiled by using the same compiler toolset, flags, and target architecture.
The decorated name for a C++ function contains the following information:
- The function name.
- The class that the function is a member of if it is a member function. This may include the class that encloses the class that contains the function, and so on. The namespace the function belongs to if it is part of a namespace.
- The types of function parameters.
- The calling convention.
- The return type of the function. The function and class names are encoded in the decorated name. The rest of the decorated name is a code that has internal meaning only for the compiler and the linker.
However, do you think can we make the C++ compiler smarter? For example, can we implement a compile-time feature which gives us the ability we never need to reimplement an add function for different data types? Yes. C++ with template features can solve this problem too and makes software coding a lot simpler.
With this feature, we can give a blueprint as templates to the C++ compiler which can generate an overloaded function based on parameters that we passed to the function template.
As you may understand, Functions generated based on the blueprint of the templates rely on the overloading capability of the C++ compiler internally.
These function templates are special functions that can operate with generic types. This allows us to create a function template whose functionality can be adapted to more than one type without repeating the entire code for each type.
As you can see in the above sample code, In C++ we used the template to reduce our efforts to reimplement a code for an operation for different data types. C++ compiler now can manage this task automatically in the background.
A template parameter is a special kind of parameter that can be used to pass a type as the argument: just like regular function parameters can be used to pass values to a function, template parameters allow to pass also types to a function. These function templates can use these parameters as if they were any other regular type.
If you see the disassembled output of the program, you will find out compiler generated a set of overload decorated functions for handle different type of parameters which we pass to the function template.
In another word, when we use function template, we give a blueprint to the compiler which it can use that blueprint to generate a set of overloaded functions based on the data type of the input we give to it.
But do you think we can make the C++ compiler smarter than before now? for example, it can be able to guess what is the data type of the return value of a function? Yes, we can do it. If we want to give this opportunity to the compiler that can specify the data type of the return value of a function itself, we can use the auto keyword now.
The auto keyword, for variables, specifies that the type of the variable that is being declared will be deducted from its initializer automatically. for functions, specifies that the return type will be deduced from its return statements.
As you can see now, our code becomes simpler and beautiful than before with the usage of template and auto deduction capability of the c++ compiler. I think these features of c++ make programming and software development with C++ more enjoyable than before.
In this article, I wanted to discuss how overloading, template, and auto keyword idea invented which they made C++ programming more enjoyable than before.