zeusUnnamed repository; edit this file 'description' to name the repository. |
git clone Unknown |
Log | Files | Refs |
visitor_template_acyclic.cpp (1759B)
0 #include <cassert>
1 #include <iostream>
2 #include <memory>
3 #include <string>
4 #include <string_view>
6 class VisitorBase {
7 public:
8 virtual ~VisitorBase() = default;
9 };
11 template <class Visitable> class Visitor {
12 public:
13 virtual void visit(Visitable *p) = 0;
14 };
16 template <typename... V> struct Visitors;
18 template <typename V1>
19 struct Visitors<V1> : public VisitorBase, public Visitor<V1> {};
21 template <typename V1, typename... V>
22 struct Visitors<V1, V...> : public Visitor<V1>, public Visitors<V...> {};
24 template <typename Base, typename Visitable> class VisitableBase : public Base {
25 public:
26 using Base::Base;
28 void accept(VisitorBase &v) override {
29 if (Visitor<Visitable> *pv = dynamic_cast<Visitor<Visitable> *>(&v)) {
30 pv->visit(static_cast<Visitable *>(this));
31 } else {
32 assert(false);
33 }
34 }
35 };
37 class Pet {
38 std::string m_color;
40 public:
41 virtual ~Pet() = default;
42 Pet(std::string_view color) : m_color(color) {}
44 virtual void accept(VisitorBase &v) = 0;
46 const std::string &color() const { return m_color; }
47 };
49 template <class Visitable> using PetVisitable = VisitableBase<Pet, Visitable>;
51 class Cat : public PetVisitable<Cat> {
52 public:
53 using PetVisitable<Cat>::PetVisitable;
54 };
56 class Dog : public PetVisitable<Dog> {
57 public:
58 using PetVisitable<Dog>::PetVisitable;
59 };
61 class FeedingVisitor : public Visitors<Cat, Dog> {
62 public:
63 void visit(Cat *c) override {
64 std::cout << "Feed tuna to the " << c->color() << " cat\n";
65 }
67 void visit(Dog *c) override {
68 std::cout << "Feed streak to the " << c->color() << " dog\n";
69 }
70 };
72 int main() {
73 std::unique_ptr<Pet> c(new Cat("orange"));
74 std::unique_ptr<Pet> d(new Dog("brown"));
76 FeedingVisitor fv;
77 c->accept(fv);
78 d->accept(fv);
80 return 0;
81 }