views:

39

answers:

1

I'm getting the following linker errors:

Error   1   error LNK2001: unresolved external symbol "public: __thiscall AguiEvent<class AguiEmptyEventArgs>::AguiEvent<class AguiEmptyEventArgs>(void)" (??0?$AguiEvent@VAguiEmptyEventArgs@@@@QAE@XZ)    AguiWidgetBase.obj
Error   2   error LNK2001: unresolved external symbol "public: void __thiscall AguiEvent<class AguiEmptyEventArgs>::call(class AguiEmptyEventArgs)" (?call@?$AguiEvent@VAguiEmptyEventArgs@@@@QAEXVAguiEmptyEventArgs@@@Z)  AguiWidgetBase.obj
Error   3   error LNK2001: unresolved external symbol "public: __thiscall AguiEvent<class AguiControlEventArgs>::AguiEvent<class AguiControlEventArgs>(void)" (??0?$AguiEvent@VAguiControlEventArgs@@@@QAE@XZ)  AguiWidgetBase.obj
Error   4   error LNK2001: unresolved external symbol "public: void __thiscall AguiEvent<class AguiControlEventArgs>::call(class AguiControlEventArgs)" (?call@?$AguiEvent@VAguiControlEventArgs@@@@QAEXVAguiControlEventArgs@@@Z)  AguiWidgetBase.obj
Error   5   fatal error LNK1120: 4 unresolved externals C:\Users\Josh\Documents\Visual Studio 2008\Projects\Agui\STATIC Release\Agui.exe

I have AguiEventArgs.h which has this:

class AguiWidgetBase;

class AguiEmptyEventArgs {
public:
    AguiEmptyEventArgs();
};

class AguiMouseEventArgs {
    AguiPoint position;
    int mouseWheelChange;
    AguiMouseButtonEnum button;
public:
    AguiPoint getPosition() const;
    int getMouseWheelChange() const;
    AguiMouseButtonEnum getButton() const;
    int getX() const;
    int getY() const;
    AguiMouseEventArgs();
    AguiMouseEventArgs(const AguiPoint &position,
        int mouseWheelChange, AguiMouseButtonEnum button);
};

class AguiKeyEventArgs {
    AguiKeyEnum key;
    AguiKeyModifierEnum modKey;
    bool isAlt;
    bool isControl;
    bool isShift;
public:
    bool getAlt() const;
    bool getControl() const;
    bool getShift() const;
    AguiKeyEnum getKey() const;
    AguiKeyModifierEnum getModifierKeyFlags() const;
    AguiKeyEventArgs();
    AguiKeyEventArgs(AguiKeyEnum key, AguiKeyModifierEnum modKey);
};

class AguiControlEventArgs {
    AguiWidgetBase* control;
public:
    AguiWidgetBase* getControl() const;
    AguiControlEventArgs();
    AguiControlEventArgs(AguiWidgetBase* control);
};

I have double checked and defined all of these.

My Agui event is here:

template <typename T>
class AguiEvent {
void (*onEvent)(T arg);
public:
void setHandler(void (*eventProc)(T arg));
void removeHandler();
void call(T arg);
AguiEvent();
};

its defined:

template <typename T>
void AguiEvent<T>::setHandler( void (*eventProc)(T arg) )
{
    onEvent = eventProc;
}


template <typename T>
void AguiEvent<T>::removeHandler()
{
    onEvent = 0;
}


template <typename T>
void AguiEvent<T>::call(T arg)
{
    if(onEvent)
        onEvent(arg);
}

template <typename T>
AguiEvent<T>::AguiEvent()
{
    onEvent = 0;
}

it is used like this:

 AguiEvent<AguiEmptyEventArgs> eventThemeChanged;
    AguiEvent<AguiControlEventArgs> eventChildControlAdded;
    AguiEvent<AguiControlEventArgs> eventChildControlRemoved;

ex:

void AguiWidgetBase::addChildControl( AguiWidgetBase *control )
{
    onAddChildControl(control);
    eventChildControlAdded.call(AguiControlEventArgs(control));

}

Thanks

+4  A: 

You need to define templated class functions in your header file, you cannot put them in a separate .cpp file (don't even think about using the poorly supported export keyword to do that).

The reason for this is because the compiler needs the source code for the template every time it's instantiated: it has to generate separate code for each template instantiation. The linker is smart enough to make sure that only one copy of each instantiation gets used in the final executable, even if the same template gets instantiated multiple times across different translation units.

Adam Rosenfield
Oh okay thanks.
Milo
@Adam: export is not non-standard, at least for today. Agree with everything else though
Armen Tsirunyan
just took it out of the cpp and it worked
Milo
@Armen: Oops, you're right; I changed the wording a little bit to reflect that.
Adam Rosenfield