Undefined reference to member function of template base class

烂漫一生 提交于 2019-12-24 00:52:59

问题


Consider following code:

myclass.h :

template <class T>
struct S {
    void f();
};

struct MyClass : public S<int>
{
    void g();
};

myclass.cpp :

#include "myclass.h"
#include <iostream>

template <class T>
void S<T>::f()
{
    std::cout << "f()\n";
    /* some code here that could not be in header */
}

void MyClass::g()
{
    std::cout << "g()\n";
}

main.cpp :

#include "myclass.h"

int main()
{
    MyClass m;
    m.g();
    m.f(); // problem here
}

I've got linker error:

undefined reference to `S::f()'

Can I solve this issue without transferring implementation of S::f() to header file? Why S::f() not instantiated when I declare a MyClass derived from full specialized template base class?


回答1:


Why S::f() not instantiated when I declare a MyClass derived from full specialized template base class?

Because your myclass.cpp makes no use of that template, and like all unused templates in translation units, they amount to nothing in the produced code. The derivation is all well and good, and if MyClass::g() used S<T>::f() you would pull in that code and life would be good. But you don't, so you have to pull it in another way...

You should be able to do this with explicit instantiation. Note the following addition to your .cpp file:

#include "myclass.h"
#include <iostream>

template <class T>
void S<T>::f()
{
    std::cout << "f()\n";
}

void MyClass::g()
{
    std::cout << "g()\n";
}

template struct S<int>; // ADDED

Be warned, however. This will only work if the only usage is S<int>. Additional expansions would need additional entries of explicit instantiations.

You could also do it with direct specialization, such as changing your .cpp to just do this:

#include "MyClass.h"
#include <iostream>

template <>
void S<int>::f()
{
    std::cout << "f()\n";
}

void MyClass::g()
{
    std::cout << "g()\n";
}

but that would be rather limiting in my mind, as each additional type you add would need its own specialization.

Anyway, best of luck.




回答2:


Adding an explicit instantiation

template
struct S<int>;

to "myclass.cpp" makes the code compile.

Loosely speaking, the derivation from S<int> only "instantiates" the class definition, not the members.
There is no way for the compiler to instantiate f at that point since the definition of f isn't known.

You'll need to provide explicit instantiations for all the types you're using, which somewhat limits the utility of the template.

A popular way of keeping template definitions out of headers is to have them in their own file which is #included at the end of the header.




回答3:


You can't solve this problem without transferring implementation of s::f() function to header file. this is because compiler must know implementation of template before using it.



来源:https://stackoverflow.com/questions/28212558/undefined-reference-to-member-function-of-template-base-class

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!