Home > OS >  C template specialization in shared library - call to specialized function does not work
C template specialization in shared library - call to specialized function does not work

Time:01-20

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
  • Related