
This post goes toward providing a config or log file output of the input to Boost program_options. This was a requested capability but apparently without further work. See the lines under 'config out:' at the end. http://boost.2283326.n4.nabble.com/program-options-save-configuration-td2565... The following Boost any page provides methods to convert the any values upon iterating the vm map. http://www.boost.org/doc/libs/1_50_0/doc/html/any/s02.html // program_options_wrapper.hpp // Latest boost program_options: // See http://boost-sandbox.sourceforge.net/doc/html/program_options.html // See http://svn.boost.org/svn/boost/trunk/libs/program_options/example/ #ifndef PROGRAM_OPTIONS_WRAPPER_HPP #define PROGRAM_OPTIONS_WRAPPER_HPP #include <boost/any.hpp> #include <boost/program_options.hpp> #include <string> namespace po = boost::program_options; class program_options_wrapper { public: po::variables_map vm; po::options_description cmd_line; po::options_description config; po::options_description hidden; po::options_description version; po::options_description all; // Singleton static program_options_wrapper& instance() { static program_options_wrapper instance_; return instance_; } bool initialize(int argc, char **argv); private: std::string config_file; // Singleton helpers program_options_wrapper() {} program_options_wrapper(program_options_wrapper const& copy); program_options_wrapper& operator=(program_options_wrapper const& copy); bool is_empty(const boost::any & operand); bool is_int(const boost::any & operand); bool is_double(const boost::any & operand); bool is_char_ptr(const boost::any & operand); bool is_string(const boost::any & operand); // void get_typeid(const boost::any & operand); }; // class program_options_wrapper #endif // #define PROGRAM_OPTIONS_WRAPPER_HPP // program_options_wrapper.cpp #include <boost/any.hpp> #include <boost/program_options.hpp> #include <string> #include <vector> #include <fstream> #include "program_options_wrapper.hpp" namespace po = boost::program_options; bool program_options_wrapper::initialize(int argc, char **argv) { version.add_options() ("version: program_options.cpp", "1.0") ("version: program_options.hpp", "1.0") ; cmd_line.add_options() ("help,h", "produce help message") ("version,v", "list component versions") ("config,c", "configuration file name") ("report,r", "report run options") ("vector,x", boost::program_options::value<std::vector<std::string>
(), "test string vector") ("double,d", boost::program_options::value<double>(), "test double") ; all.add(cmd_line).add(config).add(hidden);
// po::store(po::parse_command_line(argc, argv, cmd_line), vm); // po::notify(vm); po::parsed_options parsed = po::command_line_parser(argc, argv).options(cmd_line).allow_unregistered().run(); po::store(parsed, vm); // po::store(po::command_line_parser(argc, argv).options(cmd_line).allow_unregistered().run(), vm); po::notify(vm); if (vm.count("config")) { std::ifstream ifs(config_file.c_str()); if (!ifs) { std::cout << "can not open config file: " << config_file << std::endl; return false; } else { po::store(parse_config_file(ifs, config), vm); po::notify(vm); } } if (vm.count("help")) { std::cout << all; return false; } if (vm.count("version")) { std::cout << version; return false; } if (vm.count("report")) { std::cout << all; std::cout << version << std::endl; std::cout << "command-line:"; for(int j=0;j<argc;j++) std::cout << " " << argv[j]; std::cout << std::endl << std::endl; std::cout << "config out:" << std::endl; for (po::variables_map::iterator it=vm.begin(); it != vm.end(); it++ ) { if (is_empty(it->second.value())) std::cout << "# " << it->first << "=is_empty" << std::endl; if (vm[it->first].defaulted()) std::cout << "# " << it->first << "=is_defaulted" << std::endl; if (is_int(it->second.value())) std::cout << it->first << "=" << vm[it->first].as<int>() << std::endl; else if (is_double(it->second.value())) std::cout << it->first << "=" << vm[it->first].as<double>() << std::endl; else if (is_char_ptr(it->second.value())) std::cout << it->first << "=" << vm[it->first].as<const char *>() << std::endl; else if (is_string(it->second.value())) { std::cout << it->first << "="; std::string temp = vm[it->first].as<std::string>(); if (temp.size()) std::cout << temp << std::endl; else std::cout << "true" << std::endl; } else { // Assumes that the only remainder is vector<string> std::vector<std::string> poVector = vm[it->first].as<std::vector<std::string> >(); for (std::vector<std::string>::iterator vecIt=poVector.begin() ; vecIt != poVector.end(); vecIt++ ) std::cout << it->first << "=" << (*vecIt) << std::endl; } } std::vector<std::string> unrecognized_options = po::collect_unrecognized(parsed.options, po::include_positional); if (unrecognized_options.size()) { std::cout << std::endl << "unrecognized options:"; for (int j=0;j<unrecognized_options.size();j++) std::cout << " " << unrecognized_options[j]; std::cout << std::endl; } std::cout << std::endl; } return true; } bool program_options_wrapper::is_empty(const boost::any & operand) { return operand.empty(); } bool program_options_wrapper::is_int(const boost::any & operand) { return operand.type() == typeid(int); } bool program_options_wrapper::is_double(const boost::any & operand) { return operand.type() == typeid(double); } bool program_options_wrapper::is_char_ptr(const boost::any & operand) { try { boost::any_cast<const char *>(operand); return true; } catch(const boost::bad_any_cast &) { return false; } } bool program_options_wrapper::is_string(const boost::any & operand) { return boost::any_cast<std::string>(&operand); } /* void program_options_wrapper::get_typeid(const boost::any & operand) { std::cout << operand.type().name() << std::endl; } */ // test.cpp /* program_options.o: program_options_wrapper.hpp program_options_wrapper.cpp g++-4.7 -g -c -Wall -std=c++11 program_options_wrapper.cpp -o \ program_options_wrapper.o test: test.cpp program_options_wrapper.o g++-4.7 -Wall -g -std=c++11 test.cpp -o test \ program_options_wrapper.o -lboost_program_options */ #include <boost/program_options.hpp> #include <iostream> #include "program_options_wrapper.hpp" int main(int argc, char **argv) { auto& po_wrap = program_options_wrapper::instance(); po_wrap.version.add_options()("version: build_state_tree.cpp", "1.0"); if (!po_wrap.initialize(argc, argv)) exit(0); return 1; } // test output -h [ --help ] produce help message -v [ --version ] list component versions -c [ --config ] configuration file name -r [ --report ] report run options -x [ --vector ] arg test string vector -d [ --double ] arg test double --version: build_state_tree.cpp 1.0 --version: program_options.cpp 1.0 --version: program_options.hpp 1.0 command-line: ./build_state_tree -r -x str1 -x str2 -d 345.67 -z testing config out: double=345.67 report=true vector=str1 vector=str2 unrecognized options: -z testing Neil Nelson