3
NOVEMBER 2007 | LINUX FOR YOU | www.linuxforu.com C M Y K his article is a follow-up to the ‘An Introduction to C++ Templates’ article published in the October issue of LFY. So, 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 T Overview Understanding C++ Templates In this article, we’ll learn the basic syntax and semantics of the features in the templates in C++ and write small programs. 88 NOVEMBER 2007 | LINUX FOR YOU | www.linuxforu.com C M Y K

C++ Templates 2

Embed Size (px)

Citation preview

Page 1: C++ Templates 2

88 NOVEMBER 2007 | L INUX FOR YOU | www.linuxforu.com

C M Y K

Overview

his article is a follow-up to the‘An Introduction to C++Templates’ article published inthe October issue of LFY. So,without further ado, let’s get

started.

Class and function templatesThere are two kinds of templates: functiontemplates and class templates. To define atemplate, use the template keyword with thetemplate parameters given within anklebrackets, and provide the class or functiondefinition 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 fortemplate-type arguments are T and Type, butit can be any valid variable name.

Template instantiationWe can ‘use’ the template by providingnecessary arguments, which is known asinstantiating the template. An instancecreated from that template is a templateinstantiation. For class templates, we have toexplicitly provide the instantiation arguments.For function templates, we can explicitlyprovide the template arguments or else the

T

Overview

Understanding C++TemplatesIn this article, we’ll learn the basic syntax andsemantics of the features in the templates in C++ andwrite small programs.

88 NOVEMBER 2007 | L INUX FOR YOU | www.linuxforu.com

C M Y K

Page 2: C++ Templates 2

www.linuxforu.com | L INUX FOR YOU | NOVEMBER 2007

C M Y K

89

Overview

compiler will automatically infer the template argumentsfrom the function arguments.

For example, here is how we can instantiate thearray_container and swap templates:

// type arguments are explicitly provided

array_container<int> arr_int;

float i = 10.0, j = 20.0;

// compiler infers the type of argument as float and

// implicitly instantiates swap<float>(float &, float &);

swap(i, j);

// or explicitly provide template arguments like this:

// swap<float>(i, j);

cout<<“after swap : “<< i << “ “ << j;

// prints after swap : 20 and 10

Template parametersTemplate parameters are of three types: type parameters,non-type parameters and template-template parameters.Type parameters are used for abstracting the type detailsin data-structures and algorithms. Non-type parametersare used for abstracting the values known at compile-timeitself. A template itself can be passed as a parameter toanother template, which is a template-template parameter.We’ve already seen an example for type parameters, andwe’ll cover non-type parameters in the next section.Template-template parameters are not covered in thisarticle as it’s an advanced topic.

Type parameters can be declared with class ortypename keywords and both are equivalent. Using thekeyword class for a template type parameter can be a littleconfusing, since the keyword class is mainly used fordeclaring a class; so it is preferable to use the typenamekeyword for type parameters. For example:

// instead of template <class T> use

template <typename T>

class array_container;

Template non-type parametersNon-type parameters are used for abstracting constantvalues in a template class. Non-type parameters cannot beof floating-point type. Also, the value of a non-typeparameter should be known at the compile-time itself astemplates are a compile-time mechanism and templateinstantiation is done by the compiler.

In the array_container template we saw earlier, weabstracted the type of the array and hard-coded the size ofthe array. It will be flexible if we can change the size of thearray for different uses. Non-type parameters come handyfor purposes like this:

template <class T, int size>

class array_container {

T arr[size];

public:

int getLength() {

return size;

}

// other members

};

array_container<float, 10> arr_flt;

cout<<“array size is “ << arr_flt.getLength();

// prints: array size is 10

Implicit instantiation and type inferenceThe implicit inference of function templates is veryconvenient to use; the users of the template need not evenknow that it is a template (well, in most cases), and use itas if it were an ordinary function. This is a powerfulfeature, particularly when used with function overloading.We’ll look at a simple example for inference of templateparameters here:

// the types T and SIZE are implicitly inferred from the

// use of this function template

template<typename T, int SIZE>

int infer_size(T (*arr)[SIZE]) {

return SIZE;

}

int main() {

int int_arr[] = {0, 1} ;

char literal[] = “literal”;

cout<<“length of int_arr: “<<infer_size(&int_arr)<<endl;

cout<<“length of literal: “<<infer_size(&literal)<<endl;

}

// prints

// length of int_arr: 2

// length of literal: 8

In this program, the type and non-type parameters areautomatically inferred from the instantiation of infer_size.The first instantiation is for the integer array of Size 2. TheT in infer_size is inferred as int and SIZE as 2. Similarly,for the string literal, it becomes char and 8.

Template specialisationA template is to provide the description for the generic

implementation of a class or a function. For specific types(or values, in case of non-type parameters), the templateis instantiated or specialised. For class and functiontemplates, specialisation results in class and functiondefinitions. Such generated class and function definitionscan be used just like any other class or function definitions(they are ‘first class citizens’). If you want to provide aspecific implementation for particular types (or values in

Page 3: C++ Templates 2

90 NOVEMBER 2007 | L INUX FOR YOU | www.linuxforu.com

C M Y K

Overview

case of non-type arguments), you can explicitly provide aspecialised implementation; this is known as explicitspecialisation.

In case an instantiation is needed for those particulartypes or values, instead of creating a class or functiondefinition from the template, if any of the explicitspecialisations match, it will be used.

Consider that the user-defined class my_vector has amember swap that provides an efficient implementationfor swapping two my_vectors. If a swap function with twoarguments passing my_vector instances are passed, weprefer to call my_vector::swap instead, using the code inthe general swap template. Here is how we can do it:

// generic swap is a ‘function template’

template <class Type>

void swap(Type &t1, Type &t2) {

Type temp = t1;

t1 = t2;

t2 = temp;

}

// explicit specialization for swapping my_vector’s

template <>

void swap(my_vector &t1, my_vector &t2) {

// call my_vector::swap for swapping two my_vector’s

By: S.G. Ganesh By: S.G. Ganesh By: S.G. Ganesh By: S.G. Ganesh By: S.G. Ganesh is a research engineer in Siemens

(Corporate Technology). He has authored a book “Deep C”

(ISBN 81-7656-501-6). You can reach him at

[email protected].

t1.swap(t2);

}

int main() {

int i = 20, j = 10;

// compiler instantiates swap<int>(int &, int &)

swap(i, j);

my_vector v1(20), v2(10);

// however, for my_vector, the specialization is used

swap(v1, v2);

}

When the explicit specialisation has one or moreparameters that still depend on the type or non-typeparameters of the primary template, it is referred to aspartial specialisation.

C++ templates is a very powerful feature, but it is alsocomplex and it takes time to learn the features and masterit. In this article, we had a brief overview of the features ofthe templates in C++, which is a good starting point forexploring it further.