W
ith
the exception of a handful of template gurus who delve deeply into C++
template metaprogramming, hardly anybody makes much use of the C++ template
feature. The vast majority of C++ programmers see templates mostly as a
mechanism for implementing container class templates. At best, templates
are understood as a means of avoiding code duplication because you can
let the compiler generate various flavors of your class rather than duplicating
the code manually via copy-and-paste. One programmer or the other might
have even come across the principles of generic programming via templates,
as demonstrated by the STL for instance. But nobody has used templates
for problem-solving in practice as creatively as Andrei Alexandrescu has,
or at least nobody has written such an interesting book about it before.
What
is
Modern C++ Design: Generic Programming and Design Patterns Applied
about? Alexandrescu explains the implementation of a generic library called
Loki, which is freely available and can be downloaded from the
book's
site
(click on the "Source Code" link). This library contains a bunch
of useful and reusable abstractions like a singleton, a smart pointer,
object factories, and a multimethod dispatcher. The interesting aspect
of Loki is not necessarily its functionality, but its implementation style:
all abstractions are entirely generic and can be configured. The "configuration"
is achieved by means of template instantiation. In essence, Alexandrescu
uses the compiler's template instantiation mechanism to generate code?especially
generate various flavors of a class from thoughtfully parameterized class
templates.
Let's
take a look at an example from Loki?the smart pointer abstraction?to get
a better idea of what this "code generation technique" means. Smart pointers
in general are a well-understood abstraction in software development, but
the details of their functionality can vary substantially. For instance,
in the way they handle ownership of the pointed-to object once the smart
pointer is copied, one ownership policy is to copy the pointee object whenever
the smart pointer is copied. This way there is exactly one smart pointer
for each pointee object.
An
alternative strategy is reference counting, where the smart pointer keeps
track of the number of smart pointers that point to the same object. Yet
another policy is "destructive copy," which means that during copying the
object being copied is destroyed; this is also known as "transfer of ownership"
and is the policy used by the standard auto_ptr class. Given these three
choices for the ownership policy of a smart pointer implementation, Alexandrescu
does not provide different smart pointer classes for each of these cases,
but defines a template for a smart pointer class that takes the ownership
policy as a template argument (as a "template template" argument, to be
precise). This way different smart pointer classes can be generated with
different behavior via template instantiation.
The
ownership policy is not the only strategy relevant for a smart pointer
implementation. Loki's smart pointer is one example out of a dozen of generic
programming via templates. The idea of parameterizing classes by a policy
and providing the policy as a template argument is not entirely new; the
STL does it, too. But Alexandrescu takes it one step further by demonstrating
truly creative uses of templates for achieving amazingly powerful result.
The strength of
Modern C++ Design
is that it shows how to exploit
the power of template programming for solving common problems like implementing
well-known abstraction such as a smart pointer or other patterns. This
book can teach you much about template programming; you will certainly
close the book with a radically different view of this C++ language feature.
A word
of caution, though. Alexandrescu's code is written in standard C++, which
means that much of the code presented in this book will challenge your
compiler. If it starts to smoke, move on to a more recent compiler version,
or use a better compiler if you can. For instance, if you are a dedicated
Microsoft programmer and use MVC 6.0, all bets are off?it won't fly! The
same is true for every C++ compiler that does not support standard C++.
That, of course, limits the usefulness of Alexandrescu's techniques?at
least for the time being.
Another
word of caution. Writing programs in the style suggested by
Modern C++
Design
can be perceived as difficult. This is because this kind of
template programming is not really programming in the usual sense of the
word. It relies heavily on template instantiation. For instance, errors
cannot be debugged because they do not happen while the programs is executed,
but occur while the source code is compiled. There is no way to debug the
compilation process. In addition, much of the code looks just weird, according
to common C++ standards. We are just not accustomed to template programming
in this style, mainly because intense use of template techniques is not
yet common practice. Over time we might get accustomed to it, but it is
not mainstream?not yet.
Having
said that, we do see this sort of template programming pop up in many places.
Another example can be found in Czarnecki and Eisenecker's
Generative
Programming
, which devotes an entire chapter to template metaprogramming.
Further examples can be studied in the
Boost
Library
, which is likely to be the foundation of future extensions
to the standard C++ library.
It
is certainly worth it for C++ programmers to familiarize themselves with
these new techniques. They are not applicable in all places and they only
solve a certain type of problem, but they are an addition to every C++
programmer's skill set. In that sense
Modern C++ Design: Generic Programming
and Design Patterns Applied
is definitely worth reading. If you want
to learn more about templates and C++ and if you want to expand your horizon,
go for it. This book will most likely change the way you use and understand
C++ templates.
Angelika
Langer
develops and teaches classes on Java, C++, multithreading, and
internationalization. She is an internationally recognized speaker and
served on the ANSI/ISO C++ Committee from 1993 to 1998.
Klaus Kreft
is a software architect and senior consultant with 15+ years of experience
in industrial software development. He currently works for Siemens Business
Services in Germany. Langer and Kreft are authors of "Standard C++ IOStreams
and Locales" (Addison-Wesley, 2000) and are columnists for the C/C++ Users
Journal.
|