This post has already been read 1856 times!

http://www.parashift.com/c++-faq/separate-template-class-defn-from-decl.html

Tell your C++ compiler which instantiations to make while it is compiling your template class's .cpp file.

(If you've already read the previous FAQ, this answer is completely symmetric with that one, so you can probably skip this answer.)

As an example, consider the header file Foo.h which contains the following template class. Note that method Foo<T>::f() is inline and methods Foo<T>::g() and Foo<T>::h() are not.

// File "Foo.h"
template<typename T>
class Foo {
public:
  void f();
  void g();
  void h();
};

template<typename T>
inline
void Foo<T>::f()
{
  ...
}

Now suppose file Foo.cpp actually defines the non-inline methods Foo<T>::g() and Foo<T>::h():

// File "Foo.cpp"
#include <iostream>
#include "Foo.h"

template<typename T>
void Foo<T>::g()
{
  std::cout << "Foo<T>::g()\n";
}

template<typename T>
void Foo<T>::h()
{
  std::cout << "Foo<T>::h()\n";
}

Suppose file main.cpp uses this template class by creating a Foo<int> and calling its methods:
// File "main.cpp"
#include "Foo.h"

int main()
{
  Foo<int> x;
  x.f();
  x.g();
  x.h();
  ...
}

If you compile and (try to) link these two .cpp files, most compilers will generate linker errors. There are two solutions for this. The first solution is to physically move the definition of the template functions into the .h file, even if they are not inline functions. This solution may (or may not!) cause significant code bloat, meaning your executable size may increase dramatically (or, if your compiler is smart enough, may not; try it and see).

The other solution is to leave the definition of the template function in the .cpp file and simply add the line template class Foo<int>; to that file:

// File "Foo.cpp"
#include <iostream>
#include "Foo.h"

...definition of Foo<T>::f() is unchanged -- see above...
...definition of Foo<T>::g() is unchanged -- see above...

template class Foo<int>;

If you can't modify Foo.cpp, simply create a new .cpp file such as Foo-impl.cpp as follows:

// File "Foo-impl.cpp"
#include "Foo.cpp"

template class Foo<int>;
Notice that Foo-impl.cpp #includes a .cpp file, not a .h file. If that's confusing, click your heels twice, think of Kansas, and repeat after me, "I will do it anyway even though it's confusing." You can trust me on this one. But if you don't trust me or are simply curious, the rationale is given earlier.

If you are using Comeau C++, you probably want to learn about the export keyword.


Comments are closed.

Post Navigation