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, thehpp
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.