// Copyright (c) 2012 Jan Herrmann // most parts of this example are borrowed from // http://svn.boost.org/svn/boost/sandbox/variadic_templates/libs/composite_storage/sandbox/pack/predator_prey.cpp #include #include #include #include "gofvisitor.hpp" #include "visitable_classes.hpp" #include "accept_n.hpp" // begin predator namespace animals { namespace predator { struct Lion; struct Anaconda; struct Bear; struct Predator_Visitable_Classes : ::boost::mpl::vector {}; struct Predator_Visitor : visitor::gofvisitor < Predator_Visitor // crtp , Predator_Visitable_Classes > {}; struct Predator { virtual ~Predator() {} VISITOR_GOFVISITOR_PURE_VIRTUAL_ACCEPT(Predator_Visitor) }; VISITOR_GOFVISITOR_NON_MEMBER_ACCEPT(Predator,Predator_Visitor) }} VISITOR_CREATE_VISITABLE_CLASSES_TRAIT(animals::predator::Predator,animals::predator::Predator_Visitable_Classes) namespace animals { namespace predator { struct Lion : Predator { VISITOR_GOFVISITOR_VIRTUAL_ACCEPT(Predator_Visitor) }; struct Anaconda : Predator { VISITOR_GOFVISITOR_VIRTUAL_ACCEPT(Predator_Visitor) }; struct Bear : Predator { VISITOR_GOFVISITOR_VIRTUAL_ACCEPT(Predator_Visitor) }; }} // end predators // begin prey namespace animals { namespace prey { struct Gazelle; struct Girrafe; struct Prey_Visitable_Classes : ::boost::mpl::vector {}; struct Prey_Visitor : visitor::gofvisitor < Prey_Visitor // crtp , Prey_Visitable_Classes > {}; struct Prey { virtual ~Prey() {} VISITOR_GOFVISITOR_PURE_VIRTUAL_ACCEPT(Prey_Visitor) }; VISITOR_GOFVISITOR_NON_MEMBER_ACCEPT(Prey,Prey_Visitor); }} VISITOR_CREATE_VISITABLE_CLASSES_TRAIT(animals::prey::Prey,animals::prey::Prey_Visitable_Classes) namespace animals { namespace prey { struct Gazelle : Prey { VISITOR_GOFVISITOR_VIRTUAL_ACCEPT(Prey_Visitor) }; struct Girrafe : Prey { VISITOR_GOFVISITOR_VIRTUAL_ACCEPT(Prey_Visitor) }; }} // end prey // start "method" struct hunt_visitor { std::string result; // templated template void operator()(animals::predator::Lion const&, concrete_prey const& ) { result = std::string("Lion jumps on ") + typeid(concrete_prey).name() + " and bites it."; } // normal void operator()(animals::predator::Anaconda const&, animals::prey::Gazelle const& ) { result="Anaconda injects venom into Gazelle."; } void operator()(animals::predator::Anaconda const&, animals::prey::Girrafe const& ) { result="Anaconda ignores Girraffe."; } // inheritance void operator()(animals::predator::Bear const&, animals::prey::Prey const&) { result = "Bear sleeps and does nothing"; } }; std::string hunt(animals::predator::Predator const& aPredator, animals::prey::Prey const& aPrey) { hunt_visitor sv; visitor::accept_2(aPredator, aPrey, sv); return sv.result; } // end method int main() { using namespace animals::predator; Lion l; Anaconda a; Bear b; Predator const& lion=l; Predator const& anaconda=a; Predator const& bear=b; using namespace animals::prey; Gazelle ga; Girrafe gi; Prey const& gazelle=ga; Prey const& giraffe=gi; std::cout << hunt(lion,gazelle) << std::endl; std::cout << hunt(lion,giraffe) << std::endl; std::cout << hunt(anaconda,gazelle) << std::endl; std::cout << hunt(anaconda,giraffe) << std::endl; std::cout << hunt(bear,gazelle) << std::endl; std::cout << hunt(bear,giraffe) << std::endl; return 0; }