Using STL with VC++ 4.x


By now, most CUJ readers who are interested in STL have probably had a chance to get their hands on an implementation and experiment with it. If you have VC++ 4.0 or better, you have the STL headers and a compiler capable of using them. But the STL shipped with VC++ 4.x won't run "straight from the box." You will have to modify both the STL headers and some project/compiler settings before you can make any use of the STL.

When VC++ runs its setup, it does not load the STL source. The STL source resides in the \STL directory of the VC++ CD. You'll need to modify the source files, so copy all those files over to an STL subdirectory of your choosing. The required modifications are simple. In that STL directory, the README.WRI file gives the file names and line numbers that need to be changed. Basically, the STL must be wrapped into the std namespace, so all the changes involve adding the std:: identifier in front of some STL function calls.

You also need to tell VC++ where to find these new system headers. The "permanent" solution is to add the STL directory via "Tools" from the main menu, then "Options," then the "Directories" tab. Just add your STL directory to that list. (By the way, you might be in for a surprise if you haven't checked your include paths before. The first time I checked, I saw that VC++ searched not only within itself, but had also somehow found a directory of QuickC headers on another drive and had added them to the include path list!)

One other detail for MFC applications (as opposed to console apps) is that you must define NOMINMAX. This definition must be in effect before VC++ tries to declare its own min and max routines. You can define NOMINMAX either in the IDE via the `Build,' `Settings,' `C/C++,' `General' route or you can #define NOMINMAX in "stdafx.h".

If you forget to define NOMINMAX, you'll get errors at the min and max STL templates. At that point, it you define NOMINMAX in the IDE, make sure you do a 'Rebuild All' since NOMINMAX affects VC++'s precompiled headers.

All that's left is to include the the appropriate STL header. But there's some picky stuff here too. The STL with VC++ needs <new.h> and <fstream.h> #included outside of the std namespace, but all the STL headers must be wrapped inside the std namespace. The following snippet shows how to make an STL stack with VC++:


#pragma warning (disable : 4146 4018) //see a little further down
#define <new.h>
#define <fstream.h>
namespace std {
#include <stack.h>
#include <deque>
}
std::stack<std::deque<int> > intStack; //a stack of ints!

Unfortunately, VC++ 4.x doesn't give us the std namespace for free, hence the std namespace designator for each and every use of an STL component. The using directive is one alternative to this cumbersome process. You can include a using namespace std; statement to get around continuous explicit namespace resolution.

One easier way to include the STL headers is to create an stl.h file which consists of a macro guard, the #shut up pragma (or not) and then #include all the STL headers into the std namespace. (Don't forget to #include new.h and fstream.h outside of the std namespace.) If you also include a using namespace std; at the end of the stl.h file, you won't have to namespace qualify the STL components you use. Then whenever you need some STL functionality, just #include "stl.h" and start cranking out code. You can even #include your STL headers inside stdafx.h and take advantage of of VC++'s precompiled header capability.

Adding the warning pragma can be a practical necessity when adding STL to your development tools. Otherwise, you can get several nuisance warnings (I call it "noisy code") such as signed and unsigned mismatches and unary operators applied to unsigneds. F4-ing to the next error is a pain when you've got to hit F4 six, eight, or more times to get to a "real" error.

Since the STL code is only partially compiled until a template is instantiated, the time honored method of sandwiching noisy code with "turn off warning pragma" and then the "turn it back on" isn't so easy. You will have to sandwich each instantiation of a noisy STL component rather than doing it just once when the resource is included.

VC++ 4.2 gives you one more STL option. The VC++ 4.2 Standard Library includes the STL, but the standard containers in this library were designed for a compiler that can understand default template arguments -- which VC++ 4.2 does not. To eliminate the resulting cumbersome syntax required to instantiate a template, Microsoft has provided a replacement stl.h header. Replace your stl.h (if you have one) with this one (provided on the code disk), or else move the replacement stl.h into one of your include directories. o