boost::program_options - 验证失败时在错误信息中显示用户输入的值
boost::program_options - display the value entered by the user in error msg when validation fails
我正在使用 boost program_options,但我找不到指定异常消息以包含用户输入的值的方法,例如:
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;
}
我刚找到一种解决方案,可以在验证失败时显示用户输入的值:
...
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());
}
它给出如下输出:
error: the argument for option '--ipc' is invalid: shm
我们可以做得更好吗(即不重复错误消息)?
我正在使用 boost program_options,但我找不到指定异常消息以包含用户输入的值的方法,例如:
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;
}
我刚找到一种解决方案,可以在验证失败时显示用户输入的值:
...
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());
}
它给出如下输出:
error: the argument for option '--ipc' is invalid: shm
我们可以做得更好吗(即不重复错误消息)?