Skip to the content.
class Element;

class Visitor {
 public:
  virtual void VisitA(const Element&) = 0;
  virtual void VisitB(const Element&) = 0;
  virtual ~Visitor() = default;
};

class ConcreteVisitor : public Visitor {
 public:
  void VisitA(const Element&) override { std::cout << "visit A\n"; }

  void VisitB(const Element&) override { std::cout << "visit B\n"; }
};
class Element {
 public:
  virtual void Accept(const std::shared_ptr<Visitor>& vistor) = 0;
  virtual ~Element() = default;
};

class ElementA : public Element {
 public:
  void Accept(const std::shared_ptr<Visitor>& vistor) override {
    vistor->VisitA(*this);
  }
};

class ElementB : public Element {
 public:
  void Accept(const std::shared_ptr<Visitor>& vistor) override {
    vistor->VisitB(*this);
  }
};
class ObjectStructure {
 public:
  void Append(const std::shared_ptr<Element>& element) {
    elements_.emplace_back(element);
  }

  void Remove(const std::shared_ptr<Element>& element) {
    elements_.remove(element);
  }

  void Accept(const std::shared_ptr<Visitor>& visitor) {
    for (auto&& x : elements_) {
      x->Accept(visitor);
    }
  }

 private:
  std::list<std::shared_ptr<Element>> elements_;
};

int main() {
  std::shared_ptr<Element> a = std::make_shared<ElementA>();
  std::shared_ptr<Element> b = std::make_shared<ElementB>();

  ObjectStructure o;
  o.Append(a);
  o.Append(b);

  std::shared_ptr<Visitor> visitor = std::make_shared<ConcreteVisitor>();
  o.Accept(visitor);  // visit A\nvisit B\n
}