Skip to content

Instantly share code, notes, and snippets.

@mirth
Last active April 26, 2016 10:04
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mirth/0ff4ca8f414019d1eeffde0eec881f52 to your computer and use it in GitHub Desktop.
Save mirth/0ff4ca8f414019d1eeffde0eec881f52 to your computer and use it in GitHub Desktop.
#include <iostream>
#include <memory>
#include <vector>
#include "visitor.hpp"
struct foo;
struct bar;
using visitor_t = basic_visitor<std::tuple<foo, bar>, void(int)>;
struct foo: public basic_visitable<foo, visitor_t> {
};
struct bar: public basic_visitable<bar, visitor_t> {
};
class concrete_visitor0: public visitor_t {
public:
void visit(foo&, int i) override {
std::cout << "concrete_visitor0 visiting foo " << i << '\n';
}
void visit(bar&, int i) override {
std::cout << "concrete_visitor0 visiting bar " << i << '\n';
}
};
class concrete_visitor1: public visitor_t {
public:
void visit(foo&, int i) override {
std::cout << "concrete_visitor1 visiting foo " << i << '\n';
}
void visit(bar&, int i) override {
std::cout << "concrete_visitor1 visiting bar " << i << '\n';
}
};
int main() {
{
concrete_visitor0 visitor0;
concrete_visitor1 visitor1;
foo target;
target.accept(visitor0, 1);
target.accept(visitor1, 1);
}
{
std::vector<std::unique_ptr<basic_visitable_pure<visitor_t>>> vec;
vec.emplace_back(std::make_unique<foo>());
vec.emplace_back(std::make_unique<bar>());
concrete_visitor0 visitor;
for(auto& obj : vec) {
obj->accept(visitor, 2);
}
}
}
#include <tuple>
template<typename TargetsVector, typename SignatureVector>
struct visit_method;
template<typename TargetType, typename ReturnType, typename ... ArgsTypes>
struct visit_method<TargetType, ReturnType(ArgsTypes ...)> {
virtual ReturnType visit(TargetType&, ArgsTypes...) = 0;
virtual ~visit_method() {
}
};
template<typename TargetsVector, typename SignatureVector>
struct basic_visitor;
template<typename ... TargetsTypes, typename ReturnType, typename ... ArgsTypes>
struct basic_visitor<std::tuple<TargetsTypes ...>, ReturnType(ArgsTypes ...)> : visit_method<TargetsTypes, ReturnType(ArgsTypes ...)> ...
{
template<typename VisitableType>
ReturnType visit_name_lookup_adhoc(VisitableType& visitable, ArgsTypes... args) {
using VisitMethod = visit_method<VisitableType, ReturnType(ArgsTypes ...)>;
auto const hack = &VisitMethod::visit;
return (this->*hack)(visitable, args...);
}
};
template<typename VisitorType>
struct basic_visitable_pure;
template<typename TargetsVector, typename ReturnType, typename ... ArgsTypes>
struct basic_visitable_pure<basic_visitor<TargetsVector, ReturnType(ArgsTypes ...)>>
{
using visitor_type = basic_visitor<TargetsVector, ReturnType(ArgsTypes ...)>;
virtual ReturnType accept(visitor_type& visitor, ArgsTypes... args) = 0;
virtual ~basic_visitable_pure() {
}
};
template<typename SelfType, typename VisitorType>
struct basic_visitable;
template<typename SelfType, typename TargetsVector, typename ReturnType, typename ... ArgsTypes>
struct basic_visitable<SelfType, basic_visitor<TargetsVector, ReturnType(ArgsTypes ...)>>: basic_visitable_pure<basic_visitor<TargetsVector, ReturnType(ArgsTypes ...)>>
{
using basic_type = basic_visitable_pure<basic_visitor<TargetsVector, ReturnType(ArgsTypes ...)>>;
ReturnType accept(typename basic_type::visitor_type& visitor, ArgsTypes ... args) {
return visitor.visit_name_lookup_adhoc(static_cast<SelfType&>(*this), args ...);
}
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment