【问题标题】:Boost program_options store multiple config file parse results into one parsed_optionsBoost program_options 将多个配置文件解析结果存储到一个 parsed_options
【发布时间】:2020-06-16 00:17:51
【问题描述】:

我正在尝试解析命令行提供的任意数量文件中的未注册选项。假设我有文件:

configs0.ini
configs1.ini
configs2.ini

我想支持任意数量的这些。

我的代码(简化):

namespace po = boost::program_options;
po::options_description cmd_opts{"Options"};
po::options_description config_file_opts;
po::variables_map vm;

cmd_opts.add_options()                                                                                                                                                                                                     
   ("help,h", "Help message")                                       
   ("config_files", po::value<std::vector<std::string>>()->multitoken(), "Configuration files to get settings from")

po::parser.options(reg_config_file_opts).allow_unregistered();

po::store(parse_command_line(argc, argv, cmd_opts), vm);

config_files = vm["config_files"].as<std::vector<std::string>>();
po::parsed_options parsed_opts;

for(auto file : config_files) {
   std::ifstream ifs(file, std::ifstream::in);                                                                                                                                                                             
   if(ifs.fail()) {
      std::cerr << "Error opening config file: " << file << std::endl;
      return false;
   }
   ifs.close();

   <NEED HELP HERE>
   parsed_opt.add(parse_config_file(ifs, reg_config_file_opts));
}

po::store(parsed_opts, vm);

parsed_options 是否有某种 .add 能力?

【问题讨论】:

    标签: c++ boost


    【解决方案1】:

    图书馆distinguishes three layers:

    • 描述组件
    • 解析器组件
    • 存储组件

    该设计假设您将使用一组或多组描述与一个或多个解析器,并将结果组合到一个存储中。

    实际上,这意味着您将存储到同一个变量映射中,并通知更新任何具有副作用的值语义。

    现场演示

    • 文件main.cpp

      #include <boost/program_options.hpp>
      #include <boost/program_options/cmdline.hpp>
      #include <boost/program_options/config.hpp>
      #include <fmt/format.h>
      #include <fmt/ranges.h>
      #include <fstream>
      
      namespace po = boost::program_options;
      
      int main() {
          for (auto args : {
                  std::vector{"test.exe"},
                  std::vector{"test.exe", "--config_files", "a.cfg", "b.cfg", "c.cfg"},
              })
          {
              int const argc    = args.size();
              char const** argv = args.data();
      
              po::options_description cmd_opts{"Options"};
      
              using values = std::vector<std::string>;
              cmd_opts.add_options()                                                                                                                                                                                                     
                  ("help,h", "Help message")                                       
                  ("config_files", po::value<values>()->multitoken(), "Configuration files to get settings from")
                  ;
      
              po::variables_map vm;
              po::variables_map cfg_vm; // can also reuse vm
              po::store(parse_command_line(argc, argv, cmd_opts), vm);
      
              auto& config_files = vm["config_files"];
              if (!config_files.empty()) {
      
                  po::options_description config_file_opts;
                  config_file_opts.add_options()                                                                                                                                                                                                     
                      ("foo", po::value<values>()->composing())
                      ("bar_a", po::value<values>()->composing())
                      ("bar_b", po::value<values>()->composing())
                      ("bar_c", po::value<values>()->composing())
                      ;
      
                  for(auto file : config_files.as<values>()) try {
                      std::ifstream ifs(file);
                      po::store(parse_config_file(ifs, config_file_opts), cfg_vm);
                  } catch(std::exception const& e) {
                      fmt::print(stderr, "{}: {}\n", file, e.what());
                  }
      
                  fmt::print("Cmdline opts\n");
                  for (auto& [k, v] : vm) {
                      fmt::print("{}={}\n", k, v.as<values>());
                  }
                  fmt::print("Combined configs\n");
                  for (auto& [k, v] : cfg_vm) {
                      fmt::print("{}={}\n", k, v.as<values>());
                  }
              }
          }
      }
      
    • 文件a.cfg

      foo=foo_val_a
      bar_a=bar_val_a
      
    • 文件b.cfg

      foo=foo_val_b
      bar_b=bar_val_b
      
    • 文件c.cfg

      foo=foo_val_c
      bar_c=bar_val_c
      

    打印:

    Cmdline opts
    config_files={"a.cfg", "b.cfg", "c.cfg"}
    Combined configs
    bar_a={"bar_val_a"}
    bar_b={"bar_val_b"}
    bar_c={"bar_val_c"}
    foo={"foo_val_a", "foo_val_b", "foo_val_c"}
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-02-02
      • 1970-01-01
      • 2023-03-11
      • 2019-01-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多