【问题标题】:is there a way to print config file for boost program options有没有办法打印提升程序选项的配置文件
【发布时间】:2026-02-06 22:30:01
【问题描述】:

我正在使用 boost::program_options 从配置文件中获取参数。

我知道我可以手动创建一个文件,程序选项会解析它。但我正在寻找一种让程序自动生成文件的方法。意思是打印出选项的名称和它的值。例如:

>./main 

没有选项会生成如下所示的 init.cfg

[wave packet]
width = 1
position = 2.0
[calculation parameters]
levels = 15

然后我会进入该文件使用文本编辑器更改值并使用此文件:

>./main init.cfg

解决这个问题的一个好方法是让 variables_map 拥有operator<<。这样我就可以将它写入文件。更改值。读取文件。都是一样的格式,不用写每一行。

我在文档或示例中找不到类似的内容。请让我知道这是否可能

编辑:Sam Miller 展示了如何分段解析 ini 文件。但是,我仍然无法从 boost::program_options::variables_map vm 获取值。 我尝试了以下

  for(po::variables_map::iterator it = vm.begin(); it != vm.end(); ++it)
  {
    if(it->first!="help"&&it->first!="config")
    cout << "first - " << it->first << ", second - " << it->second.value() << "\n";
  }

出现错误,而不是 it-&gt;second.value()。我也试过it-&gt;second。我也遇到了错误:

icpc -lboost_serialization -lboost_program_options -c programOptions.cc
programOptions.cc(60): error: no operator "<<" matches these operands
            operand types are: std::basic_ostream<char, std::char_traits<char>> << boost::any
      cout << "first - " << it->first << ", second - " << it->second.value() << "\n";
                                                       ^

compilation aborted for programOptions.cc (code 2)
make: *** [programOptions.o] Error 2

如果我使用it-&gt;second.as&lt;int&gt;(),我会正确获取值,但并非我的所有值都是整数,一旦我达到双倍,程序就会崩溃:

terminate called after throwing an instance of 'boost::exception_detail::clone_impl<boost::exception_detail::error_info_injector<boost::bad_any_cast> >'
  what():  boost::bad_any_cast: failed conversion using boost::any_cast

【问题讨论】:

    标签: c++ boost boost-program-options


    【解决方案1】:

    据我所知,没有一种使用 program_options 的方法。您可以使用属性树库来write the ini file

    这是一个简短的例子:

    macmini:* samm$ cat property.cc 
    #include <boost/property_tree/ptree.hpp>
    #include <boost/property_tree/ini_parser.hpp>
    
    #include <iostream>
    
    int
    main()
    {
        using boost::property_tree::ptree;
    
        ptree root;
    
        ptree wave_packet;
        wave_packet.put( "width", "1" );
        wave_packet.put( "position", "2.0" );
    
        ptree calculation_parameters;
        calculation_parameters.put( "levels", "15" );
    
        root.push_front(
                ptree::value_type( "calculation parameters", calculation_parameters )
                );
        root.push_front(
                ptree::value_type( "wave packet", wave_packet )
                );
    
        write_ini( std::cout, root );
    
        return 0;
    }
    
    macmini:* samm$ g++ property.cc 
    macmini:* samm$ ./a.out
    [wave packet]
    width=1
    position=2.0
    [calculation parameters]
    levels=15
    macmini:* samm$ 
    

    【讨论】:

    • 有什么方法可以写一个简短的例子吗?或者给个路线图怎么做?
    • @kirill_igum 我添加了一个示例。
    【解决方案2】:

    据我了解,这是关于如何根据给定的 option_description 编写配置文件。

    这是可能的解决方案,如何将选项描述写入配置文件。它与每个参数都有一些默认值这一事实有关。

    void SaveDefaultConfig()
    {
        boost::filesystem::ofstream configFile(configFilePath_);
        auto descOptions = algorithmsDesc_.options();
        boost::property_tree::ptree tree;
    
        for (auto& option : descOptions)
        {
            std::string name = option->long_name();
            boost::any defaultValue;
            option->semantic()->apply_default(defaultValue);
    
            if (defaultValue.type() == typeid(std::string))
            {
                std::string val = boost::any_cast<std::string>(defaultValue);
                tree.put(name, val);
            }
            ///Add here additional else.. type() == typeid() if neccesary
        }
    
        //or write_ini
        boost::property_tree::write_json(configFile, tree);
    }
    

    这里的算法描述是 boost::program_options::options_description,这是你描述选项的地方,例如:

    algorithmsDesc_.add_options()
        ("general.blur_Width", po::value<int>(&varWhereToStoreValue)->default_value(3), "Gaussian blur aperture width")
    

    问题是您是否需要配置文件中的部分。 options_description 没有通过其构造函数获取标题的方法。获取它的肮脏方法是从 print() 生成的输出流中剪切它:

    std::string getSectionName()
    {
        std::stringstream ss;
        algorithmDesc_.print(ss)
    
        std::string caption;
        std::getline(ss,caption)
    
        //cut last ':'
        return caption.substr(0, caption.size() - 1)
    }
    

    将它们组合在一起很简单。

    【讨论】:

      最近更新 更多