tags:

views:

529

answers:

5

It used to be that to use a template class in C++, the implementations had to be in the header file or #included into the header file at the bottom.

I've not used C++ templates for a few years; I just started using them again and observed that this behavior seems to persist. Is this still the case? Or are the compilers smart enough now to have the implementation separate from the interface?

+2  A: 

To separate the implementation from the declaration the standard forces you to use the export keyword. As far as I know there's only one compiler that knows how to handle it: Comeau.

However, C++0x will include a mechanism that tells the compiler not to instantiate certain specializations automatically (extern templates). So, if you want to cut compilation time you will be able to do so by explicitly instantiating some specializations in one compilation unit and declaring them in the header as extern.

sellibitze
+2  A: 

You are referring to exported templates (using the export keyword), which seem to be supported only by Comeau C++ (according to this section of the C++ FAQ Lite).

A common technique to keep the interface devoid of implementation code is to put the inline function definitions into a separate "implementation" header that can be included at the end of the declaration header.

Carl Seleborg
To be honest, I'm not per se looking for export. I was just looking for the header not to have to include the template implementations inside of it(like other language features?).
Paul Nathan
+1  A: 

Export is only support by the EDG frontend, comercially only available in the Comeau compiler as far as I know.

Export doesn't eliminate the need for source disclosure, nor does it reduce compile dependencies, while it requires a massive effort from compiler builders.

So Herb Sutter himself asked compiler builders to 'forget about' export. As the time investment needed would be better spend elsewhere... so I don't think export will ever be implemented by other compilers after they saw how long it took, and how little was gained.

The paper is called "Why we can't afford export", it's listed on Sutters blog but no pdf there (a quick google should turn it up though), it's six years old now, I suppose they all listened and never bothered :)

Many people use two header files (e.g. .hpp and .ipp), one with only the declaration, and one with the definitions, then it's simply a matter of including one in the other.

foo.hpp

#ifndef MY_TEMPLATES_HPP
#define MY_TEMPLATES_HPP

template< class T >
void foo(T & t);

#include "foo.ipp"
#endif

foo.ipp

#ifdef MY_TEMPLATES_IPP
  nonsense here, that will generate compiler error
#else
#define MY_TEMPLATES_IPP

template< class T >
void foo(T & t) {
   ... // long function
}

#endif

This only gains some clarity of course, nothing really changes compared to simply inlining everything in one header file.

Pieter
Found the pdf you refer to: http://ra.dkuug.dk/jtc1/sc22/wg21/docs/papers/2003/n1426.pdf, dated of March 2003
Matthieu M.
+2  A: 

Technically they do not need to be in the header file.

An example of this usage is when you have a template class with a fixed set of versions (lets say for arguments sake char and wchar_t). Then you can put all the method delcarations into a source file and explicitly instanciate these two versions. This has the safety that others can not istanciate the template for types it was not meant to be used for.

// X.h
template<typename T>
class X
{
     // DECLARATION ONLY OF STUFF
     public:
       X(T const& t);
     private:
       T m_t;
};

// X.cpp
#include "X.h"

// DEFINTION OF STUFF
template<typename T>
X<T>::X(T const& t)
    :m_t(t)
{}

// INSTANCIATE The versions you want.
template class X<char>;
template class X<wchar_t>;


// Main.cpp
#include "X.h"

int main()
{
    X<chat>    x1('a');
    X<wchar_t> x2(L'A');
    // X<int>     x3(5);   // Uncomment for a linker failure.
}

Assuming people can't just directly include X.cpp (because it is not provided by the distribution) then others can not use X<int> or X<float> etc. But the abovr classes are fully defined.

I have also seen this technique used to reduce compilatio time. Because each compilation unit is not re-generating the same version of X we only get the defintion in one place (thus one compilation cost). The downsize to this is that you must manually instanciate each seprate version of X that you use.

Martin York
This is pretty spiffy, although it doesn't do what I need. I'll remember it, though.
Paul Nathan
A: 

GCC goes through a lengthy collect stage unless you explicitly instantiate all templates. VC++ seems to cope, but I prefer to avoid this step anyway and in cases where I know how template is going to be used, which is usually the case for applications, not so much for libraries, I put template definitions into a separate file. This also makes code more readable by making declarations less cluttered with implementation details.

Andre