-1

I keep receiving linker errors when I do this:

//function declaration
template<typename T>
T * EntityManager::GetComponent(EID _entity, CType _type)

//Main.cpp
Position * pos = GetComponent<Position>(eid, POSITION);

Error LNK2019 unresolved external symbol "public: struct Position * __thiscall EntityManager::GetComponent(unsigned int,enum CType)" (??$GetComponent@UPosition@@@EntityManager@@QAEPAUPosition@@IW4CType@@@Z) referenced in function _main

I believe the error resides in "struct Position * GetComponent(...)" I don't want it to return a "struct Position pointer" I want it to return a "Position pointer!" I've tried various template prefaces such as "class" and "struct"

I would like for this to be possible as it is much more concise than

Position * pos = static_cast<Position *>(GetComponent(eid, POSITION));

(which does work)

Thanks for any help!

EDIT: Here is the full source to prove that its not the function, but something to do with the template...

//EntityManager.h
template<typename T>
T * GetComponent(EID _entity, CType _type);

//EntityManager.cpp
template<typename T>
T * EntityManager::GetComponent(EID _entity, CType _type)
{
    T * component = nullptr;
    int index = GetComponentIndex(_entity, _type);

    if (index >= 0)
        component = m_entities.find(_entity)->second[index];

    return component;
}

//Main.cpp
EntityManager EM;
Position * pos = EM.GetComponent<Position>(eid, POSITION);

struct Position inherits from struct Component

As I said, the function works flawlessly if I remove the template and replace "T" with "Component" then static_cast the return value. I want to avoid having to use the static cast

EDIT EDIT...

This compiles:

//EntityManager.h
class EntityManager
{
public:
    Component * GetComponent();
};

//EntityManager.cpp
Component * EntityManager::GetComponent()
{
 return new Position;
}

//Main.cpp
EntityManager EM;
Position * pos = static_cast<Position *>(EM.GetComponent());

This does not:

//EntityManager.h
class EntityManager
{
public:
    template<typename T>
    T * GetComponent();
};

//EntityManager.cpp
template<typename T>
T * EntityManager::GetComponent()
{
 return new T;
}

//Main.cpp
EntityManager EM;
Position * pos = EM.GetComponent<Position>();

WHY? All I'm asking is what format the template should be in.

(Yes, I tested this simplified example, please don't nitpick syntax)

Garrett Fleischer
  • 177
  • 1
  • 3
  • 13
  • 2
    It seems to me that this isn't due to the return type but due to it not finding the body of the template in the correct place. Where are you defining the body? It needs to be somewhere that can be seen where it is used, usually in a header file – jcoder Oct 06 '15 at 07:06
  • 1
    What is `EntityManager`? Is it a class or a namespace? Why doesn't it figure in your `main` call? – Roger Rowland Oct 06 '15 at 07:07
  • 2
    Have you defined the function? In the header file? – Emil Laine Oct 06 '15 at 07:54
  • Yes, it is defined in EntityManager.h. I merely simplified everything for the question. The only thing I changed is adding "template" above the function in the .h and .cpp files. And I replaced "Component" with "T" – Garrett Fleischer Oct 06 '15 at 15:02
  • I updated the question with the full source code – Garrett Fleischer Oct 06 '15 at 15:10
  • But your first snippet seems to be calling a free function GetComponent, not a member of EntityManager. Similarly your declaration in EntityManager.h appears to be a free function... you need to make an SSCCE (short, self-contained, correct (compilable) example). – user673679 Oct 06 '15 at 15:28
  • @user673679 The first snippet was a simplified example for clarity of the problem. Could we forget semantics for a minute, and focus on the question? – Garrett Fleischer Oct 06 '15 at 22:39
  • 1
    When you "simplify" the example, don't remove the fault or add complications. That's your responsibility not ours. Semantics are precisely what we should be focusing on here, if you want us to correct your program for you. – Lightness Races in Orbit Oct 06 '15 at 22:54
  • `//EntityManager.cpp` http://stackoverflow.com/q/495021/560648 Unfortunately I already wasted my closevote so I cannot dupevote. – Lightness Races in Orbit Oct 06 '15 at 22:56
  • You should clarify where you have put the definition and declaration of `struct Position`. – Keith Oct 06 '15 at 22:57

1 Answers1

1

You can't separate declaration and definition in classes which uses generic templates, as you do with non generic classes.

Try to move all your EntityManager.cpp to EntityManager.h.

lilezek
  • 6,976
  • 1
  • 27
  • 45