
According to Hoyle...
C++0x Part 2: A Step Forward
macCompanion
November 2009
by Jonathan Hoyle
jonhoyle@mac.com
http://www.jonhoyle.com
Last month, we began examining the upcoming changes to the C++ language. In it we
discussed the evolution of C++ and where it is today. Having examined C++'s past and the present, we move on to
describe its future. However, before doing that, we take one look back for a cautionary tale.
The Cautionary Tale of EC++
From 1996-1999, a consortium of Japanese embedded systems tool developers (including NEC, Hitachi, Fujitsu and Toshiba) were
putting together a proposal for a language subset of C++. This subset would essentially be C++ with a number of
language features removed which (they thought) was too complicated and could hurt performance. The features targeted
for removal included: multiple inheritance, templates, exceptions, RTTI, the new cast operators and namespaces. This
new language subset would be called Embedded C++, or EC++
for short.
To the surprise of the consortium members, the EC++ compilers were not only no faster than their C++ cousins, but in some
domains EC++ was actually slower! C++ founder Bjarne Stroustrup later explained that templates were used in much of the
Standard Library to improve performance, and their removal put EC++ at a disadvantage. Upon hearing this, the dazed
members of the EC++ consortium scrambled to put together a new proposal: Extended EC++, which was simply EC++ with templates
put back in.
When the Extended EC++ compilers became available, they were once again put to the test against their C++ cousins. To
the consortium's bewilderment, once again the performance gains relative to C++ turned out to be negligible. Part of the
problem has the consortium's ignorance of C++'s Zero Overhead Principle: "what you don't use, you don't pay
for". After this final embarassment, ISO refused endorse any of the EC++ proposals.
In 2004, inspired by the EC++ debacle, the C++0x committee called for a Performance TR to determine which features of the C++
language which truly had the greatest penalties in performance. As it turned out, there were only three areas in which
there was any measurable performance issues:
- Free Store (new and delete)
- RTTI (dynamic_cast<> and typeid())
- Exceptions (throw and catch)
Memory allocation and deallocation turned out to have the largest impact on performance; however, it is unlikely that you
would want to use a language which did not allocation memory off the heap. As for RTTI and exception handling, many
compilers have switches allowing the developer to disable these, if desired. Modern compilers often have greatly
optimized their implementation of Exception Handling, making RTTI the only outlier. In any case, with the Zero Overhead
Principle in place, simply not using a C++ language feature is no different than having it removed.
As for EC++, Stroustrup is quoted as saying: "To the best of my
knowledge EC++ is dead, and if it isn't it ought to be."
Is there a moral which can be gleaned from this decade old lesson? Only that knee-jerk reactions tend to result in
unexpected consequences. The whole Embedded C++ fiasco could have been avoided with only a little bit of time and effort
to properly research the problem. So now (finally), onto some changes in C++0x ...
Embarrassments, Fixes & Improvements
Although the C++ standard in 1998 was an astounding achievement, there were a small number of flaws which remained. Some
of this was simply oversight; others were known, but there had not been sufficient agreement for resolution. Bjarne
Stroustrup described some of these as embarrassments, particularly when trying to explain them to novices. Some of these
improvements include:
vector<vector<int>> x; // Finally, legal!
vector<double> x = { 1.2, 2.3, 3.4 }; ; // Initializing STL containers
stronger typing of enum's // Enumerated types remain in their scope
extern-ing of template's // No duplication across translation units
If you are not familiar as to why any of the above caused errors, you needn't even bother to understand why. They are
problems that are going away in C++0x. I will delve into the first item only (Stroustrup's biggest embarrassment), to give
you a flavor of the problem. The flaw lies simply with the fact that C++98 parses the ">>" portion of vector<vector<int>> x; as a right shift operator and generates an error; C++0x fixes
this. One of the reasons this took so long is that ANSI/ISO committee members are very hesitant to put in silent changes
in the specification. A silent change is one which would keep the meaning of some C++ code with generating an
error. Surprisingly, the reinterpretation of ">>" within templates can yield a silent change, as this example below shows:
template<int I>
struct X
{
static int const x = 2;
}
template<>
struct X<0>
{
typedef int x;
}
template<typename T>
struct Y
{
static int const x = 3;
}
static int const x = 4;
cout << (Y<X<1>>::x>::x>::x) << endl; // C++98 prints “3”
// C++0x prints “0”
ANSI/ISO C99 Synchronization
The ANSI/ISO C specification was updated in 1999 with a number of improvements in the language. Many of these improvements
were simply acquiring behavior which was already legal in C++ but seemed to make sense for C as well. Other changes were
not part of C++, but the ANSI/ISO C++ committee in turn saw some of these features as valuable and are rolling these into the
C++0x specification. These include:
__func__ // returns the name of the function
long long // extended integral type, eg: 64-bit
int16_t, int32_t, intptr_t, etc. // fixed-sized integers
Hex floating point types, eg: double x = 0x1.F0;
Complex versions of some math functions, such as arcsin(), arccos(), fabs(), etc.
Variadic macros, that is macros taking a variable number of arguments, such as:
#define S(...) sum(__VA_ARGS__)
With these changes, C++0x is modernized for the upcoming decade.
Coming Up
C++0x Part 3: Making Coding Easier
C++0x Part 4: Smart Pointers
C++0x Part 5: Rvalue References
C++0x Part 6: Final Thoughts
http://www.maccompanion.com/macc/archives/November2009/Columns/AccordingtoHoyle.htm