views:

185

answers:

1

We've got a reasonable sized C++ application that's pretty old at this stage, so it's got a few quirks.

One of these quirks is in how it deals with C++ compilers that use a pre-standisation standard library. There's one header file that's supposed to resolve any differences between a standards compliant compiler and this one non-compliant compiler. For various reasons we can't / don't want to stop supporting this compiler.

#include <vector>
#include <set>
#if defined(NO_STD_LIB)
    #include <iostream.h>
#else
    #incude <iostream>

    using std::string;
    using std::cout;
    using std::vector;
    using std::cout;
#endif

You use this as follows

#include stl.h
int main() {
    vector<string> foo;
    .....
    return 0;
}

There are 2 main issues with this approach:

  1. Each compilation unit that includes std.h has to compile lots of un-needed code (and we're trying to reduce compile times as much as possible at the minute)
  2. The global namespace gets polluted with pretty much everything that would normally be in the std namespace.

I really would like to address both of these points as part of a code cleanup project. The first one really is the more important reason for doing this.

As we have to support this old compiler then our code will always have to avoid clashing names with things that it exposes in it's standard lib, so point 2 isn't really relevant, though I'd like to see a solution that works when / if we can finally drop support for it.

My idea so far is to break up the super header into a set of smaller headers. e.g. stl_vector, stl_iostream, stl_set, etc. This way we can only include the parts of the standard library that we're interested in. These filenames follow the pattern of the std headers, but with an easily searched for prefix. So when the time comes to dump the offending compiler, it'll be simple to search for the prefix and remove it.

I think that will fix issue 1 easily enough.

My real problem is fixing issue 2. I thought of doing someting like this

#if defined(NO_STD_LIB)
    #include <iostream.h>
    #define std
#else
    #include <iostream>

then we could code as follows:

#incude "stl_iostream"

int main() {
  std::string foo("bar");
  std::cout << foo << std::endl;
}

And that almost worked. Where there was no standard namespace the #define std made std::string decompose into ::string and life was good.

Then I tried this with a .cc file that used the dreaded "using namespace std;" and I get a compile error because that becomes "using namespace ", so that obviously won't work.

Now obviously I could ban people from writing "using namespace std;", but as much as it should be avoided in headers, it's sometimes useful in .cc files where you're making heavy use of lots of STL classes.

So, finally, to the question. Is there a standard idiom for dealing with this issue. Or if there isn't a standard way to deal with this, then what tricks do you use to support compilers that use a pre-standard standard library.

I've thought of using pre-compiled headers to solve the compilation speed issue, but we target different compilers and the effort of getting this working across all of them may mean its not worth our time doing it.

Answers that advise me to drop the non-conforming compiler may be popular, but won't be accepted as this is something that we can't do just now.

+6  A: 

You can try:

#if defined(NO_STD_LIB)
namespace std {
    using ::string;
    using ::cout;
    using ::vector;
    using ::cout;
}
#endif

Then std::string will work.

It would have been much better if the using namespace ::; directive existed in the language; however it doesn't.

Andreas Bonini