1. Introduction
The topic of Design Patterns sounds dry, academically constipated and, in all honesty, done to death in almost every programming language imaginableincluding programming languages such as JavaScript that arent even properly OOP! So why another book on it?
I guess the main reason this book exists is that C++ is great again. After a long period of stagnation, its now evolving, growing, and despite the fact that it has to contend with backwards C compatibility, good things are happening, albeit not at the pace wed all like. (Im looking at modules, among other things.)
Now, on to Design Patternswe shouldnt forget that the original Design Patterns book was published with examples in C++ and Smalltalk. Since then, plenty of programming languages have incorporated design patterns directly into the language: for example, C# directly incorporated the Observer pattern with its built-in support for events (and the corresponding event keyword). C++ has not done the same, at least not on the syntax level. That said, the introduction of types such as std::function sure made things a lot simpler for many programming scenarios.
Design Patterns are also a fun investigation of how a problem can be solved in many different ways, with varying degrees of technical sophistication and different sorts of trade-offs. Some patterns are more or less essential and unavoidable, whereas other patterns are more of a scientific curiosity (but nevertheless will be discussed in this book, since Im a completionist).
Readers should be aware that comprehensive solutions to certain problems (e.g., the Observer pattern) typically result in overengineering, that is, the creation of structures that are far more complicated than is necessary for most typical scenarios. While overengineering is a lot of fun (hey, you get to really solve the problem and impress your coworkers), its often not feasible.
Preliminaries
Who This Book Is For
This book is designed to be a modern-day update to the classic GoF book, targeting specifically the C++ programming language. I mean, how many of you are writing Smalltalk out there? Not many; that would be my guess.
The goal of this book is to investigate how we can apply Modern C++ (the latest versions of C++ currently available) to the implementations of classic design patterns. At the same time, its also an attempt to flesh out any new patterns and approaches that could be useful to C++ developers.
Finally, in some places, this book is quite simply a technology demo for Modern C++, showcasing how some of its latest features (e.g., coroutines) make difficult problems a lot easier to solve.
On Code Examples
The examples in this book are all suitable for putting into production, but a few simplifications have been made in order to aid readability:
Quite often, youll find me using struct instead of class in order to avoid writing the public keyword in too many places.
I will avoid the std:: prefix, as it can hurt readability, especially in places where code density is high. If Im using string , you can bet Im referring to std::string .
I will avoid adding virtual destructors, whereas in real life, it might make sense to add them.
In very few cases I will create and pass parameters by value to avoid the proliferation of shared_ptr / make_shared /etc. Smart pointers add another level of complexity, and their integration into the design patterns presented in this book is left as an exercise for the reader.
I will sometimes omit code elements that would otherwise be necessary for feature-completing a type (e.g., move constructors) as those take up too much space.
There will be plenty of cases where I will omit const whereas, under normal circumstances, it would actually make sense. Const-correctness quite often causes a split and a doubling of the API surface, something that doesnt work well in book format.
You should be aware that most of the examples leverage Modern C++ (C++11, 14, 17 and beyond) and generally use the latest C++ language features that are available to developers. For example, you wont find many function signatures ending in -> decltype(...) when C++14 lets us automatically infer the return type. None of the examples target a particular compiler, but if something doesnt work with your chosen compiler, youll need to find workarounds.
At certain points in time, I will be referencing other programming languages such as C# or Kotlin. Its sometimes interesting to note how designers of other languages have implemented a particular feature. C++ is no stranger to borrowing generally available ideas from other languages: for example, the introduction of auto and type inference on variable declarations and return types is present in many other languages.
On Developer Tools
The code samples in this book were written to work with modern C++ compilers, be it Clang, GCC, or MSVC. I make the general assumption that you are using the latest compiler version that is available, and as a consequence, will use the latest-and-greatest language features that are available to me. In some cases, the advanced language examples will need to be downgraded for earlier compilers; in others it might not work out.
As far as developer tools are concerned, this book does not touch on them specifically, so provided you have an up-to-date compiler, you should follow the examples just fine: most of them are self-contained .cpp files. Regardless, Id like to take this opportunity to remind you that quality developer tools such as the CLion or ReSharper C++ greatly improve the development experience. For a tiny amount of money that you invest, you get a wealth of additional functionality that directly translates to improvements in coding speed and the quality of the code produced.
Piracy
Digital piracy is an inescapeable fact of life. A brand new generation is growing up right now that has never purchased a movie or a bookeven this book. Theres not much that can be done about this. The only thing I can say is that if you pirated this book, you might not be reading the latest version.
The joy of online digital publishing is I get to update the book as new versions of C++ come out and I do more research. So if you paid for this book, youll get free updates in the future as new versions of the C++ language and the Standard Library are released. If not oh, well.
Important Concepts
Before we begin, I want to briefly mention some key concepts of the C++ world that are going to be referenced in this book.
Curiously Recurring Template Pattern
Hey, this is a pattern, apparently! I dont know if it qualifies to be listed as a separate design pattern, but its certainly a pattern of sorts in the C++ world. Essentially, the idea is simple: an inheritor passes itself as a template argument to its base class:
1 struct Foo : SomeBase
2 {
3 ...
4 }
Now, you might be wondering why one would ever do that? Well, one reason is to be able to access a typed this pointer inside a base class implementation.
For example, suppose every single inheritor of SomeBase implements a begin()/end() pair required for iteration. How can you iterate the object inside a member of SomeBase ? Intuition suggests that you cannot, because SomeBase itself does not provide a begin()/end() interface. But if you use CRTP, you can actually cast this to a derived class type: