views:

198

answers:

3

Hi there,

The project in question is about different endpoints communicating with each other. An endpoint sends events (beyond the scope of the current problem) and can process incoming events. Each event is represented in a generic object as follows:

#pragma interface
... // some includes

template<typename T>
class Event
{
   public:
                       Event(int senderId, Type type, T payload); // Type is an enum
                       Event(int senderId, Type type, int priority, T payload);
      virtual          ~Event();
      virtual int      getSenderId();
      virtual int      getPriority();
      virtual T        getPayload();
      void             setPriority(const int priority);

   protected:
      const int        senderId;
      const Type       type;
      const T          payload;
      int              priority;
};

It has its implementing class with #pragma implementation tag.

An endpoint is defined as follows:

#pragma interface
#include "Event.h"

template<typename T>
class AbstractEndPoint
{
   public:
                        AbstractEndPoint(int id);
      virtual           ~AbstractEndPoint();
      virtual int       getId();
      virtual void      processEvent(Event<T> event) = 0;    

   protected:
      const int         id;
};

It has its implementing class too, but only the constructor, destructor and getId() are defined.

The idea is to create concrete endpoints for each different payload type. Therefore I have different payload objects and specific event classes for each type, e.g.

Event<TelegramFormatA>, Event<TelegramFormatB>

and

ConcreteEndPoint for TelegramFormatA, 
ConcreteEndPoint for TelegramFormatB

respectively. The latter classes are defined as

class ConcreteEndPoint : AbstractEndPoint<TelegramFormatA>
{
    ...
}

I'm using g++ 4.4.3 and ld 2.19. Everything compiles nicely, but the linker complaints about undefined references to type-specific event classes, like

Event<TelegramFormatA>::Event(....) .

I tried explicit instantiation using

template class AbstractEndPoint<TelegramFormatA>;

but couldn't get past the aforementioned linker errors.

Any ideas would be appreciated.

+3  A: 

Function templates and member functions of class templates must be implemented in header files, not .cpp files. I suppose you have Event<T>::Event() implemented in a .cpp file?

sbi
A: 

As sbi alread pointed out it is not allowed to seperate interface and implementation of templates in source and header files. Check this link for details (end of page) http://www.cplusplus.com/doc/tutorial/templates/

Holger Kretzschmar
It is allowed to have the implementation in a .cpp file but then it must be #included in the header file so that implementation is visible. It must not be compiled by itself either. When it is organized this way, a different file extension is normally used (usually .inc).
yngvedh
A: 

I've just found the solution. Believe it or not, it links perfectly with v2.20 of the GNU linker (ld) but fails to do so with ld 2.19.

By the way

#pragma interface 

and

#pragma implementation

is a g++-specific workaround addressing the problem of implementing template classes in header files. Using the pragma tags it can be avoided, so it wasn't the problem, but thank you for your suggestions anyway.