-1

I've defined a public template function in a class called EventDispatcher:

public:
    template <class className> void AddEventListener ( className* );

The function implements like this:

template <class className>
void EventDispatcher::AddEventListener ( className* ptr )
{

};

Then in some class I create an insatnce of Timer which is a child EventDispatcher and call AddEventListener:

timer->AddEventListener ( this );

After what I'm getting an error

/tmp/ccjRF7sK.o: In function `AirHockeyServer::AirHockeyServer()':
AirHockeyServer.cpp:(.text+0xa5): undefined reference to `void EventDispatcher::AddEventListener<AirHockeyServer>(AirHockeyServer*)'
/tmp/ccjRF7sK.o: In function `AirHockeyServer::AirHockeyServer()':
AirHockeyServer.cpp:(.text+0x187): undefined reference to `void EventDispatcher::AddEventListener<AirHockeyServer>(AirHockeyServer*)'
collect2: ld returned 1 exit status
Cœur
  • 37,241
  • 25
  • 195
  • 267
Kolyunya
  • 5,973
  • 7
  • 46
  • 81
  • 2
    Does your function have an implementation? – Lubo Antonov Aug 27 '12 at 10:57
  • Sure, it does implements. Updated – Kolyunya Aug 27 '12 at 10:59
  • @Kolyunya: Could you add in which files the declaration and the implementation live? I assume the second is in some `.cpp` file. – bitmask Aug 27 '12 at 11:01
  • @Kolyunya: Is that definition in a souce file? If so, you'll need to [move it into a header](http://stackoverflow.com/questions/495021). – Mike Seymour Aug 27 '12 at 11:01
  • 1
    possible duplicate of [Why can templates only be implemented in the header file?](http://stackoverflow.com/questions/495021/why-can-templates-only-be-implemented-in-the-header-file) – Mike Seymour Aug 27 '12 at 11:08
  • possible duplicate of ["Undefined reference to" template class constructor](http://stackoverflow.com/questions/8752837/undefined-reference-to-template-class-constructor) – Aaron McDaid Aug 27 '12 at 11:40

6 Answers6

4

You say you've defined the function, but you've only shown us a declaration. You'll also need a definition:

template <class className> void AirHockeyServer::AddEventListener ( className* )
{
    // code goes here
}

NOTE The question has now been updated to show that there is a definition somewhere.

Since it's a template, this needs to go in a header, included from every source file that uses the function. Templates are instantiated at the point of use, and their full definition is needed to instantiate them.

Equivalently, you could define it inside the class definition:

public:
    template <class className> void AddEventListener ( className* )
    {
        // code goes here
    }
Mike Seymour
  • 249,747
  • 28
  • 448
  • 644
1

This is a linker error that tells you that the linker does not see the implementation of the AddEventListener member function. With templates it is common to put the implementation of functions in the header file, so they can be instantiated for any template parameter argument.

bitmask
  • 32,434
  • 14
  • 99
  • 159
1

The linker cannot find an implementation for template<class className> AddEventListener<className*>. For templates the implementation has to be in the same file as the declaration.

bjoernz
  • 3,852
  • 18
  • 30
1

when you have templates, you can't really split the classes up in separate header and source files. You need to put the definitions in the header file as well.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
1

The template functions needs to be instantiated for a specific type. Putting the implementation in a .cpp file will not do that.

The easiest way is to place it in the class definition itself, or right after it in the header file.

Another way is to keep it in a .cpp file and then do an explicit instantiation for the type that you need:

template void EventDispatcher::AddEventListener(AirHockeyServer*);
Lubo Antonov
  • 2,301
  • 14
  • 18
0

(This question is a duplicate of "Undefined reference to" template class constructor ) and the answers there are sufficient.

To summarize, there are two ways to solve this:

  • As @LuboAntonov has said, you could place template void EventDispatcher::AddEventListener(AirHockeyServer*); after the definition of the function template.
  • Move the implementation into the header, as described by many others.

See the other question for full details.

Community
  • 1
  • 1
Aaron McDaid
  • 26,501
  • 9
  • 66
  • 88