<<

. 6
( 9)



>>


return (i->second)(Strike);
}

PayOffFactory& PayOffFactory::Instance()
{
static PayOffFactory theFactory;
return theFactory;
}
Other than for the Instance() method, which we have already discussed, the
methods are really just wrappers for the inner map object.
In case the reader is not familiar with the STL map container, we discuss a little
how it works. A map is a collection of pairs. We used the pair class to store
162 The factory

the nodes of a tree in Chapter 8. Recall that a pair is a simple class consisting
of two public data members known as first and second. The types of these
data members are template parameters. When working with a map, first is the
key or identi¬er used to look up the object we wish to ¬nd which is stored in
second.
For us this means that the type of the map is

map<std::string, CreatePayOffFunction>

and every pair that we use will be of the same type. The insert method is
used to place pairs of strings and CreatePayOffFunctions into the map. A
map has the property that each key is unique so if you insert two pairs with the
same key then the second one is ignored. For us, this means that if we give two
PayOff classes the same string identi¬er only one will be registered. It is possi-
ble to examine the return type of the insert to determine whether the insertion
was successful. The method RegisterPayOff carries out this insertion for our
factory.
The retrieval is carried out in CreatePayOff: a string is passed in and the
find method of map is used. This method returns a const iterator pointing to
the pair which has the correct key (i.e. first element) if such a pair exists, and
otherwise the iterator points to the end of the map. For the reader who is not familiar
with iterators, an iterator is an abstraction of a pointer and works in similar fashion.
Just like pointers, they can be dereferenced via * or ->. A const iterator is
similar to a non-const pointer to const objects. That is, the iterator™s value can
be changed, but the value of the thing it points to cannot.
Our method therefore uses find to get an iterator. This iterator is then checked to
see if the look-up succeeded. If it failed we print an error message and return a null
pointer. If is succeeded, we take the second element of the pair pointed to, which
is a function pointer, dereference it and call it with argument Strike. Since this
function™s job is to create a PayOff object of the relevant type and return a pointer
to it, we have achieved our objective; objects of any class previously registered can
be created by entering the appropriate string and strike.
Whilst we certainly could have programmed our factory without using the STL
map class, its existence certainly made the task much easier. We refer the reader to
Stroustrup, [31], Section 17.4, Josuttis, [12], and Meyers, [20], for further informa-
tion on the map class.


10.5 Automatic registration
We discussed above how we could manage registration of PayOff classes by using
global variables. Here we look at how to carry out this out. As we mentioned above,
10.5 Automatic registration 163

the code is the same except for class names for each registration so it makes sense to
use a template class. We present this template code in PayOffConstructible.h:

Listing 10.3 (PayOffConstructible.h)

#ifndef PAYOFF_CONSTRUCTIBLE_H
#define PAYOFF_CONSTRUCTIBLE_H

#if defined(_MSC_VER)
#pragma warning( disable : 4786)
#endif

#include <iostream>
#include <PayOff3.h>
#include <PayOffFactory.h>
#include <string>

template <class T>
class PayOffHelper
{
public:
PayOffHelper(std::string);
static PayOff* Create(double);
};

template <class T>
PayOff* PayOffHelper<T>::Create(double Strike)
{
return new T(Strike);
}

template <class T>
PayOffHelper<T>::PayOffHelper(std::string id)
{
PayOffFactory& thePayOffFactory = PayOffFactory::Instance();
thePayOffFactory.RegisterPayOff(id,PayOffHelper<T>::Create);
}
#endif

The helper class we de¬ne here has to do two things. It must de¬ne a constructor
that carries out the registration of the class de¬ned by the template parameters, and
164 The factory

it must de¬ne a function which will carry out the creation so we have something to
use in the registration process!
The constructor takes in a string as an argument; this string will be needed to
identify the class being registered. The constructor simply ¬rst calls Instance to
get the address of the factory object, and then calls the RegisterPayOff method
of the factory to carry out the registration. Note that the constructor does not actu-
ally do anything as regards the actual object being created! In fact, the class has no
data members so it would not be possible to do anything.
The method Create de¬nes the function used to create the pay-off object on
demand. Note that it is static as it should not be associated to any particular
class object. The function simply calls the constructor for objects of type T with
argument Strike. Of course, there is something slightly subtle here in that the
speci¬cation of the template parameter, T, is making the choice of which object
to construct. Note that we use new as we want the created object to persist after
the function is ¬nished. One consequence of this is that the object will have to be
properly deleted at some point.
PayOffRegistration.cpp includes an example of using the PayOff
Helper class.

Listing 10.4 (PayOffRegistration.cpp)

#include <PayOffConstructible.h>

namespace
{
PayOffHelper<PayOffCall> RegisterCall("call");

PayOffHelper<PayOffPut> RegisterPut("put");
}

Note that if we were de¬ning a new class, we would probably put this registra-
tion in the source ¬le for the class but as we have already de¬ned the call and
put classes, we do not do so here. The registration ¬le is quite short. We de-
¬ne two global variables, RegisterCall and RegisterPut. These are of type
PayOffHelper<Call> and PayOffHelper<Put>. As global variables, they are
initialized at the start of the program. This initialization carries out the registration
as required. Note that we have put a namespace command around the declaration.
This means that the variables are in an unnamed namespace and as such are invisi-
ble to the rest of the program. So the variables are both global and invisible. Why
do we want them invisible? Their purpose is purely to perform the registration, and
once that has been done we have no further use for them so it is best to put them
out of sight and out of temptation™s reach.
10.6 Using the factory 165

10.6 Using the factory
Now we have done all the set-up work, how do we use the factory? We give a very
simple example in PayFactoryMain.cpp.

Listing 10.5 (PayFactoryMain.cpp)
/*
Uses
PayOff3.cpp
PayOffBridge.cpp
PayOffFactory.cpp
PayOffRegistration.cpp
*/

#include <PayOff3.h>
#include <PayOffConstructible.h>
#include <PayOffBridge.h>
#include <PayOffFactory.h>
#include <string>
#include <iostream>
using namespace std;

int main()
{
double Strike;
std::string name;

cout << "Enter strike\n";
cin >> Strike;

cout << "\npay-off name\n";
cin >> name;

PayOff* PayOffPtr =
PayOffFactory::Instance().CreatePayOff(name,Strike);

if (PayOffPtr != NULL)
{
double Spot;

cout << "\nspot\n";
cin >> Spot;
166 The factory

cout << "\n" << PayOffPtr->operator ()(Spot) << "\n";
delete PayOffPtr;
}

double tmp;
cin >> tmp;
return 0;
}
This routine is very simple but illustrates the important points. The user inputs spot,
strike and the name of the option. If an option with that name has been registered
then the pay-off is computed, and the object is then deleted.
The important point here is that the name de¬nitions are carried out in the ¬le
PayOffRegistration.cpp, and this ¬le is not seen directly by any of the other
¬les including the main routine. If we wanted to add another PayOff, say the
forward, we could so without modifying any of the existing ¬les. In fact, all we
would have to do is add the header and source ¬le for the forward, and in a new ¬le
PayOffForwardRegistration.cpp add the declaration
PayOffHelper<PayOffForward> RegisterForward("forward");
As we originally required, this would not require recompilation of any of the orig-
inal ¬les. We have therefore achieved our original objective of an open-closed pat-
tern.


10.7 Key points
In this chapter we have developed the factory pattern and the singleton pattern
in order to give a method of adding new pay-off classes to an interface without
modifying existing ¬les.

• The singleton pattern allows us to create a unique global object from a class and
provide a way of accessing it.
• The factory pattern allows us to add extra inherited classes to be accessed from
an interface without changing any existing ¬les.
• The factory pattern can be implemented using the singleton pattern.
• The standard template library map class is a convenient way to associate objects
with string identi¬ers.
• Placing objects in an unnamed namespace is a way of ensuring that they are not
accessed elsewhere.
• We can achieve automatic registration of classes by making their registration a
side-effect of the creation of global variables from a helper class.
10.8 Exercises 167

We will return to the factory pattern in Chapter 14; there we will see how to imple-
ment it in a generic way so that one implementation will do forever.


10.8 Exercises
Exercise 10.1 Write a straddle class and register it with the factory.

Exercise 10.2 Our class cannot handle a double digital as it needs two strikes. Work
out a solution that will handle options with multiple parameters.

Exercise 10.3 Integrate the factory with a Monte Carlo routine.
11

Design patterns revisited




11.1 Introduction
In this chapter, we revisit and catalogue the design patterns from earlier chapters.
We also mention a few other patterns we have not studied which the reader may ¬nd
helpful. Finally, we discuss further reading on the topic of design
patterns.
The design patterns we have studied are a small subset of those in the classic
book on the topic: Design Patterns, [7], which is often referred to as the ˜Gang
of Four™ book. As well as listing the patterns, the authors attempt to classify the
patterns according to the contexts in which they are used. In this ¬nal chapter,
we revisit the patterns the we have studied in the context of that classi¬cation.
We also mention some patterns discussed there which we have not examined
here.


11.2 Creational patterns
A creational pattern is a pattern that deals primarily with the creation of new ob-
jects. Their purpose is to abstract the creation process which helps the system to be
developed independently of the types of individual objects. In fact, sometimes all
we can be sure of about these objects, is what class they are inherited from, or in
other terms what interface they implement.


11.2.1 Virtual copy constructor
We have extensively used the concept of cloning. We need a copy of an object, we
do not know its type so we cannot use the copy constructor so we ask the object to
provide a copy of itself. Note the general philosophy here is that the object knows
more about itself than we do so we ask it to help us out. Note we could easily


168
11.3 Structural patterns 169

modify this pattern to ask the object to make a default object from its class, as once
again it knows its class type and we do not. In [7] virtual constructors are known
as the ˜Factory Method™.


11.2.2 The factory
This is called the ˜abstract factory™ in [7]. The purpose of this pattern is to allow
us to have an object that spits out objects as and when we need them. This means
in particular that responsibility for creating objects of the relevant type lies with a
single object. We thus gain greater control over their creation, which yields greater
¬‚exibility in changing the objects used. We principally used this pattern to give an
easily extended interface. In particular, we saw that the pattern allows the addition
of new classes to an interface without the rewriting of any code.


11.2.3 Singleton
We used the singleton pattern to implement our factory. The big advantage of the
singleton pattern is that there is a single copy of the object which is accessible
from everywhere, without introducing global variables and all the dif¬culties they
imply. Note that if for some reason we wanted more than one copy of the object to
exist then we could easily modify the pattern to given us a doubleton or a tripleton
and so on. For example, we could de¬ne more than one method that performed
similarly to our Instance method.


11.2.4 Monostate
We have not examined the monostate pattern nor is it covered in Design Patterns,
however, it is a useful alternative to the singleton pattern. Rather than only allowing
one object from the class to exist, we allow an unlimited number but make them
all have the same member variables. Thus all the objects from the class act as one.
The way we do this is by making all the data members static. This approach
allows us to treat each object from the class like any other, although they are all
really the same object. Our factory could easily have been implemented using this
pattern.


11.3 Structural patterns
A structural pattern is one that deals mainly with how classes are composed to
de¬ne more intricate structures. They allow us to design code that has extra func-
tionality without having to rewrite existing code.
170 Design patterns revisited

11.3.1 Adapter
The adapter is a class that translates an interface into a form that other classes
expect. It is most useful when we wish to ¬t code into a structure for which it was
not originally designed, either because we have changed our way of doing things
or because the code originates elsewhere. For example, if we download a library
from the web, its interface is unlikely to conform to what we have been using. By
adapting the interface, we can seamlessly integrate it into existing code. We gave
an example of the adapter when implementing random number generators.


11.3.2 Bridge
The bridge is similar to the adapter in that it de¬nes an interface, and acts as an in-
termediary between a client class and the classes implementing the interface. Thus
the implementing class can easily be changed without the client class being aware
of the change. The main difference between the bridge and the adapter is that the
bridge is intended to de¬ne an intermediary interface from the start, whereas the
adapter is introduced a later stage in order to solve incompatibilities. We used
the bridge to create the PayOff and Parameters objects.


11.3.3 Decorator
The decorator patterns allows us to change the behaviour of a class at run-time
without changing its interface. We add a wrapper class that processes incoming
or outgoing messages and then passes them on. We saw that a decorator could be
used to implement anti-thetic sampling when studying random number generation.
We also saw that it could be used to create convergence tables of statistics when
designing statistics gatherers. An attractive aspect of decoration is that we can dec-
orate as many times as we like since the interface after decoration is the same as
the interface before.


11.4 Behavioural patterns
Behavioural patterns are used for the implementation of algorithms. They allow
us to vary aspects of algorithms interchangeably. They can also allow us to re-use
algorithms in wildly unrelated contexts.


11.4.1 Strategy
In the strategy pattern, we defer an important part of algorithm to an inputted
object. This allows us to easily change how this particular part of the algorithm
11.5 Why design patterns? 171

behaves. We have used this pattern implicitly and explicitly all through the book.
By making the PayOff or VanillaOption an input to our pricer, we are using
this pattern. Less trivially, we made the random number generator an input to our
Monte Carlo, and the generator is a key part of the algorithm.


11.4.2 Template
In the template pattern, rather than inputting an aspect of the algorithm, we defer
part of the algorithm™s implementation to an inherited class. The base class thus
provides the structure of how the different parts of the algorithm ¬t together, but
does not specify all the details of the implementation. We adopted this approach
when designing our exotics Monte Carlo pricer; there we de¬ned the process for the
stock price evolution in an inherited class. This allowed the possibility of pricing
exotics using a different model in the future.


11.4.3 Iterator
We have only brie¬‚y mentioned iterators; however, they are an important compo-
nent of the standard template library. An iterator is essentially an abstraction of a
pointer. As such it should be possible to dereference it, i.e. look at what it points to,
increment and decrement it. The idea of iterators is that one can be de¬ned for any
sort of data structure, and so if an algorithm is de¬ned in terms of iterators it can
be applied to any sort of data structure. In the STL, algorithms take the type of the
iterator as a template argument, which allows this generality to be implemented.


11.5 Why design patterns?
Why think in terms of design patterns? What has this classi¬cation bought us? The
¬rst simple thing is that it becomes much easier to explain our code to someone
else; remember that re-use is ultimately de¬ned socially not analytically. When
describing our code to someone else, if we can describe a class by saying this is
such and such standard pattern then they immediately have a mental model of how
it works from their previous familiarity with that pattern.
A second advantage is that by having familarity with a collection of standard
design patterns, we gain an immediate toolbox for solving any problem put in front
of us. Thus when confronted with a programming problem, we can approach it by
thinking “what design pattern is appropriate here?” rather than by attempting to
solve it from scratch. Even if none of the known patterns are appropriate, exami-
nation of the problem through the lens of design patterns will help us to solve it.
In particular, the knowledge of why the patterns are inappropriate will aid us in
developing a solution.
172 Design patterns revisited

Of course, most programmers have patterns they implicitly use regularly. Indeed,
many experienced programmers reading this book may feel they are only learning
a formalization of what they did in any case. The advantage for them in using
patterns is that it will help them to think more clearly about what they do and
why.

11.6 Further reading
There are now many books on the topic of design patterns. We mention a few
that the author has found useful. One good and straightforward book which was
deliberately written as an easier companion to Design Patterns is Design Pat-
terns Explained by Shalloway & Trott. The authors carefully go through many
patterns explaining in simple language the concepts introduced in the original
book.
C++ Programming: with Design Patterns Revealed by Muldner is another in-
troductory book which is accessible, and takes the point of view that C++ should
be learnt from the start in terms of design patterns.
Modern C++ Design by Alexandrescu is a more advanced book. It covers many
more intricate ideas using templates than we have had the opportunity to cover
here.
As well as books explicitly on design patterns, a C++ programmer needs many
other standard texts. Some favourites of the author are
Effective C++, More Effective C++ and Effective STL by Scott Meyers. These
books are collections of programming gems by a C++ expert.
The C++ Programming Language by Bjarne Stroustrup. This is the ultimate
reference book on C++ by the man who invented the language.
The C++ Standard Library by Nicolai Josuttis. This is a comprehensive de-
scription of the standard library that ships with any C++ compiler.
My favourite introductory book on object-oriented programming is
The Tao of Objects by Gary Entsminger. It™s an easy read and concentrates on
introducing the basic ideas of OO design.
There are now a number of books on C++ and numerical techniques in ¬nance.
Of all of these, the one closest in style and approach to this book is the forthcoming:
Quantitative Finance: An Object-oriented Approach + C++ by Eric Schl¨ gl. o
The books by Daniel Duffy are also worthwhile but take a different tack with
more emphasis on templates and less on virtual functions.


11.7 Key points
• Design patterns can be classi¬ed into behavioural, structural and creational pat-
terns.
11.8 Exercise 173

• Behavioural patterns are used for the implementation of algorithms.
• Structural patterns deal with how classes are composed to create more intricate
designs.
• A creational pattern deals primarily with the creation of new objects.


11.8 Exercise
Exercise 11.1 Implement the factory from Chapter 10 using the monostate pattern
instead of the singleton pattern.
12

The situation in 2007




12.1 Introduction
The ¬rst eleven chapters of this book were written in the summer of 2002. In-
evitably, both C++ and quantitative ¬nance have moved on in the last ¬ve years,
and, in addition, my view of the two subjects has evolved. In this brief chap-
ter, I want to discuss some of the changes and set the stage for the newly added
chapters.


12.2 Compilers and the standard library
In 2002, the most popular compiler for C++ was Visual Studio 6.0. Other pop-
ular compilers were g++ 2.95 and Borland 5.5. I therefore targeted the book
and the code at those three compilers. Today, Visual Studio has gone through
a couple of versions and the most popular version is 8.0. In addition, the up-
grade process has been faster than usual in that Microsoft decided to make the
“Express” version free. This version contains the full optimizing compiler and
IDE (integrated development environment) but omits various added features which
are not particularly important to the lone developer. The open source compiler
g++ has also evolved and the most recently released version is as part of gcc
4.2.0. In addition, the standard libraries that ship with the compilers have been
updated.
What difference does this make? The biggest difference for the programmer is
that the compilers and libraries are much closer to the C++ ANSI/ISO standard,
which was rati¬ed in 1997. They are still not fully compatible in that they do not
implement the export keyword. In fact, the only compiler that does is the Comeau
Compiler (www.comeaucomputing.com), which is the only fully compatible com-
piler. If you are wondering what the export keyword is; don™t. (If you must know,
it gives an alternate way of implementing templates that does not require all the
code to be in the header ¬le.)

174
12.2 Compilers and the standard library 175

Most of the advantages relate to complicated template code, which we do not
attempt to discuss in this book, but refer the reader to [35] for how to make a
Turing machine run at compile time using template code.
However, some of the advantages are more mundane and are de¬nitely worth
mentioning. One example is that for loops variables are now properly scoped.
If you declare
for (int i =0; i < 10; ++i)
{
// do stuff
}

i =0;
then you will get a compilation error unless you have declared i before the for
loop; this was not true in 6.0. On the other hand, the following code did not compile
in 6.0
for (int i =0; i < 10; ++i)
{
// do stuff
}

for (int i =0; i < 10; ++i)
{
// do more stuff
}
as the variable i is declared twice in the same scope. This can be quite annoying if
you are writing for cross-platform compatibility! One solution is to put {,} around
the ¬rst for loop forcing the correct behaviour in 6.0 without affecting behaviour
on the other compilers.
Another relevant improvement is that changing the return type of inherited class
pointers is supported in 8.0. So we can now make our clone method return a
pointer of an inherited class type. That is we can code
class Base
{
public:
virtual Base* clone() const=0;

// etc

};
176 The situation in 2007

class Inherited : public Base
{
public:
virtual Inherited* clone() const;

// etc

};
and not get an error about the fact that the return type has changed. This is mainly
useful if we have 3 level hierarchies. For example, suppose we decided to imple-
ment pay-off type via inheritance (I don™t recommend this, but it serves to illustrate
the point), so we have a base class EquityOption, we inherit VanillaOption
from this, and CallOption from VanillaOption.
Now suppose we declare clone in EquityOption, it will return a pointer of
type EquityOption*. Under the old rules, the clone method of CallOption
would have had to return a pointer of type EquityOption. This would have made
it impossible to use Wrapper<VanillaOption>, which would be rather inconve-
nient.
Under the new rules, we return a pointer of the most derived type and it can
always be treated as a pointer to a class further up the hierarchy so we have no
problems.
Another big change that is very convenient is that the standard template library
has range-checking in Debug mode in Visual C++ 8.0. With previous versions
of the library, this was always a big disadvantage when working with the STL
vector in that one either used .at all the time and suffered a performance penalty
in Release mode, or spent ages trying to track down out-of-range errors which
were not reported. Note that if you are using another compiler, you can get an
alternative implementation of the standard library from www.stlport.org which
does feature range-checking.


12.3 Boost
The Boost project is an open source library designed to extend the C++ standard
library. It can be found at www.boost.org. The code is heavily peer-reviewed
and required to work across multiple compilers. The intention is that the libraries
incorporated in Boost will become part of the C++ Standard in the future, and,
indeed, it is already planned to incorporate many of them. Because of this, the
licence is very unrestrictive and allows the user basically to do whatever they want
with the code. This is different from the GNU licence, which restricts use of the
code to applications that distribute source code and allow the user to do the same.
From the Boost website, here are some of the requirements met by the licence:
12.5 xlw 177

• Must grant permission without fee to copy, use and modify the software for any
use (commercial and non-commercial).
• Must require that the license appear with all copies [including redistributions] of
the software source code.
• Must not require that the license appear with executables or other binary uses of
the library.
• Must not require that the source code be available for execution or other binary
uses of the library.
What all this means is that you can use code from Boost in your work without
ever having to worry about licensing issues.
The main downside of Boost used to be that the installation process was an-
noying, they had their own customized routines for installation that you had to use.
However, there is now an installer that gives you the pre-compiled binaries for the
libraries if you use Visual C++ 7.1 or Visual C++ 8.0.
There are far too many libraries to attempt to discuss them here. However, two
of particular interest to quantitative analysts are the random number library, and the
multi-dimensional array library. We will discuss the smart pointers library a little
in Chapter 13. Books are now being written on Boost and a useful one is Beyond
the C++ Standard Library by Karlsson. Boost is used heavily by the Quantlib
project.


12.4 QuantLib
QuantLib is the biggest and most successful open-source project for quantitative
¬nance. It is a large repository of C++ code and can be found at quantlib.org.
Similarly to Boost, the license is very unrestrictive, allowing free use in commer-
cial software. The objective is to provide a large pricing library for derivatives that
can used for many purposes. The code is very much structured as one library, and
whilst individual routines can be cut out, it is not designed to facilitate this. Famil-
iarity with QuantLib will certainly be an important skill in the future. The author
of this book is now a developer on the project.
As well as providing a C++ library, QuantLib comes with code for building
interfaces to various applications, particularly EXCEL. The main dif¬culty with
QuantLib is that requires a certain amount of sophistication to make sense of the
library, so once you are comfortable with C++ start learning, but wait until you
are.


12.5 xlw
Although in the ¬rst part of this book, we concentrated on writing console appli-
cations, it is actually rare for quants to work in that way. One of the most common
178 The situation in 2007

modes of working is to write EXCEL plug-ins, known as xlls. These add extra
functions to EXCEL, which can be called from the spread-sheet. These work via
the C API, which was never very well documented. In order to make interfacing
easier, Jerome Lecomte wrote a C++ wrapper called xlw. This made the whole
process much simpler but still involved writing a lot of repetitive code. Ferdinando
Ametrano took over the project and ported it to sourceforge.net. The author
of this book then took over the project and made various changes. The biggest of
these is that the interfacing code is now automatically generated; this means that
the user has to do very little. Another important aspect of the package is that it
works with the free MingW g++ compiler as well as Visual C++ 6.0, 7.1, and
8.0. We will discuss using examples from xlw in the rest of the book, particularly
in Chapter 14 where we develop a generic factory using the implementation in xlw
as an example. We discuss how to use the xlw project in detail in Chapter 15.
The code for xlw can be obtained from xlw.sourceforge.net.


12.6 Key points
• The most popular compilers are now Visual Studio 8.0 and gcc 4.2.0.
• The new compilers are closer to being compliant with the C++ standard.
• Boost is a high-quality free library of C++ code.
• QuantLib is the largest library of open source C++ code for quantitative ¬nance.
• Most work in quantitative ¬nance is done via interfacing with EXCEL.
• xlw provides an easy way to interface with EXCEL.


12.7 Exercises

Exercise 12.1 Install Boost on your computer.

Exercise 12.2 Interface the Boost random number classes with the path-dependent
exotic option pricer developed here.

Exercise 12.3 Download and build Quantlib!
13

Exceptions




13.1 Introduction
Up till now we have focussed on clarity and code reusability, we have not consid-
ered how to cope with things going wrong at run time. The mechanism in C++
designed for coping with errors is throwing an exception. Writing code that func-
tions well in the presence of exceptions raises a host of issues that did not exist
before. We will look at some of these and see how most of them can be avoided by
following some simple rules.
Exceptions are raised by the throw command. We specify as an argument an
object, X, of any type Y. Execution then immediately moves to the end of the current
scope and objects going out of scope are destroyed. If there is a catch command
at the end of the scope, which catches objects of type Y, then control passes to the
scope of the catch command. If not, then control passes to the end of the enclosing
scope, and this keeps happening until the exception is caught, or the enclosing
scope is the end of the program and execution terminates, i.e. your program crashes.
Note that we can always do a catch-all statement with catch(...).
The great virtue of this approach is that we do not have to test the return value of
every function or method call to ensure that the last call did not generate an error.
The great downside is that code execution order becomes a lot less predictable, and
this can cause problems. In particular, if we write code for cleaning up at the end
of a scope it may be bypassed by a throw, resulting in things being left in a poor
state.
This is particularly a problem when memory allocation is in use. Consider the
following code snippet with the PayOff class as in Chapter 4.

double evaluate(const PayOff& p,
double y)
{
PayOff* payOffPtr = p.clone();

179
180 Exceptions

double x = (*payOffPtr)(y);
delete payOffPtr;
return x;
}

This is a little arti¬cial in that no useful purpose is served by making a copy, but
if operator() were non-const, this could be useful. In any case, it serves to il-
lustrate a point: it is possible that calling operator() will throw an exception.
This will be caught somewhere outside the function. The catcher will have no idea
that payOffPtr needs to be deleted. The effect will be that the memory allocated
by the clone will never be deallocated. If this happens enough times, your appli-
cation will run out of memory and crash. If we are writing a stand-alone program
that does not bother to catch exceptions, this is not such an issue but as soon as we
are working in a system which is not supposed to die every time an exception is
thrown, it is a real problem.
Given that any piece of code we call may throw an exception, to be sure that our
code is correct and remains correct (for the code called may change its implemen-
tation), we are forced to program defensively as if an exception could be thrown at
any time.

13.2 Safety guarantees
There are two standard safety guarantees:

• The weak guarantee: the object and program are left in a valid state, and no
resources have been leaked.
• The strong guarantee: if an exception is thrown during an operation (e.g. a call
to a method or a function), then the program is left in the state it was at entry to
the operation.

The essential difference here is that with the weak guarantee an object™s state can
change even though the operation failed, whereas with the strong guarantee the
class is promising to undo all changes before throwing.
Clearly, the strong guarantee is harder to implement than the weak one. However,
it is important to realize that code that is not written with exception safety in
mind will satisfy neither. The weak guarantee is also sometimes called the basic
guarantee.



13.3 The use of smart pointers
Consider again the example of the introduction. What we want to happen is that
when the function is exited the memory allocated by the clone command is
13.3 The use of smart pointers 181

deallocated by a call to delete. Exiting can occur either in the conventional way
via the return statement, or by the exception being thrown. For both of these, all
automatic (i.e. ordinary local) variables are destroyed at the end of the scope. So
the solution is to make the deletion a side-effect of these destructions.
We have already looked at one smart pointer Wrapper<T>. If we use it here, the
code snippet becomes
double evaluate(const PayOff& p,
double y)
{

Wrapper<PayOff> payOffPtr(p);
double x = (*payOffPtr)(y);
return x;
}
Recall that the Wrapper class will call the clone method internally. The delete
command is no longer necessary because the destructor of Wrapper calls it auto-
matically.
As written, Wrapper<T> cannot be used to take ownership of a raw pointer since
it has no constructors that take pointers. However, we can easily add to the ¬le
Wrapper.h (see Listing 5.6) an extra constructor in the public section of the class
Wrapper(T* DataPtr_ )
{
DataPtr =DataPtr_;
}
and then it would be legitimate to code
double evaluate(const PayOff& p,
double y)
{
PayOff* payPtr1 = p.clone();
Wrapper<PayOff> payOffPtr(payPtr1);
double x = (*payOffPtr)(y);
return x;
}
and retain the automatic deletion of the allocated memory.
The Wrapper<T> class is just one example of a smart pointer. There are many
examples both in Boost and the standard library. These generally vary according
to what happens on copying the pointer.
There are four obvious solutions to copying:
182 Exceptions

(1) Copy the pointed-to object.
(2) Make copying illegal.
(3) Have the pointers share ownership of the object.
(4) Transfer ownership of the pointer to the new object.

The ¬rst of these is the approach adopted by the Wrapper<T> class. The main
downsides of this approach are that copying may be slow and that it relies heavily
on the writer of the pointed-to class having provided a clone() method.
With the second, we make the copy constructor and the assignment operator
of the object private. Whenever a coder attempts to copy (or assign) the smart
pointer, an error message saying that the copy constructor is not available is gen-
erated and the user is forced to ¬nd an alternate approach. If you want this sort of
pointer, use the scoped ptr class from Boost de¬ned in boost/scoped ptr.
hpp. Note that the error is generated at compile time rather than run time, since it
arises from access permissions to class methods “ these are checked only at com-
pile time.
An alternate implementation would be to make the copy constructor and as-
signment operator throw. This would be less desirable, however, in that the error
would only be generated whilst the code was running, and if the code was rarely
used, might take a long time to show up.
The third of these approaches is adopted by the boost shared pointer class:
shared ptr de¬ned in boost/shared ptr.hpp . We then essentially have a
reference-counted pointer class (cf. Exercise 5.6). Every time the shared ptr is
copied, a count of how many pointers there are to the object is increased by one,
and every time one is destroyed the count is decreased by one. When the count
hits zero the pointed-to object is destroyed. We again do not have to worry about
exception safety since when the last shared ptr goes out of scope the object is
deleted.
The main downside of shared ptr is that there is only ever one copy of the
object. This means that if one piece of code changes the object, then the object
pointed to by all the copied pointers also changes since it is the same object. This
means that the programmer has to think a little more than with the scoped ptr or
the Wrapper since you have linkage between not obviously connected things.
The last of these alternatives is used by the auto ptr class in the standard library
de¬ned in the ¬le memory. As with all the other smart pointers, when it goes out of
scope the pointed-to object is deleted. However, suppose we code the following

double evaluate(const PayOff& p,
double y)
{
std::auto_ptr<PayOff> payPtr1 = p.clone();
13.4 The rule of almost zero 183

double z = (*payPtr1)(y);
std::auto_ptr<PayOff> payPtr2(payPtr1);
double x = (*payPtr1)(y);
return x+z;
}
We will get a nasty run-time crash at the line where x is declared. Why? The copy-
ing of the object payPtr1 into payPtr2 changes the object payPtr1. This is very
counter intuitive “ we ordinarily expect copying an object to have no effect on the
original object, but with auto ptrs a great deal changes. All ownership is trans-
ferred to the new object and the ¬rst pointer becomes a null pointer.
This behaviour is occasionally useful when creating an object in a function or
method and wishing to return a pointer to it. We want the client to take ownership of
the object immediately without further copying and without having to use an unsafe
raw pointer, and auto ptr provides this facility. However, so does shared ptr
without the strange behaviour.
Ultimately, which smart pointer to use is a matter of personal style. The im-
portant thing is always to use one and to stay away from raw pointers. I person-
ally almost always use the Wrapper, and very occasionally use shared ptr and
auto ptr. The reason for preferring Wrapper is that it requires least thought: all
deletions occur naturally, and all objects have intuitive copying behaviour. Its only
real downside is that it makes object copying slower, but in numerical code you
should avoid all copying within tight loops in any case, so this actually has little
impact.


13.4 The rule of almost zero
The use of smart pointers brings us to a rule of programming. We previously stud-
ied the “rule of three”; this said that if you de¬ne one of copy constructor, assign-
ment operator, and destructor for a class, then you should de¬ne all three. The “rule
of almost zero” does not contradict this rule but supersedes it by saying that you
should always be in the case of not de¬ning any of them.
How do we avoid the shallow copy problem discussed in Chapter 4? We use
smart pointers to ensure that a shallow copy is suf¬cient. Every data member will
be either an ordinary object which can be copied, or a smart pointer which is copied
and assigned in the fashion we have chosen. So if we want objects to be shared
between copies, we use shared ptr; if we want to make copying illegal, we use
scoped ptr; and if we want the pointed-to objects to be cloned, we use Wrapper.
There will be no memory leak issues because the smart pointers delete the
pointed-to objects when the compiler-generated destructor is called. We do not
waste time writing copy constructors or assignment operators, and we do not have
184 Exceptions

to remember to update them when we change the data members of the class “ for-
getting to keep them in line with the class data members is a common source of
bugs.
Why have we named it the “rule of almost zero” instead of the “rule of zero”?
There is one case in which we must declare a destructor but only an empty one!
Every time we have a class with abstract methods it is likely to be deleted via
pointers to the base class and so we must declare a virtual destructor as discussed
in Section 3.5.



13.5 Commands to never use
Some commands to never use are:

malloc
free
delete
new []
delete []

The ¬rst two of these are C commands not C++, and have been superseded by the
versions of new and delete. You will get bizarre effects (i.e. crashes) if you try to
mix the two sets of commands.
The delete command is never necessary because of smart pointers. As long as
you ensure that anything created by new is owned by a smart pointer, you need
never code delete. The only time I therefore use the delete command is when I
am writing a smart pointer. However, with the advent of Boost, you should never
need to do this “ if a pointer doing what you want exists there, use that instead.
If I want to create an array of objects, I use the standard library container classes.
So if I want n objects of class Option, I just put

std::vector<Option> v(n);

The memory will then be deleted automatically when necessary; in addition, copy-
ing and assignment are done for me by the std::vector class. In fact, we can
think of a vector as a smart pointer owning an array of objects.
Since I never use new [], I never need delete [], and that allows the avoid-
ance of nasty bugs caused by accidentally using the wrong version of the delete
command.
In the unlikely event of needing to write a new container class, we can just use
the vector class as a data member to handle the memory for us. Why is it unlikely
you will need to write a container class? The standard library and Boost contain
13.6 Making the wrapper class exception safe 185

enough such classes to cover any reasonable case that is likely to arise in quant
work.
Note that if we pass vector s by reference, it will be just as fast as passing
pointers. The compiler inlines the data access operator, [], so we do not lose any
speed on deferencing either.
Another plus of using the standard library containers over direct memory alloca-
tion is that modern versions of the standard library include range-checking in debug
mode. So if you accidentally wander off the end of an array, you immediately get
an exception, alerting you to a logical error instead of wondering where the silly
numbers came from. Such a range-checked library ships with Visual Studio 8.0,
and you can get range-checked libraries for other compilers from
http://www.stlport.org
Of course, the memory allocation commands have their uses but if you ¬nd them
becoming part of your regular usage, one of the following is the case:
• you are a hard-core developer and should not be wasting your time reading a
low-level book like this one;
• you have lost sight of what you should be doing, and should start focussing on
numerical modelling instead.


13.6 Making the wrapper class exception safe
We have argued that we should use smart pointers since they make exception safety
easy. However, we must also make sure that the smart pointers we write for our-
selves are exception safe. In fact, the Wrapper class as we originally wrote it is not
exception safe. Consider the assignment operator

Wrapper& operator=(const Wrapper<T>& original)
{
if (this != &original)
{
if (DataPtr!=0)
delete DataPtr;

DataPtr = (original.DataPtr !=0)
? original.DataPtr->clone() : 0;
}

return *this;
}
186 Exceptions

If the call to the clone method of the original object passed in throws, we
have a problem. We have already deleted DataPtr so the strong guarantee is vi-
olated. But worse, any attempt to access the underlying object will be an attempt
to access a dead object, and we can expect a crash. This will happen when the
Wrapper goes out of scope and a second attempt is made to delete DataPtr, if not
before. Thus not even the weak guarantee is satis¬ed.
We therefore need to recode the assignment operator in Wrapper to avoid this
problem

Wrapper& operator=(const Wrapper<T>& original)
{
if (this != &original)
{
T* newPtr = (original.DataPtr !=0) ?
original.DataPtr->clone() : 0;

if (DataPtr!=0)
delete DataPtr;

DataPtr = newPtr;
}

return *this;
}

If the cloning throws, then the object has not been changed, so with the new design,
the strong guarantee is satis¬ed.


13.7 Throwing in special functions
As well as throwing in ordinary code, there is the issue of what to do when an error
occurs in a constructor or destructor. In this section, we look at the issues. The short
version is, “it™s ok to throw in a constructor but never throw in a destructor.”
We examine constructors ¬rst. The main danger of throwing in a constructor is
that resources acquired may not be released. The important fact to know here is
that destructors are only called for fully constructed objects. So if an exception
is thrown in the main body of the constructor, the destructors for all the data mem-
bers are called but the destructor for the object being created is not.
So if the destructor carries out some non-trivial operations such as calling
delete, we have a problem. This can be tackled in two ways. The ¬rst is simply
to do any tidying up that the destructor would have done before calling throw. The
13.8 Floating point exceptions 187

second is to follow the rule of almost zero and have a trivial destructor. The second
approach is much safer in that exceptions could arise in unexpected
places.
One subtlety to be aware of is that the constructor of one of the data members
of the class could also throw. These constructors are all called before the main
routine is entered. They are called in the order that they are declared in the class
declaration. On the throw, the destructors for all the objects already created will
be called in reverse order. So we must also design our class data members so they
will automatically delete any memory they have allocated.
What about destructors? Suppose we write a destructor for a class A that throws
when it™s unhappy. We let B have a data member of type A. Now consider the
following snippet

bool flag = true;
try
{
{
B testObject;

if (flag)
throw("flag is true");
}
}
catch(...)
{
}

When the throw is called, the stack is unwound and the object of type B is de-
stroyed. As part of this is destruction, its data-member of type A is destroyed. If
the destructor of A throws, the application terminates, i.e. crashes. This is speci-
¬ed in the C++ standard; the reason being that the compiler will not know which
exception to deal with.
So never ever throw in a destructor.


13.8 Floating point exceptions
Our discussion so far has looked at C++ exceptions. There is, however, an addi-
tional source of exceptions when working with numerical code: the ¬‚oating point
exception. This section although important lies outside the C++ standard, and I
am therefore going to restrict to discussing purely what happens with Visual Stu-
dio 8.0. For example, consider the following code
188 Exceptions

double x=0;
double y=1e6;
double z = y/x;
std::cout << z;

The default behaviour with Visual Studio is to output 1#INF. However, it would be
nice to have an exception thrown at the moment such a problematic operation oc-
curs rather than realizing at some point much later on that the computation became
garbage halfway through.
It is possible to enable ¬‚oating point exceptions. In this section, we discuss how
to do this and how to catch them. Enabling ¬‚oating point exceptions is in fact rather
easy, one simply includes Float.h and the line of code

_controlfp(_EM_INEXACT,_MCW_EM);

Note that this is a run-time command so you can decide at run time whether you
want ¬‚oating point exceptions to be thrown. For example, it can be useful to switch
them off when “¬‚oat under¬‚ow” errors are being generated “ these generally result
from numbers being too small; however, too small numbers often have zero impact
on the ¬nal result.
The only problem with the controlfp command is that a “structured excep-
tion” is generated not a C++ exception. The effect of this is that you get an un-
handled exception error even if you put a catch-all statement immediately after the
offending line, and the program crashes.
To get a C++ exception, we have to call another command
set se translator de¬ned in Windows.h. This tells the compiler how to trans-
late structured expections into C++ exceptions. It takes as argument a function to
be called when a structured exception is thrown. Note that the ¬le Windows.h
does not ship with Visual Studio Express 8.0 and you will have to install the free
Microsoft Platform SDK to use it.
We illustrate its use in FPSetup.h and FPSetup.cpp.

Listing 13.1 (FPSetup.h)

#ifndef FP_SETUP_H
#define FP_SETUP_H

#include <Windows.h>
#include <stdexcept>

class float_exception : public std::exception {};
class fe_denormal_operand : public float_exception {};
13.8 Floating point exceptions 189

class fe_divide_by_zero : public float_exception {};
class fe_inexact_result : public float_exception {};
class fe_invalid_operation : public float_exception {};
class fe_overflow : public float_exception {};
class fe_stack_check : public float_exception {};
class fe_underflow : public float_exception {};

void se_fe_trans_func(
unsigned int u, EXCEPTION_POINTERS* pExp );

void EnableFloatingPointExceptions();

#endif

As well as declaring two functions, one that enables the exceptions and the other
that declares the translation function, we declare a number of classes expressing the
different sorts of exceptions that can be thrown. We do a two-level inheritance hi-
erarchy off the standard library exception class std::exception. First we inherit
the class float exception and then we inherit all the different types of excep-
tions from it. Note that all these classes are simply empty classes “ the information
is conveyed simply by the type of object thrown rather than data contained within
the object.
The upshot of this is that we can have a generic command catch-all standard li-
brary of exceptions, including ¬‚oating point exceptions with catch(std::
exception), or just catch ¬‚oating point exceptions with catch
(float exception), or just catch one speci¬c type of ¬‚oating point exception
of choice. For example, we can use catch(fe divide by zero) just to get divi-
sion by zeros.
We implement these functions in FPSetup.cpp.

Listing 13.2 (FPSetup.cpp)

#include"FPSetup.h"
#include <Float.h>
void se_fe_trans_func( unsigned int u,
EXCEPTION_POINTERS* pExp )
{
switch (u)
{
case STATUS_FLOAT_DENORMAL_OPERAND:
throw fe_denormal_operand();
190 Exceptions

case STATUS_FLOAT_DIVIDE_BY_ZERO:
throw fe_divide_by_zero();
case STATUS_FLOAT_INEXACT_RESULT:
throw fe_inexact_result();
case STATUS_FLOAT_INVALID_OPERATION:
throw fe_invalid_operation();
case STATUS_FLOAT_OVERFLOW:
throw fe_overflow();
case STATUS_FLOAT_UNDERFLOW:
throw fe_underflow();
case STATUS_FLOAT_STACK_CHECK:
throw fe_stack_check();

};

throw float_exception();
}


void EnableFloatingPointExceptions()
{
_set_se_translator(se_fe_trans_func);
_controlfp(_EM_INEXACT,_MCW_EM);
}

The implementation of se fe trans func is not particularly interesting “ just a
switch through the different possible types of exception. One subtlety, however, is
that you must change to the compiler ¬‚ags to get all this to work. In particular,
the /EHa ¬‚ag must be set. This can be set via project properties, C/C++, code
generation, enable exceptions, and should be set to “Enable C++ exceptions with
SEH.”
We give a simple illustration of its use in FPMain.cpp.

Listing 13.3 (FPMain.cpp)

#include "FPSetup.h"
#include <iostream>
#include <cmath>
int main()
{
13.8 Floating point exceptions 191

EnableFloatingPointExceptions();

try
{
double x;
double y;
std::cin >> x;
std::cin >> y;

double z = y/x;
double t= exp(z);
std::cout
<< z << " " << t << "\n";


}
catch (fe_divide_by_zero&)
{
std::cout << "div by zero\n";
}
catch (float_exception&)
{
std::cout << "other floating point exception\n";
}
catch(...)
{
std::cout << "exception caught\n";
};

char c;
std::cin >> c;

return 0;
};



If we run this and enter 0 and 1, we get a division by zero exception. If we enter
1 and 1E6, a ¬‚oat over¬‚ow occurs and we get the output “other ¬‚oating point
exception.” If you try it without the correct ¬‚ags set, the exceptions will not be
caught.
192 Exceptions

Note that this code also illustrates that we can catch an object as a member of
its base class as well as a member of its own class. The rules are that an object is
caught if
• the catch argument matches the type of the object thrown;
• the catch argument type is a public base class of the object thrown;
• the catch argument is a pointer and the thrown pointer can be converted to this
pointer type according to the ordinary rules of pointer conversion.
Although the exception will be thrown and we may know the type of the ¬‚oating
point failure, we still have the issue that we want to know where it was thrown. One
way to ¬nd this out is to use the debugger. In Visual Studio, in the “debug” menu
there is an “exceptions” menu that allows the user to specify that execution halt in
the debugger on various sorts of exceptions. By ticking these boxes, we can cause
it to stop at the precise instant the problem occurs and examine the computation.
Note that we can also use the call stack to go and up and down nested function calls
to see where the problem arises.


13.9 Key points
In this chapter, we have looked at various issues related to making code function
well in the presence of exceptions:
• Exceptions can cause memory leaks.
• The weak or basic exception safety guarantee says that a program will be in a
valid state after an exception is thrown.
• The strong exception safety guarantee says that if an exception is thrown during
an operation, then the program will be left in the state it was in at the start of the
operation.
• Memory leaks can be avoided by the use of smart pointers.
• The rule of almost zero advises never to write code that requires non-trivial copy
constructors, assignment operators, and destructors.
• Avoid the new [], delete and delete [] commands.
• We have to take care when writing the assignment operators of smart pointers to
avoid memory leaks when new fails.
• Floating point errors do not by default cause C++ exceptions but they can be
made to do so.


13A The new wrapper class
We have made some changes to the Wrapper class. In particular, we have added a
new constructor and rewritten the assignment operator. Here is the revised code
13A The new wrapper class 193

Listing 13.4 (wrapper2.h)

#ifndef WRAPPER_H
#define WRAPPER_H

template< class T>
class Wrapper
{
public:

Wrapper()
{
DataPtr =0;
}

Wrapper(const T& inner)
{
DataPtr = inner.clone();
}

Wrapper(T* DataPtr_ )
{
DataPtr =DataPtr_;
}

˜Wrapper()
{
if (DataPtr !=0)
delete DataPtr;
}

Wrapper(const Wrapper<T>& original)
{
if (original.DataPtr !=0)
DataPtr = original.DataPtr->clone();
else
DataPtr=0;
}

Wrapper& operator=(const Wrapper<T>& original)
194 Exceptions

{

if (this != &original)
{
T* newPtr = (original.DataPtr !=0) ?
original.DataPtr->clone() : 0;

if (DataPtr!=0)
delete DataPtr;

DataPtr = newPtr;
}
return *this;
}

T& operator*()
{
return *DataPtr;
}

const T& operator*() const
{
return *DataPtr;
}

const T* const operator->() const
{
return DataPtr;
}

T* operator->()
{
return DataPtr;
}


private:
T* DataPtr;
};
#endif
13A The new wrapper class 195

We illustrate its use in WrapperMain.cpp.

Listing 13.5 (WrapperMain.cpp)
//
// requires PayOff3.cpp

#include <iostream>
#include <Wrapper2.h>
#include <PayOff3.h>

int main()
{
double S;
double K1,K2,K3;

std::cout << " spot\n";
std::cin >> S;

std::cout << "strike1\n";
std::cin >> K1;

std::cout << "strike2\n";
std::cin >> K2;

PayOffCall one(K1);
PayOffPut two(K2);

PayOff* p = one.clone();
Wrapper<PayOff> four = p;

{
PayOff* q = two.clone();
Wrapper<PayOff> five = q;

std::cout << "four :";
std::cout << (*four)(S)
<< " five :"
<< (*five)(S) << "\n";

four = five;
196 Exceptions

}
std::cout << " four :" << (*four)(S) << "\n";

char c;
std::cin >> c;
return 0;
}
14

Templatizing the factory




14.1 Introduction
The factory pattern discussed in Chapter 10 allowed us a method of turning inputs
into objects from a generalized hierarchy. It also allowed us to add extra objects
without modifying any ¬les. This is such a useful pattern that I use it all the time
in all sorts of contexts. As such it is a natural candidate for templatization. The
objective in this chapter is to develop such a templatized factory. This will raise
additional problems regarding reusability, and we will develop new techniques to
solve them.


14.2 Using inheritance to add structure
A key part of our factory was the singleton, and a key part of the singleton was the

<<

. 6
( 9)



>>