• No results found

An Introduction to C ++ Templates

10.4 CONSOLIDATION: UNDERSTANDING TEMPLATES

10.4.1 A test program

m second=val;

}

// Calculate distance

template <class TFirst, class TSecond>

double Point<TFirst, TSecond>::Distance(const Point<TFirst, TSecond>&

p) const {

// Get the length of the sides TFirst a=p.m first-m first;

TSecond b=p.m second-m second;

// Use Pythagoras to calculate distance return ::sqrt(a*a + b*b);

}

// Assignment operator

template <class TFirst, class TSecond>

Point<TFirst, TSecond>& Point<TFirst, TSecond>::operator = (const Point<TFirst, TSecond>& source)

{

if (this == &source) return *this;

m first=source.m first;

m second=source.m second;

return *this;

}

// Print

template <class TFirst, class TSecond>

ostream& operator << (ostream& os, const Point<TFirst, TSecond>& p) {

os << "(" << p.m first << "," << p.m second << ")\ n";

return os;

}

#endif

10.4.1 A test program

We now show how to use the above template class in an application. First, it is mandatory to in-clude the file that contains the source code of the member functions (in this case, Point.cpp) in

client code. Any other construction will not work. Then we replace the generic data types by spe-cific data types (this is called the instantiation process). To this end, consider the following code:

// TestGenericPoint.cpp //

// Testing generic points //

// (C) Datasim Education BV 2006 //

// The file that actually contains the code must be included

#include "point.cpp"

#include <iostream>

using namespace std;

int main() {

Point<double, double> p1(1.0, 1.0);

Point<double, double> p2; // Default point cout << "p1: " << p1 << endl;

cout << "p2: " << p2 << endl;

cout << "Distance between points: " << p1.Distance(p2) << endl;

return 0;

}

In this case we create points whose underlying types are double.

10.5 SUMMARY AND CONCLUSIONS

This chapter introduced the notion of generic programming as a programming paradigm and in particular we showed – by examples – how it is realised in C++ by the template mechanism.

We focused on the syntax that we must learn if we are going to be successful in using template classes and functions in Quantitative Finance applications.

A template class is not much different from a non-template class except that we explicitly state that certain members are generic. Second, all functions that use the generic data types must state that it is using these types, for example:

template <class TFirst, class TSecond>

Point<TFirst, TSecond>::Point() {

m first=TFirst();

m second=TSecond();

}

This chapter lays the foundation for the rest of this book in the sense that many of the specific instantiated classes and resulting applications make use of template classes and functions.

A good way to learn template programming is to take a working non-template class and then port it to a templated equivalent. A good example is the C++ class that models complex numbers. We have already discussed this class in Chapter 5.

10.6 EXERCISES AND PROJECTS

1. This exercise has to do with the class for a line segment in two dimensions that we discussed in Chapter 4. We give the class interface again for completeness:

// LineSegment.hpp //

// (Finite) line segments in 2 dimensions. This class represents // an undirected line segment. The functionality is basic. If you // wish to get more functions then convert the line segment to a // vector or to a line and use their respective member functions.

//

// This is a good example of Composition (a line segment consists of // two points) and the Delegation principle. For example, the member // function that calculates the length of a line is implemented as the // distance function between the line's end points.

//

// (C) Datasim BV 1995-2006 //

#ifndef LineSegment HPP

#define LineSegment HPP

#include "Point.hpp"

class LineSegment {

private:

Point e1; // End Point of line Point e2; // End Point of line public:

// Constructors LineSegment();

// Line with both end Points at the origin LineSegment(const Point& p1, const Point& p2);

LineSegment(const LineSegment& l); // Copy constructor

virtual ∼LineSegment(); // Destructor

// Accesssing functions

Point start() const; // Synonym for e1

Point end() const; // Synonym for e2

// Modifiers

void start(const Point& pt); // Set Point pt1 void end(const Point& pt); // Set Point pt2 // Arithmetic

double length() const; // Length of line // Interaction with Points

Point midPoint() const; // MidPoint of line segment };

#endif

The objective now is to model a new line class based on a generic point class. For convenience we assume that the first and second coordinates have the same underlying type:

template <class T>

class LineSegment {

private:

// Points have the same kinds of coordinates Point<T,T> e1;

Point<T,T> e2;

public:

// For you ☺ };

Answer the following questions:

(a) Complete the header and code files for this class. Test the class by creating lines with specific underlying types, for example double. You need to test each member function because a template class that compiles and works for a given member function does not mean that it works for all member functions. In short, we have the same interface as before except that the all data is generic!

(b) We now wish to extend the functionality by producing code to calculate the ‘taximan’s’

length for a line segment. This is the sum of the absolute value of the difference of the x coordinates and the absolute value of the difference of the y coordinates. LineSegment delegates to Point and this may necessitate two new useful functions in the point class:

double xExtent() const;

double yExtent() const;

2. Based on the C++ code for complex numbers in Chapter 5, the objective now is to create a generic version Complex<T>. Use the same programs as in chapter 5 to test this new template class.

166

Part II