18
votes

I saw some code in which the developer defined a class template in a .h file, and defined its methods in a .hpp file. This caught me a bit by surprise.

Are there are particular conventions in C++ when dealing with templates and what files they should be in?

For example say I had a Vector class template with methods for vector operations (add, subtract, dot, etc.). I would also want to specialize certain functions if the template argument is a float (comparison operators). How would you separate all of this between files (specify whether .h, .hpp, .cpp).

7

7 Answers

19
votes

Typically (in my experience, YMMV) an hpp file is an #include-ed CPP file. This is done in order to break the code up in to two physical files, a primary include and an implementation-details file that the users of your library don't need to know about. It is done like this:

super_lib.h (the only file your clients need to #include)

template<...> class MyGizmo
{
public:
  void my_fancy_function();
};

#include "super_lib_implementation.hpp"

super_lib_implementation.hpp (your clients do not #include this directly)

template<...> void MyGizmo<...>::my_fancy_function()
{
 // magic happens
}
2
votes

That sounds unusual to me. A template's definition and all specializations must be compiled along with its declaration, with the exception of export templates, a feature which effectively doesn't exist.

C++0x does introduce extern template declarations, which allow you to define explicit specializations in a different source file (translation unit). This exists already as an extension in GCC and probably other platforms.

Splitting into two files could help "hide" the implementation a little, or allow some kind of laziness with doxygen, maybe.

Aha! It's also possibly to improve compile time with precompiled headers. The compiler may cache headers on a per-file basis. A separate "implementation" header could then be modified without touching the "interface" header. But not vice versa, the implementation header would still take the bulk of the compile time, and the gain would be very fragile and dependent on the platform and specific changes made. In the end, PCH improves time over several source files, and optimizing header dependencies is pointless.

2
votes

It looks to me that this is a confusing way of separating code. .h stands for header and .hpp for C++ header commonly. Putting template definitions into .hpp while other code into .h seems to abuse the file extension.

Template code is usually all written in one header together with the template declaration, or in another header that may also be specially suffixed like .tcc or something and then included into the header where the template declarations are put in. But really, the file extension doesn't matter as long as you are consistent in your project.

Exceptions are when you use explicit instantiation, and know exactly what instantiations you will need. Imagine you have a template, and exactly two instantiations of it:

template<typename T>
struct SymbolTable {
  T *lookup();
  // ...
};

template struct SymbolTable<GlobalSym>;
template struct SymbolTable<LocalSym>;

You don't need to put the definition of lookup and others into the header. You can put them all into a .cpp file, alongside with the two explicit instantiation directives.

The last point you ask about is about a different topic: Explicit specializations. I recommend you to make a separate question about that. In a nutshell, explicit specialization definitions where all template arguments have concrete values/types should be put into the .cpp file, but declarations of them are needed to be put into the header (to tell others that those certain members are specialized).

1
votes

I've never heard of putting class declarations in .h and template definitions in .hpp. Every project I've seen has taken the approach that .h and .hpp mean the same thing and you should standardize on one (usually .h).

Template methods can be put at the end of the .h file, or they can be put in separate -inl.h files (as suggested by the Google C++ Style Guide, for example).

1
votes

I think one aspect of separating the interface (.h) and implementation (.hpp) file is that a user of the template (i.e. another developer) only should have to look at the .h file to understand how to use the template without being distracted by its actual implementation.

0
votes

If we define a class template in a .h file, and define its methods in a .hpp file then we have to #include the .hpp file in the .h file. It's easier to simply define methods at the end of the .h file (then no .hpp file needed).

0
votes

The Boost library uses ".hpp" for headers containing the declaration AND implementation. In such cases, there is no need to link with the (pre-compiled) library.

In respect with Boost idea, such extension as ".inl" could be a good idea to describe the "implementation" source file of a template declaration header.