Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <iostream>
- #include <vector>
- #include <memory>
- #include <cassert>
- struct Visitor;
- struct Common
- {
- virtual void apply(const Visitor&) = 0;
- virtual void apply(const Visitor&) const = 0;
- virtual void apply(Visitor&) = 0;
- virtual void apply(Visitor&) const = 0;
- virtual ~Common() = default;
- };
- struct Left : Common
- {
- virtual void doLeft() const = 0;
- };
- struct Right : Common
- {
- virtual void doRight() const = 0;
- };
- struct A : Left, Right
- {
- void apply(const Visitor& v) override;
- void apply(const Visitor& v) const override;
- void apply(Visitor& v) override;
- void apply(Visitor& v) const override;
- void doLeft() const override
- {
- std::cout << "A::doLeft" << std::endl;
- }
- void doRight() const override
- {
- std::cout << "A::doRight" << std::endl;
- }
- std::string inAonly() const { return "class A"; }
- };
- struct B : Left
- {
- void apply(const Visitor& v) override;
- void apply(const Visitor& v) const override;
- void apply(Visitor& v) override;
- void apply(Visitor& v) const override;
- void doLeft() const override
- {
- std::cout << "B::doLeft" << std::endl;
- }
- std::string inBonly() const { return "class B"; }
- };
- struct C : Right, Left
- {
- void apply(const Visitor& v) override;
- void apply(const Visitor& v) const override;
- void apply(Visitor& v) override;
- void apply(Visitor& v) const override;
- void doLeft() const override
- {
- std::cout << "C::doLeft" << std::endl;
- }
- void doRight() const override
- {
- std::cout << "C::doRight" << std::endl;
- }
- std::string inConly() const { return "class C"; }
- };
- struct D : Right
- {
- void apply(const Visitor& v) override;
- void apply(const Visitor& v) const override;
- void apply(Visitor& v) override;
- void apply(Visitor& v) const override;
- void doRight() const override
- {
- std::cout << "D::doRight" << std::endl;
- }
- std::string inDonly() const { return "class D"; }
- };
- struct Visitor
- {
- virtual void visit(const Left&) const
- {
- assert(!"If the method is called it means it had to be overrided");
- }
- virtual void visit(Left& o) const
- {
- visit(static_cast<const Left&>(o));
- }
- virtual void visit(const Right&) const
- {
- assert(!"If the method is called it means it had to be overrided");
- }
- virtual void visit(Right& o) const
- {
- visit(static_cast<const Right&>(o));
- }
- // Left siblings
- virtual void visit(const A& o) const
- {
- visit(static_cast<const Left&>(o));
- }
- virtual void visit(A& o) const
- {
- visit(static_cast<Left&>(o));
- }
- virtual void visit(const B& o) const
- {
- visit(static_cast<const Left&>(o));
- }
- virtual void visit(B& o) const
- {
- visit(static_cast<Left&>(o));
- }
- // Right siblings
- virtual void visit(const C& o) const
- {
- visit(static_cast<const Right&>(o));
- }
- virtual void visit(C& o) const
- {
- visit(static_cast<Right&>(o));
- }
- virtual void visit(const D& o) const
- {
- visit(static_cast<const Right&>(o));
- }
- virtual void visit(D& o) const
- {
- visit(static_cast<Right&>(o));
- }
- virtual ~Visitor() = 0;
- };
- // impl
- inline Visitor::~Visitor() = default;
- void A::apply(const Visitor& v)
- {
- v.visit(*this);
- }
- void A::apply(const Visitor& v) const
- {
- v.visit(*this);
- }
- void A::apply(Visitor& v)
- {
- v.visit(*this);
- }
- void A::apply(Visitor& v) const
- {
- v.visit(*this);
- }
- void B::apply(const Visitor& v)
- {
- v.visit(*this);
- }
- void B::apply(const Visitor& v) const
- {
- v.visit(*this);
- }
- void B::apply(Visitor& v)
- {
- v.visit(*this);
- }
- void B::apply(Visitor& v) const
- {
- v.visit(*this);
- }
- void C::apply(const Visitor& v)
- {
- v.visit(*this);
- }
- void C::apply(const Visitor& v) const
- {
- v.visit(*this);
- }
- void C::apply(Visitor& v)
- {
- v.visit(*this);
- }
- void C::apply(Visitor& v) const
- {
- v.visit(*this);
- }
- void D::apply(const Visitor& v)
- {
- v.visit(*this);
- }
- void D::apply(const Visitor& v) const
- {
- v.visit(*this);
- }
- void D::apply(Visitor& v)
- {
- v.visit(*this);
- }
- void D::apply(Visitor& v) const
- {
- v.visit(*this);
- }
- struct MyVisitor : Visitor
- {
- /// @todo const specific class references don't have priority
- void visit(A& o) const override
- {
- std::cout << o.inAonly() << std::endl;
- }
- void visit(B& o) const override
- {
- std::cout << o.inBonly() << std::endl;
- }
- void visit(C& o) const override
- {
- std::cout << o.inConly() << std::endl;
- }
- void visit(D& o) const override
- {
- std::cout << o.inDonly() << std::endl;
- }
- };
- int main(int argc, char* argv[])
- {
- using namespace std;
- vector<shared_ptr<Left>> lvec;
- vector<shared_ptr<Right>> rvec;
- // somewhere in depth of factory
- {
- {
- auto p = make_shared<A>();
- lvec.push_back(p);
- rvec.push_back(p);
- }
- {
- auto p = make_shared<B>();
- lvec.push_back(p);
- }
- {
- auto p = make_shared<C>();
- lvec.push_back(p);
- rvec.push_back(p);
- }
- {
- auto p = make_shared<D>();
- rvec.push_back(p);
- }
- }
- MyVisitor v;
- for (auto& p : lvec)
- {
- assert(p);
- p->doLeft();
- p->apply(v);
- }
- for (auto& p : rvec)
- {
- assert(p);
- p->doRight();
- p->apply(v);
- }
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement