C++, <windows.h>, precompiled headers and pimpl

Today we take a look at how to make best use of precompiled headers, how to avoid the <windows.h>-is-messing-up-my-symbols-syndrome and how to properly use pimpl to reduce our compile times.

Well, everything you learned about doing good headers is basically ignored here. Just look at things like ...

#undef INTERFACE
#define INTERFACE INamedPropertyBag

or

#define ERROR 0

and then try something like

class Reflection
{
    enum Type {
        INTERFACE
    };
};

No chance to prevent this from happening, the only thing you can do is to clean up behind windows.h. The worst that can happen to you is that some header includes windows.h before you could to it, and does it without clean up. If you are the first one to include it, everything is fine, as the next include will do nothing (thanks to include guards). The best way to enforce this is to include it in your precompiled header. The problem is amplified by the fact that even headers like boost/shared_ptr.hpp wind up including windows.h on Windows, and there is no chance to use PIMPL to combat this. Which brings us to our next topic ...

PIMPL

The silver bullet against windows.h and friends -- hide them away from the public. PIMPL is easy to do, you just have to keep two things in mind:

  • Make them non-copyable. As the implementation is just a pointer, the pointer gets copied by default and is then shared between the two instances, unless you implement a custom "deep copy".
  • Make sure that it can't leak memory. Just use a shared_ptr and you should be fine.

Good candidates are classes which use the filesystem, process-creation and similar low-level things. Also, classes which include expensive other classes like mutexes should be pimpled.

Precompiled headers

Not much new since my last post about this, just some things to keep in mind:

  • Make sure it compiles fine without the precompiled header.
  • Build the precompiled header after evaluating the include dependencies.
  • Try to move the headers into the implementation files as much as possible -- forward declare what you can. This can especially help if you pass classes by reference. Moreover, often you get rid of more than one include as headers tend to include other headers excessively.

That is basically, with careful layout you should get gains around 50% just by using precompiled headers.

Comments

Comments powered by Disqus