zeusUnnamed repository; edit this file 'description' to name the repository. |
git clone Unknown |
Log | Files | Refs |
commit | 338aa1a5e93c6eeb615db830455e69979ee8e335 |
parent | e58770b0d523f37a4afaa41bf760c97091079686 |
author | Dimitrije Dobrota < mail@dimitrijedobrota.com > |
date | Sat, 17 May 2025 21:14:07 +0200 |
Basic visitor example
A | visitor_basic.cpp | | | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
1 files changed, 144 insertions(+), 0 deletions(-)
diff --git a/ visitor_basic.cpp b/ visitor_basic.cpp
@@ -0,0 +1,144 @@
#include <cassert>
#include <iostream>
#include <memory>
#include <string>
#include <string_view>
#include <vector>
class Pet;
class Cat;
class Dog;
class PetVisitor {
public:
virtual ~PetVisitor() = default;
virtual void visit(Cat *c, Pet *p) = 0;
virtual void visit(Dog *d, Pet *p) = 0;
};
class Pet {
std::string m_color;
std::vector<Pet *> m_children;
public:
Pet(std::string_view color) : m_color(color) {}
virtual ~Pet() = default;
virtual void accept(PetVisitor &v, Pet *p = nullptr) = 0;
void add_child(Pet *p) { m_children.emplace_back(p); }
const std::string &color() const { return m_color; }
const auto &children() const { return m_children; }
};
class Cat : public Pet {
public:
using Pet::Pet;
void accept(PetVisitor &v, Pet *p = nullptr) override { v.visit(this, p); }
};
class Dog : public Pet {
public:
using Pet::Pet;
void accept(PetVisitor &v, Pet *p = nullptr) override { v.visit(this, p); }
};
class FeedingVisitor : public PetVisitor {
public:
void visit(Cat *c, Pet *p) override {
(void)p;
std::cout << "Feed tuna to the " << c->color() << " cat\n";
}
void visit(Dog *c, Pet *p) override {
(void)p;
std::cout << "Feed streak to the " << c->color() << " dog\n";
}
};
class PlayingVisitor : public PetVisitor {
public:
void visit(Cat *c, Pet *p) override {
(void)p;
std::cout << "Play with a feather with the " << c->color() << " cat\n";
}
void visit(Dog *c, Pet *p) override {
(void)p;
std::cout << "Play fetch with the " << c->color() << " dog\n";
}
};
class BirthVisitor : public PetVisitor {
public:
void visit(Cat *c, Pet *p) override {
assert(dynamic_cast<Cat *>(p));
c->add_child(p);
}
void visit(Dog *c, Pet *p) override {
assert(dynamic_cast<Dog *>(p));
c->add_child(p);
}
};
class FamilyTreeVisitor : public PetVisitor {
std::size_t m_child_count = 0;
template <typename T> void visit_impl(T *t, const char *s) {
std::cout << s << ": ";
for (const auto p : t->children()) {
std::cout << p->color() << " ";
++m_child_count;
}
std::cout << std::endl;
}
public:
void reset() { m_child_count = 0; }
auto child_count() const { return m_child_count; }
void visit(Cat *c, Pet *p) override {
(void)p;
visit_impl(c, "Kittens");
}
void visit(Dog *c, Pet *p) override {
(void)p;
visit_impl(c, "Puppies");
}
};
class Shelter {
std::vector<std::unique_ptr<Pet>> m_pets;
public:
void add(Pet *p) { m_pets.emplace_back(p); }
void accept(PetVisitor &v) {
for (auto &p : m_pets) {
p->accept(v);
}
}
};
int main() {
std::unique_ptr<Pet> p(new Cat("orange"));
std::unique_ptr<PetVisitor> v(new FeedingVisitor);
p->accept(*v);
std::unique_ptr<Pet> child(new Cat("yellow"));
std::unique_ptr<PetVisitor> b(new BirthVisitor);
p->accept(*b, child.get());
std::unique_ptr<PetVisitor> f(new FamilyTreeVisitor);
p->accept(*f);
return 0;
}