Templates are a relatively new addition to C++, and they introduce the concept of generic programming. Generic programming is a data structure-independent way of developing and delivering algorithms that need not be bound to a specific object. But before you dive into creating C++ templates, let's consider their advantages and disadvantages.
When I last spoke to Bjarne Stroustrup, the creator of C++, I asked him this question: “What do you believe is the true goal for templates in C++?” He responded, “To support type-safe, efficient generic containers and generic algorithms.”
Templates are used in the field for various reasons, the main one being to take advantage of generic programming. The importance of templates is evidenced by the introduction of a robust library in the C++ ISO standard. The library of algorithms and containers is called the Standard Template Library, or STL for short. It uses templates to implement an efficient code base that is reusable and extensible.
But templates have a few negative aspects that are not widely explored. First, since C++ does not have binary run-time extensibility, templates can't be linked and distributed as a library. They must be compiled at compile time, and, therefore, all implementations of a template algorithm must be included in the header files in their entirety. You can easily see this by analyzing the STL standard header files.
Also, because templates are a recent introduction to the standard, they're not as compatible as standard C++ across a variety of compilers. For example, the Mozilla.org browser development team mentions that templates should not be used in the development of the browser because of its relative newness and lack of compatibility in a cross-platform environment. Likewise, it's unadvisable to use templates in development environments that span several systems with perhaps older C++ compilers.
Even now, more advanced template features, such as partial specialization and order of specialization may not appear uniform across different implementations of the C++ standard.
Still, you can drastically reduce development time using templates in combination with STL. On a more fundamental level, templates allow you to write a single algorithm and use it across different data types. These parameterizations are done at compile time.
Suppose, for example, that you want to implement a windowing and resequencing mechanism, as evident in any TCP/IP stack. You may want to implement this for the IP packets and then use the same code to implement it across another type of packet format. Notions such as flow control, windowing, and resequencing do not change across different implementations but can be reused when using the generic programming approach with C++ templates.
Standard uses of C++ templates
Headers and namespaces
The C++ standard has enveloped all of its standard library classes and functions inside a namespace named std. All the examples below will have the following headers associated with them:
using namespace std;
Here, we are including the iostream library and promoting the std namespace to a global scope.
Declare, instantiate, and parameterize a template class
The first thing to look at is how to define a simple template. We'll assume that you have basic knowledge of C++ but have never explored generic programming and rudimentary templates. In Listing A, the template is declared. In Listing B, we create an instance and call the function.
Listing B will output bar 97, but the second instantiation of the foo template class will output bar a. That's because the template is parameterized at compile time. Templates can be parameterized with the data type at compile time, whereas in C++, the data type must be explicitly declared when the class is declared.
Declare and parameterize a template function
C++ can also declare template functions. This is essential to the concept of writing generic algorithms to be applied by a wide range of data types. A quick example of this would be to declare a function template.
In Listing C, you will notice that the declaration is a cross between a standard ANSI C function and a declaration of a template class. We will call the function with various parameters, as shown in Listing D.
In Listing D, the output of the first function called above will be b because the function is specialized implicitly with a char. The output of the second function about will be 98 because the template function is specialized implicitly with an int.
There are many more standard uses of C++ templates, including template parameters, type equivalence, template overloading, specialization, and partial specialization; however, we'll leave those topics to be covered by an extensive reference text.
Esoteric uses of C++ templates: Template metaprograms
One of the less obvious uses of templates is derived from the fact that templates are interpreted at compile time. The technique is based on a concept known as template metaprograms. This is essentially the ability to write code that is expanded at compile time to yield a result that will later be used at run time. This alleviates some of the work at run time but moves it to compile time.
Listing E shows a simple example of how a template metaprogram could be used. It calculates the nth position of the widely known Fibonacci numbers. Fi = Fi-1 + Fi-2, where the base cases are F0 = 0 and F1 = 1
When Listing E is compiled, it results in the number 55. This is the 11th position in the Fibonacci sequence, where i = 10 in Fi.
The Fibonacci numbers are as follows: 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55 ...
It's important to note that the above example is programmed using the specialization aspect of templates.
Expression templates are another somewhat esoteric use of templates. They're based on the concept of evaluating mathematical expressions at compile time to produce more efficient code that is executed at run time.
The C++ standard contains an important description of the C++ templates. Templates are an ideal method to realize the generic programming dream. They also have the unique ability to be interpreted at compile time. Although there are some problems with template portability from the previous generation of compilers, now that the ANSI/ISO standard is completed, compilers should start to conform to the standard. Templates are an ideal way to quickly provide solutions to complex problems, especially when you build using the Standard Template Library.
In future articles, we will delve into the Standard Template Library, discuss how it was introduced, and examine various fundamental principles such as iterators, containers, and algorithms.