рд╕реА ++ рдХреЗ рдореБрд╣рд╛рд╡рд░реЗред рд╕реНрдереИрддрд┐рдХ рдЖрдЧрдВрддреБрдХ

рд╡рд┐рдЬрд┐рдЯрд░ рдкреИрдЯрд░реНрди рдбреЗрдЯрд╛ рдкреНрд░реЛрд╕реЗрд╕рд┐рдВрдЧ рдПрд▓реНрдЧреЛрд░рд┐рдердо рдХреЛ рдбреЗрдЯрд╛ рд╕реЗ рдЕрд▓рдЧ рдХрд░рдиреЗ рдХрд╛ рдПрдХ рдФрд░ рддрд░реАрдХрд╛ рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реИред рдЗрд╕ рд▓реЗрдЦ рдореЗрдВ, рдореИрдВ рдореВрд▓ рдкреИрдЯрд░реНрди рдХреЗ рдкреАрдЫреЗ рдХреЗ рд╡рд┐рдЪрд╛рд░, рдЗрд╕рдХреА C ++ рд╡рд┐рд╢рд┐рд╖реНрдЯ рднрд┐рдиреНрдирддрд╛, рдФрд░ рдЙрдкрдпреЛрдЧ рдХреЗ рдХреБрдЫ рд╕рд░рд▓ рдЙрджрд╛рд╣рд░рдг рдмрддрд╛рдКрдВрдЧрд╛ред

рдЖрдЧрдВрддреБрдХ


рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рдЖрдЗрдП рдпрд╛рдж рдХрд░реЗрдВ рдХрд┐ рдХреНрд▓рд╛рд╕рд┐рдХ рд╡рд┐рдЬрд╝рд┐рдЯрд░ рдХреИрд╕реЗ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ ред рдЗрд╕ рдкреИрдЯрд░реНрди рдХреЗ рд▓рд┐рдП рдкреНрд░реЗрд░рдгрд╛ рдХрд╛рдлреА рд╕рд░рд▓ рд╣реИред рдХрд▓реНрдкрдирд╛ рдХреАрдЬрд┐рдП рдХрд┐ рд╣рдорд╛рд░реЗ рдХрд╛рд░реНрдпрдХреНрд░рдо рдореЗрдВ рд╣рдореЗрдВ рдмрд╣реБрд░реВрдкрд┐рдпреЛрдВ рдХреЗ рдПрдХ рдХрдВрдЯреЗрдирд░ (рдкреЗрдбрд╝, рдЧреНрд░рд╛рдл) рдХреЛ рд╕рдВрд╕рд╛рдзрд┐рдд рдХрд░рдиреЗ рдФрд░ рдкреНрд░рддреНрдпреЗрдХ рд╡рд╕реНрддреБ рдХреЗ рд▓рд┐рдП рдХреБрдЫ рд╕рдВрдЪрд╛рд▓рди рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рдФрд░ рдпрд╣ рд╕реЗрдЯ рдкреНрд░рддреНрдпреЗрдХ рд╡рд┐рд╢рд┐рд╖реНрдЯ рдкреНрд░рдХрд╛рд░ рдХреЗ рд▓рд┐рдП рдЕрд▓рдЧ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдПред рдпрд╣ рднреА рдзреНрдпрд╛рди рджреЗрдиреЗ рдпреЛрдЧреНрдп рд╣реИ рдХрд┐ рд╡рд╕реНрддреБрдУрдВ рдХреЛ рд╕реНрд╡рдпрдВ рдЙрдиреНрд╣реЗрдВ рд╕рдВрд╕рд╛рдзрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрд▓реНрдЧреЛрд░рд┐рджрдо рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдХреБрдЫ рднреА рдЬрд╛рдирдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИ, рд╕рд┐рд╡рд╛рдп рдЗрд╕рдХреЗ рдХрд┐ рд╣реИрдВрдбрд▓рд░ рдЙрдиреНрд╣реЗрдВ "рджреЗрдЦ рд╕рдХрддрд╛ рд╣реИ"ред
рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдлрд╝рд╛рдЗрд▓ рд╕рд┐рд╕реНрдЯрдо рдСрдмреНрдЬреЗрдХреНрдЯ: рдлрд╝рд╛рдЗрд▓, рдлрд╝реЛрд▓реНрдбрд░:

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; } }; 


рд╕реНрдереИрддрд┐рдХ рдЖрдЧрдВрддреБрдХ


рд╕реНрдЯреЗрдЯрд┐рдХ рд╡рд┐рдЬрд╝рд┐рдЯрд░ рдХрд╛ рд╕рд╛рд░ рднреА рдЗрд╕ рдбреЗрдЯрд╛ рдХреЛ рд╕рдВрд╕рд╛рдзрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрд▓реНрдЧреЛрд░рд┐рджрдо рд╕реЗ рдбреЗрдЯрд╛ рдХреЛ рдЕрд▓рдЧ рдХрд░рдиреЗ рдореЗрдВ рдирд┐рд╣рд┐рдд рд╣реИред рдореБрдЦреНрдп рдЕрдВрддрд░ рдпрд╣ рд╣реИ рдХрд┐ рдХреНрд▓рд╛рд╕рд┐рдХ рд╡рд┐рдЬрд╝рд┐рдЯрд░ рдХреЗ рдЧрддрд┐рд╢реАрд▓ рдмрд╣реБрд░реВрдкрддрд╛ рдХреЛ рд╕реНрдерд┐рд░ (рдЗрд╕рд▓рд┐рдП рдореБрд╣рд╛рд╡рд░реЗ рдХрд╛ рдирд╛рдо) рдХреЗ рд╕рд╛рде рдмрджрд▓ рджрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдЬрдм рд╣рдо рдПрд╕рдЯреАрдПрд▓ рдПрд▓реНрдЧреЛрд░рд┐рджрдо рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ рддреЛ рд╣рдо рд▓рдЧрднрдЧ рд╣рд░ рдмрд╛рд░ рдЗрд╕ рдкреИрдЯрд░реНрди рдХреЗ рдПрдХ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХрд╛ рд╕рд╛рдордирд╛ рдХрд░рддреЗ рд╣реИрдВред рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ, STL рд╡рд┐рдзреЗрдп рдПрдХ рд╕реНрдерд┐рд░ рдЖрдЧрдВрддреБрдХ рдХрд╛ рдПрдХ рдмреЗрд╣рддрд░реАрди рдЙрджрд╛рд╣рд░рдг рд╣реИред рдЗрд╕реЗ рдХрд╛рдлреА рд╕реНрдкрд╖реНрдЯ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдЫреЛрдЯреЗ рдЙрджрд╛рд╣рд░рдг рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВ:

 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) { } 


рдпрд╣рд╛рдВ рд╣рдо SFINAE рдХрд╛ рдЙрдкрдпреЛрдЧ рд╡рд░реНрддрдорд╛рди рдкреНрд░рдХрд╛рд░ рдХреЗ рд▓рд┐рдП рд╕рд╣реА рдлрд╝рдВрдХреНрд╢рди рдХреЛ "рд╕рдХреНрд╖рдо" рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд░рддреЗ рд╣реИрдВ рдФрд░ рдбрд┐рдлрд╝реЙрд▓реНрдЯ рд░реВрдк рд╕реЗ рд╡рд░реНрдЧ рдорд╛рдкрджрдВрдбреЛрдВ рдХреЗ рд▓рд┐рдП "рдЕрдХреНрд╖рдо" рдХрд░рддреЗ рд╣реИрдВред рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЛрдб рдХрд╛рдлреА рд╕рд░рд▓ рд╣реИ:

 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/In208718/


All Articles