100% found this document useful (1 vote)
60 views18 pages

C++ Templates: Characteristics of Generic Libraries

The document discusses C++ templates, which allow functions and classes to operate on generic types. It provides examples of function templates that define a single function that can work on different data types. Class templates similarly allow defining classes that can work on different types. The key benefits of templates are reusability, composability, and efficiency comparable to hand-coded implementations. The document provides examples of function and class templates, and how templates allow writing code once that can be used for multiple types through instantiation.

Uploaded by

Tg Wallas
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
100% found this document useful (1 vote)
60 views18 pages

C++ Templates: Characteristics of Generic Libraries

The document discusses C++ templates, which allow functions and classes to operate on generic types. It provides examples of function templates that define a single function that can work on different data types. Class templates similarly allow defining classes that can work on different types. The key benefits of templates are reusability, composability, and efficiency comparable to hand-coded implementations. The document provides examples of function and class templates, and how templates allow writing code once that can be used for multiple types through instantiation.

Uploaded by

Tg Wallas
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 18

09/03/2011

C++ Templates

Generic Functions and Classes

Characteristics of Generic Libraries


Reusable: able to operate on user-defined data types Composable: able to operate on data types defined in another library Efficient: performance on par with non-generic, hand-coded implementations
2

09/03/2011

Templates
Function templates
Specify entire range of related (overloaded) functions Function-template specializations

Class templates
Specify entire range of related classes
Class-template specializations

Function Templates
Overloaded functions
Similar operations
Different types of data

Function templates
Identical operations
Different types of data

Single function template


Compiler generates separate object-code functions
4

09/03/2011

Function Templates
Function-template definitions
Keyword template List formal type parameters in angle brackets (< and >)
Each parameter preceded by keyword class or typename
class and typename interchangeable template< class T > template< typename ElementType > template< class BorderType, class FillType >

Specify types of
Arguments to function Return type of function Variables within function
5

Function Templates
Current scenario
We rewrite functions Min(), Max(), and InsertionSort() for many different types There has to be a better way

Function template
Describes a function format that when instantiated with particulars generates a function definition
Write once, use multiple times
6

09/03/2011

Example: Nave Approach


void PrintInt( int n ) { cout << "***Debug" << endl; cout << "Value is " << n << endl; } void PrintChar( char ch ) { cout << "***Debug" << endl; cout << "Value is " << ch << endl; } void PrintFloat( float x ) { To output the traced values, we insert: } PrintInt(sum); void PrintDouble( double d ) { PrintChar(initial); }

PrintFloat(angle);
7

Function Overloading
The use of the same name for different C++ functions, distinguished from each other by their parameter lists
Eliminates need to come up with many different names for identical tasks. Reduces the chance of unexpected results caused by using the wrong function name.
8

09/03/2011

Function Overloading
void Print( { cout << cout << } void Print( { cout << cout << } void Print( { } int n ) "***Debug" << endl; "Value is " << n << endl; char ch ) "***Debug" << endl; "Value is " << ch << endl; float x )
To output the traced values, we insert:

Print(someInt); Print(someChar); Print(someFloat);


9

Function Template
A C++ language construct that allows the compiler to generate multiple versions of a function by allowing parameterized data types.

FunctionTemplate Template < TemplateParamList > FunctionDefinition

TemplateParamDeclaration: placeholder

class typeIdentifier typename variableIdentifier


10

09/03/2011

Example of a Function Template


template<class SomeType>
Template parameter (class, user defined type, built-in types) void Print( SomeType val ) { cout << "***Debug" << endl; cout << "Value is " << val << endl; }

Template argument

To output the traced values, we insert:

Print<int>(sum); Print<char>(initial); Print<float>(angle);

11

Instantiating a Function Template


When the compiler instantiates a template, it substitutes the template argument for the template parameter throughout the function template.
TemplateFunction Call

Function < TemplateArgList > (FunctionArgList)

12

09/03/2011

A more complex example


template<class T> void sort(vector<T>& v) { const size_t n = v.size(); for (int gap=n/2; 0<gap; gap/=2) for (int i=gap; i<n; i++) for (int j=i-gap; 0<j; j-=gap) if (v[j+gap]<v[j]) { T temp = v[j]; v[j] = v[j+gap]; v[j+gap] = temp; } }

13

Further Example: Function Template


Indicates a template is being defined Indicates T is our formal template parameter

template <class T> T Min(const T &a, const T &b) {


Instantiated functions will return a value whose type is the actual template parameter

if (a < b) return a; else return b;

Instantiated functions require two actual parameters of the same type. Their type will be the actual value for T

14

09/03/2011

Function Templates Facts


Location in program files
In current compilers
Template definitions are part of header files

Possible template instantiation failure scenario


cout << min(7, 3.14);
//different parameter types

15

Generic Sorting
template <class T> void InsertionSort(T A[], int n) { for (int i = 1; i < n; ++i) { if (A[i] < A[i-1]) { T val = A[i]; int j = i; do { A[j] = A[j-1]; --j; } while ((j > 0) && (val < A[j-1])); A[j] = val; } } }

16

09/03/2011

Summary of Three Approaches

Nave Approach Different Function Definitions Different Function Names

Function Overloading Different Function Definitions Same Function Name

Template Functions One Function Definition (a function template) Compiler Generates Individual Functions

17

Class Template
Rules
Type template parameters Value template parameters
Place holder for a value Described using a known type and an identifier name

Template parameters must be used in class definition described by template Implementation of member functions in header file
Compilers require it for now
18

09/03/2011

Class Template
A C++ language construct that allows the compiler to generate multiple versions of a class by allowing parameterized data types.

Class Template Template < TemplateParamList > ClassDefinition

TemplateParamDeclaration: placeholder

class typeIdentifier typename variableIdentifier


19

Example of a Class Template


template<class ItemType> class GList Template { parameter public: bool IsEmpty() const; bool IsFull() const; int Length() const; void Insert( /* in */ ItemType item ); void Delete( /* in */ ItemType item ); bool IsPresent( /* in */ ItemType item ) const; void SelSort(); void Print() const; GList(); // Constructor private: int length; ItemType data[MAX_LENGTH]; };
20

10

09/03/2011

Instantiating a Class Template


Class template arguments must be explicit. The compiler generates distinct class types called template classes or generated classes. When instantiating a template, a compiler substitutes the template argument for the template parameter throughout the class template.
21

Instantiating a Class Template


To create lists of different data types // Client code GList<int> list1; GList<float> list2; GList<string> list3; list1.Insert(356); list2.Insert(84.375); list3.Insert("Muffler bolt"); Compiler generates 3 distinct class types template argument

GList_int list1; GList_float list2; GList_string list3;

22

11

09/03/2011

Substitution Example
class GList_int { public:

int int

void Insert( /* in */ ItemType item ); void Delete( /* in */ ItemType item ); bool IsPresent( /* in */ ItemType item ) const; private: int length; ItemType data[MAX_LENGTH]; }; int int

23

Function Definitions for Members of a Template Class


template<class ItemType> void GList<ItemType>::Insert( /* in */ ItemType item ) { data[length] = item; length++; } //after substitution of float void GList<float>::Insert( /* in */ float item ) { data[length] = item; length++; }
24

12

09/03/2011

Another Template Example: passing two parameters


template <typename T, int size> class Stack {... non-type parameter T buf[size]; }; Stack<int,128> mystack;

25

Generic Arrays
template <class T> class Array { public: Array(int n = 10, const T &val = T()); Array(const T A[], int n); Array(const Array<T> &A); ~Array(); int size() const { return NumberValues; } Array<T> & operator=(const Array<T> &A); const T& operator[](int i) const; T& operator[](int i); private: int NumberValues; T *Values; };
26

13

09/03/2011

Default Constructor
template <class T> Array<T>::Array(int n, const T &val) { assert(n > 0); NumberValues = n; Values = new T [n]; assert(Values); for (int i = 0; i < n ++ i) { Values[i] = A[i]; } }
27

Copy Constructor
template <class T> Array<T>::Array(const Array<T> &A) { NumberValues = A.size(); Values = new T [A.size()]; assert(Values); for (int i = 0; i < A.size(); ++i) { Values[i] = A[i]; } }

28

14

09/03/2011

Destructor
template <class T> Array<T>::~Array() { delete [] Values; }

29

Example:

a swap function

Problem: Oftentimes, it is nice to be able to swap the values of two


variables. This functions behavior is similar for all data types. Templated functions let you do that in most cases without any syntax changes.

Stupid method write an overloaded function for each type


Swap for integers Swap for an arbitrary type T

void swap(int &a, int &b) { int c = a; a = b; b = c; }

void swap(T &a, T &b) { T c = a; a = b; b = c; }

Template method write one templated function


template <typename T> void swap(T &a, T &b) { T c = a; a = b; b = c; } This function can be used with any type that supports assignment and can be passed in as a non-const reference.
30

15

09/03/2011

Template Syntax:
The template<> line states that everything in the following declaration or definition is under the subject of the template. (In this case, the definition is the function swap)

swap dissected
In here goes a list of placeholders variables. In almost all cases, they will be specified with either the typename or class keywords. These two keywords are equivalent.
Template behavior: Like most things in C++, templates attempt to behave as if it were a natural part of the language. It fails. There are two ways to use templates, implicit and explicit specialization. Explicit specialization always works. Implicit sometimes works. Why ever use implicit specialization? Its much cleaner. What are they? That is explained on the next slide.
31

template <typename T> void swap(T &a, T &b) { T c = a; a = b; b = c; }

Placeholder variables have one value within each template declaration. Think of them as being replaced by whatever type you specify the template to be.

Template Syntax:
Using a template

Using it
template <typename T> void swap(T &a, T &b) { T c = a; a = b; b = c; }

To use a template, one has to specialize it. This is why it isnt quite a generic function. It does static polymorphism. It morphs itself to the right type during preprocess time.
Syntax

To explicitly specialize a template, write its name with the arguments for the placeholder variables in angle brackets. This method always works. Example:
double d1 = 4.5, d2 = 6.7; swap<double>(d1, d2);

Templates however can auto-sense its placeholder values if all information about what the placeholders represent can be inferred from its context (arguments, and for member functions, the associated class instance). This is called implicit specialization. In the previous case, the compiler is smart enough to figure out that T is a double even without the explicit <double> since the arguments are doubles. Thus this shorthand works: Example:
swap(d1, d2);
32

16

09/03/2011

Class Templates:
Syntax:

Class Definition

Templated classes basically follow same syntax as templated functions. However, the rules for which templated classes can infer their specialization (see Template Syntax) are a bit more convoluted.

Before moving on, a bit of review on templated functions:


Are the following two templates equivalent?
template <typename T> void swap(T &a, T &b) { T c = a; a = b; b = c; } template <class C> void swap(C &a, C &b) { C c = a; a = b; b = c; }

Answer:
Yes, they are equivalent. This may be relevant when writing class templates as it is possible that a situation may arise where two definitions are written for the same thing. If this happens, the program will not build since there are two equivalent function definitions. The name of the placeholder doesnt matter, and typename and class can be used interchangeably. Just something to remember.

33

Class Templates:
Notice the only addition to the class definition is the line:
template <typename T>

Example

Example: A templated, dynamic, 2 dimensional array (Matrix)*


#ifndef MATRIX_H #define MATRIX_H template <typename T> class Matrix { public: Matrix(int rows, int cols); Matrix(const Matrix &other); virtual ~Matrix(); Matrix& operator=(const Matrix &rhs); T* operator[](int i); int getRows() const; int getCols() const; protected: void copy(const Matrix &other); private: Matrix(); int m_rows; int m_cols; T *m_linArray; }; #endif /* MATRIX_H */ 34

Within the the definition block, the placeholder has can be used as a data type. When the template is specialized, it takes on the value of the specialization.

The header is pretty pedestrian. Lets have some fun. On to the fiery pits of class implementation.

File: Matrix.h

17

09/03/2011

Class Templates:
#include "Matrix.h" template <typename T> Matrix<T>::Matrix() {}

Example contd
template <typename T> T* Matrix<T>::operator[](int i) { return m_linArray + (i*m_cols); } template <typename T> void Matrix<T>::copy(const Matrix &other) { m_rows = other.m_rows; m_cols = other.m_cols; int size = m_rows * m_cols; m_linArray = new T[size]; for( int i=0; i < size; i++ ) { m_linArray[i] = other.m_linArray[i]; } } template <typename T> int Matrix<T>::getRows() const { return m_rows; } template <typename T> int Matrix<T>::getCols() const { return m_cols; }

template <typename T> Matrix<T>::Matrix(int rows, int cols) { m_rows = rows; m_cols = cols; m_linArray = new T[m_rows * m_cols]; } template <typename T> Matrix<T>::Matrix(const Matrix &other) { copy(other); } template <typename T> Matrix<T>::~Matrix() { delete[] m_linArray; } template <typename T> Matrix<T>& Matrix<T>::operator=(const Matrix &other) { if( this != &other ) { delete[] m_linArray; copy(other); } return *this; }

File: Matrix.cc
35

Shotgun Safety:
/* main.cc */ #include <iostream> using namespace std; #include <Matrix.h>

An example
The proper procedure Write the template, separated into a header and an implementation file Create an instantiation file for the template which include the implementation file. Compile the instantiation file and not the template implementation file. The instantiation file generates the object code for the template.
/* MatrixInst.cc */ #include Matrix.cc template Matrix<int>;

int main(void) { Matrix<int> m1(3,4); cout << m1.getRows() << endl; }

Example:
To make the previously unlinking piece of code link properly, it is necessary to instantiate an integer version of the Matrix template. The file would simply look like this

notice that the implementation (not header) file is included.

This line forces the instantiation of the Matrix class template, as well as all its member functions, for specialization int. Other specializations require their 36 own lines.

18

You might also like