In March 2011, the ISO C++ committee approved the final draft of the newest C++ standard. The language, which officially became standard the following August, is known as C++ 11. Now that two years have passed, we can go back and look at some issues that have affected the language (indeed, ever since the first international standard in 1998), and compare its final result and product to a popular C++ library called Boost.
Since the first standard version in 1998, C++ has included an official library specification. Prior to that, various organizations and individuals created different libraries that were sometimes based on templates and provided different types of containers such as vectors and stacks. One such library that caught the attention of ANSI/ISO was the Standard Template Library (STL), which began with a guy named Alexander Stepanov. But there was no standard of the language itself yet, and different compiler vendors took the liberty of defining the language as they saw fit. (I recall in the mid-1990s being able to “unseat” references with the Borland C++ compiler—something I couldn’t do after the standard came out.)
Templates were of particular difficulty, as different vendors implemented them differently. Nevertheless, the creation of STL filled an important gap in C++, specifically a need for some well-defined and well-tested container classes. But to complicate things further, soon there were multiple STLs. I recall using one from HP (which was the original one), although my company at the time picked the one created by Silicon Graphics. Meanwhile, there was this bizarre library by Rogue Wave Software that included a ton of additional classes—some template-based, some not—that was one of the most popular commercial libraries at the time; parts of it looked a lot like the STL. Here’s the important point: none of these libraries were drop-in replacements. You couldn’t simply change the #include line to another library and expect it to work, even if they claimed to provide the same classes and functions. They just weren’t compatible. Just because two implemented vector classes based on the original STL didn’t mean they were the same.
Then the 1998 standard came out, which included its own specification for a library called the Standard Library. It looked a lot like the original STL, and was, in fact, based on it. Although part of the language specification, the Standard Library wasn’t actually part of the language itself in the sense of being built into the compiler. The library was a specification for a set of classes that vendors could implement as C++ code that would be shipped along with the compiler. That meant you could ignore the Standard Library if you wanted to, and instead use some other library—which is precisely what a lot of organizations did, including a company I worked for as a young engineer creating software for the telecom industry. At that company, the programmers who worked there before me had relied on the Silicon Graphics version of the STL, and it would have required a huge amount of effort to unplug that STL and substitute it for an implementation of the Standard Library. Of course, in 1999 we had to upgrade to the latest compilers and make a lot of changes, after vendors proudly announced that their compilers were now standard-compliant, which meant a lot of the old code we wrote didn’t always compile under the new compilers.
And so developers and software shops were forced to choose when starting new projects: use the new Standard Library or use the tried-and-true STL—and if the STL, which version? Or go with an excellent commercial library like Rogue Wave? They also had to understand that, once they picked one, they were pretty much stuck with it. And as for the Standard Library itself, the compiler vendors were usually the ones creating their own implementation of it, even those weren’t always the same.
It was clearly a mess. And part of the problem was (and still is) in the standards process itself. The STL was first demonstrated to the standards committee in 1993, but it took five years for the standard to come out. During the interim, there wasn’t even a standard for the language itself, much less the libraries, and so compiler vendors took huge liberties not only with the constructions of their own libraries, but also the very language. By 1996 or thereabouts, the mess was truly epic. Borland included a lot of novel features in their C++ language, but you couldn’t just compile the code on another C++ compiler. And if you wanted to use the STL, you had to find one that had been ported to your own compiler.
By 1998, vendors had mostly updated their compilers to the new standard, but that didn’t help much with the huge amount of code already written for earlier versions of the compilers. Some companies, in fact, couldn’t upgrade to the new compilers because their old code would break. A lot happens in six years when dealing with computers, and the compiler vendors had to continue releasing new versions, regardless of some supposed standard on the horizon.
Little changed in this process. Back in 2006 (three years after a small update) it looked like another C++ standard was close to becoming a reality. It finally came out in 2011. That’s a lot of time.
During the first decade of the 2000s, a new library was taking shape: Boost.
Boost is a set of C++ libraries that fills in various gaps not only in the C++ Standard Library but in the language itself, pushing C++ forward into modern programming. C++ first came out in 1983, after about four years of development, and was based on C, which came out in 1972.
So let’s be blunt: Although I love C++ as much as the next guy, and even still use it (especially when doing multicore programming, which is one of my current freelance projects), the fact is, if you spend much time in a newer language such as Java or Python (both of which are aging), you’ll find an awful lot of handy features built right into the newer language—features that aren’t part of C++. Heck, true strings still aren’t built into the core language itself in terms of the compiler; they’re implemented from templates as part of the Standard Library. The language itself is still based on character pointers and references. If you want string, you have to use one of the libraries, and often have to call the string class’s c_str() function to get a pointer to a character because strings aren’t built natively into the language—much less things like lists and dictionaries. Want a list in python? Just type a = [1,2,3]. Done.
As for more advanced features such as lambda functions (which many languages also support natively), that’s where C++ libraries like Boost help out.
Of course, there’s a fundamental difference in that C++ is fully compiled. But that’s an argument that’s been tackled ad nauseum, whether C++ is “better” or “faster” than modern dynamic languages that may or may not be compiled “just in time.”
The Boost library has ultimately served a couple purposes: On one hand it provides C++ programmers with advanced features such as functional programming and generic programming along with more basic features such as smart pointers. And on the other hand it has served as sort of an incubator for possible new C++ standard features.
Right on the front page of the Boost Website is a mention that ten Boost libraries have made it into the C++ 11 standard. On Boost’s introduction page, there’s a link to a page listing the ten libraries. Oh and it’s dated 2003—ten years ago, and long before the final standard.
Since the 2011 standard took so long, a lot of development groups have adopted the use of Boost (or left C++ altogether!). So let’s compare Boost to the standard.
The 2011 Standard and Boost
The C++ 11 standard includes several changes to the language itself (such as cleaning up the template compilation mechanism by allowing for “extern template,” as well as allowing for easier initialization of container objects, and even a type inference mechanism). But it also has many improvements in the Standard Library itself.
There’s a very important caveat that bears mentioning here: Although the C++ standard includes a description of the Standard Library, the C++ standard isn’t actually an implementation of either the compiler or the library. That’s up to third parties, such as the compiler vendors. There is no official reference implementation. The standard isn’t code; it’s a description.
Also, one thing to remember about Boost is that it’s actually multiple libraries, and its designers have intentionally divided it up. This means you can include only those Boost libraries you need. There are a few interdependencies, but those are clearly documented. As such, you can combine Boost with the Standard Library as needed. For example, the good old iostreams have been part of the Standard Library since the original 1998 standard, and Boost works fine with them (but also includes its own iostreams if you prefer).
But Boost, in fact, is much bigger than the Standard Library. It has around 175 classes, and the download on SourceForge for the current version (1.53.0) is a full 93 MB (which includes documentation but unzipped the .hpp files span 9000 files and 90MB). There are some classes that I personally have found extremely helpful in my own work, such as those in the category of “Language Features Emulation.” For example, there’s a for-each construct that, with thanks to the C++ template mechanism, allows you to write loops that go beyond the usual set of C++ loops, such as this:
int i = 0;
BOOST_FOREACH( i, container )
While you can easily write code using the native loops, there are a few reasons you might want to do this. One, the coding is just a tiny bit simpler. Two, the junior programmers (and even the senior ones you know who shouldn’t have been promoted) are less likely to make the same old mistake of writing things like for (i=0; i<=length;i++) and then ask you why the code seems to sort of work some of the time, while other times it crashes inside the other function the loop is calling.
Boost also provides a huge assortment of powerful but highly specialized classes. For example, a few years ago I needed a graph theory library, and Boost provides one. Need a multi-index array? How about a stack-based variant container? Boost has all that. But one thing I really like about Boost is the whole set of nice functional programming templates, and a handy Regular Expressions library.
As it is, the implementation of Boost isn’t totally clean; the developers have had to fill the library with compiler-specific code. For example, the implementation for the for-each construct includes code like this:
# if BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
|| BOOST_WORKAROUND(__BORLANDC__, < 0×593)
|| (BOOST_WORKAROUND(BOOST_INTEL_CXX_VERSION, <= 700) && defined(_MSC_VER))
|| BOOST_WORKAROUND(__SUNPRO_CC, < 0×5100)
|| BOOST_WORKAROUND(__DECCXX_VER, <= 60590042)
# define BOOST_FOREACH_NO_RVALUE_DETECTION
That’s good for everyone using the library: It will work with pretty much any of the typical compilers, and totally abstracts away the intricacies of the compiler.
But Now There’s Another Standard
So Boost has continued to grow, even as the standard was fought over in the years leading up to 2011. It contains some nice classes such as its own Regular Expressions class, which has a lot in common with the Boost library.
But what do we have with the standard? Look at it from the perspective of the compiler vendors. The C++ standards take years to get done. The 1998 standard was important, because it standardized many fundamental aspects of the language, such as templates and references. That made life much easier for library writers. But the compilers still differ, as evidenced by all the compiler-specific macros in the Boost library. That’s partly the fault of the vendors not specifically following the standard, but also due to occasional vagueness in the library itself.
In the several years leading up to the 2011 standard, there were also multiple changes to the standard. Compiler vendors were trying to update their compilers and their implementation of the Standard Library to meet what they thought would likely be in the standard, in hopes of having a standard-compliant compiler and library ready when the standard was actually finalized. But they were shooting at a moving target.
Let’s look at two specific compilers: The GNU gcc compiler and Microsoft’s C++ compiler. According to this chart, the current 4.8 version of GCC supports almost all of the new features, except for two small items (“Rvalue reference for *this” and “Minimal support for garbage collection”). But they make it very clear that the support is still “experimental.”
This chart from Microsoft shows the status in Visual Studio 2012—there’s lots of “no” and “partial” in that list. But note this little tidbit from that Microsoft page, which shows a little bit of what they were dealing with:
“After lambda functions were voted into the Working Paper (version 0.9) and mutable lambdas were added (version 1.0), the Standardization Committee overhauled the wording. This produced lambdas version 1.1. This occurred too late to be incorporated in Visual C++ 2010, but it is in Visual C++ in Visual Studio 2012.”
The focus here is on the core language. What about the Standard Library? Microsoft actually worked hard to keep current with the standard very early on in the process; however, they make clear that there are some features of the Standard Library that require core language features they haven’t implemented—and as a result, those aspects of the Standard Library aren’t implemented, either. (They don’t actually list which parts those are.)
And here’s where GNU stands on the Standard Library. There are a lot of items listed with “N” and “Partial.”
It’s been ten years since they started to form a standard, and two years since the approval. A lot changed in that time, and the compiler vendors couldn’t really risk implementing new features if those features would be scrapped later on. The resulting picture really has not been pretty.
Boost, however, has been moving along well. The developers have done a superior job of making sure their code works with different compilers. Boost is mature, well-tested, and works well. The development process has moved forward without being encumbered by a standards committee. It continues to evolve.
And what about those parts of it that made it into the Standard Library? I mentioned the Regular Expression library is very similar and was heavily influenced by Boost. But considering that implementations of the Standard Library still lack a lot of the features in the specification, does it even matter? Remember, the C++ standard itself isn’t code, and there is no reference implementation. The standard only says what a C++ compiler should do and what should be present in an implementation of the Standard Library. If you want to use the Standard Library, you have to use one produced by a third party—usually the one that comes with the compiler, such as the GCC version or the Microsoft version. And that’s what you’re really choosing between: GCC or Microsoft’s implementation of the Standard Library, or the Boost library upon which the Standard Library was modeled. And those two implementations of the Standard Library aren’t even complete, and one is called “experimental.” Which one would you prefer to ship out to production?
The Standards Committee took some eight years to fight over what should be in the standard, and the compiler vendors had to wait for all that to get ironed out before they could publish an implementation of the Standard Library. They did publish pieces, but it was clear they were early alpha versions at best. And they’re still not completely there yet. But meanwhile the actual C++ community was moving forward on its own, building better things such as Boost.
We’re told there will be another standard in a few more years. We’ve heard that before. I imagine by then Boost will be even better yet.