Last active
February 15, 2018 12:56
-
-
Save pacmancoder/b68964e9555763392125f3e6f3fd8a33 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* 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