#include <iostream>
#include <vector>
#include <memory>
struct PBaseVisitor;
struct PBase {
virtual int get_id() { return 0; }
virtual void accept(PBaseVisitor &v);
};
struct P1 : PBase {
int get_id() override { return 1; }
void accept(PBaseVisitor &v) override;
};
struct P2 : PBase {
int get_id() override { return 2; }
void accept(PBaseVisitor &v) override;
};
class SBase {
public:
virtual ~SBase() {}
void doIt(PBase &p) { this->internalDoIt(p); }
private:
virtual void internalDoIt(PBase &p) = 0;
};
struct PBaseVisitor {
virtual ~PBaseVisitor() {}
virtual void visit(PBase &p) = 0;
virtual void visit(P1 &p) { visit(static_cast<PBase &>(p)); };
virtual void visit(P2 &p) { visit(static_cast<PBase &>(p)); };
};
void PBase::accept(PBaseVisitor &v) { v.visit(*this); }
void P1::accept(PBaseVisitor &v) { v.visit(*this); }
void P2::accept(PBaseVisitor &v) { v.visit(*this); }
class S : public SBase {
struct doItImpl : PBaseVisitor {
doItImpl(S *s) : s(s) {}
S *s;
virtual void visit(PBase &p) { s->internalDoItImpl(p); };
void visit(P1 &p) override { s->internalDoItImpl(p); };
void visit(P2 &p) override { s->internalDoItImpl(p); };
};
virtual void internalDoIt(PBase &p) {
doItImpl impl(this);
p.accept(impl);
}
void internalDoItImpl(PBase &p) { std::cout << "PBase: " << p.get_id() << '\n'; }
void internalDoItImpl(P1 &p) { std::cout << "P1: " << p.get_id() << '\n'; }
void internalDoItImpl(P2 &p) { std::cout << "P2: " << p.get_id() << '\n'; }
};
int main() {
std::vector<std::unique_ptr<PBase> > vec;
vec.emplace_back(new PBase);
vec.emplace_back(new P1);
vec.emplace_back(new P2);
S s;
SBase &bref = s; // Angenommn, dass du von irgendwo her einen
// Basisklassen-Zeiger/Referenz hast..
for (auto &p : vec)
bref.doIt(*p);
}