C++ templates declare in .h, define in .hpp
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).
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
}
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.
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).
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).
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.
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).
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.
精彩评论