0% found this document useful (0 votes)
114 views10 pages

C++11, C++14, and C++17 For The Impatient

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
0% found this document useful (0 votes)
114 views10 pages

C++11, C++14, and C++17 For The Impatient

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/ 10

C++11, C++14, and C++17 for the

Impatient: Opportunities in
Computational Finance
Daniel J. Duffy
Datasim Finance, e-mail: [email protected]
Avi R. Palley
Quantitative Developer, Baruch/Quantnet C++ TA

Abstract and early adopters in the 1990s were organizations in telecommunications, embed-
This is the first article in a mini series of two articles on applying C++11 to com- ded systems, medical devices, and computer-aided design (CAD), as well as first-
putational finance. Here we focus on the new syntax and features that improve and generation option pricing risk management systems. The rise in popularity contin-
enhance the efficiency, reliability, and usability of C++ as a language for application ued well into the late 1990s as major vendors such as Microsoft, Sun, and IBM began
development. We introduce the C++ building blocks in the form of data types, con- to endorse object-oriented technology and C++. It was also in this period that the
tainers, and polymorphic function types that allow developers to design applications Java programming language appeared, which in time became a competitor to C++.
based on a combination of the object (-oriented), generic, and functional program- C++ remains one of the most important programming languages at the moment
ming styles. In the second article we will introduce a language-independent defined of writing. It is evolving to support new hardware such as multicore processors,
process based on domain architectures (Duffy, 2004) to decompose a software system GPUs (graphics processing units), and heterogeneous computing environments.
into loosely coupled subsystems, each of which has a single responsibility and having It also has a number of mathematical libraries that are useful in computational
well-defined interfaces to and from other subsystems. Having created a design blue- finance.
print (similar to an architectural drawing), we then implement the subsystems using
the multiparadigm programming features in C++. We then design and implement C++ as a multiparadigm programming language
a Monte Carlo option pricing framework in C++11 by mapping a specific domain We give an overview of the programming paradigms that C++ supports. In general, a
architecture to C++11. We also show how the same design blueprint can be imple- programming paradigm is a way to classify programming languages according to the
mented in C#. style of computer programming. Features of various programming languages deter-
mine which programming paradigms they belong to; as a result, some languages
Keywords fall into only one paradigm, while others fall into multiple paradigms. C++ is in this
C++11, C++14, computational finance, functional programming, Monte Carlo, sense a multiparadigm programming language because it supports the following
option pricing styles.

• Procedural: it organizes code around functions, as typically seen in pro-


Background grams written in C, Fortran, and Cobol. The style originates from structured
What is C++? C++ is a general-purpose programming language that was originally programming, in which a function or program is decomposed into simpler
designed as an extension to the C programming language. Its original name was “C functions.
• Object-oriented: it organizes code around classes. A class is an abstract entity
with classes” and its object-oriented roots can be traced to the programming language
that encapsulates functions and data into a logical unit. We instantiate a class
Simula, which was one of the first object-oriented languages. C++ has been standard-
to produce objects. Furthermore, classes can be grouped into hierarchies.
ized by the International Organization for Standardization (ISO) in 1998 (called the It is probably safe to say that this style is the most popular one in the C++
C++03 standard) and C++14 is the standard at the moment of writing. This can be community.
seen as a minor extension to C++11, which is a major update to the language. • Generic/template: templates are a feature of C++ that allow functions and
C++ was designed primarily for applications in which performance, efficiency, classes to operate with generic types. A function or class can then work on
and flexibility play a vital role. In this sense it is a systems programming language different data types without having to rewrite code for each one.

38 WILMOTT magazine
15418286, 2017, 90, Downloaded from https://onlinelibrary.wiley.com/doi/10.1002/wilm.10606 by Cochrane Netherlands, Wiley Online Library on [11/05/2023]. See the Terms and Conditions (https://onlinelibrary.wiley.com/terms-and-conditions) on Wiley Online Library for rules of use; OA articles are governed by the applicable Creative Commons License
TECHNICAL PAPER

• Functional: it treats computation as the evaluation of mathematical functions the second article when we create a framework for option pricing using the Monte
and avoids changing-state and mutable data. It is a declarative programming Carlo method.
paradigm; this means that programming is done with expressions and declara- A more extensive discussion of all these topics is given in Duffy (2017).
tions instead of statements. The output value of a function depends only on its
input arguments.
I Smart memory management and move semantics
The generic programing style is becoming more important and pronounced in
C++, possibly at the expense of the pure object-oriented model which is based on class Using smart pointers in code
hierarchies and subtype (dynamic) polymorphism. In this sense, template code tends to We discuss three pointer classes in C++. In the next three subsections we focus on
perform better at run-time while many errors are caught at compile-time in contrast to the syntax of each one and give some simple examples to show what they do.
object-oriented code, where the errors tend to be caught by the linker or even at run-time.
The most recent style that C++ has (limited) support for is functional program- Class std::shared_ptr
ming. This style predates both structured and object-oriented programming. Functional This smart pointer class implements the concept of shared ownership. A resource or
programming has its origins in lambda calculus, a formal system developed in the 1930s object (a piece of memory on the heap) is shared among a number of shared point-
to investigate computability, function definition, function application, and recursion. ers. Only when the resource is no longer needed is it deleted. This is when the related
Many functional programming languages can be viewed as elaborations on the lambda reference count becomes zero.
calculus. C++ supports the notion of lambda functions. A lambda function in C++ is We discuss shared pointers. First, we show how to create empty shared pointers
an unnamed function but it has all the characteristics of a normal function. Here is an and shared pointers that are coupled to heap resources. We also show how a shared
example of defining a stored lambda function and then calling it as a normal function: pointer gives up ownership of one resource and how it becomes owner of another
resource. We can always see how many shared pointers own a resource by using the
member function use_count():

In the above cases the last owner of the resource is responsible for destroying the
In this case we see that the lambda function has a formal input string argument and it resource and by default this is achieved by a call of the operator delete.
uses a so-called captured variable cVar. Lambda functions are simple but powerful
and we shall show how they can be used in computational finance. Class std::unique_ptr
C++11 is a major improvement on C++03 and it has a number of features that Whereas std::shared_ptr allows a resource to be shared among several shared
facilitate the design of software systems based on a combination of structured analy- pointers in the case of std::unique_ptr, there is only one transferable owner of
sis and object-oriented technology. In general, we have a defined process to decom- a resource. In this case we speak of exclusive or strict ownership. Its main added value
pose a system into loosely coupled subsystems (Duffy, 2004). We then implement is in avoiding resource leaks (for example, missing calls to delete when using raw
each subsystem in C++11, as we shall see in later articles. pointers) and for this reason is can be called an exception-safe pointer. Its main mem-
This article is organized as follows: in Section I we introduce smart memory ber functions are as follows.
management in C++11, which resolves many of the problems that developers expe-
rienced with native pointers in previous versions of the language. Their application • Constructors (similar to those in std::shared_ptr).
• Assign a unique pointer.
in code promotes robustness and reliability. In Section II we discuss a number of
• Release; return a pointer to the resource and release ownership.
useful low-level features that avoid some shortcomings in C++03. Section III is
• Reset; replace the resource.
devoted to a bird’s-eye view of functional programming and how C++ supports
• Operator overloading (==, !=, <, and so on).
it using lambda functions and universal function wrappers. Tuples (generaliza-
tions of std::pair ) and variant data types are discussed in Section IV. Finally, The interface is similar to that of std::shared_ptr, which means that code
in Sections V and VI we discuss how to model stochastic differential equations will be easy to understand. Finally, std::unique_ptr succeeds auto_ptr, the
^
(SDEs) using the multiparadigm features in C+11. We shall continue in this vein in latter being considered deprecated.

WILMOTT magazine 39
15418286, 2017, 90, Downloaded from https://onlinelibrary.wiley.com/doi/10.1002/wilm.10606 by Cochrane Netherlands, Wiley Online Library on [11/05/2023]. See the Terms and Conditions (https://onlinelibrary.wiley.com/terms-and-conditions) on Wiley Online Library for rules of use; OA articles are governed by the applicable Creative Commons License
Our first example entails creating a unique pointer in a scope. Under normal Type alias and alias templates
circumstances, when the pointer goes out of scope, the corresponding resource is Developers are already familiar with the typedef specifier, which allows aliases to
cleaned up but in this case we (artificially) throw an exception before the end of the be defined for existing types. The specifier cannot be used to change the meaning of
scope is reached. What happens? When we run the code we see that the resulting an existing type name and hence it does not represent the declaration of a new type.
exception is caught and the resource is automatically destroyed: A typedef has effect in the scope in which it is visible. An example is

The use of an alias promotes code readability and maintainability. Unfortunately,


typedef cannot be used for class templates and hence the following code will not
compile:

This code also works when we use shared pointers instead of unique pointers. In But there is hope! C++11 offers the possibility to define an alias for class tem-
C++14 we can create unique pointers using std::make_unique() for non-array plates and non-template classes alike. The term is sometimes called alias tem-
types: plate or template typedef. The above example can now be formulated as
follows:

We can also use this technique in combination with user-defined types with long
std::weak_ptr names and with types having many template parameters in order to make it easier to
The third smart pointer class holds a non-owning (weak) reference to an object work with them. Let us take the simple example
(resource) that is managed by a shared pointer. It must be converted to a shared
pointer in order to access the resource. It is a helper class to std::shared_ptr
and it is needed when the latter’s behavior does not work as intended, namely:

• Resolving cyclical dependencies between shared pointers – dependencies


that occur when two objects refer to each other using shared pointers. We
cannot release the objects because each has a use count of 1. It is like a dead-
lock.
• Situations in which you wish to share an object but you do not own it. In
this case we define a reference to a resource and that reference outlives the
resource.

II Low-level syntax improvements


We now give a discussion of a number of useful features in C++. They improve the
readability and robustness of code. In other cases they represent structural solutions
to workarounds that were used in previous versions of C++ to resolve problems. You We can imagine that clients might wish to use this class in different ways, and to
may need to use these new features in your code. this end we can create various aliases, for example

40 WILMOTT magazine
15418286, 2017, 90, Downloaded from https://onlinelibrary.wiley.com/doi/10.1002/wilm.10606 by Cochrane Netherlands, Wiley Online Library on [11/05/2023]. See the Terms and Conditions (https://onlinelibrary.wiley.com/terms-and-conditions) on Wiley Online Library for rules of use; OA articles are governed by the applicable Creative Commons License
TECHNICAL PAPER

Deleted and defaulted member functions


The specifiers in this subsection are primarily concerned with C++03’s special
member functions, namely:

• Default constructor.
• Copy constructor, which corresponds to member-wise construction of
non-static data members. It is generated only if the class does not have a user-
defined copy constructor.
• Copy assignment operator. Generation of this function in a class with a user-
defined copy constructor is deprecated.

These functions are generated only if they are needed. For example, a default
constructor is generated only if a class declares no constructors whatsoever.
Generated special member functions are implicitly public and inline. In C++11 the
club of special member functions has been extended to include the move constructor
and the move assignment operator.
We use the keyword default to let the compiler generate the body of a con-
structor. At the other extreme, we may wish to suppress the use of special member
functions. The standard approach in C++03 is to declare them as private and
to not define them. C++11 uses the specifier delete to mark these functions as
so-called deleted functions, which is an improvement on C++03 for a number of
reasons:

• Deleted functions may not be used, even by friends.


• Deleted functions are public; C++ checks accessibility before deleted
status.
We have given a number of examples to show the usefulness of this technique. It • Errors are caught at compile-time rather than at link-time, in contrast to the
should not be confused with the well-known using declaration, which introduces a case with C++03.
name that is defined elsewhere. • More user-friendly error messages.
• Any function (and not just member functions) can be given the delete
Automatic type deduction and the auto specifier status. This is useful when we wish to avoid implicit conversions.
This feature allows us to declare a variable or an object without using its specific type. We take an initial example of a class with a mixture of deleted and defaulted
In other words, the variable is automatically deduced from its initializer. Some exam- functions:
ples are

We could have used explicit return types, but the compiler is clever and it knows
what the correct type should be, as the following checks show based on the C++ type
traits library:

Some test code shows what does and does not compile:
We can also use the auto specifier to make life easier when working with user-
defined types:

WILMOTT magazine 41
15418286, 2017, 90, Downloaded from https://onlinelibrary.wiley.com/doi/10.1002/wilm.10606 by Cochrane Netherlands, Wiley Online Library on [11/05/2023]. See the Terms and Conditions (https://onlinelibrary.wiley.com/terms-and-conditions) on Wiley Online Library for rules of use; OA articles are governed by the applicable Creative Commons License
Finally, we give an example of a deleted non-member function. In this case we We use uniform initialization as follows:
define some overloaded print functions that are deleted when the input argument is a
double or a bool:

We see from class Person that we can initialize a class’s member data using
braced initialization, even though the class does not have the appropriate constructors.

III Functions and functional programming


An example of use (commented lines do not compile):
An introduction to functional programming
Functional programming is a style of programming that models computation as the
evaluation of expressions. In other words, we execute programs by evaluating expres-
sions. Functional programming requires that functions be treated as first-class objects
so that they can be used just like an ordinary variable in a programming language, for
example:
• they can be passed as arguments to other functions;
• they can be returned as a result of a function;
• we can define and manipulate functions from within other functions.
Uniform initialization
In previous versions of C++ there was some confusion concerning how to initial- In general, functional programming languages support these features while histori-
ize variables and objects. It was not always clear when to use braces, parentheses, or cally imperative programming languages (such as C++) did not. In recent times a
assignment operators. In C++11 we can avail a single common syntax called uniform number of extensions to C++ have been proposed that support some of the above
(braced) initialization by placing the values between braces. Some simple examples are features, in particular several Boost C++ libraries and C++11. An imperative pro-
gramming language is one in which programs are composed of statements. These
statements can change global state when executed, while in functional programming
languages program state tends to be immutable.
Some features of functional programming languages are

• Support for higher-order functions (HOFs). A higher-order function can take


other functions as arguments. An example of a higher-order function is a loop
of the form (pseudocode)

We can use this technique to initialize the members of an aggregate object. where record is a data collection and func is a function that operates on each
Consider the classes element of that collection. Higher-order functions are useful in code refactoring
projects because their use reduces the amount of code repetition. We shall see how to
simulate higher-order functions in C++ by the use of function objects (functors) and
lambda functions.

• Purity. In general, some functional programming languages allow expressions


to yield actions in addition to returning values. These actions are called side
effects. A pure language is one that does not allow side effects.
• Recursion. This technique is pervasive in functional programming and it is
sometimes the only way to iterate. Use is often made of tail call optimization,
which avoids recursion using too much memory.
• Strict and non-strict evaluation. These terms refer to how function arguments
are processed when an expression is being evaluated. In the former case, all
arguments are instantiated and then the function returns a value. In the latter
case, some arguments have not yet been instantiated (these are called delayed

42 WILMOTT magazine
15418286, 2017, 90, Downloaded from https://onlinelibrary.wiley.com/doi/10.1002/wilm.10606 by Cochrane Netherlands, Wiley Online Library on [11/05/2023]. See the Terms and Conditions (https://onlinelibrary.wiley.com/terms-and-conditions) on Wiley Online Library for rules of use; OA articles are governed by the applicable Creative Commons License
TECHNICAL PAPER

arguments). It is then not possible to call the function in the traditional sense
but what we get is a function with a given arity, which can later be called by
instantiating all the remaining delayed arguments. This is a useful feature
because we can create new functions from existing ones by binding one or
more arguments to specific values.

Functional programming languages provide better support for structured program-


ming than imperative programming languages. This is mainly due to the fact that we This example gives an indication of what is possible with std::function<>.
can model abstractions and decompose them into software components. It is possible For example, we could use it to implement callback functions in the Observer pattern
to implement such components using higher-order functions. We shall see in Duffy (Gamma et al., 1995). More generally, we can use the Boost C++ signals2 library as
(2017) how to define higher-order functions in C++ and use them to design and implementation of Observer (Demming and Duffy, 2010).
implement applications for computational finance.
New functionality in C++: Lambda functions and lambda
New functionality in C++: std::function<> expressions
The class std::function (defined in <functional>) provides polymorphic Lambda functions are unnamed functions that can be declared within the scope of
wrappers that generalize the function pointer concept. Its origins can be traced to the other functions. They are alternatives to using free functions and function objects
Boost C++ Function library (as discussed in Demming and Duffy, 2010). The main (functors) in C++.
advantage is that it can be used as a bridge to callable objects such as free functions,
member functions, function objects, and lambda functions. To this end, the class Basic syntax
std::function<> allows us to model these callable objects as first-class objects. The general syntax for a lambda function is
As an example, we show how to use std::function<> in combination with free
functions. Let us first define three functions:

First, we see that the presence of the brackets [] announces a new lambda func-
tion having a given return type. Second, a lambda function has input arguments
as well as so-called captured variables that belong to the lambda function’s closure.
These variables correspond to the lambda function’s state. It is possible to capture
variables by value or by reference, depending on whether we wish to copy by value or
by reference into the body of the lambda function. We can specify the choice by using
the following list as exemplar:

We see that these functions accept a double as input argument and they return
a double. In order to subsume these functions in a polymorphic function wrapper
as it were, we define

We can then assign an instance of f to a free function, for example


We also note the presence of the optional keyword mutable in the above
specification. This is sometimes needed because lambda functions are const and
hence their state cannot be changed. Thus, in order to make the lambda function
non-const, we declare it as mutable. Finally, the body of the lambda function is
In client code we can work with instances of std::function<> which standard C++ and it may use both its input and captured variables.
have been instantiated somewhere else. This promotes code reusability and we can The simplest lambda function has the structure
use std::function<> with lambda functions, function objects, and member
functions.
The second example is to define an array of functions and then execute them in
turn. We add each of the above free functions to the array of std::function<>
instances and use a lambda function to execute each one:
All lambda functions have a return type (which can be void). It is not necessary
to specify explicitly what this return type is unless the body of the function contains
embedded if–else logic. We say that the return type is inferred or deduced when it is
^
absent.

WILMOTT magazine 43
15418286, 2017, 90, Downloaded from https://onlinelibrary.wiley.com/doi/10.1002/wilm.10606 by Cochrane Netherlands, Wiley Online Library on [11/05/2023]. See the Terms and Conditions (https://onlinelibrary.wiley.com/terms-and-conditions) on Wiley Online Library for rules of use; OA articles are governed by the applicable Creative Commons License
Lambda functions and classes: Capturing member data (like strike, expiration) pertaining to the first and second assets, respectively,
while the third element contains the value of the correlation between these
It is possible to define lambda functions in a class and it is also possible to capture its
assets.
member data. The rules are
• Mathematical properties of differential equations encapsulated in reusable tuples.
[this] captures the this pointer only • Essential defining parameters pertaining to numerical processes, for example
[=] captures the this pointer and local variables by value step size, tolerances, and maximum number of iterations.
[&] captures the this pointer and local variables by reference. • Any non-trivial application that needs to be configured from various sources.
To this end, we use tuples that client code reads without having to know where
Inside the body of the lambda function we access the members in the usual way. the data comes from.
We take an example of a class to calculate the trigonometric sine of a vector with
input values. To this end, we transform the input vector using a lambda function. The We give a simple example of how to create nested tuples to model people and
objective is to use a lambda function to effect the transformation: their whereabouts (it can be seen as a simple database):

IV Data types: Tuples and variants


Tuple fundamentals and simple examples
Tuples are generalizations of pairs in the sense that the number of elements in the lat-
ter type is greater than or equal to two.
We give an initial example. We present the code and it should be easy to under-
stand, as it is similar to the corresponding code for std::pair<>:

Variadic tuples
In general, a variadic template is one that takes a variable (arbitrary) number of input
arguments. In particular, tuples can be defined as having a variable number of elements:

This declaration states that this class can take any number of typenames as its
Extending the code to tuples with more than two elements is straightforward. template parameters. Incidentally, the number of arguments can be zero. If we wish
to forbid the definition of a template with zero arguments, then we can modify the
Tuple nesting definition as follows (in which case the tuple must have at least one element):
A useful feature in C++ is that we can define fixed-size recursive and composite
structures. In other words, we can define tuples that contain other tuples as well as
other types as elements. This feature can be applied to creating configuration data in
an application. This data can be created by dedicated factory objects and the data is Variadic templates also apply to functions, for example free functions:
then processed in an application at a suitable entry point in the code.
Some typical applications spring to mind:
• Modeling data for rainbow and multi-asset options by a tuple with three ele-
ments. The first and second elements are themselves tuples containing the data

44 WILMOTT magazine
15418286, 2017, 90, Downloaded from https://onlinelibrary.wiley.com/doi/10.1002/wilm.10606 by Cochrane Netherlands, Wiley Online Library on [11/05/2023]. See the Terms and Conditions (https://onlinelibrary.wiley.com/terms-and-conditions) on Wiley Online Library for rules of use; OA articles are governed by the applicable Creative Commons License
TECHNICAL PAPER

The advantages of variadic tuples are that:

• they can take an arbitrary number of arguments of any type;


• they reduce code explosion – you (supplier) can define code once that uses
variadic templates and clients can customize the code by choosing the types
and number of arguments that they wish to use;
• it is possible to design and implement highly generic code for some cases in
which traditional object-oriented technology (using subtype polymorphism,
for example) would lead to code that is difficult to understand or maintain;
• variadic templates are compile-time, which should lead to efficient and robust code.
For completeness, we include the definition for class Point:
We take an initial example of using variadic templates. In particular, we write
a function to print a tuple with any number of elements. We peel the elements of a
tuple from its end, print the last value, and then call the same function again on a
tuple with one element less than the original one. The code is

We can now get the current value in a variant by calling the get() function:

Since the function is recursive, we know that we need to define its very last action
as it were (this is the equivalent of tail recursion). To this end, we employ template
specialization:

std::variant (C++17) and boost::variant V Example: Stochastic differential equations in


The union data type is not very flexible. It seems that they will be superseded in C++11
C++17 by std::variant, which can then replace unions and union-like classes.
Since we do not have a suitable C++17 compiler at the moment of writing, we resort Application to SDEs
to a discussion of how boost::variant works (Demming and Duffy, 2010). Most developers are familiar with subtype polymorphism and developing class hier-
From the Boost online documentation: archies in application domains. In general, we can create a base class consisting of
pure virtual functions, which are then overridden by derived classes. For exam-
The variant class template is a safe, generic, stack-based discriminated ple, this was the approach taken by Duffy and Kienitz (2009) to model classes for
union container, offering a simple solution for manipulating an object SDEs. In particular, we model drift and diffusion as functions that can be customized
from a heterogeneous set of types in a uniform manner. Whereas stand- in derived classes. While this is an accepted technique, we do run the risk of creating
ard containers such as std::vector may be thought of as “multi- redundant code by essentially promoting objects to the level of a class.
value, single type,” variant is “multi-type, single value.” In this section we create a single class that models an SDE. The class is composed
The main uses of variants are: of two universal functions that implement the drift and diffusion function. It is up to
clients to decide how to implement these functions when creating an instance of the
• typesafe storage and retrieval of user-specified sets of types; SDE. This can be realized by the following:
• storing heterogeneous types in STL containers;
• compile-time checked visitation of variants (using the Visitor pattern); • a free function (traditional function pointer);
• efficient, stack-based storage for variants. • a stored lambda function or a lambda function;
• a function object;
^
We take an example of a variant consisting of three members: • a binded member function or static member function of a class.

WILMOTT magazine 45
15418286, 2017, 90, Downloaded from https://onlinelibrary.wiley.com/doi/10.1002/wilm.10606 by Cochrane Netherlands, Wiley Online Library on [11/05/2023]. See the Terms and Conditions (https://onlinelibrary.wiley.com/terms-and-conditions) on Wiley Online Library for rules of use; OA articles are governed by the applicable Creative Commons License
This approach reduces code bloat, especially at the server side, because only a single 1. Create multiple instances of SDE<>; create a specific instance of SDE<>
class is needed. We first describe some supporting syntax and shorthand notation to based on some user choice.
make the resulting code more readable: 2. Create the functions that are the components of the SDE<> instances in step 1.
3. Create the data that the functions in step 2 need.

Each of these steps can be executed by dedicated factory objects that are in fact
instances of creational design patterns as described by Gamma et al. (1995). We give
an initial example of code in which steps 1, 2, and 3 are amalgamated into one code
block. We can refine this process even more when we use the Builder design pattern
(Gamma et al., 1995) to configure a complete application. We take an example of a
function that creates an arithmetic SDE (notice that the data is hard-coded but the
We are now in a position to post the class that models the SDE; we note that it code can be generalized). We use an alias for the factory class:
makes use of functions and tuples:

The function to create an SDE instance and an example of use is

Some examples of how to interact with this class are when creating SDEs for geo-
metric Brownian motion (GBM) and constant elasticity of variance (CEV) models:

Instead of a new factory, we could have recycled as it were:

We see that we can create instances of SDE<> by defining a single lightweight


class and in-place lambda functions.
Finally, we can simulate the factory method pattern by creating a function with an
SDE factories internal switch, allowing us to choose the type of SDE that we are interested in:
From the above code sample we see how to create instances of SDE<>. In larger
applications this ad-hoc approach breaks down, in the sense that the code to initial-
ize the data and functions that are used to create instances of SDE<> tends to become
unmaintainable. For this reason we apply the separation of concerns approach, by
creating code blocks with each block having its own (single) responsibility. A typi-
cal example is to create loosely coupled modules for the following actions that we
describe in a top-down manner:

46 WILMOTT magazine
15418286, 2017, 90, Downloaded from https://onlinelibrary.wiley.com/doi/10.1002/wilm.10606 by Cochrane Netherlands, Wiley Online Library on [11/05/2023]. See the Terms and Conditions (https://onlinelibrary.wiley.com/terms-and-conditions) on Wiley Online Library for rules of use; OA articles are governed by the applicable Creative Commons License
TECHNICAL PAPER

We create an instance of ISde as follows, for example:

We can then use functions in a constructor of Sde<>, as already discussed.

Summary and conclusions


In this article we introduced some of the essential language features of C++11. With
these fundamental building blocks we are able to create generic and compact data
structures that we can use in future applications based on an innovative design.
An example of use is (notice the clever application of std::bind)
Daniel J. Duffy is founder of Datasim Financial and has been involved with C++ and its
applications since 1989. More recently he has been involved with the design of compu-
tational finance applications in C++11. He has a PhD in numerical analysis from Trinity
College (Dublin University) and can be contacted at [email protected].

Avi R. Palley works as a quantitative developer and is TA for the highly successful
C++ Programming for Financial Engineering and the Advanced C++11/C++14 and
Multidisciplinary Applications online certification courses (offered by Quantnet.com
and originated by Daniel J. Duffy). He has a Masters in Financial Engineering from Baruch
VI Emerging multiparadigm design patterns: College, New York.
Summary
In the previous section we applied modern C++ syntax to design a small framework
to model SDEs as a typical example that we can generalize. We have avoided subtype References
polymorphism and instead took an approach based on creating a single class com- Demming, R. and Duffy, D. 2010. Introduction to the Boost C++ Libraries, Volume I.
posed of universal function wrappers. This is similar to interface programming in lan- Amsterdam: Datasim Press.
guages that support interfaces (such as C# and Java, for example). In general, an inter- Demming, R. and Duffy, D. 2012. Introduction to the Boost C++ Libraries, Volume II.
face is a pure specification or protocol and it describes a collection of abstract methods. Amsterdam: Datasim Press.
An interface may not contain non-abstract methods nor may it contain member Duffy, D. J. 2004. Domain Architectures. Chichester, UK: Wiley.
data. In this sense it is very different from an abstract class in C++ (even one without Duffy, D. 2017. Financial Instrument Pricing Using C++, 2nd edn. Chichester, UK: Wiley.
Duffy, D. and Kienitz, J. 2009. Monte Carlo Frameworks. Chichester, UK: Wiley.
non-abstract member functions and member data). C++ does not support interfaces;
Gamma, E., Helm, R., Johnson, R., and Vlissides, J. 1995. Design Patterns. Boston, MA:
however, we can emulate them by creating (variadic) tuples whose elements are uni-
Addison-Wesley.
versal function wrappers. In this case we define our interface emulator as

^
W

WILMOTT magazine 47

You might also like