2

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?

2

3 Answers 3

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.

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you very much. I tried an explicit instantiation, but did so above a implementation of f(). When I move it down - code compiled successfully.
1

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.

Comments

0

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.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.