Templates share source code among structurally similar families of classes and functions.
Many data structures and algorithms can be defined independently of the type of data they manipulate. A template allows the separation of the type-dependent part from the type-independent part. The result is a significant amount of code sharing.
A template is like a cookie cutter: all the cookies it creates have the same basic shape, though they might be made from different kinds of dough. A class template describes how to build classes that implement the same data structure and algorithm, and a function template describes how to build functions that implement the same algorithm.
In other languages, these facilities are sometimes called parameterized types or genericity.
Prior to templates, macros were used as a means of implementing generics. But the results were so poor that templates have superceded them.
The syntax of a class template is the keyword template
, some template parameters, then something that looks a lot like a class. But semantically a class template is not a class: it is a cookie cutter to create a family of classes.
Consider a container class (see FAQ 2.15). In practice, the C++ source code for a container that holds int
s is structurally very similar to the C++ source code for a container that holds string
s. The resulting binary machine code is probably quite different, since, for example, copying an int
requires different machine instructions than does copying a string
. Trying to make the binary machine code the same might impose runtime overhead to generalize, for example, the copying operations for int
and string
and might also increase the complexity of the container.
Class templates give programmers another option: capturing the source code similarity without imposing extra runtime performance overhead. That is, the compiler generates special purpose code for containers of int
, containers of string
, and any others that are needed.
For example, if someone desired a container that acted like an array, in practice they would probably use the standard class template vector<T>
. However, for illustration purposes we will create a class template Array<T>
that acts like a safe array of T
.
The template<class T>
part indicates that T
represents a yet unspecified type in the class template definition. Note that the keyword class
doesn't imply that T
must be a user-defined type; it might be a built-in type such as int
or float
.
The C++ Standard defines the term instantiated class to mean the instantiation of a class template, but we will use the term instantiation of a class template instead, since most C++ programmers think of an instantiated class as an object rather than another class. When it doesn't matter whether it is a class template or a function template, we will drop the qualifying adjective and refer to the instantiation of a template.
Normally the compiler creates an instantiation of a class template when the name of a class template is followed by a particular sequence of template arguments. In this case, the only template argument is a type. The compiler generates code for the instantiated template by replacing the template argument T
with the type that is supplied, such as int
.
Use explicit specialization.
Sometimes a programmer wants the compiler to bypass the class template when creating an instantiation of a class template for a particular type and use a specialized class template instead. For example, suppose that an array of bits is needed. The natural thing to do is create an Array<bool>
using the template class from FAQ 25.02.
If the previously defined Array
template were used to generate the code for this class, it would end up creating an array of bool
which would, at best, be optimized to be an array of bytes. Clearly a bit array would be more space-efficient than a byte array. This more space-efficient implementation can be created by defining class Array<bool>
as an explicit specialization of the class template Array
. Notice how class Array<bool>
uses a bit array rather than a byte array.
Array<bool>
is an explicit specialization of the class template Array
, and Array<bool>
will be used instead of Array
whenever an Array<bool>
is needed.
Explicit specializations are often used to take advantage of special properties of the type T
and achieve space and/or speed benefits that could not be achieved using the generic class template.
It is normally best to define the explicit specialization (for example, Array<bool>
) in the same header that defines the template itself (for example, the same header that defines Array<T>
). That way the compiler is guaranteed to see the explicit specialization before any uses of the specialization occur.
The syntax of a function template is the keyword template
, some template parameters, then something that looks a lot like a function. But semantically a function template is not a function: it is a cookie cutter to create a family of functions.
Consider a function that swaps its two integer arguments. Just as with Array
in the preceding example, repeating the code for swap()
for swapping float
, char
, string
, and so on, will become tedious. A single function template is the solution.
Every time swap()
appears with a new combination of parameter types, the compiler creates yet another instantiation of the function template. Here is an example.
As with class templates, a programmer can get the compiler to bypass the function template when creating a template function: the programmer simply needs to manually create a specialized template function.
memcpy()
to copy objects of its template argument?No.
An object should be bitwise copied only when it is known that the class of the object will forever be amenable to bitwise copy. But the class of a template argument can't be known. Here is an example.
If a template uses memcpy()
to copy some T
objects, the template must have a big, fat, juicy comment warning potential users that a class with nontrivial copy semantics might destroy the world. For example, if memcpy()
were used in the example class template, and if someone created an Array<string>
, it is likely that the memcpy()
would create dangling references and/or wild pointers, and they would probably crash the application (see FAQ 32.01).
Finally, notice that the member functions that create T
objects (that is, the constructors and the assignment operator) do not have exception specifications (see FAQ 9.04). This is because the T
object's constructor may throw arbitrary exceptions, and any restrictions placed on these template member functions would be wrong for some particular type T
.
>>
when one template is used inside another?Maximal munch.
In the following example, a
is a list
of vector
of int
(list
and vector
are standard container classes; see FAQ 28.13).
If the declaration had been written without any spaces between the two >
symbols, such as list<vector<int>>
, the compiler would have interpreted the two >
symbols as a single right-shift operator.
Here are the details. The compiler's tokenizer (something the compiler does to figure out what a program means) has a rule called the maximal munch rule: “Read characters out of the source file until adding one more character causes the current token to stop making sense.” For example, the keyword int
is one token rather than three separate tokens, i
, n
, and t
. Therefore, if the tokenizer encounters two >
symbols together with no whitespace between them, the maximal munch combines them into one token: >>
.