struct A {
struct Visitor {
virtual ~Visitor() = default;
};
virtualvoid accept (A::Visitor&) = 0;
};
struct B; struct C; struct D;
struct VisitorD {
virtual ~VisitorD() = default;
virtualvoid visit (D*) = 0;
};
struct VisitorC : VisitorD {
virtual ~VisitorC() = default;
virtualvoid visit (C*) = 0;
};
struct VisitorB : VisitorC {
virtual ~VisitorB() = default;
virtualvoid visit (B*) = 0;
};
struct B : A {
virtualvoid accept (A::Visitor& visitor) override {
VisitorB* v = dynamic_cast<VisitorB*>(&visitor);
if (v) v->visit (this);
}
};
struct C : B {
struct Visitor : B::Visitor {
virtual ~Visitor() = default;
virtualvoid visit (C*) = 0;
};
virtualvoid accept (A::Visitor& visitor) override {
VisitorC* v = dynamic_cast<VisitorC*>(&visitor);
if (v) v->visit (this);
}
};
struct D : C {
struct Visitor : C::Visitor {
virtual ~Visitor() = default;
virtualvoid visit (D*) = 0;
};
virtualvoid accept (A::Visitor& visitor) override {
VisitorD* v = dynamic_cast<VisitorD*>(&visitor);
if (v) v->visit (this);
}
};
struct CountB : A::Visitor, VisitorB { // to count the number of objects of type B
int count = 0;
virtualvoid visit (B*) override {count++;}
virtualvoid visit (C*) override {count++;}
virtualvoid visit (D*) override {count++;}
operatorint() const {return count;}
} countB;
int main() {
A* objects[] = {new B, new C, new D};
for (A* x : objects)
x->accept (countB);
std::cout << "count = " << countB << std::endl;
std::cin.get();
}
give the correct:
count = 3
but it is scrappy. The visitor classes had to be placed outside the classes they belonged to, and CountB lost its template because of that. Also, it is very awkward that I have to construct a "reverse hierarchy" for the Visitor classes (which means that this has to be painfully changed if I ever change the hierarchy for A, B, C, ...). How to improve my solution (using acyclic visitor pattern)? Forward declaring nested classes is not possible in c++.