Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Do template class member function implementations always have to go in the header file in C++? [duplicate]

Tags:

c++

templates

Normally when I create a class, I create a header and a source for that class. I have heard that with a template class, you have to put the function implementation in the header. I tried doing it both ways, and got compilation errors the first way. The second way worked fine. However, I like to organize my code into headers and source files, so is it possible to put the function implementations into a source file? (Maybe it requires special compilation flags or syntax?) Or should I just keep em in the header?

Thanks!

like image 968
cat pants Avatar asked Dec 28 '11 23:12

cat pants


People also ask

Do templates have to be in header files?

To have all the information available, current compilers tend to require that a template must be fully defined whenever it is used. That includes all of its member functions and all template functions called from those. Consequently, template writers tend to place template definition in header files.

Can you put implementation in header file?

Location of ImplementationA function is moved to the appropriate header file and the inline implementation replaces an existing declaration. If a declaration does not exist, the move occurs anyhow; hence, you can use the refactoring to create inline functions from usage.

How are function templates implemented?

Defining a Function TemplateA function template starts with the keyword template followed by template parameter(s) inside <> which is followed by the function definition. In the above code, T is a template argument that accepts different data types ( int , float , etc.), and typename is a keyword.

What is the correct syntax of defining function template template functions?

What is the correct syntax of defining function template/template functions? Explanation: Starts with keyword template and then <class VAR>, then use VAR as type anywhere in the function below. 7.


2 Answers

Generally, all template code must be in a header file since the compiler needs to know the complete type at the point of instantiation.

As Aaron says below it is possible to put the implementation details in a .cpp-file in the specific case where you know on before hand all possible types the template will be instantiated with and explicitly instantiate it with those types. You'll then get a linker error if the template gets instantiated with another type somewhere in your code.

A quite common general solution to at least visually separate interface from implementation is to put all implementation in a .inc (or .tcc or .ipp)-file and include it at the end of the header file.

Note that the syntax for putting template class members outside the class-definition (whether you use the specific solution or the general) is slightly cumbersome. You'll need to write:

// in test.h
template <class A>
class Test
{
public:
  void testFunction();
};

#include "test.inc"

// in test.inc    
template <class A>
void Test<A>::testFunction()
{
  // do something
}
like image 70
Andreas Magnusson Avatar answered Sep 28 '22 08:09

Andreas Magnusson


(Edited: This is slightly more robust version which allows the implementation to be compiled into a separate .o file. The template should be explicitly instantiated at the end of the implementation cpp file. Perhaps this was only an issue for g++.)

You don't need to put the implementations in the header if you know which templates will be instantiated and can list them in the header implementation file. For example, if you know that you will only use int and std::string, then you can put this in the header file:

// test.h
template <class A>
class Test
{
public:
  void f();
};

and put the implementation of f() into a normal test.cpp file:

// test.cpp
#include "test.h"
template <class A> void Test<A>::f() {
   // implementation
}
template class Test<int>;
template class Test<string>;

Those last two lines explicitly instantiate the template classes. It is better to put this at the end of the implementation file, after it has seen the implementations of the member functions. Then you can compile it to a .o file g++ -c test.cpp. This test.o file will contain complete implementations of both Test<int> and Test<string> and can be linked without any difficulty in the rest of your application.

It works, but is it a good idea? It depends on context. In many cases, this works very well. If you are writing a template for 'internal' use in your project, then you know which templates will be instantiated and which will not. But if instead you're making something available to the public which must be very flexible, then you will need to include the implementations in the header file.

A tip: Even if it's for public consumption, take a look at the methods and see if there are any methods whose parameters and return type are independent of the template parameters. If so, you could place them into a Base class as (pure) virtual functions. This Base class doesn't use any templates and hence you may be able to use this Base* in much of your application (template <class A> class Test : public Base { ..., allowing you to limit the reach of the templated code throughout your application. I found this useful recently when much of the underlying behaviour and construction of a class depended on the template parameters, but the interface to the already-constructed object did not depend on the template parameters.

like image 28
Aaron McDaid Avatar answered Sep 28 '22 06:09

Aaron McDaid