#include <iostream>

using namespace std;

class ShapeVisitor;

struct Shape {
    virtual void accept(ShapeVisitor& v) = 0;
    virtual bool overlaps(Shape& other) = 0;
};

class Circle;
class Square;

struct ShapeVisitor {
    virtual void visitCircle(Circle& c) = 0;
    virtual void visitSquare(Square& s) = 0;
};

bool checkOverlap(Square& s, Circle& c) {
    cout << "Checking if square overlaps circle" << endl;
    return false;
}
bool checkOverlap(Square& a, Square& b) {
    cout << "Checking if square overlaps square" << endl;
    return false;
}
bool checkOverlap(Circle& a, Circle& b) {
    cout << "Checking if circle overlaps circle" << endl;
    return false;
}

class Square : public Shape {
    struct OverlapVisitor : public ShapeVisitor {
        OverlapVisitor(Square& _my) : result(false), my(_my) {}
        virtual void visitCircle(Circle& c) {
            result = checkOverlap(my, c);
        }
        virtual void visitSquare(Square& s) {
            result = checkOverlap(my, s);
        }
        bool result;
        Square& my;
    };
public:
    virtual void accept(ShapeVisitor& v) {
        v.visitSquare(*this);
    }
    virtual bool overlaps(Shape& other) {
        OverlapVisitor v(*this);
        other.accept(v);
        return v.result;
    }
};

class Circle : public Shape {
    struct OverlapVisitor : public ShapeVisitor {
        OverlapVisitor(Circle& _my) : result(false), my(_my) {}
        virtual void visitCircle(Circle& c) {
            result = checkOverlap(my, c);
        }
        virtual void visitSquare(Square& s) {
            result = checkOverlap(s, my);
        }
        bool result;
        Circle& my;
    };
public:
    virtual void accept(ShapeVisitor& v) {
        v.visitCircle(*this);
    }
    virtual bool overlaps(Shape& other) {
        OverlapVisitor v(*this);
        other.accept(v);
        return v.result;
    }
};

int main() {
    Square s;
    Circle c;
    s.overlaps(c);
    s.overlaps(s);
    c.overlaps(s);
    c.overlaps(c);
    return 0;
}