13.1. Introduction To Templates

template, template variable, T, extensible (definition), cross compiler (see footnote)
Time: 00:03:15 | Download: Large, Large (CC), Small | Streaming, Streaming (CC) | Slides: PDF, PPTX

The C Programming Language was deliberately designed to be small and simple to make it easy for programmers to port the compiler to new systems.1 Consequently, it implements fundamental operations like assignment, loops, and function calls as language primitives, but it but relegates complex, less frequently used operations like sqrt and pow to library functions that programmers can implement once the compiler is functional. C library functions are often tied tightly to specific data types, frequently requiring programs to cast their data to or from the function's types.

double	sqrt(double x);
 
float		sqrtf(float x);
long double	sqrtl(long double x);
(a)(b)
The evolution of the sqrt function. The original version of the C Programming language, often called K&R C for its implementors, Brian Kernighan and Dennis Ritchie, was not governed by any standards. The American National Standards Institute (ANSI) formally adopted a C standard in 1989, often called C89 or ANSI-C.
  1. The ANSI C89 standard requires a single sqrt function as part of the language's math library. This function only processed double data, requiring type casts to deal with other data types.
  2. The ANSI C99 standard added two versions of the square root function whose names indicated the data types they process.

 

double		sqrt(double x);
float		sqrt(float x);
long double	sqrt(long double x);
 
double		sqrt(double x);
float		sqrt(float x);
long double	sqrt(long double x);
double		sqrt(T x);
(a)(b)
The ANSI C++98 and C++11 standards. Unlike C, C++ allows programmers to overload functions, enabling C++ compilers to refer to multiple functions with a single name.
  1. The first ANSI C++ standard, C++98, began with three overloaded sqrt functions.
  2. The C++11 standard adds another overloaded sqrt function to the <cmath> library. The T (printed in red) data type is a generalized or shorthand that matches any integral type: int, long, char, wchar_t, bool. This version is an example of a template function that effectively casts its integral argument to double.

C++ is an extensible language, meaning that programmers can add new data types to their C++ programs without modifying the compiler or the language's syntax. C++ allows programmers to create new types with enumerations, structures, and classes. Although extensibility is a powerful feature, it makes creating library functions challenging.

Calculating the square root of a value suggests that it is numeric in nature. That is, the sqrt(T x) function requires that T is an unspecified integral type. Imagine that a program specifies a class named number_with_knobs_on.2 Programs can use the generalized square root function with instances of the class, if the class supports an automatic conversion to an integral type. Providing the number_with_knobs_on class with an overloaded conversion operator satisfies this requirement.

Data structures are another, perhaps more easily understood, example. The operations necessary to manage most data structures (e.g., insert, search, remove, etc.) are independent of the data they store and organize, while others require an ordering function. For example, the Actor 5 demonstration introduced a circularly linked list named CList that could only store instances of the Person class. To further demonstrate polymorphism, it organized the objects alphabetically by name. C programs use void pointers as a general data type, which works but is clumsy, potentially confusing, and error-prone. Alternatively, templates provide a clear generalizing mechanism using a template variable, often T, as a placeholder whenever the code refers to the generalized type, fully embracing C++'s extensibility. During the compilation process, the compiler replaces the template variable with a program-supplied type name.


  1. In the past, the porting process required programmers to bootstrap a small, simple C compiler, often written in assembly language, on the new system. The bootstrap compiler compiled a larger, more complete C compiler, which in turn compiled the final compiler. Contemporary cross-compilers offer a faster and more efficient approach. A cross compiler runs on one system but generates machine code for another. For example, a cross compiler might run on an Intel processor but generate code for an ARM CPU.
  2. The informal phrase "with knobs on" means that something has additional features or embellishments or is in some way beyond ordinary.