tags:

views:

81

answers:

5

Hello

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?

+5  A: 

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.

Matias Valdenegro
Sorry, I forgot to specify that I use g++ in Linux.
xyzt
@xyzt: This is valid for Linux as well.
Dacav
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
A: 

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
A: 

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
The first consequence is false, the second may be. And all modern linkers manage the (possible) multiple instances with no problems.
anon
@Neil Butterworth: I edited my first point to make it more clear.
Dacav
It is still wrong. Are you talking about C++'s lack of an "export" feature for templates?
anon
A: 

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.

Seth Illgard
+2  A: 

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
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
@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
@Martin York: Interesting point of view, thanks!
Dacav
@Martin York: http://stackoverflow.com/questions/3419265/c-templates-and-object-code-instantiation
Dacav