【问题标题】:boost program options short / long parameter namesboost 程序选项短/长参数名称
【发布时间】:2015-08-27 16:33:33
【问题描述】:

我已经实现了一个路由,通过遍历po::variable_map 来打印出我的boost::program_options 对象中可用的所有选项及其当前值。

有了这个,我可以直接打印选项的长名称及其值。但是,我不知道如何从长选项名称中检索短选项名称(即来自 --help 的 -h)。有什么建议吗?

【问题讨论】:

    标签: c++ boost


    【解决方案1】:

    我记得在最近的一个回答中描述了为什么variable_map“为时已晚”无法了解选项描述:

    简而言之,variable_map 位于库的 Storage Component 中,因此与选项描述(位于 Options Description Component 中)隔离。

    可以做什么?

    您可以使用中间结果,即Parsers Component 的原始输出:

    解析结果作为parsed_options 类的实例返回。通常,该对象直接传递给存储组件。不过也可以直接使用,也可以做一些额外的处理

    所以,让我们在这里尝试制作一个示例:

        po::parsed_options const intermediate = po::parse_command_line(ac, av, desc);
    
        //////////////////////////////////
        // print the extended usage info as per the question
        //
        for (auto& entry : intermediate.options)
        {
            po::option_description const& opt = desc.find(entry.string_key, false, false, false); 
    
            std::cout << "\nActual tokens involved: ";
            for (auto& tok : entry.original_tokens)
                std::cout << "'" << tok << "' ";
            for (std::string const& v : entry.value)
                std::cout << "\nAssociated value: " << v;
            std::cout << "\n-----------------------------------------------------------\n";
            std::cout << "opt.format_name()        : "        << opt.format_name()                                      << "\n";
            std::cout << "opt.long_name()          : "        << opt.long_name()                                        << "\n";
            std::cout << "opt.canonical_display_name('-'): "  << opt.canonical_display_name(cls::allow_dash_for_short)  << "\n";
            std::cout << "opt.canonical_display_name('/'): "  << opt.canonical_display_name(cls::allow_slash_for_short) << "\n";
            std::cout << "opt.canonical_display_name('--'): " << opt.canonical_display_name(cls::allow_long)            << "\n";
        }
    

    注意:通过按键查找,您实际上也可以使用variable_map

    打印例如

    Actual tokens involved: '-C' '42' 
    Associated value: 42
    -----------------------------------------------------------
    opt.format_name()        : -C [ --compression ]
    opt.long_name()          : compression
    opt.canonical_display_name('-'): -C
    opt.canonical_display_name('/'): /C
    opt.canonical_display_name('--'): --compression
    
    Actual tokens involved: '--name' 'santa' 
    Associated value: santa
    -----------------------------------------------------------
    opt.format_name()        : -n [ --name ]
    opt.long_name()          : name
    opt.canonical_display_name('-'): -n
    opt.canonical_display_name('/'): /n
    opt.canonical_display_name('--'): --name
    Compression level was set to 42.
    

    Live On Coliru

    #include <boost/program_options.hpp>
    #include <boost/program_options/detail/parsers.hpp>
    #include <iostream>
    
    namespace po  = boost::program_options;
    namespace cls = po::command_line_style;
    
    int main(int ac, char** av) {
        // Declare the supported options.
        po::options_description desc("Allowed options");
        desc.add_options()
            ("help", "produce help message")
            ("name,n", po::value<std::string>(), "specify the name")
            ("compression,C", po::value<int>(), "set compression level")
            ;
    
        po::variables_map vm;
        po::parsed_options const intermediate = po::parse_command_line(ac, av, desc);
    
        //////////////////////////////////
        // print the extended usage info as per the question
        //
        for (auto& entry : intermediate.options)
        {
            po::option_description const& opt = desc.find(entry.string_key, false, false, false); 
    
            std::cout << "\nActual tokens involved: ";
            for (auto& tok : entry.original_tokens)
                std::cout << "'" << tok << "' ";
            for (std::string const& v : entry.value)
                std::cout << "\nAssociated value: " << v;
            std::cout << "\n-----------------------------------------------------------\n";
            std::cout << "opt.format_name()        : "        << opt.format_name()                                      << "\n";
            std::cout << "opt.long_name()          : "        << opt.long_name()                                        << "\n";
            std::cout << "opt.canonical_display_name('-'): "  << opt.canonical_display_name(cls::allow_dash_for_short)  << "\n";
            std::cout << "opt.canonical_display_name('/'): "  << opt.canonical_display_name(cls::allow_slash_for_short) << "\n";
            std::cout << "opt.canonical_display_name('--'): " << opt.canonical_display_name(cls::allow_long)            << "\n";
        }
    
        //////////////////////////////////
    
        po::store(intermediate, vm);
        po::notify(vm);    
    
        if (vm.count("help")) {
            std::cout << desc << "\n";
            return 1;
        }
    
        if (vm.count("compression")) {
            std::cout << "Compression level was set to " 
                << vm["compression"].as<int>() << ".\n";
        } else {
            std::cout << "Compression level was not set.\n";
        }
    }
    

    【讨论】:

    • 如果你愿意,你仍然可以看到我是如何通过这个 API 偶然发现的:part #1part #2 (experiment)
    • 如果我们只想要不带“-”或“--”的选项名称,那么 opt.canonical_display_name(0)/opt.canonical_display_name(default_style) 似乎可以工作。那是对的吗?这对配置文件选项也有效吗?
    • @abhishekgupta 我希望如此。但是很容易检查。而且很难提出替代理论。
    猜你喜欢
    • 2014-12-13
    • 1970-01-01
    • 1970-01-01
    • 2011-12-31
    • 1970-01-01
    • 1970-01-01
    • 2016-04-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多