zeusUnnamed repository; edit this file 'description' to name the repository. |
git clone Unknown |
Log | Files | Refs |
visitor_basic.cpp (2979B)
0 #include <cassert>
1 #include <iostream>
2 #include <memory>
3 #include <string>
4 #include <string_view>
5 #include <vector>
7 class Pet;
8 class Cat;
9 class Dog;
11 class PetVisitor {
12 public:
13 virtual ~PetVisitor() = default;
15 virtual void visit(Cat *c, Pet *p) = 0;
16 virtual void visit(Dog *d, Pet *p) = 0;
17 };
19 class Pet {
20 std::string m_color;
21 std::vector<Pet *> m_children;
23 public:
24 Pet(std::string_view color) : m_color(color) {}
25 virtual ~Pet() = default;
27 virtual void accept(PetVisitor &v, Pet *p = nullptr) = 0;
29 void add_child(Pet *p) { m_children.emplace_back(p); }
31 const std::string &color() const { return m_color; }
32 const auto &children() const { return m_children; }
33 };
35 class Cat : public Pet {
36 public:
37 using Pet::Pet;
39 void accept(PetVisitor &v, Pet *p = nullptr) override { v.visit(this, p); }
40 };
42 class Dog : public Pet {
43 public:
44 using Pet::Pet;
46 void accept(PetVisitor &v, Pet *p = nullptr) override { v.visit(this, p); }
47 };
49 class FeedingVisitor : public PetVisitor {
50 public:
51 void visit(Cat *c, Pet *p) override {
52 (void)p;
53 std::cout << "Feed tuna to the " << c->color() << " cat\n";
54 }
56 void visit(Dog *c, Pet *p) override {
57 (void)p;
58 std::cout << "Feed streak to the " << c->color() << " dog\n";
59 }
60 };
62 class PlayingVisitor : public PetVisitor {
63 public:
64 void visit(Cat *c, Pet *p) override {
65 (void)p;
66 std::cout << "Play with a feather with the " << c->color() << " cat\n";
67 }
69 void visit(Dog *c, Pet *p) override {
70 (void)p;
71 std::cout << "Play fetch with the " << c->color() << " dog\n";
72 }
73 };
75 class BirthVisitor : public PetVisitor {
76 public:
77 void visit(Cat *c, Pet *p) override {
78 assert(dynamic_cast<Cat *>(p));
79 c->add_child(p);
80 }
82 void visit(Dog *c, Pet *p) override {
83 assert(dynamic_cast<Dog *>(p));
84 c->add_child(p);
85 }
86 };
88 class FamilyTreeVisitor : public PetVisitor {
89 std::size_t m_child_count = 0;
91 template <typename T> void visit_impl(T *t, const char *s) {
92 std::cout << s << ": ";
93 for (const auto p : t->children()) {
94 std::cout << p->color() << " ";
95 ++m_child_count;
96 }
97 std::cout << std::endl;
98 }
100 public:
101 void reset() { m_child_count = 0; }
102 auto child_count() const { return m_child_count; }
104 void visit(Cat *c, Pet *p) override {
105 (void)p;
106 visit_impl(c, "Kittens");
107 }
109 void visit(Dog *c, Pet *p) override {
110 (void)p;
111 visit_impl(c, "Puppies");
112 }
113 };
115 class Shelter {
116 std::vector<std::unique_ptr<Pet>> m_pets;
118 public:
119 void add(Pet *p) { m_pets.emplace_back(p); }
121 void accept(PetVisitor &v) {
122 for (auto &p : m_pets) {
123 p->accept(v);
124 }
125 }
126 };
128 int main() {
129 std::unique_ptr<Pet> p(new Cat("orange"));
131 std::unique_ptr<PetVisitor> v(new FeedingVisitor);
132 p->accept(*v);
134 std::unique_ptr<Pet> child(new Cat("yellow"));
136 std::unique_ptr<PetVisitor> b(new BirthVisitor);
137 p->accept(*b, child.get());
139 std::unique_ptr<PetVisitor> f(new FamilyTreeVisitor);
140 p->accept(*f);
142 return 0;
143 }