まず、ふつーに、Cコンパイラの-Iオプションの如く、 -I <path> -I <path> とかやって複数の値を設定するのは下記でできます。
#include <vector>
#include <string>
#include <iostream>
#include <algorithm>
#include <iterator>
#include <boost/program_options/options_description.hpp>
#include <boost/program_options/parsers.hpp>
#include <boost/program_options/variables_map.hpp>
int main(int c, char** v)
{
try {
namespace po = boost::program_options;
po::options_description desc("Options");
desc.add_options()
("include,I", po::value< std::vector<std::string> >(), "include paths")
;
po::variables_map vm;
po::store(po::parse_command_line(c, v, desc), vm);
po::notify(vm);
if (vm.count("include")) {
const std::vector< std::string >& v = vm["include"].as< std::vector< std::string > >();
std::copy(v.begin(),v.end(),std::ostream_iterator<std::string>(std::cout, ", "));
}
return 0;
} catch ( const std::exception& e ) {
std::cerr << e.what() << "\n";
return -1;
}
}
./exec -I a -I b で a, b が得られます。
ではなく 、 --hoge A B --fuga C のようにして複数の値を渡したい とのこと。
ソースコードを読んだ結果、 parse_command_line の第5引数に追加のパーサを渡せばいいようです。即ち、
#include <iostream>
#include <vector>
#include <string>
#include <iterator>
#include <algorithm>
#include <exception>
#include <boost/program_options/options_description.hpp>
#include <boost/program_options/variables_map.hpp>
#include <boost/program_options/parsers.hpp>
class ext_parser
{
std::string current_key_;
bool is_target_;
public:
std::pair<std::string, std::string>
operator()(const std::string& arg);
};
std::pair<std::string, std::string>
ext_parser::operator()(
const std::string& arg
)
{
std::pair<std::string, std::string> result;
if ( !arg.empty() && arg[0] == '-' ) {
current_key_ = arg;
is_target_ = current_key_ == "--hoge";
current_key_.erase(0, current_key_.find_first_not_of('-'));
if ( is_target_ )
result.first = current_key_;
}
else if ( arg == "--" ) {
// terminate
is_target_ = false;
}
else if ( is_target_ ) {
result.first = current_key_;
result.second = arg;
}
return result;
}
int main(int c, char**v)
{
try {
namespace po = boost::program_options;
po::options_description desc("Options");
desc.add_options()
("help", "show help message")
("hoge", po::value< std::vector<std::string> >(), "hoge- hoge-")
("fuga", po::value< int >(), "fugafuga")
;
po::variables_map vm;
po::store(po::parse_command_line(c, v, desc, 0, ext_parser()), vm);
po::notify(vm);
if (vm.count("help")) {
std::cout << desc << "\n";
return 1;
}
else if (vm.count("hoge")) {
const std::vector< std::string >& v =
vm["hoge"].as< std::vector< std::string > >();
std::copy(v.begin(),v.end(),std::ostream_iterator<std::string>(std::cout, ", "));
}
return 0;
} catch (const std::exception& e) {
std::cerr << e.what() << "\n";
}
}
こんな感じ。 ext_parser クラスを作って、 parse_command_line の引数で渡しています。
めでたく、 ./exec --hoge A B --fuga 10 --hoge C D -- E F で、hoge に A, B, C, D が入りました。
ちなみに、自前でパースした結果のkeyは、add_options()で指定しているkey名に加工してやらないといけません(上の例では"--hoge" を "hoge" に加工してる)。
#「--hogeなんてオプション知りません」って言われてしばらく悩んだのは秘密だ





コメントする