Taking help from various sources, I managed to write a simple templates based factory pattern class where the factory doesn't depend on any of the derived classes. I uploaded the code here: https://github.com/piyushsoni/FactoryPattern . It might not be perfect but it works - though to my surprise only in this example. When I use this almost identically in our large actual codebase, it calls the constructor of the 'DerivedFactory' for only a few of the classes, and totally ignores for the other ones. It is only when I define a static function which can access the DerivedFactory object, and then actually call that function somewhere to assign that derived factory object to an lvalue (without there being a need) does it calls its constructor (whereas the way I create them in main.cpp should be sufficient). It looks like the compiler is doing some unneeded optimization here.
One difference can be that this sample project was tested in VC 15, while the actual codebase uses Intel Compiler with C++ 11 features enabled (which in turn uses MSVC11 on Windows and gcc on Linux). How can I fix that and make sure these simple static objects are created every time for both MSVC11 and GCC 4.8 onwards?
Edit: I wanted to avoid writing all code here to keep the question clean and putting the source code at one public location, but doing it here now on feedback (and to avoid getting it closed). I again want to write that this simple code is actually working, but almost identical code is not working when I put it in our commercial code which is compiled using Intel Compiler which is internally using MSVC11 on Windows. If you have any other questions, please ask them in comments and I'll try to answer, please don't try to close the question before letting me answer them. I have written the exact problem I'm facing above.
Here are the files:
ShapeFactory.h
#pragma once
#include <map>
using namespace std;
#include "Shape.h"
#define REGISTER_CLASS(objectClass) static DerivedFactory<objectClass> shape##objectClass(Type_ ## objectClass);
class Shape;
class ShapeFactory;
typedef map<ShapeType, ShapeFactory*> mapTypeShapeFactoryByType;
class ShapeFactory
{
private:
mapTypeShapeFactoryByType mapShapeTypeByFactory;
protected:
ShapeFactory() {}
virtual Shape* Create() { return NULL; }
private:
ShapeFactory(const ShapeFactory&);
public:
virtual ~ShapeFactory() {}
static ShapeFactory& GetShapeFactory();
Shape* CreateShape(ShapeType type);
virtual void DestroyShape(Shape* object) { delete object; object = nullptr; }
void RegisterFactory(ShapeType type, ShapeFactory* factory);
};
template<typename ShapeClass>
class DerivedFactory : public ShapeFactory
{
public:
DerivedFactory(ShapeType type)
{
ShapeFactory::GetShapeFactory().RegisterFactory(type, this);
}
~DerivedFactory() {}
Shape* Create() { return new ShapeClass(); }
};
ShapeFactory.cpp
#include "ShapeFactory.h"
//mapTypeShapeFactoryByType ShapeFactory::mapShapeTypeByFactory;
//ShapeFactory* ShapeFactory::mInstance = NULL;
ShapeFactory& ShapeFactory::GetShapeFactory()
{
static ShapeFactory instance;
return instance;
}
Shape * ShapeFactory::CreateShape(ShapeType type)
{
if (mapShapeTypeByFactory.find(type) != mapShapeTypeByFactory.end())
return mapShapeTypeByFactory[type]->Create();
else
return nullptr;
}
void ShapeFactory::RegisterFactory(ShapeType type, ShapeFactory * factory)
{
mapShapeTypeByFactory[type] = factory;
}
Shape.h
#pragma once
#include <string>
using namespace std;
enum ShapeType
{
Type_Unknown,
Type_Circle,
Type_Rectangle,
Type_Polygon
};
class Shape
{
std::string name;
public:
virtual ~Shape() {}
virtual ShapeType GetType() { return Type_Unknown; }
};
Rectangle.h
#pragma once
#include "Shape.h"
#include <iostream>
using namespace std;
class Rectangle : public Shape
{
public:
Rectangle();
virtual ~Rectangle();
virtual ShapeType GetType() { return Type_Rectangle; }
private:
float points[4][3];
};
Rectangle.cpp
#include "Rectangle.h"
#include "ShapeFactory.h"
static DerivedFactory<Rectangle> RectangleFactory(Type_Rectangle);
Rectangle::Rectangle()
{
cout << "The factory created new Rectangle! \n";
}
Rectangle::~Rectangle()
{
cout << "The Rectangle object was destroyed \n";
}
Circle.h
#pragma once
#include "Shape.h"
#include <iostream>
using namespace std;
class Circle : public Shape
{
public:
Circle();
virtual ~Circle();
virtual ShapeType GetType() { return Type_Circle; }
private:
float center[3];
float radius;
};
Circle.cpp
#include "Circle.h"
#include "ShapeFactory.h"
static DerivedFactory<Circle> CircleFactory(Type_Circle);
Circle::Circle()
{
cout << "The factory created new Circle! \n";
}
Circle::~Circle()
{
cout << "The Circle object was destroyed \n";
}
main.cpp
#include <iostream>
#include <string>
#include <map>
#include "ShapeFactory.h"
#include "Shape.h"
#include "Circle.h"
#include "Rectangle.h"
using namespace std;
int main()
{
ShapeFactory& factory = ShapeFactory::GetShapeFactory();
Circle* vec = (Circle*)factory.CreateShape(Type_Circle);
cout << "Object type is : " << vec->GetType() <<"\n";
factory.DestroyShape(vec);
Rectangle* con = (Rectangle*)factory.CreateShape(Type_Rectangle);
cout << "Object type is : " << con->GetType() << "\n";
factory.DestroyShape(con);
getchar();
return 0;
}
Thanks!!