As @Mandarse pointed out, this is a typical dual submit problem. In object-oriented languages or in C ++ languages that can implement object-oriented concepts, this is usually solved using the Visitor Pattern.
The Visitor interface itself defines one callback for a particular type.
class Circle; class Rectangle; class Square; class Visitor { public: virtual void visit(Circle const& c) = 0; virtual void visit(Rectangle const& r) = 0; virtual void visit(Square const& s) = 0; };
Then the Shape hierarchy is adapted for this. We need two methods: one to receive any type of visitor, the other to create a “suitable” visitor intersection.
class Visitor; class Intersecter; class Shape { public: virtual void accept(Visitor&) const = 0;
Intersector is simple:
#include "project/Visitor.hpp" class Intersecter: public Visitor { public: Intersecter(): result(false) {} bool result; };
For example, for Circle this will give:
#include "project/Intersecter.hpp" #include "project/Shape.hpp" class Circle; class CircleIntersecter: public Intersecter { public: explicit CircleIntersecter(Circle const& c): _left(c) {} virtual void visit(Circle const& c);
And use:
#include "project/Intersecter.hpp" #include "project/Shape.hpp" bool intersects(Shape const& left, Shape const& right) { boost::scope_ptr<Intersecter> intersecter(left.intersecter()); right.accept(*intersecter); return intersecter->result; };
If other methods need a double dispatch mechanism, all you have to do is create another class like Intersecter that wraps the result and inherits from Visitor and the new Factory method embedded in Shape , which is overridden by derived classes to provide corresponding operation. It is a little long, but it works.
Note: it is reasonable to exclude intersect(circle, rectangle) and intersect(rectangle, circle) to get the same result. You can encode the code using some methods and have CircleIntersecter::visit delegates for a specific implementation. This avoids code duplication.
Matthieu M.
source share