You are on page 1of 3

Overview

Overview

Understanding C++
Templates his article is a follow-up to the
In this article, we’ll learn the basic syntax and

T
‘An Introduction to C++
semantics of the features in the templates in C++ and Templates’ article published in
the October issue of LFY. So,
write small programs.
without further ado, let’s get
started.

Class and function templates


There are two kinds of templates: function
templates and class templates. To define a
template, use the template keyword with the
template parameters given within ankle
brackets, and provide the class or function
definition after that. For example:

// array_container is a ‘class template’


template <class T>
class array_container {
T arr[10];
// other members
};

// generic swap is a ‘function template’


template <class Type>
void swap(Type &t1, Type &t2) {
Type temp = t1;
t1 = t2;
t2 = temp;
}

The conventional names typically used for


template-type arguments are T and Type, but
it can be any valid variable name.

Template instantiation
We can ‘use’ the template by providing
necessary arguments, which is known as
instantiating the template. An instance
created from that template is a template
instantiation. For class templates, we have to
explicitly provide the instantiation arguments.
For function templates, we can explicitly
provide the template arguments or else the

88 NOVEMBER 2007 | LINUX FOR YOU | www.linuxforu.com

CMYK
Overview

compiler will automatically infer the template arguments T arr[size];


from the function arguments. public:
For example, here is how we can instantiate the int getLength() {
array_container and swap templates: return size;
}
// type arguments are explicitly provided // other members
array_container<int> arr_int; };

float i = 10.0, j = 20.0; array_container<float, 10> arr_flt;


// compiler infers the type of argument as float and cout<<“array size is “ << arr_flt.getLength();
// implicitly instantiates swap<float>(float &, float &); // prints: array size is 10
swap(i, j);
// or explicitly provide template arguments like this:
// swap<float>(i, j); Implicit instantiation and type inference
cout<<“after swap : “<< i << “ “ << j; The implicit inference of function templates is very
// prints after swap : 20 and 10 convenient to use; the users of the template need not even
know that it is a template (well, in most cases), and use it
as if it were an ordinary function. This is a powerful
Template parameters feature, particularly when used with function overloading.
Template parameters are of three types: type parameters, We’ll look at a simple example for inference of template
non-type parameters and template-template parameters. parameters here:
Type parameters are used for abstracting the type details
in data-structures and algorithms. Non-type parameters // the types T and SIZE are implicitly inferred from the
are used for abstracting the values known at compile-time // use of this function template
itself. A template itself can be passed as a parameter to template<typename T, int SIZE>
another template, which is a template-template parameter. int infer_size(T (*arr)[SIZE]) {
We’ve already seen an example for type parameters, and return SIZE;
we’ll cover non-type parameters in the next section. }
Template-template parameters are not covered in this
article as it’s an advanced topic. int main() {
Type parameters can be declared with class or int int_arr[] = {0, 1} ;
typename keywords and both are equivalent. Using the char literal[] = “literal”;
keyword class for a template type parameter can be a little cout<<“length of int_arr: “<<infer_size(&int_arr)<<endl;
confusing, since the keyword class is mainly used for cout<<“length of literal: “<<infer_size(&literal)<<endl;
declaring a class; so it is preferable to use the typename }
keyword for type parameters. For example:
// prints
// instead of template <class T> use // length of int_arr: 2
template <typename T> // length of literal: 8
class array_container;
In this program, the type and non-type parameters are
Template non-type parameters automatically inferred from the instantiation of infer_size.
Non-type parameters are used for abstracting constant The first instantiation is for the integer array of Size 2. The
values in a template class. Non-type parameters cannot be T in infer_size is inferred as int and SIZE as 2. Similarly,
of floating-point type. Also, the value of a non-type for the string literal, it becomes char and 8.
parameter should be known at the compile-time itself as
templates are a compile-time mechanism and template Template specialisation
instantiation is done by the compiler. A template is to provide the description for the generic
In the array_container template we saw earlier, we implementation of a class or a function. For specific types
abstracted the type of the array and hard-coded the size of (or values, in case of non-type parameters), the template
the array. It will be flexible if we can change the size of the is instantiated or specialised. For class and function
array for different uses. Non-type parameters come handy templates, specialisation results in class and function
for purposes like this: definitions. Such generated class and function definitions
can be used just like any other class or function definitions
template <class T, int size> (they are ‘first class citizens’). If you want to provide a
class array_container { specific implementation for particular types (or values in

www.linuxforu.com | LINUX FOR YOU | NOVEMBER 2007 89

CMYK
Overview

case of non-type arguments), you can explicitly provide a t1.swap(t2);


specialised implementation; this is known as explicit }
specialisation.
In case an instantiation is needed for those particular int main() {
types or values, instead of creating a class or function int i = 20, j = 10;
definition from the template, if any of the explicit // compiler instantiates swap<int>(int &, int &)
specialisations match, it will be used. swap(i, j);
Consider that the user-defined class my_vector has a my_vector v1(20), v2(10);
member swap that provides an efficient implementation // however, for my_vector, the specialization is used
for swapping two my_vectors. If a swap function with two swap(v1, v2);
arguments passing my_vector instances are passed, we }
prefer to call my_vector::swap instead, using the code in
the general swap template. Here is how we can do it: When the explicit specialisation has one or more
parameters that still depend on the type or non-type
// generic swap is a ‘function template’ parameters of the primary template, it is referred to as
template <class Type> partial specialisation.
void swap(Type &t1, Type &t2) { C++ templates is a very powerful feature, but it is also
Type temp = t1; complex and it takes time to learn the features and master
t1 = t2; it. In this article, we had a brief overview of the features of
t2 = temp; the templates in C++, which is a good starting point for
} exploring it further.

// explicit specialization for swapping my_vector’s By: S.G. Ganesh is a research engineer in Siemens
template <> (Corporate Technology). He has authored a book “Deep C”
void swap(my_vector &t1, my_vector &t2) { (ISBN 81-7656-501-6). You can reach him at
// call my_vector::swap for swapping two my_vector’s sgganesh@gmail.com.

90 NOVEMBER 2007 | LINUX FOR YOU | www.linuxforu.com

CMYK

You might also like