1

What I am trying to do:

Make some sort of "Registry" for my class so that every instance can be looked up using a unique string (i am checking if its unique or not but its omitted in the examples below).

My Problem:

I cant declare a reference to my static member. I dont know why.

Code (with parts omitted)

//component.h
template <class t>
class ComponentTable : InstanceCounted<ComponentTable<t>> //Instance Counted is a template that automatically counts the instances
{
private:
    //Omitted
    static std::unordered_map<std::string, ComponentTable*> componentRegistry;
public:
    //Omitted, the insert happens in the constructor and it gets removed in the destructor
}
//component.cpp
template<class t>
std::unordered_map<std::string, ComponentTable<t>*> ComponentTable<t>::componentRegistry;
//---

What I have already tried

  • Changing ComponentTable* to ComponentTable<t>* in the header
  • Checking the spelling in the header and cpp file.
  • Rebuilding the project

I really got no lead on this one so I kinda couldnt try much :(

The Error:

undefined reference to `ComponentTable<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::componentRegistry'|

This appears where I am trying to first use the member, which is in the constructor. I am doing the insert using the insert function with a simple std::pair of a correct type.

Other Data:

  • Made using CodeBlocks and compiled using MinGW under the c++14 mode.

I hope this info is enough to help me out here ;)

MoustacheSpy
  • 743
  • 1
  • 6
  • 27
  • You use `ComponentTable*` as the data in your `componentRegistry` map. But `ComponentTable` is not a type, it's a *template*. You can only get a type from `ComponentTable` by passing a template argument, like in `ComponentTable`. – Some programmer dude Feb 16 '18 at 09:29
  • @Someprogrammerdude As you can see in the "what I have tried" section I have already tried changing it to ComponentTable with the same result – MoustacheSpy Feb 16 '18 at 09:30
  • 4
    As for your error, it probably stems from the same reason behind this question: [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) – Some programmer dude Feb 16 '18 at 09:31
  • @Someprogrammerdude Isnt that only viable if I didnt already put all my code in my header? I didnt put any function definitions in the cpp file so that post doesnt propose a solution that will work? I get that the root might be the same (that the compiler cant instantiate properly) but I cant see how I can apply that solution to my problem? – MoustacheSpy Feb 16 '18 at 09:36

1 Answers1

1

Since you're dealing with templates, you should define the static member in the header itself:

//component.h
template <class t>
class ComponentTable : InstanceCounted<ComponentTable<t>>
{
    static std::unordered_map<std::string, ComponentTable*> componentRegistry;
};

template<class t>
std::unordered_map<std::string, ComponentTable<t>*> ComponentTable<t>::componentRegistry;

This is the simplest way to ensure a componentRegistry is instanciated for each ComponentTable<t>.

YSC
  • 38,212
  • 9
  • 96
  • 149