i have a factory class that i've used for quite some time, which i have tried to do a little template magic to, and it simply will not work. I don't think you'll need to see that class, as it's quite large, but if you really think it's related then i will edit it in. Anyway, i have a setup like this which i've done forever.
class Base :
public Factory<Base>
{
};
class Derived :
public Base
{
static Factory<Base>::DerivedRegister<Derived> m_Reg;
};
Factory<Base>::DerivedRegister<Derived> Derived::m_Reg;
the factory gives it the static method createInstance(const std::string& name) which will return an instance of the registered object. The DerivedRegister object derives from the factory object and when declared statically, must be constructed during static initialization. This means i have access to the factories static internals within it's constructor, and so i utilize it's constructor to have all registered object available to the factory during static initialization. This works and has for awhile, but then i tried something like this so that derived classes could avoid needing to explicitly make that static derivedregister object:
class Base :
public Factory<Base>
{
};
template<class TDerived>
class BaseReg :
public Base
{
static Factory<Base>::DerivedRegister<TDerived> m_Reg;
};
template<class TDerived>
Factory<Base>::DerivedRegister<TDerived> BaseReg<TDerived>::m_Reg;
class Derived :
public BaseReg<Derived>
{
};
When i run the program and try to create an instance of the Derived class, it doesn't exist in the factory, and after a little doodling, i find that the static DerivedRegister is never being constructed in derived, as in the constructor is never called. I find this odd. How could it not be forced to statically initialize if the Derived class isn't a template? When i make a dummy static object as seen below, and use a method from m_Reg in it's static construction, suddenly the DerivedRegister constructs correctly and the factory can instantiate it, no sweat.
class Base :
public Factory<Base>
{
};
template<class TDerived>
class BaseReg :
public Base
{
protected:
static Factory<Base>::DerivedRegister<TDerived> m_Reg;
};
template<class TDerived>
Factory<Base>::DerivedRegister<TDerived> BaseReg<TDerived>::m_Reg;
class Derived :
public BaseReg<Derived>
{
class RandomClass
{
public:
RandomClass(std::string meh) {}
};
private:
static RandomClass m_Obj;
};
Derived::RandomClass Derived::m_Obj(m_Reg.func());
So what am i not getting about this template class's static member initialization here? doesn't it have to statically initialize the object like any other non-template object?
EDIT: mkay, to give a little insight, i'll post the Factory object. Just beware the WALLS of text. ignore the extra includes, and the superfluous GetNames, and func functions, they are just voodoo code.
#ifndef FACTORY_H
#define FACTORY_H
// library tools
#include <map>
#include <string>
#include <typeinfo>
#include <cstdlib>
#include <vector>
#include <iostream>
#include <cxxabi.h>
const std::string demangle(const char* name);
template<class base>
class Factory
{
protected:
template<class T>
static base * createT() { return new T;}
typedef std::map<std::string, base*(*)()> map_type;
static map_type& GetMap()
{
static map_type map;
return map;
}
public:
virtual ~Factory(){}
static base * createInstance(const std::string & s)
{
if(!GetMap().count(s))
return nullptr;
typename map_type::iterator it = GetMap().find(s);
return it->second();
}
template <class TDerived>
struct DerivedRegister :
public Factory<base>
{
DerivedRegister()
{
std::string name = demangle(typeid(TDerived).name());
GetMap().insert(std::pair<std::string, base*(*)()>(name, &createT<TDerived>));
}
DerivedRegister(const std::string& name)
{
GetMap().insert(std::pair<std::string, base*(*)()>(name, &createT<TDerived>));
}
std::string func() {return "meh";}
};
static void GetNames(std::vector<std::string>& names)
{
names.clear();
for(auto it = GetMap().begin(); it != GetMap().end(); ++it)
names.push_back(it->first);
}
};
#endif