рд╡рд┐рдиреНрдпрд╛рд╕ рдлрд╛рдЗрд▓ред Libconfig рдкреБрд╕реНрддрдХрд╛рд▓рдп рдФрд░ рдЕрдкреНрд░рдпреБрдХреНрдд рд╕реЗрдЯрд┐рдВрдЧреНрд╕ рдХреА рдкрд░рд┐рднрд╛рд╖рд╛

рдкрд░рд┐рдЪрдп


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


рд╕рдорд╕реНрдпрд╛


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


рдПрдХ рдареАрдХ рджрд┐рди, рд╣рдордиреЗ рдпрд╣ рдкрддрд╛ рд▓рдЧрд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдзреНрдпрд╛рди рджрд┐рдпрд╛ рдХрд┐ рд╣рдордиреЗ рд╡рд┐рдиреНрдпрд╛рд╕ рдлрд╛рдЗрд▓реЛрдВ рдореЗрдВ рдХрд┐рддрдирд╛ рдХрдЪрд░рд╛ рдЬрдорд╛ рдХрд┐рдпрд╛ рдерд╛ред рджреБрд░реНрднрд╛рдЧреНрдп рд╕реЗ, libconfig рдХреЗ рдкрд╛рд╕ рдРрд╕рд╛ рдХреЛрдИ рд╡рд┐рдХрд▓реНрдк рдирд╣реАрдВ рдерд╛ред рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рд╣рдордиреЗ рдЧрд┐рдЯрдм рдкрд░ рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдХреЛ рдХрд╛рдВрдЯрд╛ рдФрд░ рдЙрд╕ рд╣рд┐рд╕реНрд╕реЗ рдореЗрдВ рдмрджрд▓рд╛рд╡ рдХрд░рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХреА рдЬреЛ C ++ (рд╕рднреА рдкреНрд░рдХрд╛рд░ рдХреЗ рд▓реБрдХрдЕрдк рдФрд░ рдСрдкрд░реЗрдЯрд░ [] рддрд░реАрдХреЛрдВ) рдореЗрдВ рд▓рд┐рдЦрд╛ рдЧрдпрд╛ рдерд╛, рдиреЛрдб рдХреЗ рд▓рд┐рдП рд╡рд┐рдЬрд╝рд┐рдЯ рдХрд┐рдП рдЧрдП рдзреНрд╡рдЬ рдХреЛ рд╕реЗрдЯ рдХрд░рдиреЗ рдХреА рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХреЛ рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рдХрд░рддрд╛ рд╣реИред рд▓реЗрдХрд┐рди рдЗрд╕рд╕реЗ рдПрдХ рдмрд╣реБрдд рдмрдбрд╝рд╛ рдкреИрдЪ рд╣реЛрдЧрд╛, рдЬрд┐рд╕реЗ рдЕрдкрдирд╛рдиреЗ рдореЗрдВ рд╢рд╛рдпрдж рджреЗрд░реА рд╣реЛрдЧреАред рдФрд░ рдлрд┐рд░ рдЪреБрдирд╛рд╡ рд╕реА ++ рдореЗрдВ рдЕрдкрдиреЗ рд╕реНрд╡рдпрдВ рдХреЗ рдЖрд╡рд░рдг рдХреЛ рд▓рд┐рдЦрдиреЗ рдХреА рджрд┐рд╢рд╛ рдореЗрдВ рдЧрд┐рд░ рдЧрдпрд╛, рдмрд┐рдирд╛ рд▓рд┐рдмрд╛рд╕рдлрд┐рдЧ рдХреЗ рдХреЛрд░ рдХреЛ рдкреНрд░рднрд╛рд╡рд┐рдд рдХрд┐рдПред


рдЖрдЙрдЯрдкреБрдЯ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рджреГрд╖реНрдЯрд┐рдХреЛрдг рд╕реЗ, рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рд╣реИрдВ:


#include <variti/util/config.hpp> #include <iostream> #include <cassert> int main(int argc, char* argv[]) { using namespace variti; using namespace variti::util; assert(argc = 2); config conf( [](const config_setting& st) { if (!st.visited()) std::cerr << "config not visited: " << st.path() << "\n"; }); conf.load(argv[1]); auto root = conf.root(); root["module"]["name"].to_string(); return 0; } 

 laptop :: work/configpp/example тА╣master*тА║ % cat config_example1.conf version = "1.0"; module: { name = "module1"; submodules = ( { name = "submodule1"; }, { name = "submodule2"; } ); }; laptop :: work/configpp/example тА╣master*тА║ % ./config-example1 config_example1.conf config not visited: root.module.submodules.0.name config not visited: root.module.submodules.1.name 

рдЙрджрд╛рд╣рд░рдг рдХреЛрдб рдореЗрдВ, рд╣рдордиреЗ рдореЙрдбреНрдпреВрд▓.name рд╕реЗрдЯ рдХрд┐рдпрд╛ред рд╕реЗрдЯрд┐рдВрдЧ рдореЙрдбреНрдпреВрд▓ред Submodules.0.name рдФрд░ рдореЙрдбреНрдпреВрд▓.submodules.1.name рдПрдХреНрд╕реЗрд╕ рдирд╣реАрдВ рдХрд┐рдП рдЧрдП рдереЗред рдпрд╣ рд╣рдореЗрдВ рд▓реЙрдЧ рдореЗрдВ рдмрддрд╛рдпрд╛ рдЧрдпрд╛ рд╣реИред


рд▓рдкреЗрдЯрдирд╛


рдЕрдЧрд░ рдпрд╣ рджреМрд░рд╛ рдХрд┐рдпрд╛ рдЧрдпрд╛ рдЭрдВрдбрд╛ рдпрд╛ рдРрд╕рд╛ рдХреБрдЫ рд▓рд╛рдЧреВ рдирд╣реАрдВ рд╣реЛрддрд╛ рд╣реИ рддреЛ рдпрд╣ рд▓реАрдмрдХреЙрдиреНрдлрд┐рдЧ рдХреЗ рдЕрдВрджрд░ рдХреИрд╕реЗ рд╣реИ? рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдбреЗрд╡рд▓рдкрд░реНрд╕ рдиреЗ рдкрд╣рд▓реЗ рд╕реЗ рд╕реЛрдЪрд╛ рдФрд░ config_setting_t рдиреЛрдб рдХреЛ рд╣реБрдХ рдЬреЛрдбрд╝рдиреЗ рдХреА рдХреНрд╖рдорддрд╛ рдЬреЛрдбрд╝реА, рдЬреЛ config_setting_set_hook рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рд╕реЗрдЯ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ рдФрд░ config_setting_get_hook рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдкрдврд╝рд╛ рдЧрдпрд╛ рд╣реИред


рдЗрд╕ рд╣реБрдХ рдХреЛ рдЗрд╕ рдкреНрд░рдХрд╛рд░ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░реЗрдВ:


 struct config_setting_hook { bool visited{false}; }; 

Libconfig рдХреЗ рдЕрдВрджрд░ рджреЛ рдореБрдЦреНрдп рд╕рдВрд░рдЪрдирд╛рдПрдБ рд╣реИрдВ: config_t рдФрд░ config_setting_tред рдкрд╣рд▓рд╛ рдПрдХ рдкреВрд░реЗ рдХреЗ рд░реВрдк рдореЗрдВ рдкреВрд░реЗ рдХреЙрдиреНрдлрд┐рдЧрд░ рдХреЛ рдПрдХреНрд╕реЗрд╕ рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реИ рдФрд░ рдПрдХ рдкреЙрдЗрдВрдЯрд░ рдХреЛ рд░реВрдЯ рдиреЛрдб config_setting_t рдкрд░ рд▓реМрдЯрд╛рддрд╛ рд╣реИ, рджреВрд╕рд░рд╛ - рдорд╛рддрд╛-рдкрд┐рддрд╛ рдФрд░ рдмрдЪреНрдЪреЗ рдХреЗ рдиреЛрдбреНрд╕ рддрдХ рдкрд╣реБрдВрдЪ, рд╕рд╛рде рд╣реА рд╕рд╛рде рд╡рд░реНрддрдорд╛рди рдиреЛрдб рдХреЗ рдЕрдВрджрд░ рдореВрд▓реНрдпред


рд╣рдо рджреЛрдиреЛрдВ рд╕рдВрд░рдЪрдирд╛рдУрдВ рдХреЛ рд╕рдВрдмрдВрдзрд┐рдд рд╡рд░реНрдЧреЛрдВ рдореЗрдВ рд▓рдкреЗрдЯрддреЗ рд╣реИрдВ - рд╣реИрдВрдбрд▓ред


Config_t рдХреЗ рдЖрд╕рдкрд╛рд╕ рд╕рдВрднрд╛рд▓:


 using config_notify = std::function<void(const config_setting&)>; struct config : boost::noncopyable { config(config_notify n = nullptr); ~config(); void load(const std::string& filename); config_setting root() const; config_notify n; config_t* h; }; 

рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ рдПрдХ рдлрд╝рдВрдХреНрд╢рди рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрдВрд╕реНрдЯреНрд░рдХреНрдЯрд░ рдХреЛ рдкрд╛рд░рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдЬрд┐рд╕реЗ рд╕рднреА рдЪрд░рдо рдиреЛрдбреНрд╕ рдХреЗ рдЯреНрд░реИрд╡рд░реНрд╕рд▓ рдХреЗ рд╕рдордп рд╡рд┐рдирд╛рд╢рдХрд░реНрддрд╛ рдореЗрдВ рдХрд╣рд╛ рдЬрд╛рдПрдЧрд╛ред рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдХреИрд╕реЗ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ рдпрд╣ рдКрдкрд░ рдХреЗ рдЙрджрд╛рд╣рд░рдг рдореЗрдВ рджреЗрдЦрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред


Config_setting_t рдХреЗ рдЖрд╕рдкрд╛рд╕ рд╕рдВрднрд╛рд▓:


 struct config_setting : boost::noncopyable { config_setting(config_setting_t* h, bool visit = false); ~config_setting(); bool to_bool() const; std::int32_t to_int32() const; std::int64_t to_int64() const; double to_double() const; std::string to_string() const; bool is_bool() const; bool is_int32() const; bool is_int64() const; bool is_double() const; bool is_string() const; bool is_group() const; bool is_array() const; bool is_list() const; bool is_scalar() const; bool is_root() const; std::string path() const; std::size_t size() const; bool exists(const std::string& name) const; config_setting parent() const; config_setting lookup(const std::string& name, bool visit = false) const; config_setting lookup(std::size_t indx, bool visit = false) const; config_setting operator[](const std::string& name) const; config_setting operator[](std::size_t indx) const; std::string filename() const; std::size_t fileline() const; bool visited() const; config_setting_t* h; }; 

рдореБрдЦреНрдп рдЬрд╛рджреВ рджреЗрдЦрдиреЗ рдХреЗ рддрд░реАрдХреЛрдВ рдореЗрдВ рдирд┐рд╣рд┐рдд рд╣реИред рдпрд╣ рдорд╛рдирд╛ рдЬрд╛рддрд╛ рд╣реИ рдХрд┐ рд╡рд┐рдЬрд╝рд┐рдЯ рдХрд┐рдП рдЧрдП рдиреЛрдбреНрд╕ рдзреНрд╡рдЬ рдХреЛ рдЕрдВрддрд┐рдо рддрд░реНрдХ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рд╕реЗрдЯ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдЬрд┐рд╕реЗ рд╡рд┐рдЬрд╝рд┐рдЯ рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЬреЛ рдбрд┐рдлрд╝реЙрд▓реНрдЯ рд░реВрдк рд╕реЗ рдЧрд▓рдд рд╣реИред рдЖрдкрдХреЛ рдЗрд╕ рдореВрд▓реНрдп рдХреЛ рд╕реНрд╡рдпрдВ рдЗрдВрдЧрд┐рдд рдХрд░рдиреЗ рдХрд╛ рдЕрдзрд┐рдХрд╛рд░ рд╣реИред рд▓реЗрдХрд┐рди рдЪреВрдВрдХрд┐ рдиреЛрдбреНрд╕ рдХреЗ рд▓рд┐рдП рд╕рдмрд╕реЗ рдЕрдзрд┐рдХ рд▓рдЧрд╛рддрд╛рд░ рдкрд╣реБрдВрдЪ рдЕрднреА рднреА рдСрдкрд░реЗрдЯрд░ [] рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рд╣реИ, рдЗрд╕рдХреЗ рдЕрдВрджрд░ рд▓реБрдХрдЕрдк рд╡рд┐рдзрд┐ рдХреЛ рд╕рд╣реА рдХреЗ рдмрд░рд╛рдмрд░ рдпрд╛рддреНрд░рд╛ рдХреЗ рд╕рд╛рде рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИред рдЗрд╕ рдкреНрд░рдХрд╛рд░, рдиреЛрдбреНрд╕ рдЬрд┐рд╕рдХреЗ рд▓рд┐рдП рдЖрдк рдСрдкрд░реЗрдЯрд░ рдХрд╣рддреЗ рд╣реИрдВ [] рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рд░реВрдк рд╕реЗ рдЪрд┐рд╣реНрдирд┐рдд рдХреЗ рд░реВрдк рдореЗрдВ рдЪрд┐рд╣реНрдирд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдЬреИрд╕рд╛ рдХрд┐ рджреМрд░рд╛ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ, рд╡рд░реНрддрдорд╛рди рд╕реЗ рдЬрдбрд╝ рддрдХ рдиреЛрдбреНрд╕ рдХреА рдкреВрд░реА рд╢реНрд░реГрдВрдЦрд▓рд╛ рдХреЛ рдЪрд┐рд╣реНрдирд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред


рдЖрдЗрдП рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЗ рд▓рд┐рдП рдЖрдЧреЗ рдмрдврд╝реЗрдВред рд╣рдо рдЗрд╕реЗ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рд╡рд░реНрдЧ рдХреЗ рд▓рд┐рдП рджрд┐рдЦрд╛рддреЗ рд╣реИрдВ:


 config::config(config_notify n) : n(n) { h = (config_t*)malloc(sizeof(config_t)); config_init(h); config_set_destructor(h, [](void* p) { delete reinterpret_cast<config_setting_hook*>(p); }); } config::~config() { if (n) for_each(root(), n); config_destroy(h); free(h); } void config::load(const std::string& filename) { if (!config_read_file(h, filename.c_str())) throw std::runtime_error(std::string("config read file error: ") + filename); } config_setting config::root() const { return config_setting(config_root_setting(h)); } 

рдФрд░ config_setting рдХреЗ рд▓рд┐рдП рдЖрдВрд╢рд┐рдХ рд░реВрдк рд╕реЗ:


 config_setting::config_setting(config_setting_t* h, bool visit) : h(h) { assert(h); if (!config_setting_get_hook(h)) hook(h, new config_setting_hook()) if (visit) visit_up(h); } config_setting::~config_setting() { h = nullptr; } std::size_t config_setting::size() const { return config_setting_length(h); } config_setting config_setting::parent() const { return config_setting(config_setting_parent(h)); } bool config_setting::exists(const std::string& name) const { if (!is_group()) return false; return config_setting_get_member(h, name.c_str()); } config_setting config_setting::lookup(const std::string& name, bool visit) const { assert(is_group()); auto p = config_setting_get_member(h, name.c_str()); if (!p) throw_not_found(*this); return config_setting(p, visit); } config_setting config_setting::lookup(std::size_t indx, bool visit) const { assert(is_group() || is_array() || is_list()); auto p = config_setting_get_elem(h, indx); if (!p) throw_not_found(*this); return config_setting(p, visit); } config_setting config_setting::operator[](const std::string& name) const { return lookup(name, true); } config_setting config_setting::operator[](std::size_t indx) const { return lookup(indx, true); } bool config_setting::visited() const { return boost::algorithm::starts_with(path(), "root") || boost::algorithm::starts_with(path(), "root.version") || hook(h)->visited; } 

рд╣реБрдХ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╣рдо рдЕрд▓рдЧ рд╕реЗ рдорджрдж рдХрд░рдиреЗ рд╡рд╛рд▓реЛрдВ рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВрдЧреЗ:


 void hook(config_setting_t* h, config_setting_hook* k) { config_setting_set_hook(h, k); } config_setting_hook* hook(config_setting_t* h) { return reinterpret_cast<config_setting_hook*>(config_setting_get_hook(h)); } void visit_up(config_setting_t* h) { for (; !config_setting_is_root(h) && !hook(h)->visited; h = config_setting_parent(h)) hook(h)->visited = true; } 

рдФрд░ рдЪрд░рдо рдиреЛрдбреНрд╕ рдХреЛ рдмрд╛рдпрдкрд╛рд╕ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рд╕рд╣рд╛рдпрдХ:


 template <typename F> void for_each(const config_setting& st, F f) { if (st.size()) for (std::size_t i = 0; i < st.size(); ++i) for_each(st.lookup(i), f); else f(st); } 

рдирд┐рд╖реНрдХрд░реНрд╖


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


рдЖрд╡реЗрджрди


рдпрд╣рд╛рдБ рд╕реНрд░реЛрдд рдХреЛрдб рдХреА рдЬрд╛рдБрдЪ рдХрд░реЗрдВ !

Source: https://habr.com/ru/post/hi477454/


All Articles