Check this out:
I was wanting a templated class in my library so I can easily change the amount of strings that are supported (following a class model). However, templates are compiled on demand only. Take this example (which we will say compiles into libExample.a):
Header (Example.h):
1 2 3 4 5
|
template <typename T>
class Example
public:
Example( T test );
void setTest( T test );
|
Implementation (Example.cpp):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
|
template <typename T>
class Example
{
public:
Example( T test )
{
_data = test;
}
void setTest(T test)
{
_data = T;
}
private:
T _data;
};
|
When you compile this into a library and try to link to instantiate an "Example" class with a template, you will get an error stating that a symbol with the template signature doesn't exist. The above example indeed does compile but it does not contain the given template instance.
However, we can add specialized template support through explicit template instantiation which will add the symbols needed to link (properly) against the library for use. Take the following revision of the Example.cpp:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
|
template <typename T>
class Example
{
public:
Example( T test )
{
_data = test;
}
void setTest(T test)
{
_data = T;
}
private:
T _data;
};
class template Example<int>;
class template Example<float>;
class template Example<double>;
|
Now, the header still works as long as you use only the allowed types (int, float, double). The following should work as long as you link against libExample.a:
1 2 3 4 5 6 7 8 9 10 11
|
#include "Example.h"
#include <string>
int main()
{
Example<int> example(3);
Example<float> exampletwo(4.f);
example.setTest(6);
//With the given header, the follwing will compile but generate linker errors!
Example<std::string> example("lol");
}
|
Notice the note about linker errors. The proper way to fix that is template specialization so it will generate a compiler error. I was just too lazy to make an example >.>. Also, the only reason to use template specialization inside of the implementation is if the behavior is different for different types otherwise doing so is rather pointless. My inbox is open for feedback!