Thoughts on Header File Extensions: .h vs .hpp

I'm creating a new framework which uses a mix of C and C++, and recently I stopped to consider my choice of header file extension.

I have spent my career as a C programmer, so many of my habits are simply ossified from my C days. One such habit is using .h for all header file extensions.

To make matters worse, it seems there is still not a fixed approach to C/C++ header file differentiation. While surveying comments around the internet, I see many developers only use .hpp for C++ headers which also include implementations. Other C++-only headers are left with the .h extension. Unhelpfully, many IDEs still seem to recommend .h as the default header extension, even if you are using C++.

The problem with allowing .h to represent both C and C++ code without differentiation is that you increase friction for developers:

  • How can you know that you can't include a specific library .h file in your C program because it's really C++?
  • What if you are trying to adjust your build system and want to exclude all C++ files from a specific project?

I think it is important to make conventions and language type apparent to developers without requiring manual inspection. In my new framework, I have decided to use .hpp for all headers that are C++-only. .h will be reserved for headers which can be included by either C or C++ sources. I'm not alone in this convention - at the very least, Boost uses the same approach. To quote from the Boost FAQ:

Why do Boost headers have a .hpp suffix rather than .h or none at all?
File extensions communicate the "type" of the file, both to humans and to computer programs. The '.h' extension is used for C header files, and therefore communicates the wrong thing about C++ header files. Using no extension communicates nothing and forces inspection of file contents to determine type. Using '.hpp' unambiguously identifies it as C++ header file, and works well in actual practice. (Rainer Deyke)

As an aside, it is helpful to make your C-style headers compatible with C++. Here are some simple strategies to keep in mind:

  • protect C-only code with the __cplusplus macro, which is only defined by the C++ compiler
  • Mark C functions code as extern "C" when compiling C++ code

I hope that you take some time to think about header extensions in your own projects!