There is a pattern that I like using for implementing factory classes that goes as follows (taken from my answer to this question):
class Factory
{
public:
template<class DerivedType>
DerivedType::CreatedType *createType()
{
DerivedType::CreatedType *r = (DerivedType::CreatedType) (*(m_creators[DerivedType::id]))();
return r;
}
protected:
static std::map<int,void *(*)()> m_creators;
};
std::map<int,void *(*)()> Factory::m_creators = std::map<int,void*(*)()>();
template<class Derived, class CreatedType>
class CRTPFactory : public Factory
{
typedef typename CreatedType CreatedType;
public:
static bool register()
{
Factory::m_creators.push_back(std::make_pair(Derived::id,Derived::create);
return true;
}
private:
static bool m_temp;
};
template<class Derived>
bool CRTPFactory<Derived>::m_temp = CRTPFactory<Derived>::register();
class AFactory : public CRTPFactory<AFactory,A>
{
private:
static A *create()
{
//do all initialization stuff here
return new A;
}
public:
static const int id = 0;
};
This allows extension of the factory for new types without having to change the factory class. It also allows for implementing specific creation algorithms for different types without having to change the factory class. There is a major problem with this pattern though. The class AFactory is never used explicitly. It registers its creator function at load time through CRTPFactory's member temp. This might be a little complicated to understand but it's very easy to use. The problem is AFactory isn't compiled so it's static parameters aren't initialized at load time. My question is, is it possible to force the compiler (I'm using VS 2012 but answers for GCC are also good) to compile AFactory without ever explicitly creating an instance of it? A solution that I use in VS is to dllexport AFactory, that way the compiler compiles the class even though it doesn't know of anyone instantiating it. This is because it assumes some other dll might instantiate it. The problem with this solution is that the factory class must be implemented in a separate dll as the rest of the code. And also this doesn't work on GCC.