I need to pass some specific arguments from one programm to another using boost::program_options and boost::process. Here is a simple example. In this example I need to pass all args stored in vm_slave to child process, but in common case I wanna pass one or more specific args from vm_slave.
#include <iostream>
#include <boost/process.hpp>
#include <boost/program_options.hpp>
using namespace std;
namespace po = boost::program_options;
int main(int argc, char* argv[]) {
po::options_description tester_options("Tester options");
po::options_description slave_options("Slave options");
tester_options.add_options()
("help,h", "Show help")
("iter,i", po::value<short>()->default_value(1), "TODO")
("modules,m", po::value<std::vector<string>>()->multitoken(), "TODO");
slave_options.add_options()
("size,s", po::value<size_t>()->required(), "TODO")
("threads,t", po::value<short>()->default_value(1), "TODO");
po::variables_map vm;
po::variables_map vm_slave;
auto p0 = po::command_line_parser(argc, argv).options(tester_options).allow_unregistered().run();
auto p1 = po::command_line_parser(argc, argv).options(slave_options).allow_unregistered().run();
po::store(p0, vm);
po::store(p1, vm);
po::store(p1, vm_slave);
// Do some stuff such as write help if needed
// ...
// I need call child process with all (or specific) args from vm_slave
boost::process::ipstream pipe;
boost::process::child cp(
"slave" /* + vm_slave args */,
boost::process::std_err > pipe,
boost::process::std_out > pipe
);
cp.wait();
return 0;
}
Of course I can do something like this:
ostringstream args;
for (const auto& arg : p1.options) {
if (vm_slave.count(arg.string_key) == 0)
continue;
args << arg.string_key << " ";
for (const auto& val : arg.value)
args << val << " ";
}
string cmd_args = args.str();
But in this case some args stored in vm_slave by default is lost.
Or I can do this:
ostringstream args;
for (const auto& arg : vm_slave) {
args << arg.first << " ";
const auto& any_val = arg.second.value();
if (boost::any_cast<size_t>(any_val))
args << to_string(boost::any_cast<size_t>(any_val));
else if (boost::any_cast<short>(any_val))
args << to_string(boost::any_cast<size_t>(any_val));
// And more and more casts...
args << " ";
}
But now we have many any_cast...
If I just pass argv to child process, the child might fail because extra args presented (args like iter not intended for this application).
All this attempts seem bad to me.
What is the proper way to convert parsed arguments back to command line?