Skip to content

Instantly share code, notes, and snippets.

@mumreg
Last active April 21, 2016 16:52
Show Gist options
  • Save mumreg/f1237fc3fed7e8497320670fd0c6497d to your computer and use it in GitHub Desktop.
Save mumreg/f1237fc3fed7e8497320670fd0c6497d to your computer and use it in GitHub Desktop.
First approach of template visitor
#include <iostream>
class BaseVisitor
{
public:
virtual ~BaseVisitor() {}
};
template <class T, typename R = void>
class Visitor {
public:
using ReturnType = R;
virtual ReturnType visit(T&) = 0;
virtual ~Visitor() {}
};
template <typename R = void>
class BaseVisitable {
public:
using ReturnType = R;
virtual ~BaseVisitable() {}
virtual ReturnType accept(BaseVisitor&) = 0;
protected:
template <class T>
static ReturnType AcceptImpl(T& visited, BaseVisitor& guest) {
if (Visitor<T, R>* p = dynamic_cast<Visitor<T, R>*>(&guest)) {
return p->visit(visited);
}
return ReturnType();
}
};
#define DEFINE_VISITABLE() \
virtual ReturnType accept(BaseVisitor& guest) \
{ return AcceptImpl(*this, guest); }
class Derived1 : public BaseVisitable<int>
{
public:
DEFINE_VISITABLE()
};
class Derived2 : public BaseVisitable<>
{
public:
DEFINE_VISITABLE()
};
class IVisitor :
public BaseVisitor,
public Visitor<Derived1, int>,
public Visitor<Derived2>
{
};
class SomeVisitor : public IVisitor
{
public:
int visit(Derived1& ctx) { std::cout << "Derived1" << std::endl; return 1; }
void visit(Derived2& ctx) { std::cout << "Derived2" << std::endl; }
};
int main(int argc, const char * argv[]) {
auto a1 = std::shared_ptr<BaseVisitable<int>>(new Derived1());
auto a2 = std::shared_ptr<BaseVisitable<>>(new Derived2());
SomeVisitor v;
a1->accept(v);
a2->accept(v);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment