C++ templates declare in .h, define in .hpp
Asked Answered
N

7

19

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

Nahuatl answered 19/8, 2010 at 21:14 Comment(0)
A
20

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
}
Angora answered 19/8, 2010 at 21:22 Comment(4)
I've done this in the past, and I believe boost does it a lot.Snick
Thanks for explaining the reasoning. I don't think I will use it in that way though.Nahuatl
@rhubarb: If you're looking for other options in implementing templates, you may find this interesting: #3040980Angora
@Nahuatl you stole my name! :-)Swee
S
2

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.

Scarabaeoid answered 19/8, 2010 at 21:18 Comment(3)
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.Angora
@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.Scarabaeoid
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.Angora
Y
2

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

Yi answered 19/8, 2010 at 21:23 Comment(3)
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.Angora
@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.Yi
@litb: Fair enough. Admittedly, I don't use boost a lot, and it escaped my memory that boost uses hpp in this way.Angora
M
1

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

Meliorism answered 19/8, 2010 at 21:17 Comment(2)
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.Angora
@Scarabaeoid How about making your comment constructive by suggesting a better alternative along with your rationale?Coombs
D
1

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.

Digiovanni answered 19/8, 2010 at 21:18 Comment(1)
Separation of interface and implementation is a good idea, but it can be done in one file by putting the interface on the top.Bihari
S
0

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

Suzettesuzi answered 19/8, 2010 at 21:18 Comment(1)
Not true. You only need to #include the .hpp file in the .cpp file somewhere.Snick
P
0

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.

Phosphoresce answered 17/8, 2015 at 18:8 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.