35

So, I heard that C++ templates shouldn't be separated into a header (.h) and source (.cpp) files.

For instance, a template like this:

template <class T>
class J
{   
   T something;
};

Is this true? Why is it so?

If because of that I'm gonna have to put both declaration and implementation in the same file, should I put it in a .h file or a .cpp file?

Azeem
  • 11,148
  • 4
  • 27
  • 40
kamikaze_pilot
  • 14,304
  • 35
  • 111
  • 171
  • An answer exists in the C++ FAQ: http://www.parashift.com/c++-faq-lite/templates.html#faq-35.12 – wkl Apr 10 '11 at 15:41

4 Answers4

38

Headers.

It's because templates are instantiated at compile-time, not link-time, and different translation units (roughly equivalent to your .cpp files) only "know about" each other at link-time. Headers tend to be widely "known about" at compile-time because you #include them in any translation unit that needs them.

Read https://isocpp.org/wiki/faq/templates for more.

Ethan T
  • 1,390
  • 12
  • 28
Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
17

The reason you can't put a templated class into a .cpp file is because in order to "compile" a .cpp file you need to know what the type that is being used in place of T. As it stands a templated class (like your class J) doesn't have enough information to compile. Thus it must be all in headers.

If you want the break up the implementation into another file for cleanliness, the best practice is to use an .hxx file. Like this: inside your header file, J.h, put:

#ifndef _J_H__
#define _J_H__

template <class T> class J{  // member definitions };

#include "j.hxx"

#endif // _J_H__

and then, in j.hxx you'll have

template <class T> J<T>::J() { // constructor implementation }

template <class T> J<T>::~J() { // destructor implementation }

template <class T> void J<T>::memberFunc() { // memberFunc implementation }

// etc.

Finally in your .cpp file that uses the templated class, let's call it K.cpp you'll have:

#include "J.h" // note that this always automatically includes J.hxx    
void f(void)
{
     J<double> jinstance;  // now the compiler knows what the exact type is.
}
Chris A.
  • 6,817
  • 2
  • 25
  • 43
  • 2
    I'm not sure about the use of the `.hpp` extension. By convention, in C++ `.h` and `.hpp` are pretty much interchangeable, so you're not imbuing `j.hpp` with a filename that distinguishes it functionally from `J.h`. [The convention here would be `J.hxx`.](http://bytes.com/topic/c/answers/132004-inline-template-file-extensions) – Lightness Races in Orbit Oct 26 '11 at 00:43
  • +1 Good point, and I've always used .hxx in practice too (mostly learning by others' examples), but I never understood why it was correct until now. – Chris A. Oct 26 '11 at 01:13
  • If I may ask, what use is this? In the end, every #including .cpp file is recompiled if the .h *or* .hxx files are modified; and modifying the implementation where it is in .h (not this example; I mean when the whole template is in the .h) should be pretty much identical, mechanically, no? – Noein Mar 30 '15 at 19:39
  • It's identical to the compiler and it's simply a convention that I've seen in practice and that I've liked. In my experience, it's just a matter of breaking up the implementation so that you can have a short .h file with implementations of templated classes in the .hxx file. If you have evidence to the contrary, let me know. – Chris A. Mar 31 '15 at 23:08
  • what .hxx stays for? – Nick Mar 25 '16 at 21:53
  • It's a take on the `.cxx` extension, which is an older way of specifying that it's a C++ source file. However, `.hxx` files are not going to be compiled directly; they will be included during compilation of other files. See [this SO question](http://stackoverflow.com/questions/5171502/c-vs-cc-vs-cpp-vs-hpp-vs-h-vs-cxx) for a list of C++ extensions. – Chris A. Mar 27 '16 at 15:54
4

Yes, it's true. Declaration and implementation are generally put into the header file all together. Some compilers experimented with an export keyword that would allow them to be separated, but that has been removed from C++0x. Check out this FAQ entry for all the dirty details.

jonsca
  • 10,218
  • 26
  • 54
  • 62
2

If you need the template code to be usable by other translation units (.cpp files), you need to put the implementation in the .h file or else those other units won't be able to instantiate the template (expand it according to the types they use).

If your template function is only instantiated in one .cpp file, you can define it there. This happens sometimes when a class has a private member function which is a template (and it is only called from the implementation file, not the class header file).

John Zwinck
  • 239,568
  • 38
  • 324
  • 436