Hello everyone,
I recently started fiddling with generic programming and want to improve on it.
As I am programming microcontrollers, the size of the created code matters a lot more than usual.
The common way of writing the prototypes in the .h and the implementation into the corresponding .cpp does not work due to the way the linker works.
What I want to achieve is:
- Using template classes split up into two files.
- Minimizing the resulting code size.
Which are good ways to achieve this?
What I found so far:
https://isocpp.org/wiki/faq/templates#templates-defn-vs-decl
http://stackoverflow.com/questions/495021/why-can-templates-only-be-implemented-in-the-header-file
http://stackoverflow.com/questions/115703/storing-c-template-function-definitions-in-a-cpp-file
Several solutions are provided in these sources, but I dont know which would be most efficient. I strongly dislike the explicit instantiation in form of
|
template class GenericClass<int,10>;
|
as I think it defies the generic Concept.
Some of the solutions are used in the following example.
GenericClass.h :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
|
template<typename T1, T1 BUFFER_SIZE >
class GenericClass
{
public:
GenericClass(){}
void pushValue(T1 value) // Implementation 1
{
_buffer[0] = value;
}
T1 getValue();
T1 foo();
~GenericClass(){};
private:
T1 _a, _b;
T1 _buffer[BUFFER_SIZE];
};
// Implementation 2, works and currently my way to go
template<typename T1, T1 BUFFER_SIZE >
T1 GenericClass<T1, BUFFER_SIZE>::getValue()
{
return _buffer[0];
}
|
GenericClass.cpp :
1 2 3 4 5 6 7 8 9
|
#include "GenericClass.h"
// Implementation 3 , leads to Linker Error
// "undefined reference to 'GenericClass<int, 10>::foo()'
template<typename T1, T1 BUFFER_SIZE >
T1 GenericClass<T1, BUFFER_SIZE>::foo()
{
return _buffer[0];
}
|
Including the .cpp at the end of .h leads to "expected initializer before '<' token":
1 2 3 4 5 6 7 8 9 10 11
|
// GenericClass.h
//... like above
#include "GenericClass.cpp"
// GenericClass.cpp
// Implementation 4
template<typename T1, T1 BUFFER_SIZE >
T1 GenericClass<T1, BUFFER_SIZE>::foo()
{
return _buffer[0];
}
|
http://isocpp.org/wiki/faq/templates#separate-template-fn-defn-from-decl
The above mentions using extern to solve linker errors, but has not been updated so far. I dont know how I would use this.
I work with AtmelStudio and the AVR/GNU C++ compiler (C++ 11 Standard, without most libraries). Still I am interested in general answers.
Thanks for your time.