2

Possible Duplicate:
C++ template, linking error

I have two linking errors and I have no idea what's wrong with the code and how to fix them:

main.obj:-1: error: LNK2019: unresolved external symbol "public: __thiscall A::A(void)" (??0?$A@VB@@@@QAE@XZ) referenced in function "public: __thiscall B::B(void)" (??0B@@QAE@XZ)

and

main.obj:-1: error: LNK2019: unresolved external symbol "public: void __thiscall A::exec(void (__thiscall B::*)(void))" (?exec@?$A@VB@@@@QAEXP8B@@AEXXZ@Z) referenced in function "public: void __thiscall B::run(void)" (?run@B@@QAEXXZ)

Explaining the code a little: This class has to execute a function from the derived class. function exec is called from the derived class with a function from the derived class parameter. Signature of this function is void function();

//header.h

#ifndef HEADER_H
#define HEADER_H

template <class T>
class A
{
public:
    typedef void (T::*ExtFunc)();

    A();
    void funcA();
    void exec(ExtFunc func);
};

#endif // HEADER_H

//header.cpp

#include "header.h"

template<typename T>
A<T>::A() { }

template<typename T>
void A<T>::funcA()
{
    cout << "testA\n";
}

template<typename T>
void A<T>::exec(ExtFunc func)
{
    (T().*func)();
}

In main.cpp I derive a class from A class and pass the derived class as template paramtere. Then I execute function exec through the run() function. //main.cpp

#include <iostream>
#include "header.h"
using namespace std;

class B : public A<B>
{
public:
    B() { }

    void run()
    {
        exec(&B::funcB);
    }

    void funcB()
    {
        cout << "testB\n";
    }
};

int main()
{
    B ob;
    ob.run();

    return 0;
}

Can anyone tell me what's going on?...

Community
  • 1
  • 1
Jacob Krieg
  • 2,834
  • 15
  • 68
  • 140

1 Answers1

2

When you are using templates, generally you cannot put the implementation in a .cpp file - you have to put the whole class in the header. So move all the code from header.cpp to the .h.

You can get around this by doing an explicit instantiation inside the .cpp file - instantiating the template for a particular type. But this requires that you know ahead of time which types will need an instantiation and will prevent you from adding new instantiations. The only benefit is a reduction in compile time.

Lubo Antonov
  • 2,301
  • 14
  • 18
  • Another possible `hack` is to _include the source file in the header file_. – Hindol Sep 03 '12 at 07:12
  • thank you for the answer. I did some search on the web to see what could be wrong with the code before and I found what you just said. But on the cplusplus.com forum I found a guy that says that this _is_ possible. Problem is I didn't figure out how to do it from what he commented. http://www.cplusplus.com/forum/general/14162/#msg69074 It's the first comment of `guestgulkan (2668)` – Jacob Krieg Sep 03 '12 at 07:16
  • @JohnSmith, that was the reason for my carefully qualified answer :). If you instantiate the template explicitly inside the .cpp file, it will actually create the type, so it will become available to the linker. But the main reason to do that is to reduce compile time, so in most cases you should simply keep the implementation in the header. – Lubo Antonov Sep 03 '12 at 07:22
  • And if I really want to put compiletime on the second place for the sake of organizing things better, isn't it any possibility to do so? I've seen template classes declared separated like this (header/source) and they worked fine. I didn't figure out what was special about them if they didn't report any error. – Jacob Krieg Sep 03 '12 at 07:33
  • @JohnSmith, as Hindol pointed out, you can also split them up, as long as you treat the "source" file as a header. In fact, in cases of libraries that do that, they specifically use a different extension for these files to indicate that they are not .cpp files. – Lubo Antonov Sep 03 '12 at 07:39