// generalisierte Klassen
template <typename T>
struct single_visitor
{
virtual void visit(T&) = 0;
};
template <typename ... Ts>
struct generic_visitor : single_visitor<Ts>... {};
template <class Visitor>
struct generic_acceptor
{
virtual void accept(Visitor&) = 0;
};
#define OVERRIDE_ACCEPT \
void accept(visitor &v) override \
{ \
using this_t = typename std::decay<decltype(*this)>::type; \
static_cast<single_visitor<this_t>&>(v).visit(*this); \
}
// Nutzung
#include <memory>
#include <vector>
#include <iostream>
struct concrete_node_1;
struct concrete_node_2;
using visitor = generic_visitor<concrete_node_1, concrete_node_2>;
using acceptor = generic_acceptor<visitor>;
struct node : acceptor {};
struct concrete_node_1 : node
{
OVERRIDE_ACCEPT
};
struct concrete_node_2 : node
{
OVERRIDE_ACCEPT
};
struct concrete_visitor_1 : visitor
{
void visit(concrete_node_1 &cn1) override { std::cout << "v1 cn1\n"; }
void visit(concrete_node_2 &cn2) override { std::cout << "v1 cn2\n"; }
};
struct concrete_visitor_2 : visitor
{
void visit(concrete_node_1 &cn1) override { std::cout << "v2 cn1\n"; }
void visit(concrete_node_2 &cn2) override { std::cout << "v2 cn2\n"; }
};
int main()
{
std::vector<std::shared_ptr<node>> nodes;
nodes.push_back(std::make_shared<concrete_node_1>()); // 1
nodes.push_back(std::make_shared<concrete_node_1>()); // 1
nodes.push_back(std::make_shared<concrete_node_2>()); // 2
concrete_visitor_1 v1;
for (auto const &n : nodes)
n->accept(v1);
concrete_visitor_2 v2;
for (const auto &n : nodes)
n->accept(v2);
}