C++ boost::program_options-当验证失败时,显示用户在错误消息中输入的值

C++ boost::program_options-当验证失败时,显示用户在错误消息中输入的值,c++,boost,boost-program-options,C++,Boost,Boost Program Options,我正在使用boost program_选项,但找不到方法指定异常消息以包含用户输入的值,如: error: the argument for option '--ipc' is invalid: "shm" 我将用户输入的值传递给下面的调用,但这不起作用: throw po::validation_error(po::validation_error::invalid_option_value, enteredValue); 错误消息仍然是: error: the argument for

我正在使用boost program_选项,但找不到方法指定异常消息以包含用户输入的值,如:

error: the argument for option '--ipc' is invalid: "shm"
我将用户输入的值传递给下面的调用,但这不起作用:

throw po::validation_error(po::validation_error::invalid_option_value, enteredValue);
错误消息仍然是:

error: the argument for option '--ipc' is invalid
下面是我的完整代码:

#include <iostream>
#include <vector>
#include <boost/program_options.hpp>
#include <boost/algorithm/string.hpp>

using namespace std;

namespace po_style = boost::program_options::command_line_style;
namespace po = boost::program_options;

enum class Ipc : int8_t
{
    TCP = 0,
    UDP,
};

// Convert a log severity level to its name formatted as a string
// Enum cannot contain methods but you can add external methods like this one
static const char* to_string(const Ipc& id)
{
    switch (id)
    {
    case Ipc::TCP:  return "TCP";
    case Ipc::UDP:  return "UDP";
    default:        return "TCP";
    }
}

// This function is called for arguments of the type Ipc
void validate(boost::any& v, const vector<string>& values, Ipc*, int)
{
    po::validators::check_first_occurrence(v);
    const string& enteredValue = po::validators::get_single_string(values);
    const string& enteredValueUpper = boost::to_upper_copy(enteredValue);

    if (enteredValueUpper == "TCP")
    {
        v = boost::any(Ipc::TCP);
    }
    else if (enteredValueUpper == "UPD")
    {
        v = boost::any(Ipc::UDP);
    }
    else
    {
        throw po::validation_error(po::validation_error::invalid_option_value, enteredValue);
    }
}

int main(int argc, char* argv[])
{
    try
    {
        // Declare all allowed options using the options_description class. 
        po::options_description desc("Usage");
        desc.add_options()
            ("help,h", "produce help message")
            ("ipc,i", po::value<Ipc>()->default_value(Ipc::TCP, "TCP"), "set the inter-process communication");

        po::variables_map cmdline;
        po::store(po::command_line_parser(argc, argv)
            .options(desc)
            .style(po_style::unix_style | po_style::case_insensitive)
            .run(), cmdline);
        po::notify(cmdline);

        // -i[--ipc] set the inter-process communication
        if (cmdline.count("ipc"))
        {
            Ipc level = cmdline["ipc"].as<Ipc>();
            cout << "ipc=" << to_string(level) << endl;
        }

        // -h[--help] produce help message
        if (cmdline.count("help"))
        {
            cout << desc << "\n";
            return 0;
        }
    }
    catch (exception& e)
    {
        cerr << "error: " << e.what() << "\n";
        return 1;
    }
    catch (...)
    {
        cerr << "Exception of unknown type!\n";
    }

    return 0;
}
#包括
#包括
#包括
#包括
使用名称空间std;
名称空间po_style=boost::程序选项::命令行样式;
名称空间po=boost::program\u选项;
枚举类Ipc:int8\t
{
TCP=0,
UDP,
};
//将日志严重性级别转换为字符串格式的名称
//枚举不能包含方法,但您可以添加像这样的外部方法
静态常量字符*到字符串(常量Ipc&id)
{
开关(id)
{
案例Ipc::TCP:返回“TCP”;
案例Ipc::UDP:返回“UDP”;
默认值:返回“TCP”;
}
}
//对于Ipc类型的参数调用此函数
无效验证(boost::any&v、常量向量和值、Ipc*、int)
{
po::validators::check_first_occurrence(v);
常量字符串&enteredValue=po::验证程序::获取单个字符串(值);
常量字符串&enteredValueUpper=boost::to_upper_copy(enteredValue);
如果(输入值上限==“TCP”)
{
v=boost::any(Ipc::TCP);
}
否则如果(输入值上限==“UPD”)
{
v=boost::any(Ipc::UDP);
}
其他的
{
抛出po::validation\u error(po::validation\u error::无效的\u选项\u值,输入值);
}
}
int main(int argc,char*argv[])
{
尝试
{
//使用options_description类声明所有允许的选项。
采购订单:选项描述说明(“使用”);
说明添加选项()
(“帮助,h”,“生成帮助消息”)
(“ipc,i”,po::value()->默认_值(ipc::TCP,“TCP”),“设置进程间通信”);
po::变量\映射cmdline;
po::store(po::命令行解析器(argc,argv)
.选项(描述)
.style(po_样式::unix_样式| po_样式::不区分大小写)
.run(),cmdline);
po::通知(cmdline);
//-i[--ipc]设置进程间通信
if(cmdline.count(“ipc”))
{
Ipc级别=cmdline[“Ipc”].as();

cout我刚刚找到一个解决方案,在验证失败时显示用户输入的值:

...
else
{
    // ***************************************************
    // SOLUTION FOUND BY Dan Mašek
    // ***************************************************
    throw po::invalid_option_value(enteredValue);



    // This line does not display the enteredValue
    //throw po::validation_error(po::validation_error::invalid_option_value, enteredValue);

    // This works but hardcode the option name --ipc
    //std::ostringstream ss;
    //ss << "the argument for option '--ipc' is invalid: " << enteredValue;
    //throw std::invalid_argument(ss.str());
}

我们能做得更好吗(即不复制错误消息)?

这是哪个版本的Boost?是吗?我正在使用Boost 1.64.0(这是我第一个使用Boost的程序)。到底什么是奇数?奇数部分是该类型消息的格式字符串是
“选项“%canonical\u option%”的参数(“%value%”)无效”
。被
%
包围的标记被适当的参数所取代。乍一看,即使是空值,我也希望
(“”)
bit留下来。我必须仔细研究一下格式化代码,看看那里发生了什么。如果有帮助,我使用的是Visual Studio 2015,问题包括一个完整的生成代码示例。答案很简单,使用派生的异常类:
throw po::invalid_option_value(enteredValue);
Dan Masek找到了解决方案:
error: the argument for option '--ipc' is invalid: shm