I do have a templated function as well as a specialization thereof in a library that I want to link to another project. Below a minimial example - the specialization of the template works as expected.
lib.h
#include <iostream>
template <typename T>
void f(T t)
{
std::cout << "generic template\n";
}
lib.cpp
#include "lib.h"
template <>
void f(int t)
{
std::cout << "integer specialization\n";
}
int main()
{
double d = 3.0;
int i = 3;
f(d);
f(i);
}
output
generic template
integer specialization
In a next step i compile the library into a shared library (commenting the main function)
g -fPIC -c -o lib.o lib.cpp
g -shared lib.o -o libLIB.so
main.cpp
#include "lib.h"
int main()
{
double d = 3.0;
int i = 3;
f(d);
f(i);
}
compiling main and linking LIB
g -L . main.cpp -lLIB
with lib as a shared library the function specialization does not work as expected, output:
generic template
generic template
I know that simply moving the specialized template into the lib.h file resolves the issue. But I would like to keep the specialization in a seperate .cpp file. Does anyone have an explanation for the described behaviour?
CodePudding user response:
You were almost there.
You have to remove the generic implementation and add the double, like this:
lib.h
template <typename T>
void f(T t);
lib.cpp
#include "lib.h"
#include <iostream>
template <>
void f(int t)
{
std::cout << "integer specialization\n";
}
template <>
void f(double t)
{
std::cout << "double specialization\n";
}
main.cpp
#include "lib.h"
int main()
{
double d = 3.0;
int i = 3;
f(d);
f(i);
}
Compile and run with
$ g -fPIC -shared lib.cpp -o libtest.so
$ g -fPIC main.cpp -L. -l test -o main
$ LD_LIBRARY_PATH=. ./main
double specialization
integer specialization
Alternatively (as you suggested) you can define a generic implementation and let the compiler know that you have a specialization defined elsewhere.
lib.h
#include <iostream>
template <typename T>
void f(T t) {
std::cout << "Generic implementation\n";
}
template<>
void f( double t );
template<>
void f( int t );
lib.cpp
#include "lib.h"
template <>
void f(int t)
{
std::cout << "integer specialization\n";
}
template <>
void f(double t)
{
std::cout << "double specialization\n";
}
main.cpp
#include "lib.h"
int main()
{
double d = 3.0;
int i = 3;
float x = 0;
f(d);
f(i);
f("string");
f(x);
}
Compile and run:
$ g -fPIC -shared lib.cpp -o libtest.so
$ g -fPIC main.cpp -L. -l test -o main
$ LD_LIBRARY_PATH=. ./main
double specialization
integer specialization
Generic implementation
Generic implementation