2

I have a template function in a shared library written in C++(the function is not called anywhere in the library, so it shouldn't be generated, am i wrong?) [g++, Linux]

I try to use this template function in the application but compiler gives link error.I searched the function using objdump but I can not see the function in the .so Is there a way to solve this problem?

xyzt
  • 1,201
  • 4
  • 18
  • 44
  • If you've put the template function implementation in a source file then this is just a duplicate of [C++ template, linking error](http://stackoverflow.com/questions/1353973/c-template-linking-error). – Troubadour Aug 05 '10 at 18:08

5 Answers5

7

Template functions belong to library headers, they aren't compiled in the DLL shared library. So, move all template functions into a header, and include that header in your application.

Dr. Snoopy
  • 55,122
  • 7
  • 121
  • 140
  • Sorry, I forgot to specify that I use g++ in Linux. – xyzt Aug 05 '10 at 17:23
  • 2
    @xyzt: This is valid for Linux as well. – Dacav Aug 05 '10 at 17:30
  • 1
    That is one method. Tempaltes themselves are not in the shared library but any instanciation of those templates are in the shared library. There are two types of instanciation. 1) Implicit 2) explicit both will be avbilable when linking against the shared library. – Martin York Aug 05 '10 at 17:48
  • I seem to get all sorts of errors about multiple symbol definitions if I do this – Ben Farmer Jun 01 '18 at 05:49
7

The easiest way is just to move all template code into the header file (as described in other answers)
BUT this is not the only solution.

Template are not actual functions.

A template becomes a function when there is an instanciation of the function. This can be done implicitly or explicitly. Any time the function is used there is an implicit instanciation. But you can also explicitly instanciate the template function.

So you should be able to link against any instanciated version of the template function in your share lib.

Header file so we obey the one definition rule.

// tt.h
template<typename T>
int doStuff(Tconst &t);

Source file:

// tt.cpp
#include "tt.h"
template<typename T>
int doStuff(Tconst &t)
{
    return 4;
}

void plop()
{
    int x = 6;
    // implicit instanciation of doStuff<int>(int const&);
    doStuff(x);
}

// explicit instanciation of template
template int doStuff<float>(float const&);

If I compiled the above into a shared lib.
Then there would be two doStuff() methods that are available.

  • doStuff<int>(int const&) // Implicit instanciation
  • doStuff<float>(float const&) // explit instanciation

g++ -shared -o tt.so tt.cpp

Now if we have a seprate file that we link against the shared lib:

// main.cpp
#include "tt.h"

int main()
{
    doStuff(5);   // doStuff<int>()
    doStuff(6.0f); // doStuff<float>()
}

g++ main.cpp t.so

Compiles fine even though main can not see any of the template code.

Martin York
  • 257,169
  • 86
  • 333
  • 562
  • This solution works, but forces you to do an instantiation for each type you are planning to use. This may be a problem if you are writing a library. – Dacav Aug 05 '10 at 18:02
  • 1
    @Dacav: Not quite. This forces you to instanciate all versions you want to export from the shared library. Which is an advantage as you can control the instanciations that are available. If you want them all availalable then you put it in the header file (as noted on line 1 aboove). – Martin York Aug 05 '10 at 18:12
  • York: http://stackoverflow.com/questions/3419265/c-templates-and-object-code-instantiation – Dacav Aug 05 '10 at 21:23
1

Templates are hard to implement by compiler developers, and thus, most C++ compilers actually require you to put template code in header files, even complete class implementations (there are some exceptions and tricks to avoid this though).

For your case, all you need to do is move your function template to a header file (probably with other function templates) and import that when you need it.

Hope that helps.

Daniel Rodriguez
  • 1,443
  • 12
  • 19
0

The function you want to use needs to be instantiated somewhere, either in your library or in your code. Your compiler should be generating the instantiation for you in your program code unless the prototype was declared extern. It sounds like you want to explicitly instantiate the function in your library. In one of the source files in your library, you can just add a line like:

template return_type function_name(param_type,param_type);

and the code for the function should be explicitly generated.

More on explicit instantiation: http://publib.boulder.ibm.com/infocenter/comphelp/v8v101/index.jsp?topic=/com.ibm.xlcpp8a.doc/language/ref/explicit_instantiation.htm

phooky
  • 288
  • 1
  • 6
0

I found myself in the same situation some time ago, so I investigated on this. Basically templates do not produce any object code, they are simply a definition for the compiler. When you instantiate a object like std::list<Foo> l the compiler will produce both the instance and the specialized code for a list of Foo objects.

This leads to two consequences:

  • It's not possible to write template-classes code into a dedicated .cpp file (like you would do for a normal module), since you don't know in advance which data types you'll need to instanciate;
  • Two .cpp files both using std::list<Foo> as data type will produce a copy of the same executable code.

The second point makes things difficult during linking phase, since the linker is supposed to deal with double definitions. A possible linking strategy would be keeping a copy for each object code. A smarter linker may try to optimize things, but this gives a great complexity.

I guess this is why gcc takes so long to compile C++, while it's far more quick with C.

Dacav
  • 13,590
  • 11
  • 60
  • 87
  • 1
    The first consequence is false, the second may be. And all modern linkers manage the (possible) multiple instances with no problems. –  Aug 05 '10 at 17:45
  • @Neil Butterworth: I edited my first point to make it more clear. – Dacav Aug 05 '10 at 17:59
  • It is still wrong. Are you talking about C++'s lack of an "export" feature for templates? –  Aug 05 '10 at 18:01