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!
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.
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.
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? Explanation: Starts with keyword template and then <class VAR>, then use VAR as type anywhere in the function below. 7.
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
}
(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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With