I am getting errors trying to compile a C++ template class which is split between a .hpp
and .cpp
file:
$ g++ -c -o main.o main.cpp
Another possibility is to do something like:
#ifndef _STACK_HPP
#define _STACK_HPP
template <typename Type>
class stack {
public:
stack();
~stack();
};
#include "stack.cpp" // Note the include. The inclusion
// of stack.h in stack.cpp must be
// removed to avoid a circular include.
#endif
I dislike this suggestion as a matter of style, but it may suit you.
If you know what types your stack will be used with, you can instantiate them expicitly in the cpp file, and keep all relevant code there.
It is also possible to export these across DLLs (!) but it's pretty tricky to get the syntax right (MS-specific combinations of __declspec(dllexport) and the export keyword).
We've used that in a math/geom lib that templated double/float, but had quite a lot of code. (I googled around for it at the time, don't have that code today though.)
The 'export' keyword is the way to separate out template implementation from template declaration. This was introduced in C++ standard without an existing implementation. In due course only a couple of compilers actually implemented it. Read in depth information at Inform IT article on export
You can do it in this way
// xyz.h
#ifndef _XYZ_
#define _XYZ_
template <typename XYZTYPE>
class XYZ {
//Class members declaration
};
#include "xyz.cpp"
#endif
//xyz.cpp
#ifdef _XYZ_
//Class definition goes here
#endif
This has been discussed in Daniweb
Also in FAQ but using C++ export keyword.
It is not possible to write the implementation of a template class in a separate cpp file and compile. All the ways to do so, if anyone claims, are workarounds to mimic the usage of separate cpp file but practically if you intend to write a template class library and distribute it with header and lib files to hide the implementation, it is simply not possible.
To know why, let us look at the compilation process. The header files are never compiled. They are only preprocessed. The preprocessed code is then clubbed with the cpp file which is actually compiled. Now if the compiler has to generate the appropriate memory layout for the object it needs to know the data type of the template class.
Actually it must be understood that template class is not a class at all but a template for a class the declaration and definition of which is generated by the compiler at compile time after getting the information of the data type from the argument. As long as the memory layout cannot be created, the instructions for the method definition cannot be generated. Remember the first argument of the class method is the 'this' operator. All class methods are converted into individual methods with name mangling and the first parameter as the object which it operates on. The 'this' argument is which actually tells about size of the object which incase of template class is unavailable for the compiler unless the user instantiates the object with a valid type argument. In this case if you put the method definitions in a separate cpp file and try to compile it the object file itself will not be generated with the class information. The compilation will not fail, it would generate the object file but it won't generate any code for the template class in the object file. This is the reason why the linker is unable to find the symbols in the object files and the build fails.
Now what is the alternative to hide important implementation details? As we all know the main objective behind separating interface from implementation is hiding implementation details in binary form. This is where you must separate the data structures and algorithms. Your template classes must represent only data structures not the algorithms. This enables you to hide more valuable implementation details in separate non-templatized class libraries, the classes inside which would work on the template classes or just use them to hold data. The template class would actually contain less code to assign, get and set data. Rest of the work would be done by the algorithm classes.
I hope this discussion would be helpful.
It is possible, as long as you know what instantiations you are going to need.
Add the following code at the end of stack.cpp and it'll work :
template class stack<int>;
All non-template methods of stack will be instantiated, and linking step will work fine.