Hoping you had a nice holiday break, it is now the time to resume our series on header files with a new topic covering the world of template definitions in C++.

If you have ever used the Boost libraries, you may have noticed that aside from the regular hpp header files, they also provide a bunch of accompanying ipp files.

ipp files, in the general case, are used to provide the implementation for a template class defined in a corresponding hpp file. This stems from the fact that, in C++, the code for such template definitions must be available whenever the class is instantiated, and this in turn means that the template definitions cannot be placed in separate modules as is customary with non-template classes. In other words: putting the template definitions in cpp files just does not work. (I hear the C++ standards committee wants to “fix” this but I forget the details now and cannot find a reference.)

By splitting the implementation of a template class from its definition, the developer controls when and where the implementation of such class is instantiated and made available. The developer does this by explicitly including the ipp file instead of the hpp file where necessary.

There are two advantages to doing the above:

  • Shorter build times: Most modules where you include a header file wouldn’t care less about the implementation internals of the class they need. If you don’t need something in a module, don’t include it in the first place!
  • Cleaner header files: Because classes exist to encapsulate some behavior, it is extremely likely for the implementation of a class to require the inclusion of more header files than its corresponding hpp counterpart. By keeping the two separate, the hpp files are leaner dependency-wise and prevent inadvertently introducing additional indirect dependencies in your code. This, again, is just a side-effect of C++ lacking a proper modules system.

Obviously, all of the above applies not only to template class definitions, but also to template functions and even inline functions. The guideline, therefore, is: place definitions in cpp or ipp files and restrict hpp files to contain declarations only.

And keep in mind that including ipp files from within hpp files is almost always the wrong thing to do.