我正在尝试使用类来动态组合不同应用程序的程序选项。当使用desc
的普通指针时,一切正常。在下面的shared_ptr
情况下,解析器无法识别添加的程序选项。
我错过了什么?
非常感谢。
namespace config = boost::program_options;
class Parser {
public:
Parser();
void add_all();
void add_x_options();
void add_y_options();
void add_z_options();
void parse(int argc, char** argv);
std::shared_ptr<boost::program_options::options_description> desc;
};
Parser::Parser() {
desc = std::shared_ptr<boost::program_options::options_description>(new boost::program_options::options_description("Options"));
}
void Parser::add_x_options() {
...
desc->add_options()
("option1", config::value<std::string>()->required())
("option2", config::value<std::string>()->required());
}
void Parser::parse(int argc, char** argv) {
config::variables_map vmap;
try {
config::store(config::parse_command_line(argc, argv, *desc), vmap);
if (vmap.count("help")) {
std::cout << *desc << std::endl;
return false;
}
vmap.notify();
}
catch(std::exception& e) {
std::cout << "Error message.\n";
return false;
}
return true;
}
答案 0 :(得分:1)
我不知道你错过了什么,但它可能不在显示的代码中。除非您实际忘记及时致电add_x_options()
?
这是我的测试计划:看到 Live On Coliru
int main()
{
do_test({ "--help" });
do_test({ "--option1" });
do_test({ "--option1", "value1" });
do_test({ "--option2", "value2" });
do_test({ "--option1", "value1", "--option2", "value2" });
}
哪些输出(我在add_x_options
中添加了--help选项,因此可以对其进行测试):
---------------------------------------------------------------------------
Test: fake_program.exe --help
without add_x_options: Error message: unrecognised option '--help'
after add_x_options: Options:
--help print usage instructions
--option1 arg
--option2 arg
---------------------------------------------------------------------------
Test: fake_program.exe --option1
without add_x_options: Error message: unrecognised option '--option1'
after add_x_options: Error message: the required argument for option '--option1' is missing
---------------------------------------------------------------------------
Test: fake_program.exe --option1 value1
without add_x_options: Error message: unrecognised option '--option1'
after add_x_options: Error message: the option '--option2' is required but missing
---------------------------------------------------------------------------
Test: fake_program.exe --option2 value2
without add_x_options: Error message: unrecognised option '--option2'
after add_x_options: Error message: the option '--option1' is required but missing
---------------------------------------------------------------------------
Test: fake_program.exe --option1 value1 --option2 value2
without add_x_options: Error message: unrecognised option '--option1'
after add_x_options:
#include <boost/program_options.hpp>
#include <boost/config.hpp>
#include <memory>
#include <iostream>
class Parser {
public:
Parser();
void add_all();
void add_x_options();
void add_y_options();
void add_z_options();
bool parse(int argc, char** argv);
private:
std::shared_ptr<boost::program_options::options_description> desc;
};
Parser::Parser() {
desc = std::shared_ptr<boost::program_options::options_description>(new boost::program_options::options_description("Options"));
}
namespace config = boost::program_options;
void Parser::add_x_options() {
//...
desc->add_options()
("help", "print usage instructions")
("option1", config::value<std::string>()->required())
("option2", config::value<std::string>()->required());
}
bool Parser::parse(int argc, char** argv) {
config::variables_map vmap;
try {
config::store(config::parse_command_line(argc, argv, *desc), vmap);
if (vmap.count("help")) {
std::cout << *desc << std::endl;
return false;
}
vmap.notify();
return true;
}
catch(std::exception& e) {
std::cout << "Error message: " << e.what() << "\n";
return false;
}
}
void do_test(std::initializer_list<const char*> args)
{
std::string fake_program = "fake_program.exe";
std::vector<char*> fake_argv { &fake_program[0] };
for(auto&& arg : args)
fake_argv.push_back(const_cast<char*>(arg));
Parser parser;
std::cout << "---------------------------------------------------------------------------\n";
std::cout << "Test: ";
for(auto const& a : fake_argv)
std::cout << a << " ";
std::cout << "\n";
std::cout << "without add_x_options: ";
parser.parse(fake_argv.size(), fake_argv.data());
std::cout << "after add_x_options: ";
parser.add_x_options();
parser.parse(fake_argv.size(), fake_argv.data());
}
int main()
{
do_test({ "--help" });
do_test({ "--option1" });
do_test({ "--option1", "value1" });
do_test({ "--option2", "value2" });
do_test({ "--option1", "value1", "--option2", "value2" });
}