Skip to content

Instantly share code, notes, and snippets.

@pacmancoder
Last active February 15, 2018 12:56
Show Gist options
  • Save pacmancoder/b68964e9555763392125f3e6f3fd8a33 to your computer and use it in GitHub Desktop.
Save pacmancoder/b68964e9555763392125f3e6f3fd8a33 to your computer and use it in GitHub Desktop.
/* Vladislav Nikonov [2018]
*
* Template visitor implementation, which will wait for concrete visitor dispatch,
* and will throw on other events. This can be done by method overload based on template type.
* This method will be overriden by function call, provided by client code
*/
#include <iostream>
#include <memory>
#include <vector>
#include <functional>
class VisitorA;
class VisitorB;
class IVisitable
{
public:
virtual void visit(VisitorA&) { unexpected_visit(); };
virtual void visit(VisitorB&) { unexpected_visit(); };
virtual void unexpected_visit() = 0;
};
class IVisitor
{
public:
virtual void visit(IVisitable& v) = 0;
void visit(IVisitable&& v)
{
visit(v);
}
};
class VisitorA : public IVisitor
{
public:
void visit(IVisitable& v) override {v.visit(*this);}
};
class VisitorB : public IVisitor
{
public:
void visit(IVisitable& v) override {v.visit(*this);}
};
template<class V>
class Visitable : public IVisitable
{
public:
using VisitFunc = std::function<void(V&)>;
explicit Visitable(VisitFunc visitFunc) :
visitFunc_(std::move(visitFunc)) {}
void visit(V& visitor) override
{
visitFunc_(visitor);
}
void unexpected_visit() override
{
throw std::runtime_error("Unexpected visit");
}
private:
VisitFunc visitFunc_;
};
std::unique_ptr<IVisitor> getSomeVisitor(int id)
{
if (id == 42)
{
return std::unique_ptr<VisitorA>(new VisitorA());
}
return std::unique_ptr<VisitorB>(new VisitorB());
}
int main()
{
int succeededCalls = 0;
try
{
auto visitable = Visitable<VisitorA>([&succeededCalls](VisitorA&)
{
std::cout << "VisitorA found!" << std::endl;
++succeededCalls;
});
// all is ok!
getSomeVisitor(42)->visit(visitable);
// this will fail
getSomeVisitor(11)->visit(visitable);
}
catch (const std::runtime_error& e)
{
// something bad is happened
std::cout << "Exception: " << e.what() << std::endl;
}
getSomeVisitor(69)->visit(Visitable<VisitorB>([&succeededCalls](VisitorB&)
{
// all is ok!
std::cout << "VisitorB found!\n" << std::endl;
++succeededCalls;
}));
std::cout << "Succeded call count: " << succeededCalls << std::endl;
/*
* VisitorA found!
* Exception: Unexpected visit
* VisitorB found!
*
* Succeded call count: 2
*/
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment