21
WRITING APPLICATIONS
691
Program Support . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 692
Handling Program Termination and Cleanup . . . . . . . . . . . . . . . . . . . . . . . 693
Communicating with the Environment . . . . . . . . . . . . . . . . . . . . . . . . . . . . 697
Managing Operating System Signals . . . . . . . . . . . . . . . . . . . . . . . . . . . . 699
Boost ProgramOptions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 700
The Options Description . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 701
Parsing Options . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 703
Storing and Accessing Options . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 704
Putting It All Together . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 705
Special Topics in Compilation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 708
Revisiting the Preprocessor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 708
Compiler Optimization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 710
Linking with C . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 711
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 712
INDEX
715
F O R E W O R D
“C++ is a complicated language.” This is a reputation C++ has earned across
a number of decades of use, and not always for the right reasons. Often, this
is used as a reason to disallow people from learning C++, or as a reason why
a different programming language would be better. These arguments are
hard to substantiate because the basic premise they rely on is wrong: C++ is
not a complicated language. The biggest problem C++ has is its reputation,
and the second biggest problem is the lack of high-quality educational
materials for learning it.
The language itself has evolved over the past four decades from C. It
started off as being a fork of C (with minor additions) and a pre-compiler
called Cfront, which compiles early C++ code to C that is then to be pro-
cessed with the C compiler. Hence the name Cfront—in front of C. After
a few years of progress and development, this proved to limit the language
too much and work was undertaken to create an actual compiler. This com-
piler, written by Bjarne Stroustrup (the original inventor of the language),
could compile a C++ program stand-alone. Other companies were also
interested in continuing from basic C support and made their own C++
compilers, mostly compatible with either Cfront or the newer compiler.
xxvi
Foreword
This proved to be untenable because the language was unportable
and wildly incompatible between compilers. Not to mention the fact that
keeping all decisions and direction within the hands of a single person is
not the way to make a cross-company international standard—there are
standard procedures for that, and organizations that manage them. C++
was thus moved to become an ISO standard belonging to the International
Standards Organization. After a number of years of development, the first
official C++ standard came out in 1998, and people rejoiced.
They rejoiced for only a short while though, because while C++98 was a
good definition, it had included a few new developments that people didn’t
see coming, and had some features that interacted in weird ways. In some
cases the features themselves were well-written, but the interaction between
common features was just not present—for example, being able to have a
filename as a
std::string
and then opening a file with that.
Another late addition was support of templates, which was the main
underlying technology supporting the Standard Template Library, one of the
most important pieces in C++ today. Only after its release did people discover
that it itself is Turing complete, and that many advanced constructs could
be done by doing computations at compile time. This greatly enhanced the
ability for library writers to write generic code that would be able to handle
arbitrarily complex deductions, which was unlike anything other languages
in existence at the time could do.
A final complication was that while C++98 was good, many compilers
were not suited for implementing templates. The two major compilers of
the time, GNU GCC 2.7 and Microsoft Visual C++ 6.0, were both unable to
do a two-step name lookup required by templates. The only way to fully get
this right was to do a full compiler rewrite. . .
GNU tried to keep adding onto its existing code base, but finally went
for a rewrite around the 2.95 time frame. This meant that there were no new
features or releases for a multi-year period, and many were unhappy with
this. Some companies took the code base and tried to continue its develop-
ment, creating 2.95.2, 2.95.3 and 2.96—all three of which are remembered
for their lack of stability. Finally, the completed rewrite GCC 3.0 came out.
It was not very successful initially, because while it would compile templates
and C++ code much better than 2.95 ever did, it would not compile the Linux
kernel to a working binary. The Linux community plainly objected to modify-
ing their code to adapt to the new compiler, insisting that the compiler was
broken. Eventually, around the 3.2 timeframe, the Linux community came
around and the Linux world recentered around GCC 3.2 and up.
Microsoft tried to avoid rewriting their compiler for as long as they
could. They added cornercase upon cornercase and heuristic methods to
guess whether something should have been resolved in the first or second
template name lookup pass. This worked nearly completely, but libraries
written in the early 2010s showed that there was no possible way to make
all of them work—not even with source modifications. Microsoft finally
rewrote their parser and released the updated version in 2018—but many
people did not enable the new parser. In 2019 the new parser was finally
included by default on new projects.
Foreword
xxvii
But before 2019, there was a major event in 2011: the release of C++11.
After C++98 was released, major new features were proposed and worked
on. But due to one feature in particular not working out quite as was
expected, the new C++ release was postponed from around 2006 until
around 2009. During that time attempts were made to make it work with
the new feature. In 2009 it was finally removed and the rest was fixed up for
release, and the 1998 version of C++ was finally updated. There were a ton
of new features and library enhancements. Compilers were again slow to
catch up, and most of the compilers could compile most of C++11 only by
the end of 2013.
The C++ committee had learned from their earlier failure, and now
had a battle plan of creating a new release every three years. The plan was to
conjure and test new features in one year, integrate them well in the next,
and stabilize and officially release in the third, and repeat this process every
three years. C++11 was the first instance, and 2014 was the year for the sec-
ond. Much to their credit, the committee did exactly as they had promised,
making a major update over C++11 and enabling the C++11 features to be
much more usable than they had been. In most of the places where careful
limits had been implemented, the limits were moved to what was then con-
sidered acceptable—in particular around
constexpr
.
Compiler writers who were still trying to get all the C++11 features
running well now realized that they needed to adjust their pace or be
left behind. By 2015 all compilers supported just about all of C++14—a
remarkable feat, given what happened to C++98 and C++11 before. This
also renewed participation in the C++ committee from all major compiler
writers—if you know about a feature before it’s released, you can be the
leading compiler supporting it. And if you find that a certain feature does
not match your compiler’s design, you can influence the C++ committee
to adjust it in a way that makes it much easier for you to support, allowing
people to use it sooner.
C++ is now experiencing a rebirth. This period started around 2011
when C++11 was introduced and the “Modern C++” programming style that
it enabled was adopted. It has improved only so far though, because all the
ideas from C++11 were fine-tuned in C++14 and C++17, and all compilers
now fully support all of the features that you would expect. Even better, the
new standard for C++20 will soon be released, and all compilers in their
most up-to-date versions already support major parts of it.
Modern C++ allows developers to skip most of the original trouble of
trying to first learn C, then C++98, then C++11 and then unlearning all
the parts of C and C++98 that had been fixed. Most courses used to start
with an introduction about the history of C++ because it was necessary
to understand why some things were as weird as they were. For this book
though, I’m including this information in the foreword because Josh right-
fully left it out.
You don’t need to know this history anymore to learn C++. Modern C++
style allows you to skip it entirely and write well-designed programs know-
ing just the basic tenets of C++. There is no better time to start learning
C++ than now.
xxviii
Foreword
But now to return to an earlier point—the lack of high-quality edu-
cational opportunities and materials for learning C++. High-quality C++
education is now being provided within the C++ committee itself—there’s
a study group dedicated just to teaching C++!—and the latter issue is in my
opinion completely resolved by the very book you’re holding.
Unlike all other C++ books I’ve read, this book teaches you the basics
and the principles. It teaches you how to reason, and then lets you reason
through the things that the Standard Template Library offers you. The
payoff may take a bit longer, but you will be so much more satisfied to see
your first results compile and run when you fully understand how C++
works. This book even includes topics that most C++ books shy away from:
setting up your environment and testing your code before running the full
program.
Enjoy reading this book and trying out all its exercises, and good luck
on your C++ journey!
Peter Bindels
Principal Software Engineer, TomTom
|