0

Reading the following undefined reference to template function I solved my problem, however my template function is actually being called, within the library so it is being implementation I would have thought this should have defined its type in the shared objects, however I keep getting linker errors. Consider...

I have the following files (common.h, common.cpp, myclass.h and myclass.cpp) defined below:

common.h

namespace myn
{
    template<class T> T map(T val1, T val2);
};

common.cpp

#include "common.h"
template<class T> T myn::map(T val1, T val2)
{
    return val1+val2;
}

myclass.h

#include "common.h"
class myclass
{
private:
    int val;
public:
    myclass(int v1, int v2);
};

myclass.cpp

#include "myclass.h"
myclass::myclass(int v1, int v2)
{
    this->val = myn::map<int>(v1, v2);
}

I compile the library using:

g++ -Wall -fPIC -c common.cpp -o common.o
g++ -Wall -fPIC -c myclass.cpp -o myclass.o
g++ -shared -Wl,-soname,libmylib.so -o libmylib.so common.o myclass.o

When given main.cpp:

#include "common.h"
#include "myclass.h"

int main(int argc, char ** argv)
{
    myclass * x = 0;

    if (argc == 1)
        x = new myclass(20, 40);
    else
        x = new myclass(2343, 435);

    delete x;
    return 0;
}

I compile using:

g++ -Wall -L. main.cpp -o main.out -lmylib

I get the following error:

./libmylib.so: undefined reference to `int myn::map<int>(int, int)'
collect2: error: ld returned 1 exit status

Shouldn't the <int> version of the map function be defined? I know that if i try doing something like myn::map<char>('a', 'b'); It should complain as it has not been defined, but surely in my case <int> template is defined.

Community
  • 1
  • 1
Angel.King.47
  • 7,922
  • 14
  • 60
  • 85
  • 1
    Of course, I'm assuming that you got the syntax right in the first place, e.g., that the comma in `common.h` actually sits before the `}` not after it. – Dietmar Kühl Oct 28 '13 at 21:43
  • @Dietmar Kuhl Yes the syntax works, I have a working version, in a tar file must have forgotten something when typing, and I don't believe this is a duplicate. – Angel.King.47 Oct 28 '13 at 21:47
  • @Angel.King47: You are correct, it would be a duplicate if the question had been asked twice. It has been asked *a lot* more than that...! – Dietmar Kühl Oct 28 '13 at 21:56
  • Hang on my quandry is not why the template is complaining, but why is it not being defined as it is explicitly being called in myclass constructor. – Angel.King.47 Oct 28 '13 at 22:01
  • I call `myn::map` explicitly inside the constructor of `myclass` shouldn't this be then defined. – Angel.King.47 Oct 28 '13 at 22:02
  • Correct, I noticed that. Your problem seems to be that you haven't, yet, followed the link to question yours is a duplicate of! Follow the link, read the answer, contemplate. – Dietmar Kühl Oct 28 '13 at 22:02
  • @Angel.King.47 read the linked duplicate. It explains the problem. And you can show evidence that is the case by doing what Dietmar has both described and linked: move the implementation to `myn::map`'s implementation to the header. That will validate he is correct and you can read why if you're really interested (and you *should* be interested). – WhozCraig Oct 28 '13 at 22:04
  • Reading that again and again, I am still lost as to why myn::map call in the myclass construct is not as the link puts it `// explicit instantiations`. I dont argue that my answer is not related to the linked question, but it still does not answer my question (marked in bold at the bottom); or I am confusing my self – Angel.King.47 Oct 28 '13 at 22:11
  • It says on part III of the link "Another solution is to keep the implementation separated, and explicitly instantiate all the template instances you'll need:" My question is, am I not explicitly instantiating the version of the myn::maps function in myclass.cpp – Angel.King.47 Oct 28 '13 at 22:17
  • @Angel.King.47: An explicit template instantiation looks something like this: `template int myn::map(int, int);` in a location where `template T myn::map(T, T)` happens to be defined. The only place this function template is defined is in `common.cpp` which clearly doesn't include an explicit instantiation (well, none of the code contains an explicit instantation; there is a specialization which is probably what you are referring to). – Dietmar Kühl Oct 28 '13 at 22:22
  • Ok so why is the specialization not enough, surely it needs to compile myn::map version somewhere. and so why does it not turn the specialized version to an explicit instantiation. As myclass can be initiated any where and it needs to use myn::map. – Angel.King.47 Oct 28 '13 at 22:31
  • *There is no instantiation of the aforementioned function*. `common.cpp` generates exactly *nothing* in terms of linkable code because the template is not used whatsoever in that translation unit. Templates amount to *nothing* if they're never instantiated in a translation unit, and this is *markedly* different than traditional functions. An explicit instantiation in that .cpp file would solve your problem as well, but why bother? Just move the implementation to the place it belongs: the header file. – WhozCraig Oct 28 '13 at 22:43
  • 1
    Please read the referenced answer again. Specifically pay attention to the following sentence: "Consequently, the compiler needs to have access to the implementation of the methods, to instantiate them with the template argument [...]." – Dietmar Kühl Oct 28 '13 at 22:44

0 Answers0