Search code examples
c++ooptemplatesfactory-pattern

Attempting to reference a deleted function in objects factory


I get next error, when compining code.

Error   C2280   'Square::Square(void)': attempting to reference a deleted function  objectfactory.h 11

I have next object factory, for objects:

template<class ID, class Base, class ... Args> class GenericObjectFactory {
private:
    typedef Base* (*fInstantiator)(Args ...);
    template<class Derived> static Base* instantiator(Args ... args) {
        return new Derived(args ...);
    }
    std::map<ID, fInstantiator> classes;

public:
    GenericObjectFactory() {}
    template<class Derived> void add(ID id) {
        classes[id] = &instantiator<Derived>;
    }
    fInstantiator get(ID id) {
        return classes[id];
    }
};

Base class for example:

class BaseFigure
{
private:
    BaseFigure(const BaseFigure&);
    int m_params_num;
public:
    BaseFigure() : m_params_num(0) {};
    virtual void draw(WDraw &drawer)=0;
    virtual void boundingBox(WDraw &drawer) = 0;
    virtual ~BaseFigure() {};
};

And derived class from BaseFigure:

class Square :
    public BaseFigure
{
private:
    Point2d points[2];
public:
    std::string type();
    void draw(WDraw &drawer);
    void boundingBox(WDraw &drawer);
    ~Square();
};

Square realization below:

 void Square::draw(WDraw &drawer) {
    Point2d cournerSecond(points[0].x(), points[1].y()), cournerFour(points[1].x(), points[0].y());
    drawer.drawSegment(points[0], cournerSecond);
    drawer.drawSegment(cournerSecond, points[1]);
    drawer.drawSegment(points[1], cournerFour);
    drawer.drawSegment(cournerFour, points[0]);
}
void Square::boundingBox(WDraw &drawer) {
    this->boundingBox(drawer);
}

Example of using:

GenericObjectFactory<std::string , BaseFigure> figureFactory;
figureFactory.add<Square>("sq");
BaseFigure *sq = figureFactory.get("sq")();

I can't understand, where is error? P.S Added Point2D and WDraw. All methods of this classes have realization.

class Point2d
{
public:
    Point2d(double xx, double yy);
    virtual ~Point2d(void);
    double x() const { return m_dX; }
    double y() const { return m_dY; }
private:
    double m_dX;
    double m_dY;
};
class WDraw
{    
public:
    WDraw(void);
    virtual ~WDraw(void);
    virtual void drawSegment(const Point2d& p1, const Point2d& p2);
};

Solution

  • This line:

    classes[id] = &instantiator<Derived>;
    

    sets up your instantiator to use this instantiated function:

    static BaseFigure* instantiator() {
        return new Square();
    }
    

    But Square isn't default-constructible, because its member:

    Point2d points[2];
    

    isn't default-constructible, because it has a user-declared non-default constructor:

    Point2d(double xx, double yy);
    

    hence the error. The implicitly declared Point2d default constructor is declared as deleted, which makes the implicitly declared default constructor of Square declared as deleted as well.

    To make this work, you'd have to either add a default constructor to Point2d or allow a way to pass in arguments through Square's constructor into points. Probably the latter makes the most sense.