class abstract_file_t { public: virtual std::string name() const = 0; virtual void accept(visitor_t& v) = 0; virtual ~abstract_file_t(){} }; //////////////////////////////////////////////////////////////////////////// class regular_file_t : public abstract_file_t { public: std::string name() const; void accept(visitor_t& v); size_t size(); }; //////////////////////////////////////////////////////////////////////////// typedef std::vector<abstract_file_t*> file_vector_t; class directory_t : public abstract_file_t { public: void accept(visitor_t& v); std::string name() const; file_vector_t& files(); };
void regular_file_t::accept(visitor_t& v) {v.visit(*this);}
class visitor_t { public: virtual void visit(regular_file_t& f) = 0; virtual void visit(directory_t& dir) = 0; virtual ~visitor_t(){} }; class print_info_visitor_t : public visitor_t { public: void visit(regular_file_t& f); { std::cout << "visiting concrete file. file name: " << f.name() << " file size: " << f.size() << std::endl; } void visit(directory_t& dir) { std::cout << "visiting directory. directory name: " << dir.name() << ". contains " << dir.files().size() << “files” << std::endl; } };
class person_t { public: person_t(const std::string& name, size_t age) : name_(name), age_(age){} template<typename Visitor> void accept(Visitor& v) {v.visit(*this);} size_t age() const {return age_;} private: std::string name_; size_t age_; }; //////////////////////////////////////////////////////////////////////////////// struct person_visitor_t { person_visitor_t(size_t age_limit) : age_limit_(age_limit){} bool operator()(const person_t& p) {return visit(p);} bool visit(const person_t& p) {return p.age() < age_limit_;} size_t age_limit_; }; //////////////////////////////////////////////////////////////////////////////// int main() { std::vector<person_t> person_vec; person_vec.push_back(person_t("Person 1", 43)); person_vec.push_back(person_t("Person 2", 20)); auto it = std::find_if( person_vec.begin(), person_vec.end(), person_visitor_t(30)); if(it != person_vec.end()) std::cout << it->age() << std::endl; return 0; }
template<typename T> struct node_t { node_t(){} // accept template<typename V> void on_init(V& v) {v.on_init(t_);} // accept template<typename V> void on_print(V& v) {v.on_print(t_);} T t_; };
template<typename T, typename Graph> void generate_graph(Graph& g, size_t size); template<typename T, typename Graph, typename Visitor> void generate_graph(Graph& g, Visitor& v, size_t size) { for(size_t i = 0; i < size; ++i) { node_t<T> node; node.on_init(v); g.push_back(node); } } //////////////////////////////////////////////////////////////////////////////// template<typename Graph> void print_graph(Graph& g); template<typename Graph, typename Visitor> void print_graph(Graph& g, Visitor& v) { for(size_t i = 0; i < g.size(); ++i) { g[i].on_print(v); } }
struct person_t { std::string name; int age; }; //////////////////////////////////////////////////////////////////////////////// // visitor struct person_visitor_t { // visit() void on_init(person_t& p) { p.name = "unknown"; p.age = 0; } // visit() void on_print(const person_t& p) { std::cout << p.name << ", " << p.age << std::endl; } }; //////////////////////////////////////////////////////////////////////////////// int main() { person_visitor_t person_visitor; typedef std::vector<node_t<person_t> > person_vec_t; person_vec_t graph; generate_graph<person_t>(graph, person_visitor, 10); print_graph(graph, person_visitor); }
template< typename T1 = default_param1, typename T2 = default_param2, typename T3 = default_param3 > class variant { ... public: // accept() template<typename Visitor> void apply_visitor(const Visitor& v) { switch(type_tag_) // { case 1: apply1(v, T1()); break; case 2: apply2(v, T2()); break; case 3: apply3(v, T3()); break; default: break; } } };
template<typename Visitor, typename U> void apply1( const Visitor& v, U u, typename std::enable_if< !std::is_same<U, default_param1>::value>::type* = 0) { // data_ - . // visit() operator() v(*(T1*)(&data_[0])); } // . template<typename Visitor, typename U> void apply1( const Visitor& v, U u, typename std::enable_if< std::is_same<U, default_param1>::value>::type* = 0) { }
struct visitor_t { void operator()(int i)const ; void operator()(double d)const; void operator()(const std::string& s)const; }; variant<int, double> test_v(34); test_v.apply_visitor(visitor_t());
Source: https://habr.com/ru/post/208718/
All Articles