A Beginners Guide To Templates

Posts 1–4 of 4 · Page 1 of 1
A Beginners Guide To Templates
Introduction

Templates can save you a lot of time when developing large applications, by using shared code for different functions and classes. By definition templates are common functions or classes, which work independent from data types. In this beginner tutorial I handle template functions and templates classes. Imagine you have implemented a class that handles a stack and all it's work, pushing, popping, reading status and so on. This stack class can handle double values. But what if you later need a stack for ints, for Cstrings or whatever in the same program? Without the template mechanism you would have to copy and paste code for each stack class. That's not very effective. But with templates you just define the template function or class with all it's own functions and variables, and declare a new variable that gets all the stuff from the template definition. So let's see how this works.

Function templates

Let's assume we need a function template for searching the minimum value from an array of different types:

Code:
template < class ElemType >
ElemType calcmin(ElemType elemField[], int iFieldSize)
{
	int iMin = 0;
	for (int  i=1; i < iFieldSize; ++i)
	{
		if (elemField[i] < elemField[iMin])
			iMin = i;
	}
	return elemField[iMin];
}

This is the template definition. The template expects a data type which is being searched and returned within the function. To use the template with the data types you want to be searched, use the template like this:

Code:
void LetsTestTheFunctionTemplate()
{
	int iField[] = {1,2,3,4,5,6};
	double dField[] = {2.5, 2.31, 10.23, 15.2};

	int iSize1 = sizeof(iField) / sizeof (int);
	int i = calcmin(iField, iSize1);
	int iSize2 = sizeof(dField) / sizeof(double);
	double d = calcmin(dField, iSize2);
}

The template min is being used for two different data types, an int[] and a double[], but providing the same functionality for each, searching the minimum value in the array and returning it.

Function templates can also be declared as inline, extern or static. When doing so, it's important to put the fields after the keyword template and it's parameters:

Code:
template < class ElemType >
inline ElemType swap(ElemType& a, ElemType& b);
Class templates

Defining a class template is almost similar to defining a function template. Let's catch up the example I used at the beginning, the common stack class to handle different data type's stack. The prototype will be defined as the following:

Code:
template < typename ElemType, int iSize=100 >
class Stack
{
public:
	Stack();
	~Stack();
	void push(const ElemType& anElement);
	void pop(ElemType& anElement);
	bool wasError() const;
	bool isEmpty() const;
private:
	ElemType elems[iSize];
	int iTop;
	bool bErrorOccd;
};

The implementation doesn't differ much from a normal class implementation, instead of a little more difficult notation. When a class template is defined, it can be used like a normal class, but you've got to specify the parameters within the < and >, and within the template the class name can be used without parameters. So let's look at the implementation for our stack example:

Code:
// include your prototype here or use a #define


template < class ElemType, int iSize >
Stack< ElemType, iSize >::Stack()
: iTop(0), bErrorOccd(false)
{
}

template < class ElemType, int iSize >
Stack< ElemType, iSize >::~Stack()
{
}

template < class ElemType, int iSize >
void Stack< ElemType, iSize >::push(const ElemType& anElement)
{
	bErrorOccd = (iTop == iSize);
	if (!bErrorOccd)
		elems[iTop++] = anElement;
}

template < class ElemType, int iSize >
void Stack< ElemType, iSize >::pop(ElemType& anElement)
{
	bErrorOccd = (iTop == 0);
	if (!bErrorOccd)
		anElement = elems[--iTop];
}

template < class ElemType, int iSize >
bool Stack< ElemType, iSize >::wasError() const
{
	return bErrorOccd;
}

template < class ElemType, int iSize >
bool Stack< ElemType, iSize >::isEmpty() const
{
	return (iTop==0);
}

You can use the class template by declaring a new variable like this:

Code:
Stack< int > iTheIntStack;
Stack< double, 30 > dTheDoubleStack;
Part2
Overloading function templates

Function templates can be overloaded with other function templates as well as with normal functions. The compiler will step through the list of possible function templates and creates the appropriate template function. The result is complemented with other possible template functions. This list is being searched by normal overloaded functions for the one that fits best.

Using friend and templates inside a template

Class templates like the one used in part 1 can include other templates or classes as well as having other classes as friends. When a class template includes another class, there are two possibilities:

-The second inner class can be a common class. Therefore this inner class is also dependent from the template parameters. Otherwise the inner class is again a class template.

-The outer class template contains another template that is dependent from the outer class as well as its own template parameters. In this first example, we include some list processing into a class template:

Code:
template < class ElemType >
class Tree
{
//...


public:
    class Node
    {
        friend Tree < ElemType >;
        //...

    };
};
Here the inner class Node is dependent from Tree and therefore gets its parameters. The outer class is defined as a friend of Node with a parameter list.

Template types

When using types that are declared within the scope of template parameters they have to be declared using the word typename:

Code:
template < typename T >
class X
{
//...

    typename T::X theStuff; // T::X is the type

    //...

};

class Test
{
//...

    class X { /* ... */ };
};
Without specifying the keyword typename, the compiler expects T::X to be a variable or constant and returns an error!

Element templates

When using element templates, it is possible e.g. to create a common class Builder that creates objects. This class provides an element function to allocate custom memory. This element function will be implemented as template element function and can be used for any types:

Code:
class Builder
{
//...

    template < class T > static T* allocateMem();
};

Note: Template element functions can not be declared as virtual!


I hope I gave you an easy overview of the possibilities how templates can help you saving time while developing your projects. And remember, this took me like 1 hour to compile it so press thanks!
Looks good. I hope it is not leeched ;]

Quote Originally Posted by akimo360
this took me like 1 hour to compile it so press thanks!
Lolwut ? Compile or write ?
Quote Originally Posted by Hassan View Post
Looks good. I hope it is not leeched ;]


Lolwut ? Compile or write ?
I wrote all of the codes while the explanations I leeched. (Too lazy to write those.)
Posts 1–4 of 4 · Page 1 of 1

Post a Reply

Similar Threads

Tags for this Thread

None

Talk with us