views:

151

answers:

6

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).

+1  A: 

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).

Josh Kelley
They can also be put in `.hpp` files. In fact, they could be put in `.super_ball` files, `.i_like_pizza` files, or any other type of file.
John Dibling
The Google Style Guide is not particularly good.
Potatoswatter
In fact, in my opinion it's terrible.
John Dibling
A: 

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).

PC2st
Not true. You only need to #include the .hpp file in the .cpp file somewhere.
T.E.D.
@T.E.D. Thanks ;-) you're right.
PC2st
+1  A: 

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.

Andre Holzner
Separation of interface and implementation is a good idea, but it can be done in one file by putting the interface on the top.
David Thornley
+1  A: 

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.

Potatoswatter
+1 for `export templates` ;-)
PC2st
Disagree with "silly". If the template library is complex or has a number of functions, splitting the implementation in the an hpp file makes a lot of sense from a readability standpoint.
John Dibling
@John: Fine, "unusual". But how much readability can you possibly gain from just splitting the file in the middle and joining with `#include`? The readability comes from putting prototype declarations at the top, not splitting the file.
Potatoswatter
@Potatoswatter: Sometimes a lot. I agree the same can be accomplished by shoving the implementation to the end of the same file, but I personally prefer putting only what the user needs to know in the header file when possible. Adding more stuff becomes confusing. I don't think there is a right or wrong opinion here, though.
John Dibling
+4  A: 

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
}
John Dibling
I've done this in the past, and I believe boost does it a lot.
T.E.D.
Thanks for explaining the reasoning. I don't think I will use it in that way though.
rhubarb
@rhubarb: If you're looking for other options in implementing templates, you may find this interesting: http://stackoverflow.com/questions/3040480/c-template-function-compiles-in-header-but-not-implementation/3040706#3040706
John Dibling
Thanks! Very helpful!
rhubarb
A: 

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).

Johannes Schaub - litb
I've never seen `hpp` used for anything other that an `#include`-ed implementation file. Diffrent strokes, I suppose. Personally, I use `inc` for such a purpose.
John Dibling
@John *all* boost headers end with `.hpp`, including `cstdint.hpp`. In fact, in my boost header directory, there are only 8 `.h` files (some C python stuff and such) but 7074 `.hpp` files.
Johannes Schaub - litb
@litb: Fair enough. Admittedly, I don't use boost a lot, and it escaped my memory that boost uses `hpp` in this way.
John Dibling