【问题标题】:Change the metavars in boost::program_options更改 boost::program_options 中的元变量
【发布时间】:2021-08-08 03:56:11
【问题描述】:

这纯粹是审美问题。 我用 C++ 编写了一个 CLI 程序并使用 boost::program_options 来传递它的参数。 默认情况下,boost 将所有元变量命名为 arg。我想改变它。

代码如下:

#include <iostream>
using std::cerr;
using std::cout;

#include <optional>
using std::optional;

#include <string>
using std::string;

#include <boost/program_options.hpp>
using boost::program_options::unknown_option;

#include "Net.h"

#include "GameServer.h"
using proto::GameServer;

namespace args = boost::program_options;

static auto parseArgs(int argc, const char *argv[])
{
    args::options_description desc("Command line options");
    desc.add_options()
        ("help,h", "Show this page")
        ("address,a", args::value<string>()->default_value(net::Defaults::HOST), "IP address to listen on")
        ("port,p", args::value<unsigned short>()->default_value(net::Defaults::PORT), "Port to listen on")
    ;

    optional<args::variables_map> result;
    args::variables_map varMap;

    try {
        args::store(args::parse_command_line(argc, argv, desc), varMap);
    } catch (unknown_option const &error) {
        cerr << "Invalid option: " << error.get_option_name() << "\n";
        cerr << desc << "\n";
        return result;
    }

    args::notify(varMap);

    if (varMap.count("help")) {
        cout << desc << "\n";
        return result;
    }

    return result = varMap;
}

int main(int argc, const char *argv[])
{
    auto parsedArgs = parseArgs(argc, argv);
    if (!parsedArgs.has_value())
        return 1;

    auto args = parsedArgs.value();
    auto address = args.at("address").as<string>();
    auto port = args.at("port").as<unsigned short>();

    GameServer server(address, port);
    server.listen();
}

以及帮助页面生成的输出:

Command line options:
  -h [ --help ]                     Show this page
  -a [ --address ] arg (=127.0.0.1) IP address to listen on
  -p [ --port ] arg (=9000)         Port to listen on

我想将arg-a 重命名为ip_address,将-p 的名称分别重命名为portnum

【问题讨论】:

    标签: c++ boost c++17 command-line-arguments


    【解决方案1】:

    似乎它是boost::program_options 的未记录部分,我快速浏览了boost::program_options 的实现,发现有一个global variable 用于控制行为,所以我们想出了一行代码hack :

    args::arg = "i_am_not_arg";
    

    修改全局变量不是一个优雅的方法,但是我还没有找到任何可用的API来做,你可以做更多的研究并尝试找到更好的解决方案(不要忘记在这里通知我!)

    在代码的某个位置插入这一行,然后我们得到--help 命令行的输出:

    ->./a.out --help
    Command line options:
      -h [ --help ]                         Show this page
      -a [ --address ] i_am_not_arg (=1234) IP address to listen on
      -p [ --port ] i_am_not_arg (=42)      Port to listen on
    

    关于 SO 的提问建议:

    • 提供一个最小的、可重复的程序。您的代码无法在我的机器上编译,因为您使用了未提供的文件中的变量。

    Online demo

    【讨论】:

      【解决方案2】:

      @prehistoricpenguin 的回答让我走上了正轨。在 boost 中,typed_value 类有一个方法 value_name() 来设置参数名称,其工作方式类似于设置默认值,即它修改值对象并将其返回以进行后续操作:

      static auto parseArgs(int argc, const char *argv[])
      {
          options_description desc("Command line options");
          desc.add_options()
                  ("help,h", "Show this page")
                  ("address,a", value<string>()->default_value(HOST)->value_name("ip_address"),
                          "IP address to connect to")
                  ("port,p", value<unsigned short>()->default_value(PORT)->value_name("portnum"),
                          "Port to connect to");
          return parseArgDesc(argc, argv, desc);
      }
      

      导致:

      Command line options:
        -h [ --help ]                         Show this page
        -a [ --address ] ip_address (=127.0.0.1)
                                              IP address to connect to
        -p [ --port ] portnum (=9000)         Port to connect to
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-01-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-12-20
        • 1970-01-01
        • 2019-05-01
        相关资源
        最近更新 更多