Boost.Program_Options で、1オプションに複数の値を与える [C++]

| コメント(0) | トラックバック(0)

ネタ元

まず、ふつーに、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なんてオプション知りません」って言われてしばらく悩んだのは秘密だ

トラックバック(0)

トラックバックURL: http://floralcompany.jp/mt/mt-tb.cgi/107

コメントする

AUTHOR

  • turugina (虎王 剱奈)
  • E-mail: turugina {at} floralcompany.jp
  • pixiv
  • ニジエ

2014年5月

        1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31

アーカイブ

OpenID対応しています OpenIDについて
Powered by Movable Type 5.2.10

- 警 告 -

本サイトにはいわゆる「18禁画像」(イラスト)へのリンクが存在します。 未成年の方や、その手の画像に不快感を覚える方は、 該当記事(「えちぃの」及び「ちょっとえちぃの」カテゴリ) をご覧にならないようお願いいたします。

上記を理解した上で非表示のブログパーツを表示する
あわせて読みたいブログパーツ
ついった
drawr/pixiv/twitpic