I'm trying to implement the CRTP pattern and, while awfully close, can't quite make it work. My use case is that I need to define a bunch of classes to perform lookups in order to validate values. All of these classes do essentially the same thing and differ only in the files from which they build their lookup values. For a given class type, I want to store the lookup info in a static std::set member (since some of these lookup sets are quite large) that is shared amongst all instances of that type. Research on stackoverflow led me to the CRTP pattern as a way to get "static polymorphism" which is exactly what I need.
In the example below, I have a base lookup class (which itself derives from another class, "CDE"). I then define a child class, ICD9, which should build its set values from the file "icd-9.txt." I breadboarded this concept in a simpler file and it works beautifully.
The problem is that, when compiling, I'm getting an unresolved symbol error during linking. Something, I think, having to do with the constructor. I've tried every permutation I can think of on the ICD9 constructor and can't seem to figure it out. Part of the difference between this and my prototype case is that I am now splitting into header and implementation files, and I suspect I'm getting tripped up on syntax.
Please note that I stripped a lot of extra info from these classes for readability; I think what remains is a legit representation of what's going on.
Any help would be greatly appreciated. Thanks.
The linker error:
Error 1 error LNK2019: unresolved external symbol "public: __thiscall LookupCDE<class ICD9>::LookupCDE<class ICD9>(void)" (??0?$LookupCDE@VICD9@@@@QAE@XZ) referenced in function "public: __thiscall ICD9::ICD9(void)" (??0ICD9@@QAE@XZ)
LookupCDE.h:
#include <set>
#include "CDE.h"
template <class T>
class LookupCDE : public CDE
{
typedef std::set<string> lookup;
public:
LookupCDE();
protected:
static const char* filepath;
static lookup data;
string value;
bool m1(char* s);
int f1();
};
LookupCDE.cpp
#include <fstream>
#include "LookupCDE.h"
template<class T>
LookupCDE<T>::LookupCDE()
{
ifstream file(filepath);
while (getline(file, line))
data.emplace(line);
file.close();
}
template<class T>
bool LookupCDE<T>::m1(char* s)
{
return data.count() > 0;
}
ICD9.h
#include "LookupCDE.h"
class ICD9 : public LookupCDE<ICD9>
{
public:
ICD9();
};
ICD9.cpp
#include "ICD9.h"
ICD9::ICD9()
{
}
const char* LookupCDE<ICD9>::filepath = "Data/icd-9.txt";