Introduction
C++ isn't perfect, but it can often be the right tool to use for several different types of jobs. C++ has a lot of practical language features, such as templates, functors, operator overloading, pointers, and multiple inheritance. Java, for example, does not implement any of the above things in its current incarnation.
One of the things that Java is better at than C++, however, is providing high-level tools as part of the language itself. Threading, regular expressions, GUIs, and many other features are all inside Java's API. At first glance, a similar set of tools seems to be lacking in C++, as its standard library contains only the bare basics, as well as the STL's useful containers, iterators, and algorithms. For example, C++ does not implement any threading in and of itself, despite threads being an important part of quite a few large projects.
But, C++ does have a large public code repository available for your use at the other end of a Google search. Deciding which of several similar libraries to use can be difficult, and there's always the occasional unpleasant discovery of a library not living up to its own specifications. This article tries to take some of the hard work out of a new C++ developer's life, and list a few projects that are known to be well-built. I've compiled this list partially on my personal experiences, but mostly based on the suggestions of various experienced developers in the Open Projects channel #C++.
So without further ado, the list:
Lua : The extensible extensions language
Lua is a tiny and highly efficient scripting language. It was designed from the very start to do nothing but be used for extending C or C++ programs. Since Lua is written in pure ANSI C, it's extremely portable. But the best feature of Lua may be its unbridled speed.
Lua isn't perfect, and it's C-ness comes at somewhat of a price. It's API is very typical of C libraries, in that all the functions are global and in the form lua_<something>. It uses regular function pointers for call backs, which means that you cannot set a call back to a method of a particular instance without designing around it within the Lua code itself. For example, you could have each call back require a pointer or some other sort of global object identifier, or build some sort of global wrapper around C++'s pointers-to-members.
Lua code itself is written in a clear and easy-to-understand language. I would describe it as a cross between BASIC's syntax and Scheme's first-class functions. It also provides some simplistic object oriented facilities, somewhat reminiscent of Perl's OO. Also, Lua does not have direct access to your C++ code; it can only access the external world through Lua extension libraries and call backs that you provide.
This combination of portability, speed, and simplicity all make Lua useful in a wide range of situations. You could use it in your project which must execute scripts so often that the overhead of larger languages becomes unwieldy. Or, you could use it to allow people without extensive programming experience to still extend your program to fit their needs. You could even use Lua to for either of these features while working on a system where resources are limited or with obscure portability requirements, such as a PDA or embedded network appliance.
So to conclude, Lua is, under many but not all circumstances, a good alternative to larger scripting languages such as Python. If you find Lua is too simple for your needs, though, Python is another good choice for an extensions language. Boost implements a very impressive Python API, allowing it to extend your app in an object oriented fashion. And speaking of Boost...
Boost : The handy library of handy libraries
Boost is probably the largest and most active general purpose C++ library available. It was founded by members of the C++ Standards Committee as a testing ground for new libraries, supposedly for eventual placement into the language itself. Each library submitted to Boost goes under a rigorous testing process before being admitted, and all the ones currently in the library are polished and useful.
Much of Boost is implemented entirely in headers. These usually include simple class constructs that eventually tend to show up, in one form or another, in a number of large projects. For example, there's the noncopyable utility class to prevent certain types from being copied, and the tuple library, a template for holding some specific set of objects in a single container.
Some mathematical libraries are also part of Boost. Cstdint implements some simple number classes, both guaranteed-size integer types which stay the same across different platforms (as with the C header stdint.h), and numbers designed to scale as needed to hold extremely large values. There is also the common factor library for simple LCD and GCD calculations, as well as more complex mathematical concepts like octonions, quaterions, and rational numbers.
There are also Boost libraries for further extending basic C++ features. Smart_ptr contains more flexible and specialized versions of the standard library's auto_ptr, letting you define ownership more precisely. The operators library allows you to have operators built automatically based upon other operators that you've written (for example, automatically defining not-equals based upon equals, or turning less-than and equals into the complete set of comparison operators.) Another useful library is Boost's array, which has a template class designed to give all the efficiency of the fixed C array with additional safety and sanity checks. Even more Boost libs include Static_assert for compile-time assertions, and ref which allows things you couldn't normally do with references, such as feeding them into template algorithms. Also, the concept checking library allows you to more effectively ensure that class interfaces you use and write meet their contracts concerning time complexity, valid expressions, and other such things. And finally, the conversion library provides some primitive conversions that normally require the usage of stringstreams or special library calls to perform.
Boost also contains a regular expressions library. Regular expressions are a powerful way of doing string processing of nearly all kinds besides tokenization, which Boost has a library for as well. The standard C++ library does have some regex-like features (such as the various basic_string find functions), but they aren't comparable to proper regular expression support. Th Boost regex library provides many of the general operations such as match, replace, and split, all of which are dear in the hearts of Perl developers everywhere.
In the Lua section above, I mentioned that Boost had a Python interface. While it's true that Python already comes with a C/C++ API, the Boost Python interface is in a different type of class (if you'll excuse the bad pun) altogether. The regular Python interface permits you to manually control the Python system like any other library, while Boost Python reverses this and allows Python to access and even extend C++ classes as though they were Python classes. It's
very easy to grant Python scripts access to your C++ classes, and in doing so you just make it that much simpler for others to expand your code without even having to compile anything.
The final Boost offering I'd like to look at is the thread library, a portable implementation of concurrency. Threading is the thing to use if you want your app to run efficiently across multiple processors, under complex schedulers, with faster responses to new events, or just to separate the real-time and external interface parts of your library. Threading is covered by a wide range of techniques and literature, so if you're familiar with those techniques, consider taking advantage of the Boost thread library's portability and safety.
Believe it or not, there's more. The list of continues with even more useful Boost libraries that aren't discussed above. One of those libraries, any, actually has another Kuro5hin story dedicated entirely to it.
You may find that your use of Boost classes becomes so regular as to make them seem like C++ libraries. This is easy enough to do, since they're built upon the same principles of generic programming and reviewed by many of the same people who set up the C++ standard library. But now that your project is starting to depend upon more complex and powerful external code, it may reach a higher degree of complexity then you expected. If you want to keep track of your overall design, or easily explain your library's API to other developers, you should use a good documentation system, such as...
Doxygen : The comment-parser worthy of comment
Doxygen is an API documentation system, designed in the same style as the documentation systems for Java, Perl, and Python: the docs that are generated are actually based off the comments in your source code. Doxygen has the advantage of being rather more flexible then the majority of such programs. In addition to a wide array of output formats, it can support practically any comment style you'd want to use, including those that work well in the C++ world of separate headers and implementations.
Doxygen isn't only a C++ tool; it works with C, Java, IDL, and PHP, and could probably be extended to others. In addition, it generates not only HTML, but also LaTeX, PostScript, PDFs, and even UNIX man pages. Besides this, it can understand and beautify things like dependencies and collaborations, formulas, and especially detailed and nice-looking versions of the standard class hierarchy diagrams we all love so much. Because the documentation goes right into the relevant source code, it's more difficult to forget to update your docs to match your program's evolution.
Now, your project is really cooking; other coders can use your classes in their projects, and contribute to your own code, because they can easily see what you're thinking of with your design. The next step might be to add network access of some kind, so that something can control or be controlled by your program remotely. One way to do that in a non-platform-specific way is with...
ACE : Adaptive, layered networking which just works
ACE is a collection of components, patterns, and wrappers which give your projects an adaptive way of talking with other networked apps. This is really a gross over-simplification; ACE provides more networking services then you can shake an inheritance tree at, including a related CORBA implementation, its own threading system, signal handling, IPC, message routing, containers, iostreams, a POSIXish OS adaption layer, and far more besides.
To do ACE justice on Kuro5hin would necessitate a separate story altogether, so curious programmers should read the overview, and (after their heads are suitably spinning) work through some tutorials.
But now your project is getting even more complex, especially with the possible introduction of concurrency issues, either via networking or threading. What you really need now is a way of getting rid of all those lingering bugs you can just sense lying beneath the calm waters of your class interfaces (I'm really on a roll with these bad analogies, aren't I?). Luckily for you, there's...
Libcwd : The debugger that helps you help your own code
Libcwd is a debugging support library, which has features like automated memory debugging, runtime support for printing file and line number information, and human-readable demangled typenames. It's thread safe, allows for the creation of multiple debug channels (the named frontends for debugging output) and debug devices (ostreams for actually delivering the debugging data), all of which can be turned on and off dynamically on a per-thread basis. In addition, Libcwd can automatically watch for memory allocations and certain other types of events, helping you to remove memory leaks. What all this allows you to do is to get a real-time display of whatever part of your application you're interested in at the moment, as it runs.
Among all of Libcwd's features, though, perhaps the most useful property of Libcwd is that it's easy to get rid of. When making a release of your application, you can avoid compiling in Libcwd simply by undefining a preprocessor macro and not linking to Libcwd. Since all the actual debugging code is accessed via carefully designed preprocessor macros, compiling your app without them will remove all trace of the any additional dependencies, portability restrictions, and efficiency problems associated with the actual debugging code.
The main disadvantage in using Libcwd is that, in itself, it isn't portable beyond g++, the GNU C++ compiler, and UNIX-ish operating systems, or in some cases only Linux. Your actual release code will be, though, which also means you can simply have some developers use it without affecting the portability of the project's code itself at all. Your developers using Linux will still reap its benefits.